Browse Source
This commit merges the features of @ConditionalOnPropertyValue to the existing @ConditionalOnProperty. The "match" attribute provides the value to match against. By default, the value should not be equal to "false" which is the existing default of @ConditionalOnProperty. "defaultMatch" specifies if the value should be present. The default matches also the existing behavior of @ConditionalOnProperty. Fixes gh-1000pull/1226/head
7 changed files with 360 additions and 455 deletions
@ -1,80 +0,0 @@
@@ -1,80 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.condition; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.springframework.context.annotation.Conditional; |
||||
|
||||
/** |
||||
* {@link Conditional} that only matches when a property |
||||
* has a given value. |
||||
* |
||||
* <p>If {@link #defaultMatch()} is {@code true} then the |
||||
* condition <strong>also</strong> matches if the property |
||||
* is not present at all. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
@Conditional(OnPropertyValueCondition.class) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target({ElementType.TYPE, ElementType.METHOD}) |
||||
public @interface ConditionalOnPropertyValue { |
||||
|
||||
/** |
||||
* A prefix that should be applied to the property. |
||||
* Defaults to no prefix. The prefix automatically |
||||
* ends with a dot, it does not need to be added. |
||||
*/ |
||||
String prefix() default ""; |
||||
|
||||
/** |
||||
* The property to check. If a prefix has been defined, it |
||||
* is applied to compute the full key of the property. For |
||||
* instance if the prefix is {@code app.config} and this |
||||
* property is {@code my-value}, the fully key would be |
||||
* {@code app.config.my-value} |
||||
* <p>Use the dashed notation to specify the property, that |
||||
* is all lower case with a "-" to separate words (e.g. |
||||
* {@code my-long-property}) |
||||
*/ |
||||
String property(); |
||||
|
||||
/** |
||||
* If relaxed names should be checked. Defaults to {@code true}. |
||||
*/ |
||||
boolean relaxedName() default true; |
||||
|
||||
/** |
||||
* The string representation of the expected value for the property. |
||||
*/ |
||||
String value(); |
||||
|
||||
/** |
||||
* Specify if the condition should match if the property is not set. |
||||
* Defaults to {@code false} |
||||
* <p>This means that the specified {@link #value()} is actually |
||||
* the default one (i.e. the one that you expect if the property |
||||
* is not set). |
||||
*/ |
||||
boolean defaultMatch() default false; |
||||
|
||||
} |
||||
@ -1,61 +0,0 @@
@@ -1,61 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.condition; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import org.springframework.context.annotation.ConditionContext; |
||||
import org.springframework.core.type.AnnotatedTypeMetadata; |
||||
|
||||
/** |
||||
* {@link org.springframework.context.annotation.Condition Condition} that |
||||
* checks if a property has a given value. Can also be configured so that |
||||
* the value to check is the default, hence the absence of property matches |
||||
* as well. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
* @see ConditionalOnPropertyValue |
||||
*/ |
||||
public class OnPropertyValueCondition extends SpringBootCondition { |
||||
|
||||
@Override |
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { |
||||
Map<String, Object> attributes = metadata |
||||
.getAnnotationAttributes(ConditionalOnPropertyValue.class.getName()); |
||||
String prefix = ((String) attributes.get("prefix")).trim(); |
||||
String property = (String) attributes.get("property"); |
||||
Boolean relaxedName = (Boolean) attributes.get("relaxedName"); |
||||
String value = (String) attributes.get("value"); |
||||
Boolean defaultMatch = (Boolean) attributes.get("defaultMatch"); |
||||
|
||||
PropertyHelper helper = new PropertyHelper(context.getEnvironment(), prefix, relaxedName); |
||||
String propertyKey = helper.createPropertyKey(property); |
||||
String actualValue = helper.getPropertyResolver().getProperty(propertyKey); |
||||
|
||||
if (actualValue == null && defaultMatch) { |
||||
return ConditionOutcome.match("@ConditionalOnProperty no property '" + property |
||||
+ "' is set, assuming default value '" + value + "'"); |
||||
} |
||||
if (!value.equalsIgnoreCase(actualValue)) { |
||||
return ConditionOutcome.noMatch("@ConditionalOnProperty wrong value for property '" |
||||
+ property + "': expected '" + value + "' but got '" + actualValue + "'"); |
||||
} |
||||
return ConditionOutcome.match(); |
||||
} |
||||
|
||||
} |
||||
@ -1,74 +0,0 @@
@@ -1,74 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.condition; |
||||
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver; |
||||
import org.springframework.core.env.PropertyResolver; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* Helper for properties-related operations. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
class PropertyHelper { |
||||
|
||||
private final PropertyResolver propertyResolver; |
||||
|
||||
private final String prefix; |
||||
|
||||
private final boolean relaxedNames; |
||||
|
||||
/** |
||||
* Create a new instance with the base {@link PropertyResolver} to use. If |
||||
* a prefix is set and does not end with a dot, it is added. |
||||
* |
||||
* @param propertyResolver the base property resolver |
||||
* @param prefix the prefix to lookup keys, if any |
||||
* @param relaxedNames if relaxed names should be checked |
||||
*/ |
||||
PropertyHelper(PropertyResolver propertyResolver, String prefix, boolean relaxedNames) { |
||||
this.prefix = cleanPrefix(prefix); |
||||
this.relaxedNames = relaxedNames; |
||||
if (relaxedNames) { |
||||
this.propertyResolver = new RelaxedPropertyResolver(propertyResolver, this.prefix); |
||||
} |
||||
else { |
||||
this.propertyResolver = propertyResolver; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Return the {@link PropertyResolver} to use. |
||||
*/ |
||||
public PropertyResolver getPropertyResolver() { |
||||
return propertyResolver; |
||||
} |
||||
|
||||
/** |
||||
* Create the full property key for the specified property. Applies the |
||||
* configured prefix, if necessary. |
||||
*/ |
||||
public String createPropertyKey(String property) { |
||||
return (relaxedNames ? property : prefix + property); |
||||
} |
||||
|
||||
private static String cleanPrefix(String prefix) { |
||||
return (StringUtils.hasText(prefix) && !prefix.endsWith(".") ? prefix + "." : prefix); |
||||
} |
||||
} |
||||
@ -1,196 +0,0 @@
@@ -1,196 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.condition; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Test; |
||||
|
||||
import org.springframework.boot.test.EnvironmentTestUtils; |
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* Tests for {@link ConditionalOnPropertyValue} |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
public class ConditionalOnPropertyValueTests { |
||||
|
||||
private AnnotationConfigApplicationContext context; |
||||
|
||||
@After |
||||
public void tearDown() { |
||||
if (this.context != null) { |
||||
this.context.close(); |
||||
} |
||||
} |
||||
|
||||
@Test // Enabled by default
|
||||
public void enabledIfNotConfiguredOtherwise() { |
||||
load(EnabledIfNotConfiguredOtherwiseConfig.class); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void enabledIfNotConfiguredOtherwiseWithConfig() { |
||||
load(EnabledIfNotConfiguredOtherwiseConfig.class, "simple.myProperty:false"); |
||||
assertFalse(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void enabledIfNotConfiguredOtherwiseWithConfigDifferentCase() { |
||||
load(EnabledIfNotConfiguredOtherwiseConfig.class, "simple.my-property:FALSE"); |
||||
assertFalse(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test // Disabled by default
|
||||
public void disableIfNotConfiguredOtherwise() { |
||||
load(DisabledIfNotConfiguredOtherwiseConfig.class); |
||||
assertFalse(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void disableIfNotConfiguredOtherwiseWithConfig() { |
||||
load(DisabledIfNotConfiguredOtherwiseConfig.class, "simple.myProperty:true"); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void disableIfNotConfiguredOtherwiseWithConfigDifferentCase() { |
||||
load(DisabledIfNotConfiguredOtherwiseConfig.class, "simple.myproperty:TrUe"); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void simpleValueIsSet() { |
||||
load(SimpleValueConfig.class, "simple.myProperty:bar"); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void caseInsensitive() { |
||||
load(SimpleValueConfig.class, "simple.myProperty:BaR"); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void defaultValueIsSet() { |
||||
load(DefaultValueConfig.class, "simple.myProperty:bar"); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void defaultValueIsNotSet() { |
||||
load(DefaultValueConfig.class); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void defaultValueIsSetDifferentValue() { |
||||
load(DefaultValueConfig.class, "simple.myProperty:another"); |
||||
assertFalse(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void prefix() { |
||||
load(PrefixValueConfig.class, "simple.myProperty:bar"); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void relaxedEnabledByDefault() { |
||||
load(PrefixValueConfig.class, "simple.myProperty:bar"); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void strictNameMatch() { |
||||
load(StrictNameConfig.class, "simple.my-property:bar"); |
||||
assertTrue(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
@Test |
||||
public void strictNameNoMatch() { |
||||
load(StrictNameConfig.class, "simple.myProperty:bar"); |
||||
assertFalse(this.context.containsBean("foo")); |
||||
} |
||||
|
||||
private void load(Class<?> config, String... environment) { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
EnvironmentTestUtils.addEnvironment(this.context, environment); |
||||
this.context.register(config); |
||||
this.context.refresh(); |
||||
} |
||||
|
||||
@Configuration // ${simple.myProperty:true}
|
||||
@ConditionalOnPropertyValue(prefix = "simple", property = "my-property", value = "true", defaultMatch = true) |
||||
static class EnabledIfNotConfiguredOtherwiseConfig { |
||||
@Bean |
||||
public String foo() { |
||||
return "foo"; |
||||
} |
||||
} |
||||
|
||||
@Configuration // ${simple.myProperty:false}
|
||||
@ConditionalOnPropertyValue(prefix = "simple", property = "my-property", value = "true", defaultMatch = false) |
||||
static class DisabledIfNotConfiguredOtherwiseConfig { |
||||
@Bean |
||||
public String foo() { |
||||
return "foo"; |
||||
} |
||||
} |
||||
|
||||
@Configuration |
||||
@ConditionalOnPropertyValue(prefix = "simple", property = "my-property", value = "bar") |
||||
static class SimpleValueConfig { |
||||
@Bean |
||||
public String foo() { |
||||
return "foo"; |
||||
} |
||||
} |
||||
|
||||
@Configuration |
||||
@ConditionalOnPropertyValue(property = "simple.myProperty", value = "bar", defaultMatch = true) |
||||
static class DefaultValueConfig { |
||||
@Bean |
||||
public String foo() { |
||||
return "foo"; |
||||
} |
||||
} |
||||
|
||||
@Configuration |
||||
@ConditionalOnPropertyValue(prefix = "simple", property = "my-property", value = "bar") |
||||
static class PrefixValueConfig { |
||||
@Bean |
||||
public String foo() { |
||||
return "foo"; |
||||
} |
||||
} |
||||
|
||||
@Configuration |
||||
@ConditionalOnPropertyValue(prefix = "simple", property = "my-property", value = "bar", relaxedName = false) |
||||
static class StrictNameConfig { |
||||
@Bean |
||||
public String foo() { |
||||
return "foo"; |
||||
} |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue