diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/BeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
index c43b9052218..c49b9065056 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
@@ -87,6 +87,7 @@ import org.springframework.beans.BeansException;
*
* @author Rod Johnson
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 13 April 2001
* @see BeanNameAware#setBeanName
* @see BeanClassLoaderAware#setBeanClassLoader
@@ -113,7 +114,6 @@ public interface BeanFactory {
*/
String FACTORY_BEAN_PREFIX = "&";
-
/**
* Return an instance, which may be shared or independent, of the specified bean.
* This method allows a Spring BeanFactory to be used as a replacement for the
@@ -240,7 +240,7 @@ public interface BeanFactory {
* @see #getBean
* @see #getType
*/
- boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
+ boolean isTypeMatch(String name, Class> targetType) throws NoSuchBeanDefinitionException;
/**
* Determine the type of the bean with the given name. More specifically,
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
index 4061d7f923d..e7c08c2dc55 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
@@ -110,7 +110,7 @@ public interface ListableBeanFactory extends BeanFactory {
* @see FactoryBean#getObjectType
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class)
*/
- String[] getBeanNamesForType(Class type);
+ String[] getBeanNamesForType(Class> type);
/**
* Return the names of beans matching the given type (including subclasses),
@@ -123,7 +123,7 @@ public interface ListableBeanFactory extends BeanFactory {
* FactoryBean doesn't match, the raw FactoryBean itself will be matched against the
* type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked
* (which doesn't require initialization of each FactoryBean).
-$ *
Does not consider any hierarchy this factory may participate in.
+ *
Does not consider any hierarchy this factory may participate in.
* Use BeanFactoryUtils' beanNamesForTypeIncludingAncestors
* to include beans in ancestor factories too.
*
Note: Does not ignore singleton beans that have been registered
@@ -143,7 +143,7 @@ $ *
Does not consider any hierarchy this factory may participate in.
* @see FactoryBean#getObjectType
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean)
*/
- String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit);
+ String[] getBeanNamesForType(Class> type, boolean includeNonSingletons, boolean allowEagerInit);
/**
* Return the bean instances that match the given object type (including
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/access/SingletonBeanFactoryLocator.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/access/SingletonBeanFactoryLocator.java
index 2bdc1e5e5b0..7f1f73d1cbd 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/access/SingletonBeanFactoryLocator.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/access/SingletonBeanFactoryLocator.java
@@ -432,6 +432,7 @@ public class SingletonBeanFactoryLocator implements BeanFactoryLocator {
protected BeanFactory createDefinition(String resourceLocation, String factoryKey) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
+ // TODO SPR-7508: consider whether to allow for setEnvironment() here (where would it come from?)
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try {
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/AbstractPropertyPlaceholderConfigurer.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/AbstractPropertyPlaceholderConfigurer.java
new file mode 100644
index 00000000000..c3fd69f3f6d
--- /dev/null
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/AbstractPropertyPlaceholderConfigurer.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2002-2010 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.beans.factory.config;
+
+import java.util.Properties;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.util.PropertyPlaceholderHelper;
+import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
+import org.springframework.util.StringValueResolver;
+
+
+/**
+ * TODO SPR-7508: document.
+ *
+ * @author Chris Beams
+ * @author Juergen Hoeller
+ * @since 3.1
+ */
+public abstract class AbstractPropertyPlaceholderConfigurer extends PropertyResourceConfigurer
+ implements BeanNameAware, BeanFactoryAware {
+
+ /** Default placeholder prefix: "${" */
+ public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
+ /** Default placeholder suffix: "}" */
+ public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
+ /** Default value separator: ":" */
+ public static final String DEFAULT_VALUE_SEPARATOR = ":";
+
+ protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
+
+ protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
+
+ protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;
+
+ protected boolean ignoreUnresolvablePlaceholders = false;
+
+ private String nullValue;
+
+ private String beanName;
+
+ private BeanFactory beanFactory;
+
+
+ protected abstract PlaceholderResolver getPlaceholderResolver(Properties props);
+
+ /**
+ * Set the prefix that a placeholder string starts with.
+ * The default is "${".
+ * @see #DEFAULT_PLACEHOLDER_PREFIX
+ */
+ public void setPlaceholderPrefix(String placeholderPrefix) {
+ this.placeholderPrefix = placeholderPrefix;
+ }
+
+ /**
+ * Set the suffix that a placeholder string ends with.
+ * The default is "}".
+ * @see #DEFAULT_PLACEHOLDER_SUFFIX
+ */
+ public void setPlaceholderSuffix(String placeholderSuffix) {
+ this.placeholderSuffix = placeholderSuffix;
+ }
+
+ /**
+ * Specify the separating character between the placeholder variable
+ * and the associated default value, or null if no such
+ * special character should be processed as a value separator.
+ * The default is ":".
+ */
+ public void setValueSeparator(String valueSeparator) {
+ this.valueSeparator = valueSeparator;
+ }
+
+ /**
+ * Set a value that should be treated as null when
+ * resolved as a placeholder value: e.g. "" (empty String) or "null".
+ *
Note that this will only apply to full property values,
+ * not to parts of concatenated values.
+ *
By default, no such null value is defined. This means that
+ * there is no way to express null as a property
+ * value unless you explictly map a corresponding value here.
+ */
+ public void setNullValue(String nullValue) {
+ this.nullValue = nullValue;
+ }
+
+ /**
+ * Set whether to ignore unresolvable placeholders.
+ *
Default is "false": An exception will be thrown if a placeholder fails
+ * to resolve. Switch this flag to "true" in order to preserve the placeholder
+ * String as-is in such a case, leaving it up to other placeholder configurers
+ * to resolve it.
+ */
+ public void setIgnoreUnresolvablePlaceholders(boolean ignoreUnresolvablePlaceholders) {
+ this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
+ }
+
+ /**
+ * Only necessary to check that we're not parsing our own bean definition,
+ * to avoid failing on unresolvable placeholders in properties file locations.
+ * The latter case can happen with placeholders for system properties in
+ * resource locations.
+ * @see #setLocations
+ * @see org.springframework.core.io.ResourceEditor
+ */
+ public void setBeanName(String beanName) {
+ this.beanName = beanName;
+ }
+
+ /**
+ * Only necessary to check that we're not parsing our own bean definition,
+ * to avoid failing on unresolvable placeholders in properties file locations.
+ * The latter case can happen with placeholders for system properties in
+ * resource locations.
+ * @see #setLocations
+ * @see org.springframework.core.io.ResourceEditor
+ */
+ public void setBeanFactory(BeanFactory beanFactory) {
+ this.beanFactory = beanFactory;
+ }
+
+
+ @Override
+ protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
+ throws BeansException {
+
+ StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
+ BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
+
+ String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
+ for (String curName : beanNames) {
+ // Check that we're not parsing our own bean definition,
+ // to avoid failing on unresolvable placeholders in properties file locations.
+ if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
+ BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
+ try {
+ visitor.visitBeanDefinition(bd);
+ }
+ catch (Exception ex) {
+ throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage());
+ }
+ }
+ }
+
+ // New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
+ beanFactoryToProcess.resolveAliases(valueResolver);
+
+ // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
+ beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
+ }
+
+
+ private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
+
+ private final PropertyPlaceholderHelper helper;
+
+ private final PlaceholderResolver resolver;
+
+ public PlaceholderResolvingStringValueResolver(Properties props) {
+ this.helper = new PropertyPlaceholderHelper(
+ placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
+ this.resolver = getPlaceholderResolver(props);
+ }
+
+ public String resolveStringValue(String strVal) throws BeansException {
+ String value = this.helper.replacePlaceholders(strVal, this.resolver);
+ return (value.equals(nullValue) ? null : value);
+ }
+ }
+
+
+}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java
index a755ea124a7..2be34e583b2 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java
@@ -173,7 +173,7 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
* @param requiredType type of the property
* @param propertyEditorClass the {@link PropertyEditor} class to register
*/
- void registerCustomEditor(Class requiredType, Class extends PropertyEditor> propertyEditorClass);
+ void registerCustomEditor(Class> requiredType, Class extends PropertyEditor> propertyEditorClass);
/**
* Initialize the given PropertyEditorRegistry with the custom editors
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java
index ff9d5ee1354..459003bb3d0 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java
@@ -44,7 +44,7 @@ public interface ConfigurableListableBeanFactory
* for example, String. Default is none.
* @param type the dependency type to ignore
*/
- void ignoreDependencyType(Class type);
+ void ignoreDependencyType(Class> type);
/**
* Ignore the given dependency interface for autowiring.
@@ -57,7 +57,7 @@ public interface ConfigurableListableBeanFactory
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.context.ApplicationContextAware
*/
- void ignoreDependencyInterface(Class ifc);
+ void ignoreDependencyInterface(Class> ifc);
/**
* Register a special dependency type with corresponding autowired value.
@@ -75,7 +75,7 @@ public interface ConfigurableListableBeanFactory
* implementation of the {@link org.springframework.beans.factory.ObjectFactory}
* interface, which allows for lazy resolution of the actual target value.
*/
- void registerResolvableDependency(Class dependencyType, Object autowiredValue);
+ void registerResolvableDependency(Class> dependencyType, Object autowiredValue);
/**
* Determine whether the specified bean qualifies as an autowire candidate,
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java
index 7359d4e2160..5274e9a08b5 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java
@@ -19,15 +19,12 @@ package org.springframework.beans.factory.config;
import java.util.Properties;
import java.util.Set;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanDefinitionStoreException;
-import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.core.Constants;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
-import org.springframework.util.StringValueResolver;
+
/**
* A property resource configurer that resolves placeholders in bean property values of
@@ -81,6 +78,7 @@ import org.springframework.util.StringValueResolver;
* be detected and decrypted accordingly before processing them.
*
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 02.10.2003
* @see #setLocations
* @see #setProperties
@@ -91,19 +89,9 @@ import org.springframework.util.StringValueResolver;
* @see #convertPropertyValue
* @see PropertyOverrideConfigurer
*/
-public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
+public class PropertyPlaceholderConfigurer extends AbstractPropertyPlaceholderConfigurer
implements BeanNameAware, BeanFactoryAware {
- /** Default placeholder prefix: "${" */
- public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
-
- /** Default placeholder suffix: "}" */
- public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
-
- /** Default value separator: ":" */
- public static final String DEFAULT_VALUE_SEPARATOR = ":";
-
-
/** Never check system properties. */
public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
@@ -122,52 +110,10 @@ public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
private static final Constants constants = new Constants(PropertyPlaceholderConfigurer.class);
- private String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
-
- private String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
-
- private String valueSeparator = DEFAULT_VALUE_SEPARATOR;
-
private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
private boolean searchSystemEnvironment = true;
- private boolean ignoreUnresolvablePlaceholders = false;
-
- private String nullValue;
-
- private String beanName;
-
- private BeanFactory beanFactory;
-
-
- /**
- * Set the prefix that a placeholder string starts with.
- * The default is "${".
- * @see #DEFAULT_PLACEHOLDER_PREFIX
- */
- public void setPlaceholderPrefix(String placeholderPrefix) {
- this.placeholderPrefix = placeholderPrefix;
- }
-
- /**
- * Set the suffix that a placeholder string ends with.
- * The default is "}".
- * @see #DEFAULT_PLACEHOLDER_SUFFIX
- */
- public void setPlaceholderSuffix(String placeholderSuffix) {
- this.placeholderSuffix = placeholderSuffix;
- }
-
- /**
- * Specify the separating character between the placeholder variable
- * and the associated default value, or null if no such
- * special character should be processed as a value separator.
- * The default is ":".
- */
- public void setValueSeparator(String valueSeparator) {
- this.valueSeparator = valueSeparator;
- }
/**
* Set the system property mode by the name of the corresponding constant,
@@ -218,84 +164,6 @@ public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
this.searchSystemEnvironment = searchSystemEnvironment;
}
- /**
- * Set whether to ignore unresolvable placeholders.
- *
Default is "false": An exception will be thrown if a placeholder fails
- * to resolve. Switch this flag to "true" in order to preserve the placeholder
- * String as-is in such a case, leaving it up to other placeholder configurers
- * to resolve it.
- */
- public void setIgnoreUnresolvablePlaceholders(boolean ignoreUnresolvablePlaceholders) {
- this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
- }
-
- /**
- * Set a value that should be treated as null when
- * resolved as a placeholder value: e.g. "" (empty String) or "null".
- *
Note that this will only apply to full property values,
- * not to parts of concatenated values.
- *
By default, no such null value is defined. This means that
- * there is no way to express null as a property
- * value unless you explictly map a corresponding value here.
- */
- public void setNullValue(String nullValue) {
- this.nullValue = nullValue;
- }
-
- /**
- * Only necessary to check that we're not parsing our own bean definition,
- * to avoid failing on unresolvable placeholders in properties file locations.
- * The latter case can happen with placeholders for system properties in
- * resource locations.
- * @see #setLocations
- * @see org.springframework.core.io.ResourceEditor
- */
- public void setBeanName(String beanName) {
- this.beanName = beanName;
- }
-
- /**
- * Only necessary to check that we're not parsing our own bean definition,
- * to avoid failing on unresolvable placeholders in properties file locations.
- * The latter case can happen with placeholders for system properties in
- * resource locations.
- * @see #setLocations
- * @see org.springframework.core.io.ResourceEditor
- */
- public void setBeanFactory(BeanFactory beanFactory) {
- this.beanFactory = beanFactory;
- }
-
-
- @Override
- protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
- throws BeansException {
-
- StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
- BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
-
- String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
- for (String curName : beanNames) {
- // Check that we're not parsing our own bean definition,
- // to avoid failing on unresolvable placeholders in properties file locations.
- if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
- BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
- try {
- visitor.visitBeanDefinition(bd);
- }
- catch (Exception ex) {
- throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage());
- }
- }
- }
-
- // New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
- beanFactoryToProcess.resolveAliases(valueResolver);
-
- // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
- beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
- }
-
/**
* Resolve the given placeholder using the given properties, performing
* a system properties check according to the given mode.
@@ -379,30 +247,16 @@ public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
* Only retained for compatibility with Spring 2.5 extensions.
*/
@Deprecated
- protected String parseStringValue(String strVal, Properties props, Set visitedPlaceholders) {
+ protected String parseStringValue(String strVal, Properties props, Set> visitedPlaceholders) {
PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper(
placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
PlaceholderResolver resolver = new PropertyPlaceholderConfigurerResolver(props);
return helper.replacePlaceholders(strVal, resolver);
}
-
- private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
-
- private final PropertyPlaceholderHelper helper;
-
- private final PlaceholderResolver resolver;
-
- public PlaceholderResolvingStringValueResolver(Properties props) {
- this.helper = new PropertyPlaceholderHelper(
- placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
- this.resolver = new PropertyPlaceholderConfigurerResolver(props);
- }
-
- public String resolveStringValue(String strVal) throws BeansException {
- String value = this.helper.replacePlaceholders(strVal, this.resolver);
- return (value.equals(nullValue) ? null : value);
- }
+ @Override
+ protected PlaceholderResolver getPlaceholderResolver(Properties props) {
+ return new PropertyPlaceholderConfigurerResolver(props);
}
@@ -419,4 +273,5 @@ public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
}
}
+
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
index 37e5d98fc68..b2b1741f931 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
@@ -166,7 +166,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
setParentBeanFactory(parentBeanFactory);
}
-
/**
* Set the instantiation strategy to use for creating bean instances.
* Default is CglibSubclassingInstantiationStrategy.
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java
index b991f208658..25fd17c84df 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java
@@ -21,8 +21,10 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@@ -40,7 +42,7 @@ import org.springframework.util.Assert;
* @since 11.12.2003
* @see BeanDefinitionReaderUtils
*/
-public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader {
+public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@@ -51,6 +53,8 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
private ClassLoader beanClassLoader;
+ private Environment environment = new DefaultEnvironment();
+
private BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
@@ -62,9 +66,14 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
* {@link org.springframework.context.ApplicationContext} implementations.
*
If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a
* {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}.
+ *
If the the passed-in bean factory also implements {@link EnvironmentCapable} its
+ * environment will be used by this reader. Otherwise, the reader will initialize and
+ * use a {@link DefaultEnvironment}. All ApplicationContext implementations are
+ * EnvironmentCapable, while normal BeanFactory implementations are not.
* @param registry the BeanFactory to load bean definitions into,
* in the form of a BeanDefinitionRegistry
* @see #setResourceLoader
+ * @see #setEnvironment
*/
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
@@ -77,6 +86,14 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
+
+ // Inherit Environment if possible
+ if (this.registry instanceof EnvironmentCapable) {
+ this.environment = ((EnvironmentCapable)this.registry).getEnvironment();
+ }
+ else {
+ this.environment = new DefaultEnvironment();
+ }
}
@@ -122,6 +139,21 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
return this.beanClassLoader;
}
+ /**
+ * TODO SPR-7508: document
+ * @param environment
+ */
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
+ /**
+ * TODO SPR-7508: document
+ */
+ public Environment getEnvironment() {
+ return this.environment;
+ }
+
/**
* Set the BeanNameGenerator to use for anonymous beans
* (without explicit bean name specified).
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
index bab57620706..69701005050 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
@@ -68,6 +68,9 @@ import org.springframework.beans.factory.config.Scope;
import org.springframework.core.DecoratingClassLoader;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.convert.ConversionService;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -100,6 +103,7 @@ import org.springframework.util.StringValueResolver;
* @author Rod Johnson
* @author Juergen Hoeller
* @author Costin Leau
+ * @author Chris Beams
* @since 15 April 2001
* @see #getBeanDefinition
* @see #createBean
@@ -166,6 +170,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final ThreadLocal prototypesCurrentlyInCreation =
new NamedThreadLocal("Prototype beans currently in creation");
+ private ConfigurableEnvironment environment = new DefaultEnvironment();
+
+
/**
* Create a new AbstractBeanFactory.
*/
@@ -189,7 +196,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
-
+
public T getBean(String name, Class requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@@ -682,7 +689,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return this.propertyEditorRegistrars;
}
- public void registerCustomEditor(Class requiredType, Class extends PropertyEditor> propertyEditorClass) {
+ public void registerCustomEditor(Class> requiredType, Class extends PropertyEditor> propertyEditorClass) {
Assert.notNull(requiredType, "Required type must not be null");
Assert.isAssignable(PropertyEditor.class, propertyEditorClass);
this.customEditors.put(requiredType, propertyEditorClass);
@@ -1253,7 +1260,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
-
+
private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException {
if (!ObjectUtils.isEmpty(typesToMatch)) {
ClassLoader tempClassLoader = getTempClassLoader();
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
index cabc026e12a..2a5c55ec45f 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
@@ -203,6 +203,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
*/
public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
+ // TODO SPR-7515: should also do EnvironmentAware injection here?
if (autowireCandidateResolver instanceof BeanFactoryAware) {
if (System.getSecurityManager() != null) {
final BeanFactory target = this;
@@ -460,7 +461,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
// Implementation of ConfigurableListableBeanFactory interface
//---------------------------------------------------------------------
- public void registerResolvableDependency(Class dependencyType, Object autowiredValue) {
+ public void registerResolvableDependency(Class> dependencyType, Object autowiredValue) {
Assert.notNull(dependencyType, "Type must not be null");
if (autowiredValue != null) {
Assert.isTrue((autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue)),
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/MergedBeanDefinitionPostProcessor.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/MergedBeanDefinitionPostProcessor.java
index 48a534a9142..d9846442a9f 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/MergedBeanDefinitionPostProcessor.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/MergedBeanDefinitionPostProcessor.java
@@ -43,6 +43,6 @@ public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
*/
- void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName);
+ void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName);
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
index 3e8784b1817..b9b8b8caa4f 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
@@ -33,6 +33,8 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.DefaultEnvironment;
import org.springframework.util.StringUtils;
/**
@@ -59,6 +61,9 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
/** Map from bean name to bean instance */
private final Map beans = new HashMap();
+ /** TODO SPR-7508: document */
+ private ConfigurableEnvironment environment = new DefaultEnvironment();
+
/**
* Add a new singleton bean.
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/AbstractSingleBeanDefinitionParser.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/AbstractSingleBeanDefinitionParser.java
index b7a72c099de..1c32c4f22de 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/AbstractSingleBeanDefinitionParser.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/AbstractSingleBeanDefinitionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -63,7 +63,7 @@ public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDef
if (parentName != null) {
builder.getRawBeanDefinition().setParentName(parentName);
}
- Class beanClass = getBeanClass(element);
+ Class> beanClass = getBeanClass(element);
if (beanClass != null) {
builder.getRawBeanDefinition().setBeanClass(beanClass);
}
@@ -111,7 +111,7 @@ public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDef
* the supplied Element, or null if none
* @see #getBeanClassName
*/
- protected Class getBeanClass(Element element) {
+ protected Class> getBeanClass(Element element) {
return null;
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParser.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParser.java
index aab07a52d51..93ecbb44bb5 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParser.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -42,7 +42,7 @@ public interface BeanDefinitionParser {
/**
* Parse the specified {@link Element} and register the resulting
* {@link BeanDefinition BeanDefinition(s)} with the
- * {@link org.springframework.beans.factory.xml.ParserContext#getRegistry()} BeanDefinitionRegistry}
+ * {@link org.springframework.beans.factory.xml.ParserContext#getRegistry() BeanDefinitionRegistry}
* embedded in the supplied {@link ParserContext}.
* Implementations must return the primary {@link BeanDefinition} that results
* from the parse if they will ever be used in a nested fashion (for example as
@@ -50,7 +50,8 @@ public interface BeanDefinitionParser {
* null if they will not be used in a nested fashion.
* @param element the element that is to be parsed into one or more {@link BeanDefinition BeanDefinitions}
* @param parserContext the object encapsulating the current state of the parsing process;
- * provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
+ * provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry
+ * BeanDefinitionRegistry}.
* @return the primary {@link BeanDefinition}
*/
BeanDefinition parse(Element element, ParserContext parserContext);
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParserDelegate.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParserDelegate.java
index bf96dd93518..de9123c2e3f 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParserDelegate.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParserDelegate.java
@@ -58,6 +58,7 @@ import org.springframework.beans.factory.support.ManagedProperties;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.support.MethodOverrides;
import org.springframework.beans.factory.support.ReplaceOverride;
+import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@@ -92,10 +93,14 @@ public class BeanDefinitionParserDelegate {
*/
public static final String TRUE_VALUE = "true";
+ public static final String FALSE_VALUE = "false";
+
public static final String DEFAULT_VALUE = "default";
public static final String DESCRIPTION_ELEMENT = "description";
+ public static final String AUTOWIRE_NO_VALUE = "no";
+
public static final String AUTOWIRE_BY_NAME_VALUE = "byName";
public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";
@@ -239,19 +244,25 @@ public class BeanDefinitionParserDelegate {
private final ParseState parseState = new ParseState();
+ private Environment environment;
+
/**
- * Stores all used bean names so we can enforce uniqueness on a per file basis.
+ * Stores all used bean names so we can enforce uniqueness on a per
+ * beans-element basis. Duplicate bean ids/names may not exist within the
+ * same level of beans element nesting, but may be duplicated across levels.
*/
private final Set usedNames = new HashSet();
/**
* Create a new BeanDefinitionParserDelegate associated with the
- * supplied {@link XmlReaderContext}.
+ * supplied {@link XmlReaderContext} and {@link Environment}.
*/
- public BeanDefinitionParserDelegate(XmlReaderContext readerContext) {
+ public BeanDefinitionParserDelegate(XmlReaderContext readerContext, Environment environment) {
Assert.notNull(readerContext, "XmlReaderContext must not be null");
+ Assert.notNull(readerContext, "Environment must not be null");
this.readerContext = readerContext;
+ this.environment = environment;
}
/**
@@ -261,6 +272,12 @@ public class BeanDefinitionParserDelegate {
return this.readerContext;
}
+ /**
+ * Get the {@link Environment} associated with this helper instance.
+ */
+ public final Environment getEnvironment() {
+ return this.environment;
+ }
/**
* Invoke the {@link org.springframework.beans.factory.parsing.SourceExtractor} to pull the
@@ -294,33 +311,69 @@ public class BeanDefinitionParserDelegate {
/**
* Initialize the default lazy-init, autowire, dependency check settings,
- * init-method, destroy-method and merge settings.
- * @see #populateDefaults(DocumentDefaultsDefinition, org.w3c.dom.Element)
+ * init-method, destroy-method and merge settings. Support nested 'beans'
+ * element use cases by falling back to parent in case the
+ * defaults are not explicitly set locally.
+ * @see #populateDefaults(DocumentDefaultsDefinition, DocumentDefaultsDefinition, org.w3c.dom.Element)
* @see #getDefaults()
*/
- public void initDefaults(Element root) {
- populateDefaults(this.defaults, root);
+ public void initDefaults(Element root, BeanDefinitionParserDelegate parent) {
+ populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
this.readerContext.fireDefaultsRegistered(this.defaults);
}
/**
* Populate the given DocumentDefaultsDefinition instance with the default lazy-init,
* autowire, dependency check settings, init-method, destroy-method and merge settings.
+ * Support nested 'beans' element use cases by falling back to
+ * parentDefaults in case the defaults are not explicitly set
+ * locally.
+ * @param defaults the defaults to populate
+ * @param defaults the parent BeanDefinitionParserDelegate (if any) defaults to fall back to
+ * @param root the root element of the current bean definition document (or nested beans element)
*/
- protected void populateDefaults(DocumentDefaultsDefinition defaults, Element root) {
- defaults.setLazyInit(root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE));
- defaults.setMerge(root.getAttribute(DEFAULT_MERGE_ATTRIBUTE));
- defaults.setAutowire(root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE));
+ protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
+ String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
+ if (DEFAULT_VALUE.equals(lazyInit)) {
+ lazyInit = parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE;
+ }
+ defaults.setLazyInit(lazyInit);
+
+ String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
+ if (DEFAULT_VALUE.equals(merge)) {
+ merge = parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE;
+ }
+ defaults.setMerge(merge);
+
+ String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
+ if (DEFAULT_VALUE.equals(autowire)) {
+ autowire = parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE;
+ }
+ defaults.setAutowire(autowire);
+
+ // don't fall back to parentDefaults for dependency-check as it's no
+ // longer supported in as of 3.0. Therefore, no nested
+ // would ever need to fall back to it.
defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));
+
if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
+ } else if (parentDefaults != null) {
+ defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
}
+
if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
+ } else if (parentDefaults != null) {
+ defaults.setInitMethod(parentDefaults.getInitMethod());
}
+
if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
+ } else if (parentDefaults != null) {
+ defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
}
+
defaults.setSource(this.readerContext.extractSource(root));
}
@@ -431,7 +484,8 @@ public class BeanDefinitionParserDelegate {
}
/**
- * Validate that the specified bean name and aliases have not been used already.
+ * Validate that the specified bean name and aliases have not been used already
+ * within the current level of beans element nesting.
*/
protected void checkNameUniqueness(String beanName, List aliases, Element beanElement) {
String foundName = null;
@@ -443,7 +497,7 @@ public class BeanDefinitionParserDelegate {
foundName = (String) CollectionUtils.findFirstMatch(this.usedNames, aliases);
}
if (foundName != null) {
- error("Bean name '" + foundName + "' is already used in this file", beanElement);
+ error("Bean name '" + foundName + "' is already used in this element", beanElement);
}
this.usedNames.add(beanName);
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/DefaultBeanDefinitionDocumentReader.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/DefaultBeanDefinitionDocumentReader.java
index e5447ada681..1b6ed450d1a 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/DefaultBeanDefinitionDocumentReader.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/DefaultBeanDefinitionDocumentReader.java
@@ -16,6 +16,9 @@
package org.springframework.beans.factory.xml;
+import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
+import static org.springframework.util.StringUtils.trimAllWhitespace;
+
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.LinkedHashSet;
@@ -32,11 +35,11 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
+import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
-import org.springframework.util.SystemPropertyUtils;
/**
* Default implementation of the {@link BeanDefinitionDocumentReader} interface.
@@ -59,6 +62,8 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;
+ public static final String NESTED_BEANS_ELEMENT = "beans";
+
public static final String ALIAS_ELEMENT = "alias";
public static final String NAME_ATTRIBUTE = "name";
@@ -69,14 +74,29 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
public static final String RESOURCE_ATTRIBUTE = "resource";
+ /** @see org.springframework.context.annotation.Profile */
+ public static final String PROFILE_ATTRIBUTE = "profile";
+
protected final Log logger = LogFactory.getLog(getClass());
private XmlReaderContext readerContext;
+ private Environment environment;
+
+ private BeanDefinitionParserDelegate delegate;
+
/**
- * Parses bean definitions according to the "spring-beans" DTD.
+ * TODO SPR-7508: document
+ * @param environment
+ */
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
+ /**
+ * Parses bean definitions according to the "spring-beans" DTD. TODO SPR-7508 XSD
* Opens a DOM Document; then initializes the default settings
* specified at <beans> level; then parses
* the contained bean definitions.
@@ -87,16 +107,49 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
- BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
-
- preProcessXml(root);
- parseBeanDefinitions(root, delegate);
- postProcessXml(root);
+ doRegisterBeanDefinitions(root);
}
- protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {
- BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
- delegate.initDefaults(root);
+ protected void doRegisterBeanDefinitions(Element root) {
+ String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
+ boolean isCandidate = false;
+ if (profileSpec == null || profileSpec.equals("")) {
+ isCandidate = true;
+ } else {
+ String[] profiles = commaDelimitedListToStringArray(trimAllWhitespace(profileSpec));
+ for (String profile : profiles) {
+ if (this.environment.getActiveProfiles().contains(profile)) {
+ isCandidate = true;
+ break;
+ }
+ }
+ }
+
+ if (!isCandidate) {
+ // TODO SPR-7508 logging
+ // logger.debug(format("XML is targeted for environment [%s], but current environment is [%s]. Skipping", targetEnvironment, environment == null ? null : environment.getName()));
+ return;
+ }
+
+ // any nested elements will cause recursion in this method. in
+ // order to propagate and preserve default-* attributes correctly,
+ // keep track of the current (parent) delegate, which may be null. Create
+ // the new (child) delegate with a reference to the parent for fallback purposes,
+ // then ultimately reset this.delegate back to its original (parent) reference.
+ // this behavior emulates a stack of delegates without actually necessitating one.
+ BeanDefinitionParserDelegate parent = this.delegate;
+ this.delegate = createHelper(readerContext, root, parent);
+
+ preProcessXml(root);
+ parseBeanDefinitions(root, this.delegate);
+ postProcessXml(root);
+
+ this.delegate = parent;
+ }
+
+ protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
+ BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext, environment);
+ delegate.initDefaults(root, parentDelegate);
return delegate;
}
@@ -152,6 +205,10 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
+ else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
+ // recurse
+ doRegisterBeanDefinitions(ele);
+ }
}
/**
@@ -166,7 +223,7 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
}
// Resolve system properties: e.g. "${user.dir}"
- location = SystemPropertyUtils.resolvePlaceholders(location);
+ location = environment.resolveRequiredPlaceholders(location);
Set actualResources = new LinkedHashSet(4);
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java
index fb7f12c6292..baf2ccc4e8e 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java
@@ -65,6 +65,7 @@ import org.springframework.util.xml.XmlValidationModeDetector;
*
* @author Juergen Hoeller
* @author Rob Harrop
+ * @author Chris Beams
* @since 26.11.2003
* @see #setDocumentReaderClass
* @see BeanDefinitionDocumentReader
@@ -103,7 +104,7 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
private boolean namespaceAware = false;
- private Class documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
+ private Class> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
private ProblemReporter problemReporter = new FailFastProblemReporter();
@@ -134,7 +135,6 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
super(registry);
}
-
/**
* Set whether to use XML validation. Default is true.
* This method switches namespace awareness on if validation is turned off,
@@ -283,7 +283,7 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
*
The default is {@link DefaultBeanDefinitionDocumentReader}.
* @param documentReaderClass the desired BeanDefinitionDocumentReader implementation class
*/
- public void setDocumentReaderClass(Class documentReaderClass) {
+ public void setDocumentReaderClass(Class> documentReaderClass) {
if (documentReaderClass == null || !BeanDefinitionDocumentReader.class.isAssignableFrom(documentReaderClass)) {
throw new IllegalArgumentException(
"documentReaderClass must be an implementation of the BeanDefinitionDocumentReader interface");
@@ -487,8 +487,12 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
* @see BeanDefinitionDocumentReader#registerBeanDefinitions
*/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
- // Read document based on new BeanDefinitionDocumentReader SPI.
+ // Read document based on new BeanDefinitionDocumentReader SPI. // TODO SPR-7508: polish - remove comment
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
+ // TODO SPR-7508: remove ugly cast
+ if (documentReader instanceof DefaultBeanDefinitionDocumentReader) {
+ ((DefaultBeanDefinitionDocumentReader)documentReader).setEnvironment(this.getEnvironment());
+ }
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
@@ -500,7 +504,6 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
*
The default implementation instantiates the specified "documentReaderClass".
* @see #setDocumentReaderClass
*/
- @SuppressWarnings("unchecked")
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanFactory.java
index d5c42c719d1..4abaa002a6f 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanFactory.java
@@ -19,6 +19,7 @@ package org.springframework.beans.factory.xml;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
/**
@@ -34,7 +35,7 @@ import org.springframework.core.io.Resource;
*
This class registers each bean definition with the {@link DefaultListableBeanFactory}
* superclass, and relies on the latter's implementation of the {@link BeanFactory} interface.
* It supports singletons, prototypes, and references to either of these kinds of bean.
- * See "spring-beans-2.0.dtd" for details on options and configuration style.
+ * See "spring-beans-2.0.dtd" for details on options and configuration style. // TODO SPR-7508 polish - s/dtd/xsd/
*
*
For advanced needs, consider using a {@link DefaultListableBeanFactory} with
* an {@link XmlBeanDefinitionReader}. The latter allows for reading from multiple XML
@@ -42,10 +43,14 @@ import org.springframework.core.io.Resource;
*
* @author Rod Johnson
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 15 April 2001
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory
* @see XmlBeanDefinitionReader
+ * @deprecated as of Spring 3.1 in favor of {@link DefaultListableBeanFactory} and
+ * {@link XmlBeanDefinitionReader}
*/
+@Deprecated
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
@@ -58,7 +63,7 @@ public class XmlBeanFactory extends DefaultListableBeanFactory {
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource) throws BeansException {
- this(resource, null);
+ this(resource, (BeanFactory)null);
}
/**
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/support/ResourceEditorRegistrar.java b/org.springframework.beans/src/main/java/org/springframework/beans/support/ResourceEditorRegistrar.java
index 3c61d853506..abb6d20551e 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/support/ResourceEditorRegistrar.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/support/ResourceEditorRegistrar.java
@@ -34,6 +34,8 @@ import org.springframework.beans.propertyeditors.InputSourceEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.URIEditor;
import org.springframework.beans.propertyeditors.URLEditor;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
@@ -53,9 +55,26 @@ import org.springframework.core.io.support.ResourcePatternResolver;
*/
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
+ private final Environment environment;
+
private final ResourceLoader resourceLoader;
+ /**
+ * Create a new ResourceEditorRegistrar for the given {@link ResourceLoader}
+ * using a {@link DefaultEnvironment}.
+ * @param resourceLoader the ResourceLoader (or ResourcePatternResolver)
+ * to create editors for (usually an ApplicationContext)
+ * @see org.springframework.core.io.support.ResourcePatternResolver
+ * @see org.springframework.context.ApplicationContext
+ * @deprecated as of Spring 3.1 in favor of
+ * {@link ResourceEditorRegistrar#ResourceEditorRegistrar(ResourceLoader, Environment)}
+ */
+ @Deprecated
+ public ResourceEditorRegistrar(ResourceLoader resourceLoader) {
+ this(resourceLoader, new DefaultEnvironment());
+ }
+
/**
* Create a new ResourceEditorRegistrar for the given ResourceLoader
* @param resourceLoader the ResourceLoader (or ResourcePatternResolver)
@@ -63,8 +82,9 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
* @see org.springframework.core.io.support.ResourcePatternResolver
* @see org.springframework.context.ApplicationContext
*/
- public ResourceEditorRegistrar(ResourceLoader resourceLoader) {
+ public ResourceEditorRegistrar(ResourceLoader resourceLoader, Environment environment) {
this.resourceLoader = resourceLoader;
+ this.environment = environment;
}
@@ -82,7 +102,7 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
* @see org.springframework.core.io.support.ResourceArrayPropertyEditor
*/
public void registerCustomEditors(PropertyEditorRegistry registry) {
- ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader);
+ ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.environment);
doRegisterEditor(registry, Resource.class, baseEditor);
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
@@ -96,7 +116,7 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
if (this.resourceLoader instanceof ResourcePatternResolver) {
doRegisterEditor(registry, Resource[].class,
- new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader));
+ new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.environment));
}
}
diff --git a/org.springframework.beans/src/main/resources/META-INF/spring.schemas b/org.springframework.beans/src/main/resources/META-INF/spring.schemas
index e843e676fdb..a0d82637fbe 100644
--- a/org.springframework.beans/src/main/resources/META-INF/spring.schemas
+++ b/org.springframework.beans/src/main/resources/META-INF/spring.schemas
@@ -1,12 +1,15 @@
http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
-http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
+http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
http\://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
-http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
+http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
http\://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
http\://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
-http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
+http\://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
+http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
diff --git a/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-beans-3.1.xsd b/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-beans-3.1.xsd
new file mode 100644
index 00000000000..5fa65f6bbd7
--- /dev/null
+++ b/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-beans-3.1.xsd
@@ -0,0 +1,1165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ element.
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ element (or "ref"
+ attribute). We recommend this in most cases as it makes documentation
+ more explicit.
+
+ Note that this default mode also allows for annotation-driven autowiring,
+ if activated. "no" refers to externally driven autowiring only, not
+ affecting any autowiring demands that the bean class itself expresses.
+
+ 2. "byName"
+ Autowiring by property name. If a bean of class Cat exposes a "dog"
+ property, Spring will try to set this to the value of the bean "dog"
+ in the current container. If there is no matching bean by name, nothing
+ special happens.
+
+ 3. "byType"
+ Autowiring if there is exactly one bean of the property type in the
+ container. If there is more than one, a fatal error is raised, and
+ you cannot use byType autowiring for that bean. If there is none,
+ nothing special happens.
+
+ 4. "constructor"
+ Analogous to "byType" for constructor arguments. If there is not exactly
+ one bean of the constructor argument type in the bean factory, a fatal
+ error is raised.
+
+ Note that explicit dependencies, i.e. "property" and "constructor-arg"
+ elements, always override autowiring.
+
+ Note: This attribute will not be inherited by child bean definitions.
+ Hence, it needs to be specified per concrete bean definition.
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ " element.
+ ]]>
+
+
+
+
+ ... " element.
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ".
+ ]]>
+
+
+
+
+ ..." element.
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ".
+ ]]>
+
+
+
+
+ ..."
+ element.
+ ]]>
+
+
+
+
+ ".
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-tool-3.1.xsd b/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-tool-3.1.xsd
new file mode 100644
index 00000000000..9d84906adea
--- /dev/null
+++ b/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-tool-3.1.xsd
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-util-3.1.xsd b/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-util-3.1.xsd
new file mode 100644
index 00000000000..9b5774a46c4
--- /dev/null
+++ b/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-util-3.1.xsd
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
+
+
+
+ Reference a public, static field on a type and expose its value as
+ a bean. For example <util:constant static-field="java.lang.Integer.MAX_VALUE"/>.
+
+
+
+
+
+
+
+
+
+
+
+ Reference a property on a bean (or as a nested value) and expose its values as
+ a bean. For example <util:property-path path="order.customer.name"/>.
+
+
+
+
+
+
+
+
+
+
+
+ Builds a List instance of the specified type, populated with the specified content.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Builds a Set instance of the specified type, populated with the specified content.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Builds a Map instance of the specified type, populated with the specified content.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loads a Properties instance from the resource location specified by the 'location' attribute.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurerTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurerTests.java
index 108a38b2a59..bbbd1eaacee 100644
--- a/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurerTests.java
+++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurerTests.java
@@ -1,44 +1,281 @@
+/*
+ * Copyright 2002-2010 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.beans.factory.config;
import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
+import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.core.io.ByteArrayResource;
import test.beans.TestBean;
+
/**
- * Tests cornering SPR-7547.
+ * Unit tests for {@link EnvironmentAwarePropertyPlaceholderConfigurer}.
*
+ * @see PropertyResourceConfigurerTests
* @author Chris Beams
*/
public class PropertyPlaceholderConfigurerTests {
+ private static final String P1 = "p1";
+ private static final String P1_LOCAL_PROPS_VAL = "p1LocalPropsVal";
+ private static final String P1_SYSTEM_PROPS_VAL = "p1SystemPropsVal";
+ private static final String P1_SYSTEM_ENV_VAL = "p1SystemEnvVal";
+
+ private DefaultListableBeanFactory bf;
+ private AbstractPropertyPlaceholderConfigurer ppc;
+ private Properties ppcProperties;
+
+ private AbstractBeanDefinition p1BeanDef;
+
+ @Before
+ public void setUp() {
+ p1BeanDef = rootBeanDefinition(TestBean.class)
+ .addPropertyValue("name", "${"+P1+"}")
+ .getBeanDefinition();
+
+ bf = new DefaultListableBeanFactory();
+
+ ppcProperties = new Properties();
+ ppcProperties.setProperty(P1, P1_LOCAL_PROPS_VAL);
+ System.setProperty(P1, P1_SYSTEM_PROPS_VAL);
+ getModifiableSystemEnvironment().put(P1, P1_SYSTEM_ENV_VAL);
+ ppc = new PropertyPlaceholderConfigurer();
+ ppc.setProperties(ppcProperties);
+
+ }
+
+ @After
+ public void tearDown() {
+ System.clearProperty(P1);
+ getModifiableSystemEnvironment().remove(P1);
+ }
+
+
+ // -------------------------------------------------------------------------
+ // Tests to ensure backward-compatibility for Environment refactoring
+ // -------------------------------------------------------------------------
+
+ @Test
+ public void resolveFromSystemProperties() {
+ getModifiableSystemEnvironment().put("otherKey", "systemValue");
+ p1BeanDef = rootBeanDefinition(TestBean.class)
+ .addPropertyValue("name", "${"+P1+"}")
+ .addPropertyValue("sex", "${otherKey}")
+ .getBeanDefinition();
+ registerWithGeneratedName(p1BeanDef, bf);
+ ppc.postProcessBeanFactory(bf);
+ TestBean bean = bf.getBean(TestBean.class);
+ assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
+ assertThat(bean.getSex(), equalTo("systemValue"));
+ getModifiableSystemEnvironment().remove("otherKey");
+ }
+
+ @Test
+ public void resolveFromLocalProperties() {
+ tearDown(); // eliminate entries from system props/environment
+ registerWithGeneratedName(p1BeanDef, bf);
+ ppc.postProcessBeanFactory(bf);
+ TestBean bean = bf.getBean(TestBean.class);
+ assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
+ }
+
+ @Test
+ public void setSystemPropertiesMode_defaultIsFallback() {
+ registerWithGeneratedName(p1BeanDef, bf);
+ ppc.postProcessBeanFactory(bf);
+ TestBean bean = bf.getBean(TestBean.class);
+ assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
+ }
+
+ /*
+ @Test
+ public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemProperties() {
+ registerWithGeneratedName(p1BeanDef, bf);
+ ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
+ ppc.postProcessBeanFactory(bf);
+ TestBean bean = bf.getBean(TestBean.class);
+ assertThat(bean.getName(), equalTo(P1_SYSTEM_PROPS_VAL));
+ }
+
+ @Test
+ public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemEnvironment() {
+ registerWithGeneratedName(p1BeanDef, bf);
+ System.clearProperty(P1); // will now fall all the way back to system environment
+ ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
+ ppc.postProcessBeanFactory(bf);
+ TestBean bean = bf.getBean(TestBean.class);
+ assertThat(bean.getName(), equalTo(P1_SYSTEM_ENV_VAL));
+ }
+
+ @Test
+ public void setSystemSystemPropertiesMode_toOverride_andSetSearchSystemEnvironment_toFalse() {
+ registerWithGeneratedName(p1BeanDef, bf);
+ System.clearProperty(P1); // will now fall all the way back to system environment
+ ppc.setSearchSystemEnvironment(false);
+ ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
+ ppc.postProcessBeanFactory(bf);
+ TestBean bean = bf.getBean(TestBean.class);
+ assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL)); // has to resort to local props
+ }
+ */
/**
- * Prior to the fix for SPR-7547, the following would throw
- * IllegalStateException because the PropertiesLoaderSupport base class
- * assumed ByteArrayResource implements Resource.getFilename(). It does
- * not, and AbstractResource.getFilename() is called instead, raising the
- * exception. The following now works, as getFilename() is called in a
- * try/catch to check whether the resource is actually file-based or not.
- *
- * See SPR-7552, which suggests paths to address the root issue rather than
- * just patching the problem.
+ * Creates a scenario in which two PPCs are configured, each with different
+ * settings regarding resolving properties from the environment.
*/
@Test
- public void repro() {
+ public void twoPlacholderConfigurers_withConflictingSettings() {
+ String P2 = "p2";
+ String P2_LOCAL_PROPS_VAL = "p2LocalPropsVal";
+ String P2_SYSTEM_PROPS_VAL = "p2SystemPropsVal";
+ String P2_SYSTEM_ENV_VAL = "p2SystemEnvVal";
+
+ AbstractBeanDefinition p2BeanDef = rootBeanDefinition(TestBean.class)
+ .addPropertyValue("name", "${"+P1+"}")
+ .addPropertyValue("country", "${"+P2+"}")
+ .getBeanDefinition();
+
+ bf.registerBeanDefinition("p1Bean", p1BeanDef);
+ bf.registerBeanDefinition("p2Bean", p2BeanDef);
+
+ ppc.setIgnoreUnresolvablePlaceholders(true);
+ ppc.postProcessBeanFactory(bf);
+
+ System.setProperty(P2, P2_SYSTEM_PROPS_VAL);
+ getModifiableSystemEnvironment().put(P2, P2_SYSTEM_ENV_VAL);
+ Properties ppc2Properties = new Properties();
+ ppc2Properties.put(P2, P2_LOCAL_PROPS_VAL);
+
+ PropertyPlaceholderConfigurer ppc2 = new PropertyPlaceholderConfigurer();
+ ppc2.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
+ ppc2.setProperties(ppc2Properties);
+
+ ppc2Properties = new Properties();
+ ppc2Properties.setProperty(P2, P2_LOCAL_PROPS_VAL);
+ ppc2.postProcessBeanFactory(bf);
+
+ TestBean p1Bean = bf.getBean("p1Bean", TestBean.class);
+ assertThat(p1Bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
+
+ TestBean p2Bean = bf.getBean("p2Bean", TestBean.class);
+ assertThat(p2Bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
+ assertThat(p2Bean.getCountry(), equalTo(P2_SYSTEM_PROPS_VAL));
+
+ System.clearProperty(P2);
+ getModifiableSystemEnvironment().remove(P2);
+ }
+
+ @Test
+ public void customPlaceholderPrefixAndSuffix() {
+ PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
+ ppc.setPlaceholderPrefix("@<");
+ ppc.setPlaceholderSuffix(">");
+
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean",
rootBeanDefinition(TestBean.class)
- .addPropertyValue("name", "${my.name}").getBeanDefinition());
- PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
- ppc.setLocation(new ByteArrayResource("my.name=Inigo Montoya".getBytes()));
- ppc.postProcessBeanFactory(bf);
+ .addPropertyValue("name", "@")
+ .addPropertyValue("sex", "${key2}")
+ .getBeanDefinition());
- TestBean testBean = bf.getBean(TestBean.class);
- assertThat(testBean.getName(), equalTo("Inigo Montoya"));
+ System.setProperty("key1", "systemKey1Value");
+ System.setProperty("key2", "systemKey2Value");
+ ppc.postProcessBeanFactory(bf);
+ System.clearProperty("key1");
+ System.clearProperty("key2");
+
+ assertThat(bf.getBean(TestBean.class).getName(), is("systemKey1Value"));
+ assertThat(bf.getBean(TestBean.class).getSex(), is("${key2}"));
+ }
+
+ @Test
+ public void nullValueIsPreserved() {
+ PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
+ ppc.setNullValue("customNull");
+ getModifiableSystemEnvironment().put("my.name", "customNull");
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
+ .addPropertyValue("name", "${my.name}")
+ .getBeanDefinition());
+ ppc.postProcessBeanFactory(bf);
+ assertThat(bf.getBean(TestBean.class).getName(), nullValue());
+ getModifiableSystemEnvironment().remove("my.name");
+ }
+
+
+ // -------------------------------------------------------------------------
+ // Tests for functionality not possible prior to Environment refactoring
+ // -------------------------------------------------------------------------
+
+ /**
+ * Tests that properties against a BeanFactory's Environment are used by
+ * PropertyPlaceholderConfigurer during placeholder resolution.
+ @Test @SuppressWarnings({ "unchecked", "rawtypes", "serial" })
+ public void replacePlaceholdersFromBeanFactoryEnvironmentPropertySources() {
+ System.setProperty("key1", "systemValue");
+
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.getEnvironment().addPropertySource("psCustom", new HashMap() {{ put("key1", "customValue"); }});
+ bf.registerBeanDefinition("testBean",
+ rootBeanDefinition(TestBean.class).addPropertyValue("name", "${key1}").getBeanDefinition());
+
+ new PropertyPlaceholderConfigurer().postProcessBeanFactory(bf);
+ assertThat(bf.getBean(TestBean.class).getName(), is("customValue"));
+
+ System.clearProperty("key1");
+ }
+ */
+
+
+ // -------------------------------------------------------------------------
+ // Utilities
+ // -------------------------------------------------------------------------
+
+ // TODO SPR-7508: duplicated from EnvironmentPropertyResolutionSearchTests
+ @SuppressWarnings("unchecked")
+ private static Map getModifiableSystemEnvironment() {
+ Class>[] classes = Collections.class.getDeclaredClasses();
+ Map env = System.getenv();
+ for (Class> cl : classes) {
+ if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
+ try {
+ Field field = cl.getDeclaredField("m");
+ field.setAccessible(true);
+ Object obj = field.get(env);
+ return (Map) obj;
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+ throw new IllegalStateException();
}
}
diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyResourceConfigurerTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyResourceConfigurerTests.java
index d4e59c3875d..ca4d5afbefb 100644
--- a/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyResourceConfigurerTests.java
+++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyResourceConfigurerTests.java
@@ -16,6 +16,14 @@
package org.springframework.beans.factory.config;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
+import static test.util.TestResourceUtils.qualifiedResource;
+
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -23,18 +31,12 @@ import java.util.Properties;
import java.util.Set;
import java.util.prefs.Preferences;
-import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
-import test.beans.IndexedTestBean;
-import test.beans.TestBean;
-import static test.util.TestResourceUtils.*;
-
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import org.springframework.beans.factory.support.ChildBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.ManagedList;
@@ -43,11 +45,15 @@ import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.io.Resource;
+import test.beans.IndexedTestBean;
+import test.beans.TestBean;
+
/**
* Unit tests for various {@link PropertyResourceConfigurer} implementations including:
* {@link PropertyPlaceholderConfigurer}, {@link PropertyOverrideConfigurer} and
* {@link PreferencesPlaceholderConfigurer}.
*
+ * @see PropertyPlaceholderConfigurerTests
* @since 02.10.2003
* @author Juergen Hoeller
* @author Chris Beams
@@ -794,6 +800,39 @@ public final class PropertyResourceConfigurerTests {
Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
}
+ /* TODO SPR-7508: uncomment after EnvironmentAwarePropertyPlaceholderConfigurer implementation
+ @Test
+ public void testPreferencesPlaceholderConfigurerWithCustomPropertiesInEnvironment() {
+ factory.registerBeanDefinition("tb",
+ genericBeanDefinition(TestBean.class)
+ .addPropertyValue("name", "${mypath/myName}")
+ .addPropertyValue("age", "${myAge}")
+ .addPropertyValue("touchy", "${myotherpath/myTouchy}")
+ .getBeanDefinition());
+
+ Properties props = new Properties();
+ props.put("myAge", "99");
+ factory.getEnvironment().getPropertySources().add(new PropertiesPropertySource("localProps", props));
+
+ PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
+ ppc.setSystemTreePath("mySystemPath");
+ ppc.setUserTreePath("myUserPath");
+ Preferences.systemRoot().node("mySystemPath").node("mypath").put("myName", "myNameValue");
+ Preferences.systemRoot().node("mySystemPath/myotherpath").put("myTouchy", "myTouchyValue");
+ Preferences.userRoot().node("myUserPath/myotherpath").put("myTouchy", "myOtherTouchyValue");
+ ppc.afterPropertiesSet();
+ ppc.postProcessBeanFactory(factory);
+
+ TestBean tb = (TestBean) factory.getBean("tb");
+ assertEquals("myNameValue", tb.getName());
+ assertEquals(99, tb.getAge());
+ assertEquals("myOtherTouchyValue", tb.getTouchy());
+ Preferences.userRoot().node("myUserPath/myotherpath").remove("myTouchy");
+ Preferences.systemRoot().node("mySystemPath/myotherpath").remove("myTouchy");
+ Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
+ }
+ */
+
private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {
diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests-multiLevel-context.xml b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests-multiLevel-context.xml
new file mode 100644
index 00000000000..b897d98858a
--- /dev/null
+++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests-multiLevel-context.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests-sameLevel-context.xml b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests-sameLevel-context.xml
new file mode 100644
index 00000000000..e8bf2b4469a
--- /dev/null
+++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests-sameLevel-context.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java
new file mode 100644
index 00000000000..1c9e484182e
--- /dev/null
+++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2010 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.beans.factory.xml;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+import test.beans.TestBean;
+
+
+/**
+ * With Spring 3.1, bean id attributes (and all other id attributes across the
+ * core schemas) are no longer typed as xsd:id, but as xsd:string. This allows
+ * for using the same bean id within nested elements.
+ *
+ * Duplicate ids *within the same level of nesting* will still be treated as an
+ * error through the ProblemReporter, as this could never be an intended/valid
+ * situation.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see org.springframework.beans.factory.xml.XmlBeanFactoryTests#testWithDuplicateName
+ * @see org.springframework.beans.factory.xml.XmlBeanFactoryTests#testWithDuplicateNameInAlias
+ */
+public class DuplicateBeanIdTests {
+
+ @Test
+ public void duplicateBeanIdsWithinSameNestingLevelRaisesError() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
+ try {
+ reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-sameLevel-context.xml", this.getClass()));
+ fail("expected parsing exception due to duplicate ids in same nesting level");
+ } catch (Exception ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void duplicateBeanIdsAcrossNestingLevels() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
+ reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-multiLevel-context.xml", this.getClass()));
+ TestBean testBean = bf.getBean(TestBean.class); // there should be only one
+ assertThat(testBean.getName(), equalTo("nested"));
+ }
+}
diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/EnvironmentBeansTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/EnvironmentBeansTests.java
new file mode 100644
index 00000000000..7d4a0f00b67
--- /dev/null
+++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/EnvironmentBeansTests.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2002-2010 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.beans.factory.xml;
+
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.junit.internal.matchers.TypeSafeMatcher;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * TODO SPR-7508: document
+ *
+ * @author Chris Beams
+ */
+public class EnvironmentBeansTests {
+
+ private static final String PROD_ELIGIBLE_XML = "environmentBeans-prodProfile.xml";
+ private static final String DEV_ELIGIBLE_XML = "environmentBeans-devProfile.xml";
+ private static final String ALL_ELIGIBLE_XML = "environmentBeans-noProfile.xml";
+ private static final String MULTI_ELIGIBLE_XML = "environmentBeans-multiProfile.xml";
+ private static final String UNKOWN_ELIGIBLE_XML = "environmentBeans-unknownProfile.xml";
+
+ private static final String PROD_ACTIVE = "prod";
+ private static final String DEV_ACTIVE = "dev";
+ private static final String NULL_ACTIVE = null;
+ private static final String UNKNOWN_ACTIVE = "unknown";
+ private static final String[] NONE_ACTIVE = new String[0];
+ private static final String[] MULTI_ACTIVE = new String[] { PROD_ACTIVE, DEV_ACTIVE };
+
+ private static final String TARGET_BEAN = "foo";
+
+ @Test
+ public void test() {
+ assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, DEV_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
+ assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
+
+ assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, PROD_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
+ assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
+
+ assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, NONE_ACTIVE), containsTargetBean());
+ assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, NULL_ACTIVE), containsTargetBean());
+ assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
+ assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
+ assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
+
+ assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, UNKNOWN_ACTIVE), not(containsTargetBean()));
+ assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
+ assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
+ assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
+
+ assertThat(beanFactoryFor(UNKOWN_ELIGIBLE_XML, MULTI_ACTIVE), not(containsTargetBean()));
+ }
+
+ private BeanDefinitionRegistry beanFactoryFor(String xmlName, String... activeProfileNames) {
+ DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
+ DefaultEnvironment env = new DefaultEnvironment();
+ env.setActiveProfiles(activeProfileNames);
+ reader.setEnvironment(env);
+ reader.loadBeanDefinitions(new ClassPathResource(xmlName, getClass()));
+ return beanFactory;
+ }
+
+
+ private static Matcher containsBeanDefinition(final String beanName) {
+ return new TypeSafeMatcher() {
+
+ public void describeTo(Description desc) {
+ desc.appendText("a BeanDefinitionRegistry containing bean named ")
+ .appendValue(beanName);
+ }
+
+ @Override
+ public boolean matchesSafely(BeanDefinitionRegistry beanFactory) {
+ return beanFactory.containsBeanDefinition(beanName);
+ }
+
+ };
+ }
+
+ private static Matcher containsTargetBean() {
+ return containsBeanDefinition(TARGET_BEAN);
+ }
+}
diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests.java
new file mode 100644
index 00000000000..93cc77b27b9
--- /dev/null
+++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2002-2010 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.beans.factory.xml;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.hasItems;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+import test.beans.TestBean;
+
+/**
+ * Tests for propagating enclosing beans element defaults to nested beans elements.
+ *
+ * @author Chris Beams
+ */
+public class NestedBeansElementAttributeRecursionTests {
+
+ @Test
+ public void defaultLazyInit() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
+ new ClassPathResource("NestedBeansElementAttributeRecursionTests-lazy-context.xml", this.getClass()));
+
+ BeanDefinition foo = bf.getBeanDefinition("foo");
+ BeanDefinition bar = bf.getBeanDefinition("bar");
+ BeanDefinition baz = bf.getBeanDefinition("baz");
+ BeanDefinition biz = bf.getBeanDefinition("biz");
+ BeanDefinition buz = bf.getBeanDefinition("buz");
+
+ assertThat(foo.isLazyInit(), is(false));
+ assertThat(bar.isLazyInit(), is(true));
+ assertThat(baz.isLazyInit(), is(false));
+ assertThat(biz.isLazyInit(), is(true));
+ assertThat(buz.isLazyInit(), is(true));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void defaultMerge() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
+ new ClassPathResource("NestedBeansElementAttributeRecursionTests-merge-context.xml", this.getClass()));
+
+ TestBean topLevel = bf.getBean("topLevelConcreteTestBean", TestBean.class);
+ // has the concrete child bean values
+ assertThat(topLevel.getSomeList(), hasItems("charlie", "delta"));
+ // but does not merge the parent values
+ assertThat(topLevel.getSomeList(), not(hasItems("alpha", "bravo")));
+
+ TestBean firstLevel = bf.getBean("firstLevelNestedTestBean", TestBean.class);
+ // merges all values
+ assertThat(firstLevel.getSomeList(),
+ hasItems("charlie", "delta", "echo", "foxtrot"));
+
+ TestBean secondLevel = bf.getBean("secondLevelNestedTestBean", TestBean.class);
+ // merges all values
+ assertThat(secondLevel.getSomeList(),
+ hasItems("charlie", "delta", "echo", "foxtrot", "golf", "hotel"));
+ }
+
+ @Test
+ public void defaultAutowireCandidates() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
+ new ClassPathResource("NestedBeansElementAttributeRecursionTests-autowire-candidates-context.xml", this.getClass()));
+
+ assertThat(bf.getBeanDefinition("fooService").isAutowireCandidate(), is(true));
+ assertThat(bf.getBeanDefinition("fooRepository").isAutowireCandidate(), is(true));
+ assertThat(bf.getBeanDefinition("other").isAutowireCandidate(), is(false));
+
+ assertThat(bf.getBeanDefinition("barService").isAutowireCandidate(), is(true));
+ assertThat(bf.getBeanDefinition("fooController").isAutowireCandidate(), is(false));
+
+ assertThat(bf.getBeanDefinition("bizRepository").isAutowireCandidate(), is(true));
+ assertThat(bf.getBeanDefinition("bizService").isAutowireCandidate(), is(false));
+
+ assertThat(bf.getBeanDefinition("bazService").isAutowireCandidate(), is(true));
+ assertThat(bf.getBeanDefinition("random").isAutowireCandidate(), is(false));
+ assertThat(bf.getBeanDefinition("fooComponent").isAutowireCandidate(), is(false));
+ assertThat(bf.getBeanDefinition("fRepository").isAutowireCandidate(), is(false));
+
+ assertThat(bf.getBeanDefinition("aComponent").isAutowireCandidate(), is(true));
+ assertThat(bf.getBeanDefinition("someService").isAutowireCandidate(), is(false));
+ }
+
+ @Test
+ public void initMethod() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
+ new ClassPathResource("NestedBeansElementAttributeRecursionTests-init-destroy-context.xml", this.getClass()));
+
+ InitDestroyBean beanA = bf.getBean("beanA", InitDestroyBean.class);
+ InitDestroyBean beanB = bf.getBean("beanB", InitDestroyBean.class);
+ InitDestroyBean beanC = bf.getBean("beanC", InitDestroyBean.class);
+ InitDestroyBean beanD = bf.getBean("beanD", InitDestroyBean.class);
+
+ assertThat(beanA.initMethod1Called, is(true));
+ assertThat(beanB.initMethod2Called, is(true));
+ assertThat(beanC.initMethod3Called, is(true));
+ assertThat(beanD.initMethod2Called, is(true));
+
+ bf.destroySingletons();
+
+ assertThat(beanA.destroyMethod1Called, is(true));
+ assertThat(beanB.destroyMethod2Called, is(true));
+ assertThat(beanC.destroyMethod3Called, is(true));
+ assertThat(beanD.destroyMethod2Called, is(true));
+ }
+
+}
+
+class InitDestroyBean {
+ boolean initMethod1Called;
+ boolean initMethod2Called;
+ boolean initMethod3Called;
+
+ boolean destroyMethod1Called;
+ boolean destroyMethod2Called;
+ boolean destroyMethod3Called;
+
+ void initMethod1() { this.initMethod1Called = true; }
+ void initMethod2() { this.initMethod2Called = true; }
+ void initMethod3() { this.initMethod3Called = true; }
+
+ void destroyMethod1() { this.destroyMethod1Called = true; }
+ void destroyMethod2() { this.destroyMethod2Called = true; }
+ void destroyMethod3() { this.destroyMethod3Called = true; }
+}
diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java
new file mode 100644
index 00000000000..288025eca2b
--- /dev/null
+++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java
@@ -0,0 +1,49 @@
+package org.springframework.beans.factory.xml;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+/**
+ * Tests for new nested beans element support in Spring XML
+ *
+ * @author Chris Beams
+ */
+public class NestedBeansElementTests {
+ private final Resource XML =
+ new ClassPathResource("NestedBeansElementTests-context.xml", this.getClass());
+
+ @Test
+ public void getBean_withoutActiveProfile() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ new XmlBeanDefinitionReader(bf).loadBeanDefinitions(XML);
+
+ Object foo = bf.getBean("foo");
+ assertThat(foo, instanceOf(String.class));
+ }
+
+ @Test
+ public void getBean_withActiveProfile() {
+ ConfigurableEnvironment env = new DefaultEnvironment();
+ env.setActiveProfiles("dev");
+
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
+ reader.setEnvironment(env);
+ reader.loadBeanDefinitions(XML);
+
+ bf.getBean("devOnlyBean"); // should not throw NSBDE
+
+ Object foo = bf.getBean("foo");
+ assertThat(foo, instanceOf(Integer.class));
+
+ bf.getBean("devOnlyBean");
+ }
+
+}
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-autowire-candidates-context.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-autowire-candidates-context.xml
new file mode 100644
index 00000000000..d6be7a4426f
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-autowire-candidates-context.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-autowire-context.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-autowire-context.xml
new file mode 100644
index 00000000000..49e415572c8
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-autowire-context.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-init-destroy-context.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-init-destroy-context.xml
new file mode 100644
index 00000000000..90c5495d7c6
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-init-destroy-context.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-lazy-context.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-lazy-context.xml
new file mode 100644
index 00000000000..3c3df4abf08
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-lazy-context.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-merge-context.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-merge-context.xml
new file mode 100644
index 00000000000..12dbc607928
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementAttributeRecursionTests-merge-context.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+ alpha
+ bravo
+
+
+
+
+
+
+
+ charlie
+ delta
+
+
+
+
+
+
+
+
+ echo
+ foxtrot
+
+
+
+
+
+
+
+
+ golf
+ hotel
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementTests-context.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementTests-context.xml
new file mode 100644
index 00000000000..5500aeedaee
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/NestedBeansElementTests-context.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-devProfile.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-devProfile.xml
new file mode 100644
index 00000000000..8ae82bc8cf6
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-devProfile.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-multiProfile.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-multiProfile.xml
new file mode 100644
index 00000000000..dac5fb92449
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-multiProfile.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-noProfile.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-noProfile.xml
new file mode 100644
index 00000000000..656ea3aceb1
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-noProfile.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-prodProfile.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-prodProfile.xml
new file mode 100644
index 00000000000..aba52d7066f
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-prodProfile.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-unknownProfile.xml b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-unknownProfile.xml
new file mode 100644
index 00000000000..922ba290485
--- /dev/null
+++ b/org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/environmentBeans-unknownProfile.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/org.springframework.context.support/.settings/org.eclipse.jdt.core.prefs b/org.springframework.context.support/.settings/org.eclipse.jdt.core.prefs
index a15f738edcd..4655eeb423f 100644
--- a/org.springframework.context.support/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.context.support/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:30 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.context.support/pom.xml b/org.springframework.context.support/pom.xml
index 69d83ab1025..6588fe19c70 100644
--- a/org.springframework.context.support/pom.xml
+++ b/org.springframework.context.support/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-context-support
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.context/.settings/org.eclipse.jdt.core.prefs b/org.springframework.context/.settings/org.eclipse.jdt.core.prefs
index 5a5d4fe0932..7cff560e8e1 100644
--- a/org.springframework.context/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.context/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
-#Wed Jul 15 00:01:31 PDT 2009
+#Mon Sep 06 21:53:54 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.context/.springBeans b/org.springframework.context/.springBeans
index f7eccf735e6..84849427f41 100644
--- a/org.springframework.context/.springBeans
+++ b/org.springframework.context/.springBeans
@@ -1,7 +1,7 @@
1
-
+
@@ -11,7 +11,6 @@
src/test/java/org/springframework/context/annotation/configuration/SecondLevelSubConfig-context.xml
src/test/java/org/springframework/context/annotation/configuration/ImportXmlWithAopNamespace-context.xml
src/test/java/org/springframework/context/annotation/Spr6602Tests-context.xml
- src/test/java/org/springframework/beans/factory/FactoryBeanLookupTests-context.xml
diff --git a/org.springframework.context/pom.xml b/org.springframework.context/pom.xml
index 36868ab827e..82e2d36f0fc 100644
--- a/org.springframework.context/pom.xml
+++ b/org.springframework.context/pom.xml
@@ -6,12 +6,12 @@
org.springframework
spring-context
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.context/src/main/java/org/springframework/context/ApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/ApplicationContext.java
index df117fd5508..44fe37f31aa 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/ApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/ApplicationContext.java
@@ -19,6 +19,7 @@ package org.springframework.context;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.support.ResourcePatternResolver;
/**
@@ -53,7 +54,7 @@ import org.springframework.core.io.support.ResourcePatternResolver;
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.core.io.ResourceLoader
*/
-public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory,
+public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
/**
diff --git a/org.springframework.context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java
index ad56ae9a256..08fa69d06ab 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java
@@ -19,6 +19,8 @@ package org.springframework.context;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.Environment;
/**
* SPI interface to be implemented by most if not all application contexts.
@@ -31,6 +33,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
* methods should only be used by startup and shutdown code.
*
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 03.11.2003
*/
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle {
@@ -59,6 +62,11 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
*/
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
+ /**
+ * Name of the {@link Environment} bean in the factory.
+ */
+ String ENVIRONMENT_BEAN_NAME = "environment";
+
/**
* Name of the System properties bean in the factory.
* @see java.lang.System#getProperties()
@@ -87,6 +95,16 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
*/
void setParent(ApplicationContext parent);
+ /**
+ * TODO SPR-7508: document
+ */
+ ConfigurableEnvironment getEnvironment();
+
+ /**
+ * TODO SPR-7508: document
+ */
+ void setEnvironment(ConfigurableEnvironment environment);
+
/**
* Add a new BeanFactoryPostProcessor that will get applied to the internal
* bean factory of this application context on refresh, before any of the
@@ -105,7 +123,7 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
* @see org.springframework.context.event.ContextRefreshedEvent
* @see org.springframework.context.event.ContextClosedEvent
*/
- void addApplicationListener(ApplicationListener listener);
+ void addApplicationListener(ApplicationListener> listener);
/**
* Load or refresh the persistent representation of the configuration,
diff --git a/org.springframework.context/src/main/java/org/springframework/context/EnvironmentAware.java b/org.springframework.context/src/main/java/org/springframework/context/EnvironmentAware.java
new file mode 100644
index 00000000000..7ec52896b4c
--- /dev/null
+++ b/org.springframework.context/src/main/java/org/springframework/context/EnvironmentAware.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2010 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.context;
+
+import org.springframework.core.env.Environment;
+
+/**
+ * TODO SPR-7515: document
+ *
+ * @author Chris Beams
+ */
+public interface EnvironmentAware {
+
+ void setEnvironment(Environment environment);
+
+}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java
index 3d8c76137bc..47e4ff256c6 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java
@@ -24,6 +24,9 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.env.Environment;
+import org.springframework.core.type.AnnotationMetadata;
/**
* Convenient adapter for programmatic registration of annotated bean classes.
@@ -31,6 +34,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
* the same resolution of annotations but for explicitly registered classes only.
*
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 3.0
* @see AnnotationConfigApplicationContext#register
*/
@@ -38,6 +42,8 @@ public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
+ private Environment environment = new DefaultEnvironment();
+
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
@@ -61,9 +67,17 @@ public class AnnotatedBeanDefinitionReader {
return this.registry;
}
+ /**
+ * Set the Environment to use when registering classes.
+ * The default is a {@link DefaultEnvironment}.
+ */
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
/**
* Set the BeanNameGenerator to use for detected bean classes.
- *
Default is a {@link AnnotationBeanNameGenerator}.
+ *
The default is a {@link AnnotationBeanNameGenerator}.
*/
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());
@@ -92,8 +106,45 @@ public class AnnotatedBeanDefinitionReader {
registerBean(annotatedClass, null, qualifiers);
}
+ private boolean hasEligibleProfile(AnnotationMetadata metadata) {
+ boolean hasEligibleProfile = false;
+ if (!metadata.hasAnnotation(Profile.class.getName())) {
+ hasEligibleProfile = true;
+ } else {
+ for (String profile : (String[])metadata.getAnnotationAttributes(Profile.class.getName()).get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME)) {
+ if (this.environment.getActiveProfiles().contains(profile)) {
+ hasEligibleProfile = true;
+ break;
+ }
+ }
+ }
+ return hasEligibleProfile;
+ }
+
public void registerBean(Class> annotatedClass, String name, Class extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
+ if (!hasEligibleProfile(abd.getMetadata())) {
+ // TODO SPR-7508: log that this bean is being rejected on profile mismatch
+ return;
+ }
+ /*
+ if (metadata.hasAnnotation(Profile.class.getName())) {
+ if (this.environment == null) {
+ return;
+ }
+ Map profileAttribs = metadata.getAnnotationAttributes(Profile.class.getName());
+ String[] names = (String[]) profileAttribs.get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME);
+ boolean go=false;
+ for (String pName : names) {
+ if (this.environment.getActiveProfiles().contains(pName)) {
+ go = true;
+ }
+ }
+ if (!go) {
+ return;
+ }
+ }
+ */
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java
index ebf1eee38fb..bf696d13b87 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java
@@ -16,8 +16,11 @@
package org.springframework.context.annotation;
+import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.Environment;
/**
* Standalone application context, accepting annotated classes as input - in particular
@@ -46,6 +49,9 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
private final ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this);
+ { // TODO: rework this, it's a bit confusing
+ this.setEnvironment(this.getEnvironment());
+ }
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
@@ -75,6 +81,15 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
refresh();
}
+ /**
+ * TODO SPR-7508: document
+ */
+ @Override
+ public void setEnvironment(ConfigurableEnvironment environment) {
+ super.setEnvironment(environment);
+ this.reader.setEnvironment(environment);
+ this.scanner.setEnvironment(environment);
+ }
/**
* Set the BeanNameGenerator to use for detected bean classes.
@@ -94,7 +109,6 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
-
/**
* Register an annotated class to be processed. Allows for programmatically
* building a {@link AnnotationConfigApplicationContext}. Note that
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java
index db2801e1c36..84b9fad86be 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java
@@ -39,7 +39,7 @@ import org.springframework.util.ClassUtils;
* @author Chris Beams
* @since 2.5
* @see CommonAnnotationBeanPostProcessor
- * @see org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
+ * @see org.springframework.context.annotation.ConfigurationClassPostProcessor
* @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
* @see org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
* @see org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java
index e2728d569b5..de79ccbb16a 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java
@@ -101,7 +101,7 @@ public @interface Bean {
* Note: Only invoked on beans whose lifecycle is under the full control of the
* factory, which is always the case for singletons but not guaranteed
* for any other scope.
- * @see {@link org.springframework.context.ConfigurableApplicationContext#close()}
+ * @see org.springframework.context.ConfigurableApplicationContext#close()
*/
String destroyMethod() default "";
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java
index da23b12a3e7..4f780ef343b 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java
@@ -27,6 +27,7 @@ import org.springframework.beans.factory.support.BeanDefinitionDefaults;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
+import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.PatternMatchUtils;
@@ -48,6 +49,7 @@ import org.springframework.util.PatternMatchUtils;
*
* @author Mark Fisher
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 2.5
* @see AnnotationConfigApplicationContext#scan
* @see org.springframework.stereotype.Component
@@ -87,6 +89,10 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
* {@link org.springframework.context.ApplicationContext} implementations.
*
If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a
* {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}.
+ *
If the the passed-in bean factory also implements {@link EnvironmentCapable} its
+ * environment will be used by this reader. Otherwise, the reader will initialize and
+ * use a {@link DefaultEnvironment}. All ApplicationContext implementations are
+ * EnvironmentCapable, while normal BeanFactory implementations are not.
* @param registry the BeanFactory to load bean definitions into,
* in the form of a BeanDefinitionRegistry
* @param useDefaultFilters whether to include the default filters for the
@@ -96,6 +102,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
* {@link org.springframework.stereotype.Controller @Controller} stereotype
* annotations.
* @see #setResourceLoader
+ * @see #setEnvironment
*/
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
super(useDefaultFilters);
@@ -107,6 +114,11 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
if (this.registry instanceof ResourceLoader) {
setResourceLoader((ResourceLoader) this.registry);
}
+
+ // Inherit Environment if possible
+ if (this.registry instanceof EnvironmentCapable) {
+ setEnvironment(((EnvironmentCapable) this.registry).getEnvironment());
+ }
}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java
index f10cadb9cdd..850fe621a7c 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java
@@ -25,11 +25,13 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@@ -46,7 +48,6 @@ import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
-import org.springframework.util.SystemPropertyUtils;
/**
* A component provider that scans the classpath from a base package. It then
@@ -59,18 +60,21 @@ import org.springframework.util.SystemPropertyUtils;
* @author Mark Fisher
* @author Juergen Hoeller
* @author Ramnivas Laddad
+ * @author Chris Beams
* @since 2.5
* @see org.springframework.core.type.classreading.MetadataReaderFactory
* @see org.springframework.core.type.AnnotationMetadata
* @see ScannedGenericBeanDefinition
*/
-public class ClassPathScanningCandidateComponentProvider implements ResourceLoaderAware {
+public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
protected final Log logger = LogFactory.getLog(getClass());
+ private Environment environment = new DefaultEnvironment();
+
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
@@ -110,6 +114,20 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
}
+ /**
+ * TODO SPR-7508: document
+ */
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
+ /**
+ * TODO SPR-7508: document
+ */
+ public Environment getEnvironment() {
+ return this.environment;
+ }
+
/**
* Return the ResourceLoader that this component provider uses.
*/
@@ -261,7 +279,7 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
* @return the pattern specification to be used for package searching
*/
protected String resolveBasePackage(String basePackage) {
- return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
+ return ClassUtils.convertClassNameToResourcePath(environment.resolveRequiredPlaceholders(basePackage));
}
/**
@@ -278,12 +296,28 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
- return true;
+ return hasEligibleProfile(metadataReader);
}
}
return false;
}
+ private boolean hasEligibleProfile(MetadataReader metadataReader) {
+ boolean hasEligibleProfile = false;
+ if (!metadataReader.getAnnotationMetadata().hasAnnotation(Profile.class.getName())) {
+ hasEligibleProfile = true;
+ } else {
+ for (String profile : (String[])metadataReader.getAnnotationMetadata().getAnnotationAttributes(Profile.class.getName()).get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME)) {
+ if (this.environment.getActiveProfiles().contains(profile)) {
+ hasEligibleProfile = true;
+ break;
+ }
+ }
+ }
+ return hasEligibleProfile;
+ }
+
+
/**
* Determine whether the given bean definition qualifies as candidate.
*
The default implementation checks whether the class is concrete
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScan.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScan.java
new file mode 100644
index 00000000000..9acfd337ad8
--- /dev/null
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScan.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002-2010 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.context.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.beans.factory.support.BeanNameGenerator;
+
+
+/**
+ * Configures component scanning directives for use with {@link Configuration}
+ * classes. Provides support parallel with Spring XML's
+ * <context:component-scan> element.
+ *
+ * TODO SPR-7508: complete documentation.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see FilterType
+ * @see Configuration
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ComponentScan {
+
+ /** base packages to scan */
+ String[] value() default {};
+
+ Class>[] packageOf() default Void.class;
+
+ Class extends BeanNameGenerator> nameGenerator() default AnnotationBeanNameGenerator.class;
+
+ Class extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
+
+ String resourcePattern() default "**/*.class";
+
+ ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
+
+ boolean useDefaultFilters() default true;
+
+ IncludeFilter[] includeFilters() default {};
+
+ ExcludeFilter[] excludeFilters() default {};
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @interface IncludeFilter {
+ FilterType type() default FilterType.ANNOTATION;
+ Class> value();
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ExcludeFilter {
+ FilterType type() default FilterType.ANNOTATION;
+ Class> value();
+ }
+
+}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.java
index a6dee3590ae..ee1a4920224 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.java
@@ -98,6 +98,7 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
// Delegate bean definition registration to scanner class.
ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters);
scanner.setResourceLoader(readerContext.getResourceLoader());
+ scanner.setEnvironment(parserContext.getDelegate().getEnvironment());
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/Configuration.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/Configuration.java
index 08ea04ebeee..a277ff9efe2 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/Configuration.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/Configuration.java
@@ -57,6 +57,7 @@ import org.springframework.stereotype.Component;
* @see Bean
* @see ConfigurationClassPostProcessor
* @see AnnotationConfigApplicationContext
+ * @see org.springframework.context.annotation.Profile
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java
index ce069f4d4e8..9aae2ecf32e 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java
@@ -105,7 +105,6 @@ final class ConfigurationClass {
return this.importedResources;
}
-
public void validate(ProblemReporter problemReporter) {
// An @Bean method may only be overloaded through inheritance. No single
// @Configuration class may declare two @Bean methods with the same name.
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
index 4457dc2bb1e..31c623f6ec2 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
@@ -27,6 +27,7 @@ import java.util.Stack;
import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter;
+import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
@@ -63,14 +64,18 @@ class ConfigurationClassParser {
private final Set configurationClasses =
new LinkedHashSet();
+ private final Environment environment;
+
/**
* Create a new {@link ConfigurationClassParser} instance that will be used
* to populate the set of configuration classes.
*/
- public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory, ProblemReporter problemReporter) {
+ public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory,
+ ProblemReporter problemReporter, Environment environment) {
this.metadataReaderFactory = metadataReaderFactory;
this.problemReporter = problemReporter;
+ this.environment = environment;
}
@@ -95,8 +100,28 @@ class ConfigurationClassParser {
processConfigurationClass(new ConfigurationClass(clazz, beanName));
}
-
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
+ boolean hasEligibleProfile = false;
+ if (this.environment == null) {
+ hasEligibleProfile = true;
+ } else {
+ if (!configClass.getMetadata().hasAnnotation(Profile.class.getName())) {
+ hasEligibleProfile = true;
+ } else {
+ for (String profile : (String[])configClass.getMetadata().getAnnotationAttributes(Profile.class.getName()).get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME)) {
+ if (this.environment.getActiveProfiles().contains(profile)) {
+ hasEligibleProfile = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!hasEligibleProfile) {
+ //logger.debug("TODO SPR-7508: issue debug statement that this class is being excluded");
+ // make sure XML has a symmetrical statement as well
+ return;
+ }
+
AnnotationMetadata metadata = configClass.getMetadata();
while (metadata != null) {
doProcessConfigurationClass(configClass, metadata);
@@ -120,6 +145,7 @@ class ConfigurationClassParser {
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
}
+
this.configurationClasses.add(configClass);
}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java
index 1f9c45d0e19..e26c3667c36 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java
@@ -16,6 +16,7 @@
package org.springframework.context.annotation;
+import java.awt.dnd.Autoscroll;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -38,7 +39,9 @@ import org.springframework.beans.factory.parsing.SourceExtractor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
+import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
+import org.springframework.core.env.Environment;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.Assert;
@@ -61,7 +64,8 @@ import org.springframework.util.ClassUtils;
* @author Juergen Hoeller
* @since 3.0
*/
-public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanClassLoaderAware {
+public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
+ BeanClassLoaderAware, EnvironmentAware {
/** Whether the CGLIB2 library is present on the classpath */
private static final boolean cglibAvailable = ClassUtils.isPresent(
@@ -84,6 +88,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
private boolean postProcessBeanFactoryCalled = false;
+ private Environment environment;
+
/**
* Set the {@link SourceExtractor} to use for generated bean definitions
@@ -121,8 +127,12 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
}
}
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
public int getOrder() {
- return Ordered.HIGHEST_PRECEDENCE;
+ return Ordered.HIGHEST_PRECEDENCE + 1; // make room for AutoScanningBeanDefinitionRegistrar
}
@@ -180,7 +190,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
}
// Populate a new configuration model by parsing each @Configuration classes
- ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter);
+ ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment);
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/FilterType.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/FilterType.java
index 6b63b9a0c33..9ed1b899434 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/FilterType.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/FilterType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -16,19 +16,39 @@
package org.springframework.context.annotation;
+import org.springframework.core.type.filter.AssignableTypeFilter;
+
+
/**
- * Enumeration of the valid type filters to be added for annotation-driven configuration.
+ * Enumeration of the type filters that may be used in conjunction with
+ * {@link ComponentScan @ComponentScan}.
*
* @author Mark Fisher
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 2.5
+ * @see ComponentScan
+ * @see ComponentScan.IncludeFilter
+ * @see ComponentScan.ExcludeFilter
+ * @see org.springframework.core.type.filter.TypeFilter
*/
public enum FilterType {
+ /**
+ * Filter candidates marked with a given annotation.
+ * @see org.springframework.core.type.filter.AnnotationTypeFilter
+ */
ANNOTATION,
+
+ /**
+ * Filter candidates assignable to a given type.
+ * @see AssignableTypeFilter
+ */
ASSIGNABLE_TYPE,
- ASPECTJ_PATTERN,
- REGEX_PATTERN,
+
+ /** Filter candidates using a given custom
+ * {@link org.springframework.core.type.filter.TypeFilter} implementation
+ */
CUSTOM
}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/Profile.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/Profile.java
new file mode 100644
index 00000000000..5d6cf21a63b
--- /dev/null
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/Profile.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2010 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.context.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Chris Beams
+ * @since 3.1
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({
+ ANNOTATION_TYPE, // @Profile may be used as a meta-annotation
+ TYPE // In conjunction with @Component and its derivatives
+})
+public @interface Profile {
+
+ /**
+ * @see #value()
+ */
+ static final String CANDIDATE_PROFILES_ATTRIB_NAME = "value";
+
+ /**
+ * TODO SPR-7508: document
+ */
+ String[] value();
+}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/config/PropertyPlaceholderBeanDefinitionParser.java b/org.springframework.context/src/main/java/org/springframework/context/config/PropertyPlaceholderBeanDefinitionParser.java
index 234c1d01434..afbc1a12231 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/config/PropertyPlaceholderBeanDefinitionParser.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/config/PropertyPlaceholderBeanDefinitionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -20,6 +20,7 @@ import org.w3c.dom.Element;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.context.support.EnvironmentAwarePropertyPlaceholderConfigurer;
import org.springframework.util.StringUtils;
/**
@@ -27,15 +28,24 @@ import org.springframework.util.StringUtils;
*
* @author Juergen Hoeller
* @author Dave Syer
+ * @author Chris Beams
* @since 2.5
*/
class PropertyPlaceholderBeanDefinitionParser extends AbstractPropertyLoadingBeanDefinitionParser {
@Override
- protected Class getBeanClass(Element element) {
- return PropertyPlaceholderConfigurer.class;
+ protected Class> getBeanClass(Element element) {
+ // as of Spring 3.1, the default for system-properties-mode is DELEGATE,
+ // meaning that the attribute should be disregarded entirely, instead
+ // deferring to the order of PropertySource objects in the enclosing
+ // application context's Environment object
+ if (!"DELEGATE".equals(element.getAttribute("system-properties-mode"))) {
+ return PropertyPlaceholderConfigurer.class;
+ }
+
+ return EnvironmentAwarePropertyPlaceholderConfigurer.class;
}
-
+
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
@@ -44,9 +54,11 @@ class PropertyPlaceholderBeanDefinitionParser extends AbstractPropertyLoadingBea
builder.addPropertyValue("ignoreUnresolvablePlaceholders",
Boolean.valueOf(element.getAttribute("ignore-unresolvable")));
- String systemPropertiesModeName = element.getAttribute("system-properties-mode");
- if (StringUtils.hasLength(systemPropertiesModeName)) {
- builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName);
+ if (!"DELEGATE".equals(element.getAttribute("system-properties-mode"))) {
+ String systemPropertiesModeName = element.getAttribute("system-properties-mode");
+ if (StringUtils.hasLength(systemPropertiesModeName)) {
+ builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName);
+ }
}
}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/expression/EnvironmentAccessor.java b/org.springframework.context/src/main/java/org/springframework/context/expression/EnvironmentAccessor.java
new file mode 100644
index 00000000000..0727a839c3e
--- /dev/null
+++ b/org.springframework.context/src/main/java/org/springframework/context/expression/EnvironmentAccessor.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2002-2010 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.context.expression;
+
+import org.springframework.core.env.Environment;
+import org.springframework.expression.AccessException;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.PropertyAccessor;
+import org.springframework.expression.TypedValue;
+
+/**
+ * Read-only EL property accessor that knows how to retrieve keys
+ * of a Spring {@link Environment} instance.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class EnvironmentAccessor implements PropertyAccessor {
+
+ public Class>[] getSpecificTargetClasses() {
+ return new Class[] { Environment.class };
+ }
+
+ /**
+ * Can read any {@link Environment}, thus always returns true.
+ * @return true
+ */
+ public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
+ return true;
+ }
+
+ /**
+ * Access provided {@literal target} object by calling its {@link Environment#getProperty(String)}
+ * method with the provided {@literal name}.
+ */
+ public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
+ return new TypedValue(((Environment)target).getProperty(name));
+ }
+
+ /**
+ * Read only.
+ * @return false
+ */
+ public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
+ return false;
+ }
+
+ /**
+ * Read only. No-op.
+ */
+ public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
+ }
+
+}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java b/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java
index 568874ebf74..9fb19609528 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java
@@ -126,6 +126,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());
+ sec.addPropertyAccessor(new EnvironmentAccessor());
sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
index 10def3585fe..163f9945249 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
@@ -18,7 +18,6 @@ package org.springframework.context.support;
import java.io.IOException;
import java.lang.annotation.Annotation;
-import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -33,7 +32,6 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.DisposableBean;
@@ -54,6 +52,7 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.EnvironmentAware;
import org.springframework.context.HierarchicalMessageSource;
import org.springframework.context.LifecycleProcessor;
import org.springframework.context.MessageSource;
@@ -73,6 +72,8 @@ import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.convert.ConversionService;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@@ -203,7 +204,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
private ApplicationEventMulticaster applicationEventMulticaster;
/** Statically specified listeners */
- private Set applicationListeners = new LinkedHashSet();
+ private Set> applicationListeners = new LinkedHashSet>();
+
+ /** TODO SPR-7508: document */
+ private ConfigurableEnvironment environment = new DefaultEnvironment();
/**
@@ -271,6 +275,14 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return this.parent;
}
+ public ConfigurableEnvironment getEnvironment() {
+ return this.environment;
+ }
+
+ public void setEnvironment(ConfigurableEnvironment environment) {
+ this.environment = environment;
+ }
+
/**
* Return this context's internal bean factory as AutowireCapableBeanFactory,
* if already available.
@@ -363,6 +375,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
this.beanFactoryPostProcessors.add(beanFactoryPostProcessor);
}
+
/**
* Return the list of BeanFactoryPostProcessors that will get applied
* to the internal BeanFactory.
@@ -371,7 +384,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return this.beanFactoryPostProcessors;
}
- public void addApplicationListener(ApplicationListener listener) {
+ public void addApplicationListener(ApplicationListener> listener) {
if (this.applicationEventMulticaster != null) {
this.applicationEventMulticaster.addApplicationListener(listener);
}
@@ -383,7 +396,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
/**
* Return the list of statically specified ApplicationListeners.
*/
- public Collection getApplicationListeners() {
+ public Collection> getApplicationListeners() {
return this.applicationListeners;
}
@@ -481,7 +494,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
- beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
+ beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
@@ -489,6 +502,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
+ beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
@@ -505,54 +519,16 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
// Register default environment beans.
+ if (!beanFactory.containsBean(ENVIRONMENT_BEAN_NAME)) {
+ beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
+ }
+
if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
- Map systemProperties;
- try {
- systemProperties = System.getProperties();
- }
- catch (AccessControlException ex) {
- systemProperties = new ReadOnlySystemAttributesMap() {
- @Override
- protected String getSystemAttribute(String propertyName) {
- try {
- return System.getProperty(propertyName);
- }
- catch (AccessControlException ex) {
- if (logger.isInfoEnabled()) {
- logger.info("Not allowed to obtain system property [" + propertyName + "]: " +
- ex.getMessage());
- }
- return null;
- }
- }
- };
- }
- beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);
+ beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
- Map systemEnvironment;
- try {
- systemEnvironment = System.getenv();
- }
- catch (AccessControlException ex) {
- systemEnvironment = new ReadOnlySystemAttributesMap() {
- @Override
- protected String getSystemAttribute(String variableName) {
- try {
- return System.getenv(variableName);
- }
- catch (AccessControlException ex) {
- if (logger.isInfoEnabled()) {
- logger.info("Not allowed to obtain system environment variable [" + variableName + "]: " +
- ex.getMessage());
- }
- return null;
- }
- }
- };
- }
- beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);
+ beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
@@ -664,6 +640,15 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
}
+ /**
+ * Common location for subclasses to call and receive registration of standard
+ * {@link BeanFactoryPostProcessor} bean definitions.
+ *
+ * @param registry subclass BeanDefinitionRegistry
+ */
+ protected void registerStandardBeanFactoryPostProcessors(BeanDefinitionRegistry registry) {
+ }
+
/**
* Instantiate and invoke all registered BeanPostProcessor beans,
* respecting explicit order if given.
@@ -848,7 +833,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
*/
protected void registerListeners() {
// Register statically specified listeners first.
- for (ApplicationListener listener : getApplicationListeners()) {
+ for (ApplicationListener> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
@@ -869,7 +854,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
* @deprecated as of Spring 3.0, in favor of {@link #addApplicationListener}
*/
@Deprecated
- protected void addListener(ApplicationListener listener) {
+ protected void addListener(ApplicationListener> listener) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
@@ -1099,7 +1084,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return getBeanFactory().isPrototype(name);
}
- public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException {
+ public boolean isTypeMatch(String name, Class> targetType) throws NoSuchBeanDefinitionException {
return getBeanFactory().isTypeMatch(name, targetType);
}
@@ -1128,11 +1113,11 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return getBeanFactory().getBeanDefinitionNames();
}
- public String[] getBeanNamesForType(Class type) {
+ public String[] getBeanNamesForType(Class> type) {
return getBeanFactory().getBeanNamesForType(type);
}
- public String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit) {
+ public String[] getBeanNamesForType(Class> type, boolean includeNonSingletons, boolean allowEagerInit) {
return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
}
@@ -1347,7 +1332,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
private final Map singletonNames = new ConcurrentHashMap();
- public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
+ public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
if (beanDefinition.isSingleton()) {
this.singletonNames.put(beanName, Boolean.TRUE);
}
@@ -1363,7 +1348,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
- addApplicationListener((ApplicationListener) bean);
+ addApplicationListener((ApplicationListener>) bean);
}
else if (flag == null) {
if (logger.isWarnEnabled() && !containsBean(beanName)) {
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
index e0a02ec70b8..b0a7aa9c87a 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
@@ -53,6 +53,7 @@ import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
* supports {@literal @Configuration}-annotated classes as a source of bean definitions.
*
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 1.1.3
* @see #loadBeanDefinitions
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory
@@ -217,6 +218,7 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
}
beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
+ registerStandardBeanFactoryPostProcessors(beanFactory);
}
/**
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableConfigApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableConfigApplicationContext.java
index 3dda2fe61bb..79a40093232 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableConfigApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableConfigApplicationContext.java
@@ -117,9 +117,13 @@ public abstract class AbstractRefreshableConfigApplicationContext extends Abstra
* system property values if necessary. Applied to config locations.
* @param path the original file path
* @return the resolved file path
- * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders
+ * @see SystemPropertyUtils#resolveRequiredPlaceholders(String)
*/
protected String resolvePath(String path) {
+ // TODO SPR-7508: note that ARAC cannot delegate to its beanFactory's environment
+ // to call Environment.resolve[Required]Placeholders(String), as the bean factory
+ // has not yet been initialized. This amounts to one more reason not to use the ARAC
+ // hierarchy - it won't have early access to environment property resolution.
return SystemPropertyUtils.resolvePlaceholders(path);
}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractXmlApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractXmlApplicationContext.java
index 51894a287fa..20c2734f764 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractXmlApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractXmlApplicationContext.java
@@ -83,6 +83,7 @@ public abstract class AbstractXmlApplicationContext extends AbstractRefreshableC
// Configure the bean definition reader with this context's
// resource loading environment.
+ beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java b/org.springframework.context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java
index d40ca72323d..facb86ac515 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java
@@ -27,8 +27,10 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
+import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.env.Environment;
import org.springframework.util.StringValueResolver;
/**
@@ -37,18 +39,24 @@ import org.springframework.util.StringValueResolver;
* implement the {@link ResourceLoaderAware}, {@link MessageSourceAware},
* {@link ApplicationEventPublisherAware} and/or
* {@link ApplicationContextAware} interfaces.
- * If all of them are implemented, they are satisfied in the given order.
+ *
+ * Also delegates the ApplicationContext {@link Environment} instance
+ * to beans that implement {@link EnvironmentAware}.
+ *
+ *
Implemented interfaces are satisfied in order of their mention above.
*
*
Application contexts will automatically register this with their
* underlying bean factory. Applications do not use this directly.
*
* @author Juergen Hoeller
* @author Costin Leau
+ * @author Chris Beams
* @since 10.10.2003
* @see org.springframework.context.ResourceLoaderAware
* @see org.springframework.context.MessageSourceAware
* @see org.springframework.context.ApplicationEventPublisherAware
* @see org.springframework.context.ApplicationContextAware
+ * @see org.springframework.context.EnvironmentAware
* @see org.springframework.context.support.AbstractApplicationContext#refresh()
*/
class ApplicationContextAwareProcessor implements BeanPostProcessor {
@@ -105,6 +113,9 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
+ if (bean instanceof EnvironmentAware) {
+ ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
+ }
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/EnvironmentAwarePropertyPlaceholderConfigurer.java b/org.springframework.context/src/main/java/org/springframework/context/support/EnvironmentAwarePropertyPlaceholderConfigurer.java
new file mode 100644
index 00000000000..ac9693a0f9f
--- /dev/null
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/EnvironmentAwarePropertyPlaceholderConfigurer.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2002-2010 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.context.support;
+
+import java.util.LinkedList;
+import java.util.Properties;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.AbstractPropertyPlaceholderConfigurer;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.core.env.AbstractEnvironment;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.PropertiesPropertySource;
+import org.springframework.core.env.PropertySource;
+import org.springframework.util.Assert;
+import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
+
+
+/**
+ * TODO SPR-7508: document
+ *
+ * Local properties are added as a property source in any case. Precedence is based
+ * on the value of the {@link #setLocalOverride(boolean) localOverride} property.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see PropertyPlaceholderConfigurer
+ * @see EnvironmentAwarePropertyOverrideConfigurer
+ */
+public class EnvironmentAwarePropertyPlaceholderConfigurer
+ extends AbstractPropertyPlaceholderConfigurer implements EnvironmentAware {
+
+ private ConfigurableEnvironment environment;
+ private Environment wrappedEnvironment;
+
+ public void setEnvironment(Environment environment) {
+ this.wrappedEnvironment = environment;
+ }
+
+ @Override
+ protected PlaceholderResolver getPlaceholderResolver(Properties props) {
+ return new PlaceholderResolver() {
+ public String resolvePlaceholder(String placeholderName) {
+ return environment.getProperty(placeholderName);
+ }
+ };
+ }
+
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ Assert.notNull(this.wrappedEnvironment, "Environment must not be null. Did you call setEnvironment()?");
+ environment = new AbstractEnvironment() { };
+
+ LinkedList> propertySources = environment.getPropertySources();
+ EnvironmentPropertySource environmentPropertySource =
+ new EnvironmentPropertySource("wrappedEnvironment", wrappedEnvironment);
+
+ if (!this.localOverride) {
+ propertySources.add(environmentPropertySource);
+ }
+
+ if (this.localProperties != null) {
+ int cx=0;
+ for (Properties localProps : this.localProperties) {
+ propertySources.add(new PropertiesPropertySource("localProperties"+cx++, localProps));
+ }
+ }
+
+ if (this.localOverride) {
+ propertySources.add(environmentPropertySource);
+ }
+
+ super.postProcessBeanFactory(beanFactory);
+ }
+
+ static class EnvironmentPropertySource extends PropertySource {
+
+ public EnvironmentPropertySource(String name, Environment source) {
+ super(name, source);
+ }
+
+ @Override
+ public boolean containsProperty(String key) {
+ return source.containsProperty(key);
+ }
+
+ @Override
+ public String getProperty(String key) {
+ return source.getProperty(key);
+ }
+
+ @Override
+ public int size() {
+ // TODO Auto-generated method stub
+ return source.getPropertyCount();
+ }
+ }
+}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/GenericApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
index ce38ecef471..ccd1323f51e 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
@@ -28,6 +28,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
@@ -78,6 +79,7 @@ import org.springframework.util.Assert;
* from the {@link AbstractRefreshableApplicationContext} base class.
*
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 1.1.2
* @see #registerBeanDefinition
* @see #refresh()
@@ -102,6 +104,7 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
this.beanFactory = new DefaultListableBeanFactory();
this.beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
this.beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
+ registerStandardBeanFactoryPostProcessors(this.beanFactory);
}
/**
@@ -181,7 +184,7 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
* delegate all getResource calls to the given ResourceLoader.
* If not set, default resource loading will apply.
* The main reason to specify a custom ResourceLoader is to resolve
- * resource paths (withour URL prefix) in a specific fashion.
+ * resource paths (without URL prefix) in a specific fashion.
* The default behavior is to resolve such paths as class path locations.
* To resolve resource paths as file system locations, specify a
* FileSystemResourceLoader here.
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/GenericXmlApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/support/GenericXmlApplicationContext.java
index 9346dd2b1ea..a0d45f8faaf 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/GenericXmlApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/GenericXmlApplicationContext.java
@@ -17,7 +17,7 @@
package org.springframework.context.support;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
-import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
/**
@@ -47,6 +47,7 @@ public class GenericXmlApplicationContext extends GenericApplicationContext {
* through {@link #load} calls and then manually {@link #refresh refreshed}.
*/
public GenericXmlApplicationContext() {
+ reader.setEnvironment(this.getEnvironment());
}
/**
@@ -88,6 +89,15 @@ public class GenericXmlApplicationContext extends GenericApplicationContext {
this.reader.setValidating(validating);
}
+ /**
+ * Set a custom environment. Should be called before any call to
+ * {@link #load}. TODO SPR-7508: document
+ */
+ @Override
+ public void setEnvironment(ConfigurableEnvironment environment) {
+ super.setEnvironment(environment);
+ this.reader.setEnvironment(this.getEnvironment());
+ }
/**
* Load bean definitions from the given XML resources.
diff --git a/org.springframework.context/src/main/java/org/springframework/jndi/support/SimpleJndiBeanFactory.java b/org.springframework.context/src/main/java/org/springframework/jndi/support/SimpleJndiBeanFactory.java
index 493dc7618b3..4d39882719a 100644
--- a/org.springframework.context/src/main/java/org/springframework/jndi/support/SimpleJndiBeanFactory.java
+++ b/org.springframework.context/src/main/java/org/springframework/jndi/support/SimpleJndiBeanFactory.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
@@ -29,6 +30,8 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.DefaultEnvironment;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.jndi.TypeMismatchNamingException;
@@ -67,6 +70,9 @@ public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFac
/** Cache of the types of nonshareable resources: bean name --> bean type */
private final Map resourceTypes = new HashMap();
+ /** TODO SPR-7508: should be JNDI-specific environment */
+ private ConfigurableEnvironment environment = new DefaultEnvironment();
+
public SimpleJndiBeanFactory() {
setResourceRef(true);
@@ -94,6 +100,11 @@ public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFac
}
+ //---------------------------------------------------------------------
+ // Implementation of BeanFactory interface
+ //---------------------------------------------------------------------
+
+
public Object getBean(String name) throws BeansException {
return getBean(name, Object.class);
}
diff --git a/org.springframework.context/src/main/resources/META-INF/spring.schemas b/org.springframework.context/src/main/resources/META-INF/spring.schemas
index 21fce18c554..ec51d5eeea6 100644
--- a/org.springframework.context/src/main/resources/META-INF/spring.schemas
+++ b/org.springframework.context/src/main/resources/META-INF/spring.schemas
@@ -1,13 +1,17 @@
http\://www.springframework.org/schema/context/spring-context-2.5.xsd=org/springframework/context/config/spring-context-2.5.xsd
http\://www.springframework.org/schema/context/spring-context-3.0.xsd=org/springframework/context/config/spring-context-3.0.xsd
-http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-3.0.xsd
+http\://www.springframework.org/schema/context/spring-context-3.1.xsd=org/springframework/context/config/spring-context-3.1.xsd
+http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-3.1.xsd
http\://www.springframework.org/schema/jee/spring-jee-2.0.xsd=org/springframework/ejb/config/spring-jee-2.0.xsd
http\://www.springframework.org/schema/jee/spring-jee-2.5.xsd=org/springframework/ejb/config/spring-jee-2.5.xsd
http\://www.springframework.org/schema/jee/spring-jee-3.0.xsd=org/springframework/ejb/config/spring-jee-3.0.xsd
-http\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee-3.0.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.1.xsd=org/springframework/ejb/config/spring-jee-3.1.xsd
+http\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee-3.1.xsd
http\://www.springframework.org/schema/lang/spring-lang-2.0.xsd=org/springframework/scripting/config/spring-lang-2.0.xsd
http\://www.springframework.org/schema/lang/spring-lang-2.5.xsd=org/springframework/scripting/config/spring-lang-2.5.xsd
http\://www.springframework.org/schema/lang/spring-lang-3.0.xsd=org/springframework/scripting/config/spring-lang-3.0.xsd
-http\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang-3.0.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.1.xsd=org/springframework/scripting/config/spring-lang-3.1.xsd
+http\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang-3.1.xsd
http\://www.springframework.org/schema/task/spring-task-3.0.xsd=org/springframework/scheduling/config/spring-task-3.0.xsd
-http\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task-3.0.xsd
+http\://www.springframework.org/schema/task/spring-task-3.1.xsd=org/springframework/scheduling/config/spring-task-3.1.xsd
+http\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task-3.1.xsd
diff --git a/org.springframework.context/src/main/resources/org/springframework/context/config/spring-context-3.1.xsd b/org.springframework.context/src/main/resources/org/springframework/context/config/spring-context-3.1.xsd
new file mode 100644
index 00000000000..f5366683b2a
--- /dev/null
+++ b/org.springframework.context/src/main/resources/org/springframework/context/config/spring-context-3.1.xsd
@@ -0,0 +1,500 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tag for that purpose.
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.context/src/main/resources/org/springframework/ejb/config/spring-jee-3.1.xsd b/org.springframework.context/src/main/resources/org/springframework/ejb/config/spring-jee-3.1.xsd
new file mode 100644
index 00000000000..217f391800b
--- /dev/null
+++ b/org.springframework.context/src/main/resources/org/springframework/ejb/config/spring-jee-3.1.xsd
@@ -0,0 +1,254 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.context/src/main/resources/org/springframework/scheduling/config/spring-task-3.1.xsd b/org.springframework.context/src/main/resources/org/springframework/scheduling/config/spring-task-3.1.xsd
new file mode 100644
index 00000000000..1166d499ed3
--- /dev/null
+++ b/org.springframework.context/src/main/resources/org/springframework/scheduling/config/spring-task-3.1.xsd
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.context/src/main/resources/org/springframework/scripting/config/spring-lang-3.1.xsd b/org.springframework.context/src/main/resources/org/springframework/scripting/config/spring-lang-3.1.xsd
new file mode 100644
index 00000000000..6659a769449
--- /dev/null
+++ b/org.springframework.context/src/main/resources/org/springframework/scripting/config/spring-lang-3.1.xsd
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.context/src/test/java/example/profilescan/ProfileAnnotatedComponent.java b/org.springframework.context/src/test/java/example/profilescan/ProfileAnnotatedComponent.java
new file mode 100644
index 00000000000..860c7581b78
--- /dev/null
+++ b/org.springframework.context/src/test/java/example/profilescan/ProfileAnnotatedComponent.java
@@ -0,0 +1,13 @@
+package example.profilescan;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+@Profile(ProfileAnnotatedComponent.PROFILE_NAME)
+@Component(ProfileAnnotatedComponent.BEAN_NAME)
+public class ProfileAnnotatedComponent {
+
+ public static final String BEAN_NAME = "profileAnnotatedComponent";
+ public static final String PROFILE_NAME = "test";
+
+}
diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/AsmCircularImportDetectionTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/AsmCircularImportDetectionTests.java
index 390a5cf9220..21fc1e9105c 100644
--- a/org.springframework.context/src/test/java/org/springframework/context/annotation/AsmCircularImportDetectionTests.java
+++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/AsmCircularImportDetectionTests.java
@@ -16,6 +16,7 @@
package org.springframework.context.annotation;
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
+import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
/**
@@ -32,7 +33,7 @@ public class AsmCircularImportDetectionTests extends AbstractCircularImportDetec
@Override
protected ConfigurationClassParser newParser() {
- return new ConfigurationClassParser(new CachingMetadataReaderFactory(), new FailFastProblemReporter());
+ return new ConfigurationClassParser(new CachingMetadataReaderFactory(), new FailFastProblemReporter(), new DefaultEnvironment());
}
@Override
diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java
index 4d214eb2c07..50b8cd20459 100644
--- a/org.springframework.context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java
+++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java
@@ -152,11 +152,12 @@ public class ClassPathBeanDefinitionScannerTests {
public void testSimpleScanWithDefaultFiltersAndOverriddenEqualNamedBean() {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("myNamedDao", new RootBeanDefinition(NamedStubDao.class));
+ int initialBeanCount = context.getBeanDefinitionCount();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
- int beanCount = scanner.scan(BASE_PACKAGE);
- assertEquals(5, beanCount);
- assertEquals(6, context.getBeanDefinitionCount());
+ int scannedBeanCount = scanner.scan(BASE_PACKAGE);
+ assertEquals(5, scannedBeanCount);
+ assertEquals(initialBeanCount + scannedBeanCount, context.getBeanDefinitionCount());
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
@@ -170,11 +171,12 @@ public class ClassPathBeanDefinitionScannerTests {
RootBeanDefinition bd = new RootBeanDefinition(NamedStubDao.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
context.registerBeanDefinition("myNamedDao", bd);
+ int initialBeanCount = context.getBeanDefinitionCount();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
- int beanCount = scanner.scan(BASE_PACKAGE);
- assertEquals(5, beanCount);
- assertEquals(6, context.getBeanDefinitionCount());
+ int scannedBeanCount = scanner.scan(BASE_PACKAGE);
+ assertEquals(5, scannedBeanCount);
+ assertEquals(initialBeanCount + scannedBeanCount, context.getBeanDefinitionCount());
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
@@ -362,11 +364,12 @@ public class ClassPathBeanDefinitionScannerTests {
public void testMultipleScanCalls() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
- int beanCount = scanner.scan(BASE_PACKAGE);
- assertEquals(10, beanCount);
- assertEquals(beanCount, context.getBeanDefinitionCount());
+ int initialBeanCount = context.getBeanDefinitionCount();
+ int scannedBeanCount = scanner.scan(BASE_PACKAGE);
+ assertEquals(10, scannedBeanCount);
+ assertEquals(scannedBeanCount, context.getBeanDefinitionCount() - initialBeanCount);
int addedBeanCount = scanner.scan("org.springframework.aop.aspectj.annotation");
- assertEquals(beanCount + addedBeanCount, context.getBeanDefinitionCount());
+ assertEquals(initialBeanCount + scannedBeanCount + addedBeanCount, context.getBeanDefinitionCount());
}
@Test
diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProviderTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProviderTests.java
index 3ea25d3725d..0774a66cfd0 100644
--- a/org.springframework.context/src/test/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProviderTests.java
+++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProviderTests.java
@@ -16,10 +16,30 @@
package org.springframework.context.annotation;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Pattern;
+import org.aspectj.lang.annotation.Aspect;
+import org.junit.Test;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.type.filter.AnnotationTypeFilter;
+import org.springframework.core.type.filter.AssignableTypeFilter;
+import org.springframework.core.type.filter.RegexPatternTypeFilter;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Controller;
+import org.springframework.stereotype.Repository;
+import org.springframework.stereotype.Service;
+
+import example.profilescan.ProfileAnnotatedComponent;
import example.scannable.FooDao;
import example.scannable.FooService;
import example.scannable.FooServiceImpl;
@@ -28,18 +48,6 @@ import example.scannable.NamedComponent;
import example.scannable.NamedStubDao;
import example.scannable.ServiceInvocationCounter;
import example.scannable.StubFooDao;
-import org.aspectj.lang.annotation.Aspect;
-import static org.junit.Assert.*;
-import org.junit.Test;
-
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.core.type.filter.AnnotationTypeFilter;
-import org.springframework.core.type.filter.AssignableTypeFilter;
-import org.springframework.core.type.filter.RegexPatternTypeFilter;
-import org.springframework.stereotype.Component;
-import org.springframework.stereotype.Controller;
-import org.springframework.stereotype.Repository;
-import org.springframework.stereotype.Service;
/**
* @author Mark Fisher
@@ -49,7 +57,7 @@ import org.springframework.stereotype.Service;
public class ClassPathScanningCandidateComponentProviderTests {
private static final String TEST_BASE_PACKAGE = "example.scannable";
- //ClassPathScanningCandidateComponentProviderTests.class.getPackage().getName();
+ private static final String TEST_PROFILE_PACKAGE = "example.profilescan";
@Test
@@ -102,7 +110,6 @@ public class ClassPathScanningCandidateComponentProviderTests {
assertFalse(containsBeanClass(candidates, NamedStubDao.class));
}
- @SuppressWarnings("unchecked")
@Test
public void testWithAspectAnnotationOnly() throws Exception {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
@@ -155,6 +162,59 @@ public class ClassPathScanningCandidateComponentProviderTests {
assertFalse(containsBeanClass(candidates, FooServiceImpl.class));
}
+ @Test
+ public void testWithNullEnvironment() {
+ ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
+ Set candidates = provider.findCandidateComponents(TEST_PROFILE_PACKAGE);
+ assertThat(containsBeanClass(candidates, ProfileAnnotatedComponent.class), is(false));
+ }
+
+ @Test
+ public void testWithInactiveProfile() {
+ ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
+ ConfigurableEnvironment env = new DefaultEnvironment();
+ env.setActiveProfiles("other");
+ provider.setEnvironment(env);
+ Set candidates = provider.findCandidateComponents(TEST_PROFILE_PACKAGE);
+ assertThat(containsBeanClass(candidates, ProfileAnnotatedComponent.class), is(false));
+ }
+
+ @Test
+ public void testWithActiveProfile() {
+ ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
+ ConfigurableEnvironment env = new DefaultEnvironment();
+ env.setActiveProfiles(ProfileAnnotatedComponent.PROFILE_NAME);
+ provider.setEnvironment(env);
+ Set candidates = provider.findCandidateComponents(TEST_PROFILE_PACKAGE);
+ assertThat(containsBeanClass(candidates, ProfileAnnotatedComponent.class), is(true));
+ }
+
+ @Test
+ public void testIntegrationWithAnnotationConfigApplicationContext_noProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(ProfileAnnotatedComponent.class);
+ ctx.refresh();
+ assertThat(ctx.containsBean(ProfileAnnotatedComponent.BEAN_NAME), is(false));
+ }
+
+ @Test
+ public void testIntegrationWithAnnotationConfigApplicationContext_validProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.getEnvironment().setActiveProfiles(ProfileAnnotatedComponent.PROFILE_NAME);
+ ctx.register(ProfileAnnotatedComponent.class);
+ ctx.refresh();
+ assertThat(ctx.containsBean(ProfileAnnotatedComponent.BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void testIntegrationWithAnnotationConfigApplicationContext_invalidProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.getEnvironment().setActiveProfiles("other");
+ ctx.register(ProfileAnnotatedComponent.class);
+ ctx.refresh();
+ assertThat(ctx.containsBean(ProfileAnnotatedComponent.BEAN_NAME), is(false));
+ }
+
private boolean containsBeanClass(Set candidates, Class beanClass) {
for (Iterator it = candidates.iterator(); it.hasNext();) {
ScannedGenericBeanDefinition definition = (ScannedGenericBeanDefinition) it.next();
diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationTests.java
new file mode 100644
index 00000000000..39f8dffc112
--- /dev/null
+++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2010 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.context.annotation;
+
+import org.junit.Test;
+import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
+import org.springframework.context.annotation.ComponentScan.ExcludeFilter;
+import org.springframework.context.annotation.ComponentScan.IncludeFilter;
+import org.springframework.core.type.filter.TypeFilter;
+
+/**
+ * Unit tests for {@link ComponentScan} annotation.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class ComponentScanAnnotationTests {
+ @Test
+ public void test() {
+
+ }
+}
+
+@interface MyAnnotation { }
+
+@Configuration
+@ComponentScan(
+ packageOf={TestBean.class},
+ nameGenerator = DefaultBeanNameGenerator.class,
+ scopedProxy = ScopedProxyMode.NO,
+ scopeResolver = AnnotationScopeMetadataResolver.class,
+ useDefaultFilters = false,
+ resourcePattern = "**/*custom.class",
+ includeFilters = {
+ @IncludeFilter(type = FilterType.ANNOTATION, value = MyAnnotation.class)
+ },
+ excludeFilters = {
+ @ExcludeFilter(type = FilterType.CUSTOM, value = TypeFilter.class)
+ }
+)
+class MyConfig {
+
+}
+
+@ComponentScan(packageOf=example.scannable.NamedComponent.class)
+class SimpleConfig { }
\ No newline at end of file
diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java
index bd055d3e48b..4181cc2233c 100644
--- a/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java
+++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java
@@ -16,7 +16,12 @@
package org.springframework.context.annotation;
-import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -26,11 +31,14 @@ import java.lang.annotation.Target;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
+import example.profilescan.ProfileAnnotatedComponent;
import example.scannable.AutowiredQualifierFooService;
/**
@@ -88,6 +96,31 @@ public class ComponentScanParserTests {
assertNotNull(testBean.getDependency());
}
+ @Test
+ public void testComponentScanRespectsProfileAnnotation() {
+ String xmlLocation = "org/springframework/context/annotation/componentScanRespectsProfileAnnotationTests.xml";
+ { // should exclude the profile-annotated bean if active profiles remains unset
+ GenericXmlApplicationContext context = new GenericXmlApplicationContext();
+ context.load(xmlLocation);
+ context.refresh();
+ assertThat(context.containsBean(ProfileAnnotatedComponent.BEAN_NAME), is(false));
+ }
+ { // should include the profile-annotated bean with active profiles set
+ GenericXmlApplicationContext context = new GenericXmlApplicationContext();
+ context.getEnvironment().setActiveProfiles(ProfileAnnotatedComponent.PROFILE_NAME);
+ context.load(xmlLocation);
+ context.refresh();
+ assertThat(context.containsBean(ProfileAnnotatedComponent.BEAN_NAME), is(true));
+ }
+ { // ensure the same works for AbstractRefreshableApplicationContext impls too
+ ConfigurableApplicationContext context =
+ new ClassPathXmlApplicationContext(new String[]{xmlLocation}, false);
+ context.getEnvironment().setActiveProfiles(ProfileAnnotatedComponent.PROFILE_NAME);
+ context.refresh();
+ assertThat(context.containsBean(ProfileAnnotatedComponent.BEAN_NAME), is(true));
+ }
+ }
+
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/componentScanRespectsProfileAnnotationTests.xml b/org.springframework.context/src/test/java/org/springframework/context/annotation/componentScanRespectsProfileAnnotationTests.xml
new file mode 100644
index 00000000000..a35ea025430
--- /dev/null
+++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/componentScanRespectsProfileAnnotationTests.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/org.springframework.context/src/test/java/org/springframework/context/config/ContextNamespaceHandlerTests.java b/org.springframework.context/src/test/java/org/springframework/context/config/ContextNamespaceHandlerTests.java
index c34c3f58850..c760e5d7eca 100644
--- a/org.springframework.context/src/test/java/org/springframework/context/config/ContextNamespaceHandlerTests.java
+++ b/org.springframework.context/src/test/java/org/springframework/context/config/ContextNamespaceHandlerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -16,23 +16,27 @@
package org.springframework.context.config;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import org.junit.Before;
import org.junit.Test;
-
+import org.springframework.beans.factory.config.AbstractPropertyPlaceholderConfigurer;
import org.springframework.beans.factory.config.PropertyOverrideConfigurer;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.GenericXmlApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.mock.env.MockEnvironment;
/**
* @author Arjen Poutsma
* @author Dave Syer
+ * @author Chris Beams
* @since 2.5.6
*/
public class ContextNamespaceHandlerTests {
@@ -41,9 +45,9 @@ public class ContextNamespaceHandlerTests {
public void propertyPlaceholder() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"contextNamespaceHandlerTests-replace.xml", getClass());
- Map beans = applicationContext
- .getBeansOfType(PropertyPlaceholderConfigurer.class);
- assertFalse("No PropertyPlaceHolderConfigurer found", beans.isEmpty());
+ Map beans = applicationContext
+ .getBeansOfType(AbstractPropertyPlaceholderConfigurer.class);
+ assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
String s = (String) applicationContext.getBean("string");
assertEquals("No properties replaced", "bar", s);
}
@@ -56,7 +60,7 @@ public class ContextNamespaceHandlerTests {
"contextNamespaceHandlerTests-system.xml", getClass());
Map beans = applicationContext
.getBeansOfType(PropertyPlaceholderConfigurer.class);
- assertFalse("No PropertyPlaceHolderConfigurer found", beans.isEmpty());
+ assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
String s = (String) applicationContext.getBean("string");
assertEquals("No properties replaced", "spam", s);
} finally {
@@ -66,13 +70,27 @@ public class ContextNamespaceHandlerTests {
}
}
+ @Test
+ public void propertyPlaceholderEnvironmentProperties() throws Exception {
+ MockEnvironment env = MockEnvironment.withProperty("foo", "spam");
+ GenericXmlApplicationContext applicationContext = new GenericXmlApplicationContext();
+ applicationContext.setEnvironment(env);
+ applicationContext.load(new ClassPathResource("contextNamespaceHandlerTests-simple.xml", getClass()));
+ applicationContext.refresh();
+ Map beans = applicationContext
+ .getBeansOfType(AbstractPropertyPlaceholderConfigurer.class);
+ assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
+ String s = (String) applicationContext.getBean("string");
+ assertEquals("No properties replaced", "spam", s);
+ }
+
@Test
public void propertyPlaceholderLocation() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"contextNamespaceHandlerTests-location.xml", getClass());
Map beans = applicationContext
.getBeansOfType(PropertyPlaceholderConfigurer.class);
- assertFalse("No PropertyPlaceHolderConfigurer found", beans.isEmpty());
+ assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
String s = (String) applicationContext.getBean("foo");
assertEquals("No properties replaced", "bar", s);
s = (String) applicationContext.getBean("bar");
@@ -85,9 +103,9 @@ public class ContextNamespaceHandlerTests {
public void propertyPlaceholderIgnored() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"contextNamespaceHandlerTests-replace-ignore.xml", getClass());
- Map beans = applicationContext
- .getBeansOfType(PropertyPlaceholderConfigurer.class);
- assertFalse("No PropertyPlaceHolderConfigurer found", beans.isEmpty());
+ Map beans = applicationContext
+ .getBeansOfType(AbstractPropertyPlaceholderConfigurer.class);
+ assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
String s = (String) applicationContext.getBean("string");
assertEquals("Properties replaced", "${bar}", s);
}
diff --git a/org.springframework.context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java b/org.springframework.context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java
index c48b505337a..7149bbca543 100644
--- a/org.springframework.context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java
+++ b/org.springframework.context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java
@@ -240,7 +240,6 @@ public class ApplicationContextExpressionTests {
System.getProperties().remove("country");
System.getProperties().remove("name");
}
- System.out.println(sw.getTotalTimeMillis());
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 6000);
}
diff --git a/org.springframework.context/src/test/java/org/springframework/context/expression/EnvironmentAccessorIntegrationTests.java b/org.springframework.context/src/test/java/org/springframework/context/expression/EnvironmentAccessorIntegrationTests.java
new file mode 100644
index 00000000000..755b50acefc
--- /dev/null
+++ b/org.springframework.context/src/test/java/org/springframework/context/expression/EnvironmentAccessorIntegrationTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2010 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.context.expression;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
+
+import java.util.HashMap;
+
+import org.junit.Test;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+import test.beans.TestBean;
+
+
+/**
+ * Integration tests for {@link EnvironmentAccessor}, which is registered with
+ * SpEL for all {@link AbstractApplicationContext} implementations via
+ * {@link StandardBeanExpressionResolver}.
+ *
+ * @author Chris Beams
+ */
+public class EnvironmentAccessorIntegrationTests {
+
+ @Test
+ @SuppressWarnings("all")
+ public void braceAccess() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerBeanDefinition("testBean",
+ genericBeanDefinition(TestBean.class)
+ .addPropertyValue("name", "#{environment['my.name']}")
+ .getBeanDefinition());
+
+ GenericApplicationContext ctx = new GenericApplicationContext(bf);
+ ctx.getEnvironment().addPropertySource("testMap", new HashMap() {{ put("my.name", "myBean"); }});
+ ctx.refresh();
+
+ assertThat(ctx.getBean(TestBean.class).getName(), equalTo("myBean"));
+ }
+
+}
diff --git a/org.springframework.context/src/test/java/org/springframework/context/support/EnvironmentAwarePropertyPlaceholderConfigurerTests.java b/org.springframework.context/src/test/java/org/springframework/context/support/EnvironmentAwarePropertyPlaceholderConfigurerTests.java
new file mode 100644
index 00000000000..852330cefba
--- /dev/null
+++ b/org.springframework.context/src/test/java/org/springframework/context/support/EnvironmentAwarePropertyPlaceholderConfigurerTests.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2010 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.context.support;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
+
+import org.junit.Test;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.mock.env.MockEnvironment;
+
+import test.beans.TestBean;
+
+/**
+ * Unit tests for {@link EnvironmentAwarePropertyPlaceholderConfigurer}.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see EnvironmentAwarePropertyPlaceholderConfigurerTests
+ */
+public class EnvironmentAwarePropertyPlaceholderConfigurerTests {
+
+ @Test(expected=IllegalArgumentException.class)
+ public void environmentNotNull() {
+ new EnvironmentAwarePropertyPlaceholderConfigurer().postProcessBeanFactory(new DefaultListableBeanFactory());
+ }
+
+ @Test
+ public void localPropertiesOverrideFalse() {
+ localPropertiesOverride(false);
+ }
+
+ @Test
+ public void localPropertiesOverrideTrue() {
+ localPropertiesOverride(true);
+ }
+
+ private void localPropertiesOverride(boolean override) {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerBeanDefinition("testBean",
+ genericBeanDefinition(TestBean.class)
+ .addPropertyValue("name", "${foo}")
+ .getBeanDefinition());
+
+ EnvironmentAwarePropertyPlaceholderConfigurer ppc = new EnvironmentAwarePropertyPlaceholderConfigurer();
+
+ ppc.setLocalOverride(override);
+ ppc.setProperties(MockEnvironment.withProperty("foo", "local").asProperties());
+ ppc.setEnvironment(MockEnvironment.withProperty("foo", "enclosing"));
+ ppc.postProcessBeanFactory(bf);
+ if (override) {
+ assertThat(bf.getBean(TestBean.class).getName(), equalTo("local"));
+ } else {
+ assertThat(bf.getBean(TestBean.class).getName(), equalTo("enclosing"));
+ }
+ }
+
+ @Test
+ public void simpleReplacement() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerBeanDefinition("testBean",
+ genericBeanDefinition(TestBean.class)
+ .addPropertyValue("name", "${my.name}")
+ .getBeanDefinition());
+
+ MockEnvironment env = new MockEnvironment();
+ env.setProperty("my.name", "myValue");
+
+ EnvironmentAwarePropertyPlaceholderConfigurer ppc =
+ new EnvironmentAwarePropertyPlaceholderConfigurer();
+ ppc.setEnvironment(env);
+ ppc.postProcessBeanFactory(bf);
+ assertThat(bf.getBean(TestBean.class).getName(), equalTo("myValue"));
+ }
+
+}
diff --git a/org.springframework.context/src/test/java/org/springframework/mock/env/MockEnvironment.java b/org.springframework.context/src/test/java/org/springframework/mock/env/MockEnvironment.java
new file mode 100644
index 00000000000..2a6ec523686
--- /dev/null
+++ b/org.springframework.context/src/test/java/org/springframework/mock/env/MockEnvironment.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2002-2010 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.mock.env;
+
+import org.springframework.core.env.AbstractEnvironment;
+import org.springframework.core.env.ConfigurableEnvironment;
+
+
+/**
+ * Simple {@link ConfigurableEnvironment} implementation exposing a
+ * {@link #setProperty(String, String)} and {@link #withProperty(String, String)}
+ * methods for testing purposes.
+ *
+ * @author Chris Beams
+ * @see MockPropertySource
+ */
+public class MockEnvironment extends AbstractEnvironment {
+
+ private MockPropertySource propertySource = new MockPropertySource();
+
+ public MockEnvironment() {
+ getPropertySources().add(propertySource);
+ }
+
+ public void setProperty(String key, String value) {
+ propertySource.setProperty(key, value);
+ }
+
+ public static MockEnvironment withProperty(String key, String value) {
+ MockEnvironment environment = new MockEnvironment();
+ environment.setProperty(key, value);
+ return environment;
+ }
+}
diff --git a/org.springframework.context/src/test/java/org/springframework/mock/env/MockPropertySource.java b/org.springframework.context/src/test/java/org/springframework/mock/env/MockPropertySource.java
new file mode 100644
index 00000000000..f1e7285c8ec
--- /dev/null
+++ b/org.springframework.context/src/test/java/org/springframework/mock/env/MockPropertySource.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2010 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.mock.env;
+
+import java.util.Properties;
+
+import org.springframework.core.env.PropertiesPropertySource;
+
+public class MockPropertySource extends PropertiesPropertySource {
+
+ public MockPropertySource() {
+ this(new Properties());
+ }
+
+ private MockPropertySource(Properties properties) {
+ super("mockProperties", properties);
+ }
+
+ public void setProperty(String key, String value) {
+ this.source.setProperty(key, value);
+ }
+
+ public static MockPropertySource withProperty(String key, String value) {
+ Properties properties = new Properties();
+ properties.setProperty(key, value);
+ return new MockPropertySource(properties);
+ }
+}
diff --git a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-override.xml b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-override.xml
index 571397bd6e0..647e08ff9bf 100644
--- a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-override.xml
+++ b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-override.xml
@@ -2,7 +2,7 @@
diff --git a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-replace-ignore.xml b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-replace-ignore.xml
index 727c03198d9..4714c36217a 100644
--- a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-replace-ignore.xml
+++ b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-replace-ignore.xml
@@ -2,7 +2,7 @@
diff --git a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-replace.xml b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-replace.xml
index 286cff23d92..92161968f76 100644
--- a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-replace.xml
+++ b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-replace.xml
@@ -2,7 +2,7 @@
@@ -11,7 +11,7 @@
-
+
diff --git a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-simple.xml b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-simple.xml
new file mode 100644
index 00000000000..a0b3eaf779f
--- /dev/null
+++ b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-simple.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-system.xml b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-system.xml
index 9c475282fc0..d5268c52bcc 100644
--- a/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-system.xml
+++ b/org.springframework.context/src/test/resources/org/springframework/context/config/contextNamespaceHandlerTests-system.xml
@@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
diff --git a/org.springframework.core/.settings/org.eclipse.jdt.core.prefs b/org.springframework.core/.settings/org.eclipse.jdt.core.prefs
index 5a5d4fe0932..51fbd353764 100644
--- a/org.springframework.core/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.core/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.core/pom.xml b/org.springframework.core/pom.xml
index 2c0dbf91320..4d5e6b2dbda 100644
--- a/org.springframework.core/pom.xml
+++ b/org.springframework.core/pom.xml
@@ -6,12 +6,12 @@
org.springframework
spring-core
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/AbstractEnvironment.java b/org.springframework.core/src/main/java/org/springframework/core/env/AbstractEnvironment.java
new file mode 100644
index 00000000000..7e6842b7c45
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/AbstractEnvironment.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import static java.lang.String.format;
+import static org.springframework.util.StringUtils.commaDelimitedListToSet;
+import static org.springframework.util.StringUtils.trimAllWhitespace;
+import static org.springframework.util.SystemPropertyUtils.PLACEHOLDER_PREFIX;
+import static org.springframework.util.SystemPropertyUtils.PLACEHOLDER_SUFFIX;
+import static org.springframework.util.SystemPropertyUtils.VALUE_SEPARATOR;
+
+import java.security.AccessControlException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.core.convert.support.ConversionServiceFactory;
+import org.springframework.util.PropertyPlaceholderHelper;
+import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
+
+
+/**
+ * TODO SPR-7508: document
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public abstract class AbstractEnvironment implements ConfigurableEnvironment {
+
+ public static final String SPRING_PROFILES_PROPERTY_NAME = "springProfiles";
+
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private final PropertyPlaceholderHelper nonStrictHelper =
+ new PropertyPlaceholderHelper(PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, VALUE_SEPARATOR, true);
+
+ private final PropertyPlaceholderHelper strictHelper =
+ new PropertyPlaceholderHelper(PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, VALUE_SEPARATOR, false);
+
+ private Set activeProfiles = new LinkedHashSet();
+ private LinkedList> propertySources = new LinkedList>();
+ private ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
+
+ private boolean explicitlySetProfiles;
+
+
+ public void addPropertySource(PropertySource> propertySource) {
+ propertySources.push(propertySource);
+ }
+
+ public void addPropertySource(String name, Properties properties) {
+ addPropertySource(new PropertiesPropertySource(name, properties));
+ }
+
+ public void addPropertySource(String name, Map propertiesMap) {
+ addPropertySource(new MapPropertySource(name, propertiesMap));
+ }
+
+ public LinkedList> getPropertySources() {
+ return propertySources;
+ }
+
+ public boolean containsProperty(String key) {
+ for (PropertySource> propertySource : propertySources) {
+ if (propertySource.containsProperty(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String getProperty(String key) {
+ if (logger.isTraceEnabled()) {
+ logger.trace(format("getProperty(\"%s\") (implicit targetType [String])", key));
+ }
+ return getProperty(key, String.class);
+ }
+
+ public String getRequiredProperty(String key) {
+ String value = getProperty(key);
+ if (value == null) {
+ throw new IllegalArgumentException(format("required key [%s] not found", key));
+ }
+ return value;
+ }
+
+ public T getProperty(String key, Class targetValueType) {
+ boolean debugEnabled = logger.isDebugEnabled();
+ if (logger.isTraceEnabled()) {
+ logger.trace(format("getProperty(\"%s\", %s)", key, targetValueType.getSimpleName()));
+ }
+
+ for (PropertySource> propertySource : propertySources) {
+ if (debugEnabled) {
+ logger.debug(format("Searching for key '%s' in [%s]", key, propertySource.getName()));
+ }
+ if (propertySource.containsProperty(key)) {
+ Object value = propertySource.getProperty(key);
+ Class> valueType = value == null ? null : value.getClass();
+ if (debugEnabled) {
+ logger.debug(
+ format("Found key '%s' in [%s] with type [%s] and value '%s'",
+ key, propertySource.getName(),
+ valueType == null ? "" : valueType.getSimpleName(), value));
+ }
+ if (value == null) {
+ return null;
+ }
+ if (!conversionService.canConvert(valueType, targetValueType)) {
+ throw new IllegalArgumentException(
+ format("Cannot convert value [%s] from source type [%s] to target type [%s]",
+ value, valueType.getSimpleName(), targetValueType.getSimpleName()));
+ }
+ return conversionService.convert(value, targetValueType);
+ }
+ }
+
+ if (debugEnabled) {
+ logger.debug(format("Could not find key '%s' in any property source. Returning [null]", key));
+ }
+ return null;
+ }
+
+ public T getRequiredProperty(String key, Class valueType) {
+ T value = getProperty(key, valueType);
+ if (value == null) {
+ throw new IllegalArgumentException(format("required key [%s] not found", key));
+ }
+ return value;
+ }
+
+ public int getPropertyCount() {
+ return asProperties().size();
+ }
+
+ public Properties asProperties() {
+ // TODO SPR-7508: refactor, simplify. only handles map-based propertysources right now.
+ Properties mergedProps = new Properties();
+ Iterator> descendingIterator = getPropertySources().descendingIterator();
+ while (descendingIterator.hasNext()) {
+ PropertySource> propertySource = descendingIterator.next();
+ Object object = propertySource.getSource();
+ if (object instanceof Map) {
+ for (Entry, ?> entry : ((Map, ?>)object).entrySet()) {
+ mergedProps.put(entry.getKey(), entry.getValue());
+ }
+ } else {
+ throw new IllegalArgumentException("unknown PropertySource source type: " + object.getClass().getName());
+ }
+ }
+ return mergedProps;
+ }
+
+ public Set getActiveProfiles() {
+ doGetProfiles();
+ return Collections.unmodifiableSet(activeProfiles);
+ }
+
+ private void doGetProfiles() {
+ if (explicitlySetProfiles)
+ return;
+
+ String profiles = getProperty(SPRING_PROFILES_PROPERTY_NAME);
+ if (profiles == null || profiles.equals("")) {
+ return;
+ }
+
+ this.activeProfiles = commaDelimitedListToSet(trimAllWhitespace(profiles));
+ }
+
+ public void setActiveProfiles(String... profiles) {
+ explicitlySetProfiles = true;
+ this.activeProfiles.clear();
+ this.activeProfiles.addAll(Arrays.asList(profiles));
+ }
+
+ public Map getSystemEnvironment() {
+ Map systemEnvironment;
+ try {
+ systemEnvironment = System.getenv();
+ }
+ catch (AccessControlException ex) {
+ systemEnvironment = new ReadOnlySystemAttributesMap() {
+ @Override
+ protected String getSystemAttribute(String variableName) {
+ try {
+ return System.getenv(variableName);
+ }
+ catch (AccessControlException ex) {
+ if (logger.isInfoEnabled()) {
+ logger.info(format("Caught AccessControlException when accessing system environment variable " +
+ "[%s]; its value will be returned [null]. Reason: %s", variableName, ex.getMessage()));
+ }
+ return null;
+ }
+ }
+ };
+ }
+ return systemEnvironment;
+ }
+
+ /**
+ * TODO SPR-7508: document
+ *
+ * Returns a string, string map even though the underlying system properties
+ * are a properties object that can technically contain non-string keys and values.
+ * Thus, the unchecked conversions and raw map type being used. In practice, it will
+ * always be 'safe' to interact with the properties map as if it contains only strings,
+ * because Properties copes with this in its getProperty method. We never access the
+ * properties object via its Hashtable.get() method, so any non-string keys/values
+ * get effectively ignored.
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public Map getSystemProperties() {
+ Map systemProperties;
+ try {
+ systemProperties = System.getProperties();
+ }
+ catch (AccessControlException ex) {
+ systemProperties = new ReadOnlySystemAttributesMap() {
+ @Override
+ protected String getSystemAttribute(String propertyName) {
+ try {
+ return System.getProperty(propertyName);
+ }
+ catch (AccessControlException ex) {
+ if (logger.isInfoEnabled()) {
+ logger.info(format("Caught AccessControlException when accessing system property " +
+ "[%s]; its value will be returned [null]. Reason: %s", propertyName, ex.getMessage()));
+ }
+ return null;
+ }
+ }
+ };
+ }
+ return systemProperties;
+ }
+
+ public String resolvePlaceholders(String text) {
+ return doResolvePlaceholders(text, nonStrictHelper);
+ }
+
+ public String resolveRequiredPlaceholders(String text) {
+ return doResolvePlaceholders(text, strictHelper);
+ }
+
+ private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
+ return helper.replacePlaceholders(text, new PlaceholderResolver() {
+ public String resolvePlaceholder(String placeholderName) {
+ return AbstractEnvironment.this.getProperty(placeholderName);
+ }
+ });
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " [activeProfiles=" + activeProfiles
+ + ", propertySources=" + propertySources + "]";
+ }
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java b/org.springframework.core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java
new file mode 100644
index 00000000000..d9242f527ea
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+/**
+ * TODO SPR-7508: document
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public interface ConfigurableEnvironment extends Environment, PropertySourceAggregator {
+
+ /**
+ * TODO SPR-7508: document
+ */
+ void setActiveProfiles(String... profiles);
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/DefaultEnvironment.java b/org.springframework.core/src/main/java/org/springframework/core/env/DefaultEnvironment.java
new file mode 100644
index 00000000000..6e6190e0079
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/DefaultEnvironment.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+
+/**
+ * TODO SPR-7508: document
+ *
+ * Explain why the default ordering of property sources is the way it is.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class DefaultEnvironment extends AbstractEnvironment {
+
+ public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
+ public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
+
+
+ public DefaultEnvironment() {
+ addPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment());
+ addPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties());
+ }
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/DefaultWebEnvironment.java b/org.springframework.core/src/main/java/org/springframework/core/env/DefaultWebEnvironment.java
new file mode 100644
index 00000000000..97c3986a0ac
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/DefaultWebEnvironment.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+
+/**
+ * TODO SPR-7508: document
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class DefaultWebEnvironment extends DefaultEnvironment {
+
+ public static final String SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME = "servletContextInitParams";
+ public static final String SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME = "servletConfigInitParams";
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/Environment.java b/org.springframework.core/src/main/java/org/springframework/core/env/Environment.java
new file mode 100644
index 00000000000..12fe953cc04
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/Environment.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+
+/**
+ * TODO SPR-7508: document
+ * TODO: Consider extracting a PropertyResolutionService interface
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public interface Environment {
+
+ /**
+ * TODO SPR-7508: document
+ */
+ Set getActiveProfiles();
+
+ /**
+ * TODO SPR-7508: document
+ */
+ boolean containsProperty(String key);
+
+ /**
+ * TODO SPR-7508: document
+ */
+ String getProperty(String key);
+
+ /**
+ * TODO SPR-7508: document
+ */
+ T getProperty(String key, Class targetType);
+
+ /**
+ * TODO SPR-7508: document
+ */
+ String getRequiredProperty(String key);
+
+ /**
+ * TODO SPR-7508: document
+ */
+ T getRequiredProperty(String key, Class targetType);
+
+ /**
+ * TODO SPR-7508: document
+ */
+ int getPropertyCount();
+
+ /**
+ * TODO SPR-7508: document
+ */
+ Properties asProperties();
+
+ /**
+ * TODO SPR-7508: document that this returns {@link System#getenv()} if allowed, or
+ * {@link ReadOnlySystemAttributesMap} if not.
+ */
+ Map getSystemEnvironment();
+
+ /**
+ * TODO SPR-7508: document that this returns {@link System#getProperties()} if allowed, or
+ * {@link ReadOnlySystemAttributesMap} if not. Actually, always returns
+ * {@link ReadOnlySystemAttributesMap} now.
+ * see notes within {@link AbstractEnvironment#getSystemProperties()}
+ */
+ Map getSystemProperties();
+
+ /**
+ * TODO SPR-7508: document
+ * @see #resolveRequiredPlaceholders(String)
+ * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders(String, int)
+ */
+ String resolvePlaceholders(String text);
+
+ /**
+ * TODO SPR-7508: document
+ * @see #resolvePlaceholders(String)
+ * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders(String, int)
+ */
+ String resolveRequiredPlaceholders(String path);
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/EnvironmentCapable.java b/org.springframework.core/src/main/java/org/springframework/core/env/EnvironmentCapable.java
new file mode 100644
index 00000000000..5705502aecd
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/EnvironmentCapable.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+
+/**
+ * TODO SPR-7508: document
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see Environment
+ * @see ConfigurableEnvironmentCapable
+ */
+public interface EnvironmentCapable {
+
+ Environment getEnvironment();
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/MapPropertySource.java b/org.springframework.core/src/main/java/org/springframework/core/env/MapPropertySource.java
new file mode 100644
index 00000000000..469c590cc97
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/MapPropertySource.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import java.util.Map;
+
+
+/**
+ * TODO SPR-7508: document
+ *
+ * Consider adding a TypeConvertingMapPropertySource to accommodate
+ * non-string keys and values. Could be confusing when used in conjunction
+ * with Environment.getProperty(), which also does type conversions. If this
+ * is added, consider renaming this class to SimpleMapPropertySource and
+ * rename PropertiesPropertySource to SimplePropertiesPropertySource.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class MapPropertySource extends PropertySource> {
+
+ protected MapPropertySource(String name, Map source) {
+ super(name, source);
+ }
+
+ public boolean containsProperty(String key) {
+ return source.containsKey(key);
+ }
+
+ public String getProperty(String key) {
+ return source.get(key);
+ }
+
+ @Override
+ public int size() {
+ return source.size();
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/PropertiesPropertySource.java b/org.springframework.core/src/main/java/org/springframework/core/env/PropertiesPropertySource.java
new file mode 100644
index 00000000000..98ac9647fbf
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/PropertiesPropertySource.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import java.util.Properties;
+
+
+/**
+ * TODO SPR-7508: document how this does accept a Properties object,
+ * which is capable of holding non-string keys and values (because
+ * Properties is a Hashtable), but is limited to resolving string-based
+ * keys and values.
+ *
+ * Consider adding a TypeConvertingPropertiesPropertySource to accommodate
+ * non-string keys and values (such as is technically possible with
+ * System.getProperties())
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class PropertiesPropertySource extends PropertySource {
+
+ public PropertiesPropertySource(String name, Properties source) {
+ super(name, source);
+ }
+
+ public boolean containsProperty(String key) {
+ return source.containsKey(key);
+ }
+
+ public String getProperty(String key) {
+ return source.getProperty(key);
+ }
+
+ @Override
+ public int size() {
+ return source.size();
+ }
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/PropertySource.java b/org.springframework.core/src/main/java/org/springframework/core/env/PropertySource.java
new file mode 100644
index 00000000000..31ee0124a2c
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/PropertySource.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+public abstract class PropertySource {
+
+ protected final Log logger = LogFactory.getLog(this.getClass());
+
+ protected final String name;
+ protected final T source;
+
+ public PropertySource(String name, T source) {
+ this.name = name;
+ this.source = source;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public T getSource() {
+ return source;
+ }
+
+ public abstract boolean containsProperty(String key);
+
+ public abstract String getProperty(String key);
+
+ public abstract int size();
+
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof PropertySource))
+ return false;
+ PropertySource> other = (PropertySource>) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ /**
+ * Produce concise output (type, name, and number of properties) if the current log level does
+ * not include debug. If debug is enabled, produce verbose output including hashcode of the
+ * PropertySource instance and every key/value property pair.
+ *
+ * This variable verbosity is useful as a property source such as system properties
+ * or environment variables may contain an arbitrary number of property pairs, potentially
+ * leading to difficult to read exception and log messages.
+ *
+ * @see Log#isDebugEnabled()
+ */
+ @Override
+ public String toString() {
+ if (logger.isDebugEnabled()) {
+ return String.format("%s@%s [name='%s', properties=%s]",
+ getClass().getSimpleName(), System.identityHashCode(this), name, source);
+ }
+
+ return String.format("%s [name='%s', propertyCount=%d]",
+ getClass().getSimpleName(), name, this.size());
+ }
+
+
+ /**
+ * For collection comparison purposes
+ * TODO SPR-7508: document
+ */
+ public static PropertySource> named(String name) {
+ return new ComparisonPropertySource(name);
+ }
+
+
+ /**
+ * TODO: SPR-7508: document
+ */
+ public static class ComparisonPropertySource extends PropertySource{
+
+ private static final String USAGE_ERROR =
+ "ComparisonPropertySource instances are for collection comparison " +
+ "use only";
+
+ public ComparisonPropertySource(String name) {
+ super(name, null);
+ }
+
+ @Override
+ public Void getSource() {
+ throw new UnsupportedOperationException(USAGE_ERROR);
+ }
+ public String getProperty(String key) {
+ throw new UnsupportedOperationException(USAGE_ERROR);
+ }
+ public boolean containsProperty(String key) {
+ throw new UnsupportedOperationException(USAGE_ERROR);
+ }
+ public int size() {
+ throw new UnsupportedOperationException(USAGE_ERROR);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s [name='%s']", getClass().getSimpleName(), name);
+ }
+ }
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/env/PropertySourceAggregator.java b/org.springframework.core/src/main/java/org/springframework/core/env/PropertySourceAggregator.java
new file mode 100644
index 00000000000..431d3c2a835
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/PropertySourceAggregator.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * TODO: SPR-7508 document
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public interface PropertySourceAggregator {
+
+ void addPropertySource(PropertySource> propertySource);
+
+ void addPropertySource(String name, Properties properties);
+
+ void addPropertySource(String name, Map propertiesMap);
+
+ /**
+ * TODO: SPR-7508 document
+ *
+ * Care should be taken to ensure duplicates are not introduced.
+ *
+ * Recommend using {@link LinkedList#set(int, Object)} for replacing items,
+ * and combining {@link LinkedList#remove()} with other methods like
+ * {@link LinkedList#add(Object)} to prevent duplicates.
+ *
+ * Explain how {@link PropertySource#equals(Object)} and hashCode work, and that
+ * recommend using {@link PropertySource#named(String)} for lookups in the list.
+ */
+ LinkedList> getPropertySources();
+
+}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/ReadOnlySystemAttributesMap.java b/org.springframework.core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java
similarity index 66%
rename from org.springframework.context/src/main/java/org/springframework/context/support/ReadOnlySystemAttributesMap.java
rename to org.springframework.core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java
index 992f58404a5..c31cb97d025 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/ReadOnlySystemAttributesMap.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package org.springframework.context.support;
+package org.springframework.core.env;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
+
/**
* Read-only {@code Map} implementation that is backed by system properties or environment
* variables.
@@ -28,6 +29,7 @@ import java.util.Set;
* System#getProperties()} or {@link System#getenv()}.
*
* @author Arjen Poutsma
+ * @author Chris Beams
* @since 3.0
*/
abstract class ReadOnlySystemAttributesMap implements Map {
@@ -42,7 +44,25 @@ abstract class ReadOnlySystemAttributesMap implements Map {
return getSystemAttribute(attributeName);
}
else {
- return null;
+ // TODO SPR-7508: technically breaks backward-compat. Used to return null
+ // for non-string keys, now throws. Any callers who have coded to this
+ // behavior will now break. It's highly unlikely, however; could be
+ // a calculated risk to take. Throwing is a better choice, as returning
+ // null represents a 'false negative' - it's not actually that the key
+ // isn't present, it's simply that you cannot access it through the current
+ // abstraction. Remember, this case would only come up if (a) there are
+ // non-string keys or values in system properties, (b) there is a
+ // SecurityManager present, and (c) the user attempts to access one
+ // of those properties through this abstraction. This combination is
+ // probably unlikely enough to merit the change.
+ //
+ // note also that the previous implementation didn't consider the
+ // possibility of non-string values the anonymous implementation used
+ // for System properties access now does.
+ //
+ // See AbstractEnvironment for relevant anonymous implementations
+ // See DefaultEnvironmentTests for unit tests around these cases
+ throw new IllegalStateException("TODO SPR-7508: message");
}
}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/ResourceEditor.java b/org.springframework.core/src/main/java/org/springframework/core/io/ResourceEditor.java
index 710a4fb275e..6146040cc0c 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/io/ResourceEditor.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/ResourceEditor.java
@@ -19,9 +19,11 @@ package org.springframework.core.io;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
-import org.springframework.util.SystemPropertyUtils;
+
/**
* {@link java.beans.PropertyEditor Editor} for {@link Resource}
@@ -30,24 +32,26 @@ import org.springframework.util.SystemPropertyUtils;
* "classpath:myfile.txt") to Resource
* properties instead of using a String location property.
*
- * The path may contain ${...} placeholders,
- * to be resolved as system properties: e.g. ${user.dir}.
- * Unresolvable placeholder are ignored by default.
+ *
The path may contain ${...} placeholders, to be
+ * resolved as {@link Environment} properties: e.g. ${user.dir}.
+ * Unresolvable placeholders are ignored by default.
*
*
Delegates to a {@link ResourceLoader} to do the heavy lifting,
* by default using a {@link DefaultResourceLoader}.
*
* @author Juergen Hoeller
* @author Dave Syer
+ * @author Chris Beams
* @since 28.12.2003
* @see Resource
* @see ResourceLoader
* @see DefaultResourceLoader
- * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders
- * @see System#getProperty(String)
+ * @see org.springframework.env.Environment#resolvePlaceholders
*/
public class ResourceEditor extends PropertyEditorSupport {
+ private final Environment environment;
+
private final ResourceLoader resourceLoader;
private final boolean ignoreUnresolvablePlaceholders;
@@ -55,31 +59,60 @@ public class ResourceEditor extends PropertyEditorSupport {
/**
* Create a new instance of the {@link ResourceEditor} class
- * using a {@link DefaultResourceLoader}.
+ * using a {@link DefaultResourceLoader} and {@link DefaultEnvironment}.
*/
public ResourceEditor() {
- this(new DefaultResourceLoader());
+ this(new DefaultResourceLoader(), new DefaultEnvironment());
}
/**
* Create a new instance of the {@link ResourceEditor} class
- * using the given {@link ResourceLoader}.
+ * using the given {@link ResourceLoader} and a {@link DefaultEnvironment}.
+ * @param resourceLoader the ResourceLoader to use
+ * @deprecated as of Spring 3.1 in favor of
+ * {@link #ResourceEditor(ResourceLoader, Environment)}
+ */
+ @Deprecated
+ public ResourceEditor(ResourceLoader resourceLoader) {
+ this(resourceLoader, new DefaultEnvironment(), true);
+ }
+
+ /**
+ * Create a new instance of the {@link ResourceEditor} class
+ * using the given {@link ResourceLoader} and {@link Environment}.
* @param resourceLoader the ResourceLoader to use
*/
- public ResourceEditor(ResourceLoader resourceLoader) {
- this(resourceLoader, true);
+ public ResourceEditor(ResourceLoader resourceLoader, Environment environment) {
+ this(resourceLoader, environment, true);
}
/**
* Create a new instance of the {@link ResourceEditor} class
- * using the given {@link ResourceLoader}.
+ * using the given {@link ResourceLoader} and a {@link DefaultEnvironment}.
* @param resourceLoader the ResourceLoader to use
* @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
- * if no corresponding system property could be found
+ * if no corresponding property could be found in the DefaultEnvironment
+ * @deprecated as of Spring 3.1 in favor of
+ * {@link #ResourceEditor(ResourceLoader, Environment, boolean)}
*/
+ @Deprecated
public ResourceEditor(ResourceLoader resourceLoader, boolean ignoreUnresolvablePlaceholders) {
+ this(resourceLoader, new DefaultEnvironment(), ignoreUnresolvablePlaceholders);
+ }
+
+ /**
+ * Create a new instance of the {@link ResourceEditor} class
+ * using the given {@link ResourceLoader}.
+ * @param resourceLoader the ResourceLoader to use
+ * @param environment the Environment to use
+ * @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
+ * if no corresponding property could be found in the given environment
+ */
+ public ResourceEditor(ResourceLoader resourceLoader, Environment environment, boolean ignoreUnresolvablePlaceholders) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
+ Assert.notNull(environment, "Environment must not be null");
this.resourceLoader = resourceLoader;
+ this.environment = environment;
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
}
@@ -96,14 +129,17 @@ public class ResourceEditor extends PropertyEditorSupport {
}
/**
- * Resolve the given path, replacing placeholders with
- * corresponding system property values if necessary.
+ * Resolve the given path, replacing placeholders with corresponding
+ * property values from the environment if necessary.
* @param path the original file path
* @return the resolved file path
- * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders
+ * @see Environment#resolvePlaceholders
+ * @see Environment#resolveRequiredPlaceholders
*/
protected String resolvePath(String path) {
- return SystemPropertyUtils.resolvePlaceholders(path, this.ignoreUnresolvablePlaceholders);
+ return this.ignoreUnresolvablePlaceholders ?
+ environment.resolvePlaceholders(path) :
+ environment.resolveRequiredPlaceholders(path);
}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/support/PropertiesLoaderSupport.java b/org.springframework.core/src/main/java/org/springframework/core/io/support/PropertiesLoaderSupport.java
index 65f80cec55c..e9289eed593 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/io/support/PropertiesLoaderSupport.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/support/PropertiesLoaderSupport.java
@@ -23,7 +23,6 @@ import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.springframework.core.io.Resource;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DefaultPropertiesPersister;
@@ -45,12 +44,12 @@ public abstract class PropertiesLoaderSupport {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
- private Properties[] localProperties;
+ protected Properties[] localProperties;
+
+ protected boolean localOverride = false;
private Resource[] locations;
- private boolean localOverride = false;
-
private boolean ignoreResourceNotFound = false;
private String fileEncoding;
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceArrayPropertyEditor.java b/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceArrayPropertyEditor.java
index 8e7ca5782fd..89cb3786011 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceArrayPropertyEditor.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceArrayPropertyEditor.java
@@ -25,9 +25,9 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
+import org.springframework.core.env.DefaultEnvironment;
+import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
-import org.springframework.util.SystemPropertyUtils;
/**
* Editor for {@link org.springframework.core.io.Resource} arrays, to
@@ -44,17 +44,19 @@ import org.springframework.util.SystemPropertyUtils;
* by default using a {@link PathMatchingResourcePatternResolver}.
*
* @author Juergen Hoeller
+ * @author Chris Beams
* @since 1.1.2
* @see org.springframework.core.io.Resource
* @see ResourcePatternResolver
* @see PathMatchingResourcePatternResolver
- * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders
- * @see System#getProperty(String)
+ * @see org.springframework.env.Environment#resolvePlaceholders
*/
public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
private static final Log logger = LogFactory.getLog(ResourceArrayPropertyEditor.class);
+ private final Environment environment;
+
private final ResourcePatternResolver resourcePatternResolver;
private final boolean ignoreUnresolvablePlaceholders;
@@ -62,29 +64,59 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
/**
* Create a new ResourceArrayPropertyEditor with a default
- * PathMatchingResourcePatternResolver.
+ * {@link PathMatchingResourcePatternResolver} and {@link DefaultEnvironment}.
* @see PathMatchingResourcePatternResolver
+ * @see Environment
*/
public ResourceArrayPropertyEditor() {
- this(new PathMatchingResourcePatternResolver());
+ this(new PathMatchingResourcePatternResolver(), new DefaultEnvironment(), true);
}
/**
- * Create a new ResourceArrayPropertyEditor with the given ResourcePatternResolver.
+ * Create a new ResourceArrayPropertyEditor with the given {@link ResourcePatternResolver}
+ * and a {@link DefaultEnvironment}.
* @param resourcePatternResolver the ResourcePatternResolver to use
+ * @deprecated as of 3.1 in favor of {@link #ResourceArrayPropertyEditor(ResourcePatternResolver, Environment)}
*/
+ @Deprecated
public ResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver) {
- this(resourcePatternResolver, true);
+ this(resourcePatternResolver, new DefaultEnvironment(), true);
}
/**
- * Create a new ResourceArrayPropertyEditor with the given ResourcePatternResolver.
+ * Create a new ResourceArrayPropertyEditor with the given {@link ResourcePatternResolver}
+ * and {@link Environment}.
+ * @param resourcePatternResolver the ResourcePatternResolver to use
+ * @param environment the Environment to use
+ */
+ public ResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver, Environment environment) {
+ this(resourcePatternResolver, environment, true);
+ }
+
+ /**
+ * Create a new ResourceArrayPropertyEditor with the given {@link ResourcePatternResolver}
+ * and a {@link DefaultEnvironment}.
* @param resourcePatternResolver the ResourcePatternResolver to use
* @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
* if no corresponding system property could be found
+ * @deprecated as of 3.1 in favor of {@link #ResourceArrayPropertyEditor(ResourcePatternResolver, Environment, boolean)}
*/
+ @Deprecated
public ResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver, boolean ignoreUnresolvablePlaceholders) {
+ this(resourcePatternResolver, new DefaultEnvironment(), ignoreUnresolvablePlaceholders);
+ }
+
+ /**
+ * Create a new ResourceArrayPropertyEditor with the given {@link ResourcePatternResolver}
+ * and {@link Environment}.
+ * @param resourcePatternResolver the ResourcePatternResolver to use
+ * @param environment the Environment to use
+ * @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
+ * if no corresponding system property could be found
+ */
+ public ResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver, Environment environment, boolean ignoreUnresolvablePlaceholders) {
this.resourcePatternResolver = resourcePatternResolver;
+ this.environment = environment;
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
}
@@ -160,10 +192,13 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
* corresponding system property values if necessary.
* @param path the original file path
* @return the resolved file path
- * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders
+ * @see Environment#resolvePlaceholders
+ * @see Environment#resolveRequiredPlaceholders
*/
protected String resolvePath(String path) {
- return SystemPropertyUtils.resolvePlaceholders(path, this.ignoreUnresolvablePlaceholders);
+ return this.ignoreUnresolvablePlaceholders ?
+ environment.resolvePlaceholders(path) :
+ environment.resolveRequiredPlaceholders(path);
}
}
diff --git a/org.springframework.core/src/main/java/org/springframework/util/SystemPropertyUtils.java b/org.springframework.core/src/main/java/org/springframework/util/SystemPropertyUtils.java
index 6e8eaff2f13..8fbcda5510f 100644
--- a/org.springframework.core/src/main/java/org/springframework/util/SystemPropertyUtils.java
+++ b/org.springframework.core/src/main/java/org/springframework/util/SystemPropertyUtils.java
@@ -25,6 +25,12 @@ import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
* ${user.dir}. Default values can be supplied using the ":" separator between key
* and value.
*
+ * TODO SPR-7508: review item - nearly all uses of {@link SystemPropertyUtils#resolvePlaceholders(String)}
+ * have been replaced by Environment#resolvePlaceholder(), however, there are several locations in the
+ * framework that cannot be so refactored as referring to Environment would introduce a cycle. Case in point
+ * Log4JConfigurer and Log4JWebConfigurer. Need to unify this functionality one way or another. It's
+ * currently pure duplication.
+ *
* @author Juergen Hoeller
* @author Rob Harrop
* @author Dave Syer
diff --git a/org.springframework.core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java b/org.springframework.core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java
new file mode 100644
index 00000000000..f8f8160e73f
--- /dev/null
+++ b/org.springframework.core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java
@@ -0,0 +1,75 @@
+package org.springframework.core.env;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/**
+ * Unit tests covering the extensibility of AbstractEnvironment
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class CustomEnvironmentTests {
+
+ @Ignore
+ @Test
+ public void noop() {
+ }
+ /*
+ @Retention(RetentionPolicy.RUNTIME)
+ public
+ static @interface MyEnvironment { }
+
+ /**
+ * A custom {@link Environment} that evaluates class literals
+ * for the presence of a custom annotation.
+ * /
+ static class CustomEnvironment extends AbstractEnvironment {
+ @Override
+ public boolean accepts(Object object) {
+ if (object instanceof Class>) {
+ return ((Class>)object).isAnnotationPresent(MyEnvironment.class);
+ }
+ return super.accepts(object);
+ }
+ }
+
+ @MyEnvironment
+ static class CandidateWithCustomAnnotation { }
+
+ static class CandidateWithoutCustomAnnotation { }
+
+ @Test
+ public void subclassOfAbstractEnvironment() {
+ ConfigurableEnvironment env = new CustomEnvironment();
+ env.setActiveProfiles("test");
+ assertThat(env.accepts(CandidateWithCustomAnnotation.class), is(true));
+ assertThat(env.accepts(CandidateWithoutCustomAnnotation.class), is(false));
+ assertThat(env.accepts("test"), is(true)); // AbstractEnvironment always returns true
+ assertThat(env.accepts(new Object()), is(true)); // AbstractEnvironment always returns true
+ }
+
+ static class CustomDefaultEnvironment extends DefaultEnvironment {
+ @Override
+ public boolean accepts(Object object) {
+ if (object instanceof Class>) {
+ return ((Class>)object).isAnnotationPresent(MyEnvironment.class);
+ }
+ return super.accepts(object);
+ }
+ }
+
+ @Test
+ public void subclassOfDefaultEnvironment() {
+ ConfigurableEnvironment env = new CustomDefaultEnvironment();
+ env.setActiveProfiles("test");
+ assertThat(env.accepts(CandidateWithCustomAnnotation.class), is(true));
+ assertThat(env.accepts(CandidateWithoutCustomAnnotation.class), is(false));
+ assertThat(env.accepts("test"), is(true)); // delegates to DefaultEnvironment
+ assertThat(env.accepts("bogus"), is(false)); // delegates to DefaultEnvironment
+ assertThat(env.accepts(new Object()), is(false)); // delegates to DefaultEnvironment
+ }
+ */
+
+}
diff --git a/org.springframework.core/src/test/java/org/springframework/core/env/DefaultEnvironmentTests.java b/org.springframework.core/src/test/java/org/springframework/core/env/DefaultEnvironmentTests.java
new file mode 100644
index 00000000000..f912291e62e
--- /dev/null
+++ b/org.springframework.core/src/test/java/org/springframework/core/env/DefaultEnvironmentTests.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import static java.lang.String.format;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.hasItem;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import static org.springframework.core.env.AbstractEnvironment.SPRING_PROFILES_PROPERTY_NAME;
+import static org.springframework.core.env.DefaultEnvironmentTests.CollectionMatchers.isEmpty;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.security.AccessControlException;
+import java.security.Permission;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.internal.matchers.TypeSafeMatcher;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
+
+/**
+ * Unit tests for {@link DefaultEnvironment}.
+ *
+ * @author Chris Beams
+ */
+public class DefaultEnvironmentTests {
+
+ private static final String ALLOWED_PROPERTY_NAME = "theanswer";
+ private static final String ALLOWED_PROPERTY_VALUE = "42";
+
+ private static final String DISALLOWED_PROPERTY_NAME = "verboten";
+ private static final String DISALLOWED_PROPERTY_VALUE = "secret";
+
+ private static final String STRING_PROPERTY_NAME = "stringPropName";
+ private static final String STRING_PROPERTY_VALUE = "stringPropValue";
+ private static final Object NON_STRING_PROPERTY_NAME = new Object();
+ private static final Object NON_STRING_PROPERTY_VALUE = new Object();
+
+ private ConfigurableEnvironment environment;
+ private Properties testProperties;
+
+ @Before
+ public void setUp() {
+ environment = new DefaultEnvironment();
+ testProperties = new Properties();
+ environment.addPropertySource("testProperties", testProperties);
+ }
+
+ @Test @SuppressWarnings({ "unchecked", "rawtypes", "serial" })
+ public void getPropertySources_manipulatePropertySourceOrder() {
+ AbstractEnvironment env = new AbstractEnvironment() { };
+ env.addPropertySource("system", new HashMap() {{ put("foo", "systemValue"); }});
+ env.addPropertySource("local", new HashMap() {{ put("foo", "localValue"); }});
+
+ // 'local' was added (pushed) last so has precedence
+ assertThat(env.getProperty("foo"), equalTo("localValue"));
+
+ // put 'system' at the front of the list
+ LinkedList> propertySources = env.getPropertySources();
+ propertySources.push(propertySources.remove(propertySources.indexOf(PropertySource.named("system"))));
+
+ // 'system' now has precedence
+ assertThat(env.getProperty("foo"), equalTo("systemValue"));
+
+ assertThat(propertySources.size(), is(2));
+ }
+
+ @Test @SuppressWarnings({ "unchecked", "rawtypes", "serial" })
+ public void getPropertySources_replacePropertySource() {
+ AbstractEnvironment env = new AbstractEnvironment() { };
+ env.addPropertySource("system", new HashMap() {{ put("foo", "systemValue"); }});
+ env.addPropertySource("local", new HashMap() {{ put("foo", "localValue"); }});
+
+ // 'local' was added (pushed) last so has precedence
+ assertThat(env.getProperty("foo"), equalTo("localValue"));
+
+ // replace 'local' with new property source
+ LinkedList> propertySources = env.getPropertySources();
+ int localIndex = propertySources.indexOf(PropertySource.named("local"));
+ MapPropertySource newSource = new MapPropertySource("new", new HashMap() {{ put("foo", "newValue"); }});
+ propertySources.set(localIndex, newSource);
+
+ // 'system' now has precedence
+ assertThat(env.getProperty("foo"), equalTo("newValue"));
+
+ assertThat(propertySources.size(), is(2));
+ }
+
+ @Test
+ public void getProperty() {
+ assertThat(environment.getProperty("foo"), nullValue());
+ testProperties.put("foo", "bar");
+ assertThat(environment.getProperty("foo"), is("bar"));
+ }
+
+ @Test
+ public void getProperty_withExplicitNullValue() {
+ // java.util.Properties does not allow null values (because Hashtable does not)
+ Map nullableProperties = new HashMap();
+ environment.addPropertySource("nullableProperties", nullableProperties);
+ nullableProperties.put("foo", null);
+ assertThat(environment.getProperty("foo"), nullValue());
+ }
+
+ @Test
+ public void getProperty_withStringArrayConversion() {
+ testProperties.put("foo", "bar,baz");
+ assertThat(environment.getProperty("foo", String[].class), equalTo(new String[] { "bar", "baz" }));
+ }
+
+ @Test
+ public void getProperty_withNonConvertibleTargetType() {
+ testProperties.put("foo", "bar");
+
+ class TestType { }
+
+ try {
+ environment.getProperty("foo", TestType.class);
+ fail("Expected IllegalArgumentException due to non-convertible types");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void getRequiredProperty() {
+ testProperties.put("exists", "xyz");
+ assertThat(environment.getRequiredProperty("exists"), is("xyz"));
+
+ try {
+ environment.getRequiredProperty("bogus");
+ fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void getRequiredProperty_withStringArrayConversion() {
+ testProperties.put("exists", "abc,123");
+ assertThat(environment.getRequiredProperty("exists", String[].class), equalTo(new String[] { "abc", "123" }));
+
+ try {
+ environment.getRequiredProperty("bogus", String[].class);
+ fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ @Test @SuppressWarnings({ "rawtypes", "serial", "unchecked" })
+ public void asProperties() {
+ ConfigurableEnvironment env = new AbstractEnvironment() { };
+ assertThat(env.asProperties(), notNullValue());
+
+ env.addPropertySource("lowestPrecedence", new HashMap() {{ put("common", "lowCommon"); put("lowKey", "lowVal"); }});
+ env.addPropertySource("middlePrecedence", new HashMap() {{ put("common", "midCommon"); put("midKey", "midVal"); }});
+ env.addPropertySource("highestPrecedence", new HashMap() {{ put("common", "highCommon"); put("highKey", "highVal"); }});
+
+ Properties props = env.asProperties();
+ assertThat(props.getProperty("common"), is("highCommon"));
+ assertThat(props.getProperty("lowKey"), is("lowVal"));
+ assertThat(props.getProperty("midKey"), is("midVal"));
+ assertThat(props.getProperty("highKey"), is("highVal"));
+ assertThat(props.size(), is(4));
+ }
+
+ @Test
+ public void activeProfiles() {
+ assertThat(environment.getActiveProfiles(), isEmpty());
+ environment.setActiveProfiles("local", "embedded");
+ Set activeProfiles = environment.getActiveProfiles();
+ assertThat(activeProfiles, hasItems("local", "embedded"));
+ assertThat(activeProfiles.size(), is(2));
+ try {
+ environment.getActiveProfiles().add("bogus");
+ fail("activeProfiles should be unmodifiable");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+ environment.setActiveProfiles("foo");
+ assertThat(activeProfiles, hasItem("foo"));
+ assertThat(environment.getActiveProfiles().size(), is(1));
+ }
+
+ @Test
+ public void systemPropertiesEmpty() {
+ assertThat(environment.getActiveProfiles(), isEmpty());
+
+ System.setProperty(SPRING_PROFILES_PROPERTY_NAME, "");
+ assertThat(environment.getActiveProfiles(), isEmpty());
+
+ System.getProperties().remove(SPRING_PROFILES_PROPERTY_NAME);
+ }
+
+ @Test
+ public void systemPropertiesResoloutionOfProfiles() {
+ assertThat(environment.getActiveProfiles(), isEmpty());
+
+ System.setProperty(SPRING_PROFILES_PROPERTY_NAME, "foo");
+ assertThat(environment.getActiveProfiles(), hasItem("foo"));
+
+ // clean up
+ System.getProperties().remove(SPRING_PROFILES_PROPERTY_NAME);
+ }
+
+ @Test
+ public void systemPropertiesResoloutionOfMultipleProfiles() {
+ assertThat(environment.getActiveProfiles(), isEmpty());
+
+ System.setProperty(SPRING_PROFILES_PROPERTY_NAME, "foo,bar");
+ assertThat(environment.getActiveProfiles(), hasItems("foo", "bar"));
+
+ System.setProperty(SPRING_PROFILES_PROPERTY_NAME, " bar , baz "); // notice whitespace
+ assertThat(environment.getActiveProfiles(), not(hasItems("foo", "bar")));
+ assertThat(environment.getActiveProfiles(), hasItems("bar", "baz"));
+
+ System.getProperties().remove(SPRING_PROFILES_PROPERTY_NAME);
+ }
+
+ /*
+ static class WithNoProfile { }
+ @Profile("test")
+ static class WithTestProfile { }
+
+ @Test
+ public void accepts() throws IOException {
+
+ assertThat(environment.accepts(metadataForClass(WithNoProfile.class)), is(true));
+ assertThat(environment.accepts(metadataForClass(WithTestProfile.class)), is(false));
+ assertThat(environment.accepts("foo,bar"), is(false));
+ assertThat(environment.accepts("test"), is(false));
+ assertThat(environment.accepts("test,foo"), is(false));
+
+ environment.setActiveProfiles("test");
+ assertThat(environment.accepts(metadataForClass(WithNoProfile.class)), is(true));
+ assertThat(environment.accepts(metadataForClass(WithTestProfile.class)), is(true));
+ assertThat(environment.accepts("foo,bar"), is(false));
+ assertThat(environment.accepts("test"), is(true));
+ assertThat(environment.accepts("test,foo"), is(true));
+ }
+ */
+
+ @Test
+ public void systemPropertiesAccess() {
+ System.setProperty(ALLOWED_PROPERTY_NAME, ALLOWED_PROPERTY_VALUE);
+ System.setProperty(DISALLOWED_PROPERTY_NAME, DISALLOWED_PROPERTY_VALUE);
+ System.getProperties().put(STRING_PROPERTY_NAME, NON_STRING_PROPERTY_VALUE);
+ System.getProperties().put(NON_STRING_PROPERTY_NAME, STRING_PROPERTY_VALUE);
+
+ {
+ Map, ?> systemProperties = environment.getSystemProperties();
+ assertThat(systemProperties, notNullValue());
+ assertSame(systemProperties, System.getProperties());
+ assertThat(systemProperties.get(ALLOWED_PROPERTY_NAME), equalTo((Object)ALLOWED_PROPERTY_VALUE));
+ assertThat(systemProperties.get(DISALLOWED_PROPERTY_NAME), equalTo((Object)DISALLOWED_PROPERTY_VALUE));
+
+ // non-string keys and values work fine... until the security manager is introduced below
+ assertThat(systemProperties.get(STRING_PROPERTY_NAME), equalTo(NON_STRING_PROPERTY_VALUE));
+ assertThat(systemProperties.get(NON_STRING_PROPERTY_NAME), equalTo((Object)STRING_PROPERTY_VALUE));
+ }
+
+ SecurityManager oldSecurityManager = System.getSecurityManager();
+ SecurityManager securityManager = new SecurityManager() {
+ @Override
+ public void checkPropertiesAccess() {
+ // see http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getProperties()
+ throw new AccessControlException("Accessing the system properties is disallowed");
+ }
+ @Override
+ public void checkPropertyAccess(String key) {
+ // see http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getProperty(java.lang.String)
+ if (DISALLOWED_PROPERTY_NAME.equals(key)) {
+ throw new AccessControlException(
+ format("Accessing the system property [%s] is disallowed", DISALLOWED_PROPERTY_NAME));
+ }
+ }
+ @Override
+ public void checkPermission(Permission perm) {
+ // allow everything else
+ }
+ };
+ System.setSecurityManager(securityManager);
+
+ {
+ Map, ?> systemProperties = environment.getSystemProperties();
+ assertThat(systemProperties, notNullValue());
+ assertThat(systemProperties, instanceOf(ReadOnlySystemAttributesMap.class));
+ assertThat((String)systemProperties.get(ALLOWED_PROPERTY_NAME), equalTo(ALLOWED_PROPERTY_VALUE));
+ assertThat(systemProperties.get(DISALLOWED_PROPERTY_NAME), equalTo(null));
+
+ // nothing we can do here in terms of warning the user that there was
+ // actually a (non-string) value available. By this point, we only
+ // have access to calling System.getProperty(), which itself returns null
+ // if the value is non-string. So we're stuck with returning a potentially
+ // misleading null.
+ assertThat(systemProperties.get(STRING_PROPERTY_NAME), nullValue());
+
+ // in the case of a non-string *key*, however, we can do better. Alert
+ // the user that under these very special conditions (non-object key +
+ // SecurityManager that disallows access to system properties), they
+ // cannot do what they're attempting.
+ try {
+ systemProperties.get(NON_STRING_PROPERTY_NAME);
+ fail("Expected IllegalStateException when searching with non-string key against ReadOnlySystemAttributesMap");
+ } catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ System.setSecurityManager(oldSecurityManager);
+ System.clearProperty(ALLOWED_PROPERTY_NAME);
+ System.clearProperty(DISALLOWED_PROPERTY_NAME);
+ System.getProperties().remove(STRING_PROPERTY_NAME);
+ System.getProperties().remove(NON_STRING_PROPERTY_NAME);
+ }
+
+ @Test
+ public void systemEnvironmentAccess() throws Exception {
+ getModifiableSystemEnvironment().put(ALLOWED_PROPERTY_NAME, ALLOWED_PROPERTY_VALUE);
+ getModifiableSystemEnvironment().put(DISALLOWED_PROPERTY_NAME, DISALLOWED_PROPERTY_VALUE);
+
+ {
+ Map systemEnvironment = environment.getSystemEnvironment();
+ assertThat(systemEnvironment, notNullValue());
+ assertSame(systemEnvironment, System.getenv());
+ }
+
+ SecurityManager oldSecurityManager = System.getSecurityManager();
+ SecurityManager securityManager = new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm) {
+ //see http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getenv()
+ if ("getenv.*".equals(perm.getName())) {
+ throw new AccessControlException("Accessing the system environment is disallowed");
+ }
+ //see http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getenv(java.lang.String)
+ if (("getenv."+DISALLOWED_PROPERTY_NAME).equals(perm.getName())) {
+ throw new AccessControlException(
+ format("Accessing the system environment variable [%s] is disallowed", DISALLOWED_PROPERTY_NAME));
+ }
+ }
+ };
+ System.setSecurityManager(securityManager);
+
+ {
+ Map systemEnvironment = environment.getSystemEnvironment();
+ assertThat(systemEnvironment, notNullValue());
+ assertThat(systemEnvironment, instanceOf(ReadOnlySystemAttributesMap.class));
+ assertThat(systemEnvironment.get(ALLOWED_PROPERTY_NAME), equalTo(ALLOWED_PROPERTY_VALUE));
+ assertThat(systemEnvironment.get(DISALLOWED_PROPERTY_NAME), nullValue());
+ }
+
+ System.setSecurityManager(oldSecurityManager);
+ getModifiableSystemEnvironment().remove(ALLOWED_PROPERTY_NAME);
+ getModifiableSystemEnvironment().remove(DISALLOWED_PROPERTY_NAME);
+ }
+
+ @Test
+ public void resolvePlaceholders() {
+ AbstractEnvironment env = new AbstractEnvironment() { };
+ Properties testProperties = new Properties();
+ testProperties.setProperty("foo", "bar");
+ env.addPropertySource("testProperties", testProperties);
+ String resolved = env.resolvePlaceholders("pre-${foo}-${unresolvable}-post");
+ assertThat(resolved, is("pre-bar-${unresolvable}-post"));
+ }
+
+ @Test
+ public void resolveRequiredPlaceholders() {
+ AbstractEnvironment env = new AbstractEnvironment() { };
+ Properties testProperties = new Properties();
+ testProperties.setProperty("foo", "bar");
+ env.addPropertySource("testProperties", testProperties);
+ try {
+ env.resolveRequiredPlaceholders("pre-${foo}-${unresolvable}-post");
+ fail("expected exception");
+ } catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(), is("Could not resolve placeholder 'unresolvable'"));
+ }
+ }
+
+ private AnnotationMetadata metadataForClass(Class> clazz) throws IOException {
+ return new SimpleMetadataReaderFactory().getMetadataReader(clazz.getName()).getAnnotationMetadata();
+ }
+
+ public static class CollectionMatchers {
+ public static Matcher> isEmpty() {
+
+ return new TypeSafeMatcher>() {
+
+ @Override
+ public boolean matchesSafely(Collection> collection) {
+ return collection.isEmpty();
+ }
+
+ public void describeTo(Description desc) {
+ desc.appendText("an empty collection");
+ }
+ };
+ }
+ }
+
+ // TODO SPR-7508: duplicated from EnvironmentPropertyResolutionSearchTests
+ @SuppressWarnings("unchecked")
+ private static Map getModifiableSystemEnvironment() throws Exception {
+ Class>[] classes = Collections.class.getDeclaredClasses();
+ Map systemEnv = System.getenv();
+ for (Class> cl : classes) {
+ if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
+ Field field = cl.getDeclaredField("m");
+ field.setAccessible(true);
+ Object obj = field.get(systemEnv);
+ return (Map) obj;
+ }
+ }
+ throw new IllegalStateException();
+ }
+}
diff --git a/org.springframework.core/src/test/java/org/springframework/core/env/EnvironmentPropertyResolutionLateBindingTests.java b/org.springframework.core/src/test/java/org/springframework/core/env/EnvironmentPropertyResolutionLateBindingTests.java
new file mode 100644
index 00000000000..f307415e26a
--- /dev/null
+++ b/org.springframework.core/src/test/java/org/springframework/core/env/EnvironmentPropertyResolutionLateBindingTests.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+
+/**
+ * Test that {@link Environment#getValue} performs late-resolution of property
+ * values i.e., does not eagerly resolve and cache only at construction time.
+ *
+ * @see EnvironmentPropertyResolutionSearchTests
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class EnvironmentPropertyResolutionLateBindingTests {
+ @Test
+ public void replaceExistingKeyPostConstruction() {
+ String key = "foo";
+ String value1 = "bar";
+ String value2 = "biz";
+
+ System.setProperty(key, value1); // before construction
+ DefaultEnvironment env = new DefaultEnvironment();
+ assertThat(env.getProperty(key), equalTo(value1));
+ System.setProperty(key, value2); // after construction and first resolution
+ assertThat(env.getProperty(key), equalTo(value2));
+ System.clearProperty(key); // clean up
+ }
+
+ @Test
+ public void addNewKeyPostConstruction() {
+ DefaultEnvironment env = new DefaultEnvironment();
+ assertThat(env.getProperty("foo"), equalTo(null));
+ System.setProperty("foo", "42");
+ assertThat(env.getProperty("foo"), equalTo("42"));
+ System.clearProperty("foo"); // clean up
+ }
+}
diff --git a/org.springframework.core/src/test/java/org/springframework/core/env/EnvironmentPropertyResolutionSearchTests.java b/org.springframework.core/src/test/java/org/springframework/core/env/EnvironmentPropertyResolutionSearchTests.java
new file mode 100644
index 00000000000..308da06244c
--- /dev/null
+++ b/org.springframework.core/src/test/java/org/springframework/core/env/EnvironmentPropertyResolutionSearchTests.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link DefaultEnvironment} proving that it (a) searches
+ * standard property sources (b) in the correct order.
+ *
+ * @see AbstractEnvironment#getProperty(String)
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class EnvironmentPropertyResolutionSearchTests {
+
+ @Test @SuppressWarnings({ "unchecked", "serial", "rawtypes" })
+ public void propertySourcesHaveLIFOSearchOrder() {
+ ConfigurableEnvironment env = new AbstractEnvironment() { };
+ env.addPropertySource("ps1", new HashMap() {{ put("pName", "ps1Value"); }});
+ assertThat(env.getProperty("pName"), equalTo("ps1Value"));
+ env.addPropertySource("ps2", new HashMap() {{ put("pName", "ps2Value"); }});
+ assertThat(env.getProperty("pName"), equalTo("ps2Value"));
+ env.addPropertySource("ps3", new HashMap() {{ put("pName", "ps3Value"); }});
+ assertThat(env.getProperty("pName"), equalTo("ps3Value"));
+ }
+
+ @Test
+ public void resolveFromDefaultPropertySources() throws Exception {
+ String key = "x";
+ String localPropsValue = "local";
+ String sysPropsValue = "sys";
+ String envVarsValue = "env";
+
+ Map systemEnvironment = getModifiableSystemEnvironment();
+ Properties systemProperties = System.getProperties();
+ Properties localProperties = new Properties();
+
+ DefaultEnvironment env = new DefaultEnvironment();
+ env.addPropertySource("localProperties", localProperties);
+
+ // set all properties
+ systemEnvironment.put(key, envVarsValue);
+ systemProperties.setProperty(key, sysPropsValue);
+ localProperties.setProperty(key, localPropsValue);
+
+ // local properties should have highest resolution precedence
+ assertThat(env.getProperty(key), equalTo(localPropsValue));
+
+ // system properties should be next in line
+ localProperties.remove(key);
+ assertThat(env.getProperty(key), equalTo(sysPropsValue));
+
+ // system environment variables should be final fallback
+ systemProperties.remove(key);
+ assertThat(env.getProperty(key), equalTo(envVarsValue));
+
+ // with no propertysource containing the key in question, should return null
+ systemEnvironment.remove(key);
+ assertThat(env.getProperty(key), equalTo(null));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Map getModifiableSystemEnvironment() throws Exception {
+ Class>[] classes = Collections.class.getDeclaredClasses();
+ Map env = System.getenv();
+ for (Class> cl : classes) {
+ if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
+ Field field = cl.getDeclaredField("m");
+ field.setAccessible(true);
+ Object obj = field.get(env);
+ return (Map) obj;
+ }
+ }
+ throw new IllegalStateException();
+ }
+
+}
diff --git a/org.springframework.core/src/test/java/org/springframework/core/env/PropertySourceTests.java b/org.springframework.core/src/test/java/org/springframework/core/env/PropertySourceTests.java
new file mode 100644
index 00000000000..5877ad4bd9f
--- /dev/null
+++ b/org.springframework.core/src/test/java/org/springframework/core/env/PropertySourceTests.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link AbstractPropertySource} implementations.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class PropertySourceTests {
+ @Test @SuppressWarnings("serial")
+ public void equals() {
+ Map map1 = new HashMap() {{ put("a", "b"); }};
+ Map map2 = new HashMap() {{ put("c", "d"); }};
+ Properties props1 = new Properties() {{ setProperty("a", "b"); }};
+ Properties props2 = new Properties() {{ setProperty("c", "d"); }};
+
+ MapPropertySource mps = new MapPropertySource("mps", map1);
+ assertThat(mps, equalTo(mps));
+
+ assertThat(new MapPropertySource("x", map1).equals(new MapPropertySource("x", map1)), is(true));
+ assertThat(new MapPropertySource("x", map1).equals(new MapPropertySource("x", map2)), is(true));
+ assertThat(new MapPropertySource("x", map1).equals(new PropertiesPropertySource("x", props1)), is(true));
+ assertThat(new MapPropertySource("x", map1).equals(new PropertiesPropertySource("x", props2)), is(true));
+
+ assertThat(new MapPropertySource("x", map1).equals(new Object()), is(false));
+ assertThat(new MapPropertySource("x", map1).equals("x"), is(false));
+ assertThat(new MapPropertySource("x", map1).equals(new MapPropertySource("y", map1)), is(false));
+ assertThat(new MapPropertySource("x", map1).equals(new MapPropertySource("y", map2)), is(false));
+ assertThat(new MapPropertySource("x", map1).equals(new PropertiesPropertySource("y", props1)), is(false));
+ assertThat(new MapPropertySource("x", map1).equals(new PropertiesPropertySource("y", props2)), is(false));
+ }
+
+ @Test @SuppressWarnings("serial")
+ public void collectionsOperations() {
+ Map map1 = new HashMap() {{ put("a", "b"); }};
+ Map map2 = new HashMap() {{ put("c", "d"); }};
+
+ PropertySource> ps1 = new MapPropertySource("ps1", map1);
+ ps1.getSource();
+ LinkedList> propertySources = new LinkedList>();
+ assertThat(propertySources.add(ps1), equalTo(true));
+ assertThat(propertySources.contains(ps1), is(true));
+ assertThat(propertySources.contains(PropertySource.named("ps1")), is(true));
+
+ // TODO SPR-7508: consider disallowing duplicates somehow (in the actual data structure used by environment)
+ PropertySource> ps1replacement = new MapPropertySource("ps1", map2); // notice - different map
+ assertThat(propertySources.add(ps1replacement), is(true)); // true because linkedlist allows duplicates
+ assertThat(propertySources.size(), is(2));
+ assertThat(propertySources.remove(PropertySource.named("ps1")), is(true));
+ assertThat(propertySources.size(), is(1));
+ assertThat(propertySources.remove(PropertySource.named("ps1")), is(true));
+ assertThat(propertySources.size(), is(0));
+
+ PropertySource> ps2 = new MapPropertySource("ps2", map2);
+ propertySources.add(ps1);
+ propertySources.add(ps2);
+ assertThat(propertySources.indexOf(PropertySource.named("ps1")), is(0));
+ assertThat(propertySources.indexOf(PropertySource.named("ps2")), is(1));
+ propertySources.clear();
+ }
+
+ @Test @SuppressWarnings("serial")
+ public void toString_verbosityVariesOnLogLevel() {
+ String name = "props";
+ Map map = new HashMap() {{ put("k1", "v1"); }};
+ MapPropertySource ps = new MapPropertySource(name, map);
+ Logger logger = Logger.getLogger(ps.getClass());
+ Level original = logger.getLevel();
+
+ try {
+ logger.setLevel(Level.DEBUG);
+ assertThat("PropertySource.toString() should render verbose output for log levels <= DEBUG",
+ ps.toString(),
+ equalTo(String.format("%s@%s [name='%s', properties=%s]",
+ ps.getClass().getSimpleName(),
+ System.identityHashCode(ps),
+ name,
+ map)));
+
+ logger.setLevel(Level.INFO);
+ assertThat("PropertySource.toString() should render concise output for log levels >= INFO",
+ ps.toString(),
+ equalTo(String.format("%s [name='%s', propertyCount=%d]",
+ ps.getClass().getSimpleName(),
+ name,
+ map.size())));
+ } finally {
+ logger.setLevel(original);
+ }
+ }
+}
diff --git a/org.springframework.core/src/test/java/org/springframework/core/io/ResourceEditorTests.java b/org.springframework.core/src/test/java/org/springframework/core/io/ResourceEditorTests.java
index 792115e643e..6558875c1fd 100644
--- a/org.springframework.core/src/test/java/org/springframework/core/io/ResourceEditorTests.java
+++ b/org.springframework.core/src/test/java/org/springframework/core/io/ResourceEditorTests.java
@@ -20,6 +20,7 @@ import java.beans.PropertyEditor;
import static org.junit.Assert.*;
import org.junit.Test;
+import org.springframework.core.env.DefaultEnvironment;
/**
* Unit tests for the {@link ResourceEditor} class.
@@ -40,8 +41,8 @@ public final class ResourceEditorTests {
}
@Test(expected = IllegalArgumentException.class)
- public void ctorWithNullResourceLoader() throws Exception {
- new ResourceEditor(null);
+ public void ctorWithNullCtorArgs() throws Exception {
+ new ResourceEditor(null, null);
}
@Test
@@ -74,7 +75,7 @@ public final class ResourceEditorTests {
@Test(expected=IllegalArgumentException.class)
public void testStrictSystemPropertyReplacement() {
- PropertyEditor editor = new ResourceEditor(new DefaultResourceLoader(), false);
+ PropertyEditor editor = new ResourceEditor(new DefaultResourceLoader(), new DefaultEnvironment(), false);
System.setProperty("test.prop", "foo");
try {
editor.setAsText("${test.prop}-${bar}");
diff --git a/org.springframework.expression/pom.xml b/org.springframework.expression/pom.xml
index be9165cdd69..1ac99341d02 100644
--- a/org.springframework.expression/pom.xml
+++ b/org.springframework.expression/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-expression
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.instrument.tomcat/.settings/org.eclipse.jdt.core.prefs b/org.springframework.instrument.tomcat/.settings/org.eclipse.jdt.core.prefs
index a15f738edcd..4655eeb423f 100644
--- a/org.springframework.instrument.tomcat/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.instrument.tomcat/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:30 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.instrument.tomcat/pom.xml b/org.springframework.instrument.tomcat/pom.xml
index f4425b63fb5..bf94631dfbc 100644
--- a/org.springframework.instrument.tomcat/pom.xml
+++ b/org.springframework.instrument.tomcat/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-instrument-tomcat
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.instrument/.settings/org.eclipse.jdt.core.prefs b/org.springframework.instrument/.settings/org.eclipse.jdt.core.prefs
index 0e29d554498..7a583ba283d 100644
--- a/org.springframework.instrument/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.instrument/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.instrument/pom.xml b/org.springframework.instrument/pom.xml
index 0431aa599dc..c7b4d47fe8c 100644
--- a/org.springframework.instrument/pom.xml
+++ b/org.springframework.instrument/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-instrument
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.integration-tests/.classpath b/org.springframework.integration-tests/.classpath
index 9be354aa269..23691001718 100644
--- a/org.springframework.integration-tests/.classpath
+++ b/org.springframework.integration-tests/.classpath
@@ -84,6 +84,7 @@
+
diff --git a/org.springframework.integration-tests/.project b/org.springframework.integration-tests/.project
index e09fe3e7d83..d10e4a930f7 100644
--- a/org.springframework.integration-tests/.project
+++ b/org.springframework.integration-tests/.project
@@ -10,8 +10,14 @@
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+ org.springframework.ide.eclipse.core.springnature
org.eclipse.jdt.core.javanature
diff --git a/org.springframework.integration-tests/.settings/org.eclipse.jdt.core.prefs b/org.springframework.integration-tests/.settings/org.eclipse.jdt.core.prefs
index a15f738edcd..4655eeb423f 100644
--- a/org.springframework.integration-tests/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.integration-tests/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:30 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.integration-tests/integration-tests.iml b/org.springframework.integration-tests/integration-tests.iml
index d615db5f0e9..13421323256 100644
--- a/org.springframework.integration-tests/integration-tests.iml
+++ b/org.springframework.integration-tests/integration-tests.iml
@@ -28,6 +28,7 @@
+
diff --git a/org.springframework.integration-tests/ivy.xml b/org.springframework.integration-tests/ivy.xml
index fc5be79b019..28be250ce21 100644
--- a/org.springframework.integration-tests/ivy.xml
+++ b/org.springframework.integration-tests/ivy.xml
@@ -95,6 +95,7 @@
+
diff --git a/org.springframework.integration-tests/pom.xml b/org.springframework.integration-tests/pom.xml
index 007f340aa30..9e6dc336182 100644
--- a/org.springframework.integration-tests/pom.xml
+++ b/org.springframework.integration-tests/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-integration-tests
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.integration-tests/src/main/java/.gitignore b/org.springframework.integration-tests/src/main/java/.gitignore
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/org.springframework.integration-tests/src/test/java/.gitignore b/org.springframework.integration-tests/src/test/java/.gitignore
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-dev.xml b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-dev.xml
new file mode 100644
index 00000000000..45c18434e72
--- /dev/null
+++ b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-dev.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-prod.xml b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-prod.xml
new file mode 100644
index 00000000000..472a09aed76
--- /dev/null
+++ b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-prod.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context.xml b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context.xml
new file mode 100644
index 00000000000..1ebf65c89a4
--- /dev/null
+++ b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests.java b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests.java
new file mode 100644
index 00000000000..5c3332ed2ad
--- /dev/null
+++ b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/EnvironmentIntegrationTests.java
@@ -0,0 +1,712 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isIn;
+import static org.hamcrest.Matchers.lessThan;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
+import static org.springframework.context.ConfigurableApplicationContext.ENVIRONMENT_BEAN_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DERIVED_DEV_BEAN_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DERIVED_DEV_ENV_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_BEAN_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_ENV_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.ENVIRONMENT_AWARE_BEAN_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_BEAN_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_ENV_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.TRANSITIVE_BEAN_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.XML_PATH;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.Properties;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Profile;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.context.support.GenericXmlApplicationContext;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jca.context.ResourceAdapterApplicationContext;
+import org.springframework.jca.support.SimpleBootstrapContext;
+import org.springframework.jca.work.SimpleTaskWorkManager;
+import org.springframework.mock.web.MockServletConfig;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.AbstractRefreshableWebApplicationContext;
+import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
+import org.springframework.web.context.support.GenericWebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+import org.springframework.web.portlet.context.AbstractRefreshablePortletApplicationContext;
+import org.springframework.web.portlet.context.StaticPortletApplicationContext;
+import org.springframework.web.portlet.context.XmlPortletApplicationContext;
+
+
+/**
+ * Integration tests for container support of {@link Environment}
+ * interface.
+ *
+ * Tests all existing BeanFactory and ApplicationContext implementations to
+ * ensure that:
+ * - a default environment object is always present
+ * - a custom environment object can be set and retrieved against the factory/context
+ * - the {@link EnvironmentAware} interface is respected
+ * - the environment object is registered with the container as a singleton
+ * bean (if an ApplicationContext)
+ * - bean definition files (if any, and whether XML or @Configuration) are
+ * registered conditionally based on environment metadata
+ *
+ * @author Chris Beams
+ */
+public class EnvironmentIntegrationTests {
+
+ private ConfigurableEnvironment prodEnv;
+ private ConfigurableEnvironment devEnv;
+
+ /**
+ * Constants used both locally and in scan* sub-packages
+ */
+ public static class Constants {
+ public static final String XML_PATH = "org/springframework/core/env/EnvironmentIntegrationTests-context.xml";
+
+ public static final String ENVIRONMENT_AWARE_BEAN_NAME = "envAwareBean";
+
+ public static final String PROD_BEAN_NAME = "prodBean";
+ public static final String DEV_BEAN_NAME = "devBean";
+ public static final String DERIVED_DEV_BEAN_NAME = "derivedDevBean";
+ public static final String TRANSITIVE_BEAN_NAME = "transitiveBean";
+
+ public static final String PROD_ENV_NAME = "prod";
+ public static final String DEV_ENV_NAME = "dev";
+ public static final String DERIVED_DEV_ENV_NAME = "derivedDev";
+ }
+
+ @Before
+ public void setUp() {
+ prodEnv = new DefaultEnvironment();
+ prodEnv.setActiveProfiles(PROD_ENV_NAME);
+
+ devEnv = new DefaultEnvironment();
+ devEnv.setActiveProfiles(DEV_ENV_NAME);
+ }
+
+ @Test
+ public void genericApplicationContext_defaultEnv() {
+ ConfigurableApplicationContext ctx =
+ new GenericApplicationContext(newBeanFactoryWithEnvironmentAwareBean());
+
+ ctx.refresh();
+
+ assertHasDefaultEnvironment(ctx);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, ctx.getEnvironment());
+ }
+
+ @Test
+ public void genericApplicationContext_customEnv() {
+ GenericApplicationContext ctx =
+ new GenericApplicationContext(newBeanFactoryWithEnvironmentAwareBean());
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ }
+
+ @Test
+ public void xmlBeanDefinitionReader_inheritsEnvironmentFromEnvironmentCapableBDR() {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.setEnvironment(prodEnv);
+ new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(XML_PATH);
+ ctx.refresh();
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void annotatedBeanDefinitionReader_inheritsEnvironmentFromEnvironmentCapableBDR() {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.setEnvironment(prodEnv);
+ new AnnotatedBeanDefinitionReader(ctx).register(Config.class);
+ ctx.refresh();
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void classPathBeanDefinitionScanner_inheritsEnvironmentFromEnvironmentCapableBDR_scanProfileAnnotatedConfigClasses() {
+ // it's actually ConfigurationClassPostProcessor's Environment that gets the job done here.
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.setEnvironment(prodEnv);
+ ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(ctx);
+ scanner.scan("org.springframework.core.env.scan1");
+ ctx.refresh();
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void classPathBeanDefinitionScanner_inheritsEnvironmentFromEnvironmentCapableBDR_scanProfileAnnotatedComponents() {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.setEnvironment(prodEnv);
+ ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(ctx);
+ scanner.scan("org.springframework.core.env.scan2");
+ ctx.refresh();
+ assertThat(scanner.getEnvironment(), is((Environment)ctx.getEnvironment()));
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void genericXmlApplicationContext() {
+ GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
+
+ assertHasDefaultEnvironment(ctx);
+
+ ctx.setEnvironment(prodEnv);
+
+ ctx.load(XML_PATH);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void classPathXmlApplicationContext() {
+ ConfigurableApplicationContext ctx =
+ new ClassPathXmlApplicationContext(new String[] { XML_PATH });
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+
+ assertEnvironmentBeanRegistered(ctx);
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentAwareInvoked(ctx, ctx.getEnvironment());
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void fileSystemXmlApplicationContext() throws IOException {
+ ClassPathResource xml = new ClassPathResource(XML_PATH);
+ File tmpFile = File.createTempFile("test", "xml");
+ FileCopyUtils.copy(xml.getFile(), tmpFile);
+
+ // strange - FSXAC strips leading '/' unless prefixed with 'file:'
+ ConfigurableApplicationContext ctx =
+ new FileSystemXmlApplicationContext(new String[] { "file:"+tmpFile.getPath() }, false);
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+ assertEnvironmentBeanRegistered(ctx);
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentAwareInvoked(ctx, ctx.getEnvironment());
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void annotationConfigApplicationContext_withPojos() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+
+ assertHasDefaultEnvironment(ctx);
+ ctx.setEnvironment(prodEnv);
+
+ ctx.register(EnvironmentAwareBean.class);
+ ctx.refresh();
+
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ }
+
+ @Test
+ public void annotationConfigApplicationContext_withProdEnvAndProdConfigClass() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+
+ assertHasDefaultEnvironment(ctx);
+ ctx.setEnvironment(prodEnv);
+
+ ctx.register(ProdConfig.class);
+ ctx.refresh();
+
+ assertThat("should have prod bean", ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void annotationConfigApplicationContext_withProdEnvAndDevConfigClass() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+
+ assertHasDefaultEnvironment(ctx);
+ ctx.setEnvironment(prodEnv);
+
+ ctx.register(DevConfig.class);
+ ctx.refresh();
+
+ assertThat("should not have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat("should not have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(false));
+ }
+
+ @Test
+ public void annotationConfigApplicationContext_withDevEnvAndDevConfigClass() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+
+ assertHasDefaultEnvironment(ctx);
+ ctx.setEnvironment(devEnv);
+
+ ctx.register(DevConfig.class);
+ ctx.refresh();
+
+ assertThat("should have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(true));
+ assertThat("should have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void annotationConfigApplicationContext_withImportedConfigClasses() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+
+ assertHasDefaultEnvironment(ctx);
+ ctx.setEnvironment(prodEnv);
+
+ ctx.register(Config.class);
+ ctx.refresh();
+
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ assertThat("should have prod bean", ctx.containsBean(PROD_BEAN_NAME), is(true));
+ assertThat("should not have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat("should not have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(false));
+ }
+
+ @Test
+ public void mostSpecificDerivedClassDrivesEnvironment_withDerivedDevEnvAndDerivedDevConfigClass() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ DefaultEnvironment derivedDevEnv = new DefaultEnvironment();
+ derivedDevEnv.setActiveProfiles(DERIVED_DEV_ENV_NAME);
+ ctx.setEnvironment(derivedDevEnv);
+ ctx.register(DerivedDevConfig.class);
+ ctx.refresh();
+
+ assertThat("should have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(true));
+ assertThat("should have derived dev bean", ctx.containsBean(DERIVED_DEV_BEAN_NAME), is(true));
+ assertThat("should have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void mostSpecificDerivedClassDrivesEnvironment_withDevEnvAndDerivedDevConfigClass() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.setEnvironment(devEnv);
+ ctx.register(DerivedDevConfig.class);
+ ctx.refresh();
+
+ assertThat("should not have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat("should not have derived dev bean", ctx.containsBean(DERIVED_DEV_BEAN_NAME), is(false));
+ assertThat("should not have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(false));
+ }
+
+ @Test
+ public void webApplicationContext() {
+ GenericWebApplicationContext ctx =
+ new GenericWebApplicationContext(newBeanFactoryWithEnvironmentAwareBean());
+
+ assertHasDefaultWebEnvironment(ctx);
+
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ }
+
+ // TODO SPR-7508: need to think about how a custom environment / custom property sources
+ // would be specified in an actual webapp using XmlWebApplicationContext. What do the
+ // context params look like, etc.
+ @Test
+ public void xmlWebApplicationContext() {
+ AbstractRefreshableWebApplicationContext ctx = new XmlWebApplicationContext();
+ ctx.setConfigLocation("classpath:" + XML_PATH);
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+ @Test
+ public void staticApplicationContext() {
+ StaticApplicationContext ctx = new StaticApplicationContext();
+
+ assertHasDefaultEnvironment(ctx);
+
+ registerEnvironmentBeanDefinition(ctx);
+
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ }
+
+ @Test
+ public void staticWebApplicationContext() {
+ StaticWebApplicationContext ctx = new StaticWebApplicationContext();
+
+ assertHasDefaultWebEnvironment(ctx);
+
+ registerEnvironmentBeanDefinition(ctx);
+
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ }
+
+ @Test
+ public void annotationConfigWebApplicationContext() {
+ AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
+ ctx.setEnvironment(prodEnv);
+ ctx.setConfigLocation(EnvironmentAwareBean.class.getName());
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ }
+
+ @Test
+ public void registerServletParamPropertySources_AbstractRefreshableWebApplicationContext() {
+ MockServletContext servletContext = new MockServletContext();
+ servletContext.addInitParameter("pCommon", "pCommonContextValue");
+ servletContext.addInitParameter("pContext1", "pContext1Value");
+
+ MockServletConfig servletConfig = new MockServletConfig(servletContext);
+ servletConfig.addInitParameter("pCommon", "pCommonConfigValue");
+ servletConfig.addInitParameter("pConfig1", "pConfig1Value");
+
+ AbstractRefreshableWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
+ ctx.setConfigLocation(EnvironmentAwareBean.class.getName());
+ ctx.setServletConfig(servletConfig);
+ ctx.refresh();
+
+ ConfigurableEnvironment environment = ctx.getEnvironment();
+ assertThat(environment, instanceOf(DefaultWebEnvironment.class));
+ LinkedList> propertySources = environment.getPropertySources();
+ assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
+ assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
+
+ // ServletConfig gets precedence
+ assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
+ assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME)),
+ lessThan(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME))));
+
+ // but all params are available
+ assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
+ assertThat(environment.getProperty("pConfig1"), is("pConfig1Value"));
+
+ // Servlet* PropertySources have precedence over System* PropertySources
+ assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME)),
+ lessThan(propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
+
+ // Replace system properties with a mock property source for convenience
+ MockPropertySource mockSystemProperties = new MockPropertySource(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
+ mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
+ mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
+ propertySources.set(
+ propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)),
+ mockSystemProperties);
+
+ // assert that servletconfig init params resolve with higher precedence than sysprops
+ assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
+ assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
+ }
+
+ @Test
+ public void registerServletParamPropertySources_GenericWebApplicationContext() {
+ MockServletContext servletContext = new MockServletContext();
+ servletContext.addInitParameter("pCommon", "pCommonContextValue");
+ servletContext.addInitParameter("pContext1", "pContext1Value");
+
+ GenericWebApplicationContext ctx = new GenericWebApplicationContext();
+ ctx.setServletContext(servletContext);
+ ctx.refresh();
+
+ ConfigurableEnvironment environment = ctx.getEnvironment();
+ assertThat(environment, instanceOf(DefaultWebEnvironment.class));
+ LinkedList> propertySources = environment.getPropertySources();
+ assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
+ assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME), not(isIn(propertySources)));
+
+ // ServletContext params are available
+ assertThat(environment.getProperty("pCommon"), is("pCommonContextValue"));
+ assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
+
+ // Servlet* PropertySources have precedence over System* PropertySources
+ assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME)),
+ lessThan(propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
+
+ // Replace system properties with a mock property source for convenience
+ MockPropertySource mockSystemProperties = new MockPropertySource(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
+ mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
+ mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
+ propertySources.set(
+ propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)),
+ mockSystemProperties);
+
+ // assert that servletcontext init params resolve with higher precedence than sysprops
+ assertThat(environment.getProperty("pCommon"), is("pCommonContextValue"));
+ assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
+ }
+
+ @Test
+ public void registerServletParamPropertySources_StaticWebApplicationContext() {
+ MockServletContext servletContext = new MockServletContext();
+ servletContext.addInitParameter("pCommon", "pCommonContextValue");
+ servletContext.addInitParameter("pContext1", "pContext1Value");
+
+ MockServletConfig servletConfig = new MockServletConfig(servletContext);
+ servletConfig.addInitParameter("pCommon", "pCommonConfigValue");
+ servletConfig.addInitParameter("pConfig1", "pConfig1Value");
+
+ StaticWebApplicationContext ctx = new StaticWebApplicationContext();
+ ctx.setServletConfig(servletConfig);
+ ctx.refresh();
+
+ ConfigurableEnvironment environment = ctx.getEnvironment();
+ LinkedList> propertySources = environment.getPropertySources();
+ assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
+ assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
+
+ // ServletConfig gets precedence
+ assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
+ assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME)),
+ lessThan(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME))));
+
+ // but all params are available
+ assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
+ assertThat(environment.getProperty("pConfig1"), is("pConfig1Value"));
+
+ // Servlet* PropertySources have precedence over System* PropertySources
+ assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME)),
+ lessThan(propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
+
+ // Replace system properties with a mock property source for convenience
+ MockPropertySource mockSystemProperties = new MockPropertySource(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
+ mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
+ mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
+ propertySources.set(
+ propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)),
+ mockSystemProperties);
+
+ // assert that servletconfig init params resolve with higher precedence than sysprops
+ assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
+ assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
+ }
+
+ static class MockPropertySource extends PropertiesPropertySource {
+ public MockPropertySource() {
+ this("MockPropertySource");
+ }
+
+ public MockPropertySource(String name) {
+ super(name, new Properties());
+ }
+
+ public void setProperty(String key, String value) {
+ this.source.setProperty(key, value);
+ }
+ }
+
+ @Test
+ public void resourceAdapterApplicationContext() {
+ ResourceAdapterApplicationContext ctx = new ResourceAdapterApplicationContext(new SimpleBootstrapContext(new SimpleTaskWorkManager()));
+
+ // TODO SPR-7508: should be a JCA-specific environment?
+ assertHasDefaultEnvironment(ctx);
+
+ registerEnvironmentBeanDefinition(ctx);
+
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ }
+
+ @Test
+ public void staticPortletApplicationContext() {
+ StaticPortletApplicationContext ctx = new StaticPortletApplicationContext();
+
+ // TODO SPR-7508: should be a Portlet-specific environment?
+ assertHasDefaultWebEnvironment(ctx);
+
+ registerEnvironmentBeanDefinition(ctx);
+
+ ctx.setEnvironment(prodEnv);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ }
+
+ @Test
+ public void xmlPortletApplicationContext() {
+ AbstractRefreshablePortletApplicationContext ctx = new XmlPortletApplicationContext();
+ ctx.setEnvironment(prodEnv);
+ ctx.setConfigLocation("classpath:" + XML_PATH);
+ ctx.refresh();
+
+ assertHasEnvironment(ctx, prodEnv);
+ assertEnvironmentBeanRegistered(ctx);
+ assertEnvironmentAwareInvoked(ctx, prodEnv);
+ assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
+ assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
+ }
+
+
+ private DefaultListableBeanFactory newBeanFactoryWithEnvironmentAwareBean() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ registerEnvironmentBeanDefinition(bf);
+ return bf;
+ }
+
+ private void registerEnvironmentBeanDefinition(BeanDefinitionRegistry registry) {
+ registry.registerBeanDefinition(ENVIRONMENT_AWARE_BEAN_NAME,
+ rootBeanDefinition(EnvironmentAwareBean.class).getBeanDefinition());
+ }
+
+ private void assertEnvironmentBeanRegistered(
+ ConfigurableApplicationContext ctx) {
+ // ensure environment is registered as a bean
+ assertThat(ctx.containsBean(ENVIRONMENT_BEAN_NAME), is(true));
+ }
+
+ private void assertHasDefaultEnvironment(ApplicationContext ctx) {
+ Environment defaultEnv = ctx.getEnvironment();
+ assertThat(defaultEnv, notNullValue());
+ assertThat(defaultEnv, instanceOf(DefaultEnvironment.class));
+ }
+
+ private void assertHasDefaultWebEnvironment(WebApplicationContext ctx) {
+ // ensure a default web environment exists
+ Environment defaultEnv = ctx.getEnvironment();
+ assertThat(defaultEnv, notNullValue());
+ assertThat(defaultEnv, instanceOf(DefaultWebEnvironment.class));
+ }
+
+ private void assertHasEnvironment(ApplicationContext ctx, Environment expectedEnv) {
+ // ensure the custom environment took
+ Environment actualEnv = ctx.getEnvironment();
+ assertThat(actualEnv, notNullValue());
+ assertThat(actualEnv, is(expectedEnv));
+ // ensure environment is registered as a bean
+ assertThat(ctx.containsBean(ENVIRONMENT_BEAN_NAME), is(true));
+ }
+
+ private void assertEnvironmentAwareInvoked(ConfigurableApplicationContext ctx, Environment expectedEnv) {
+ assertThat(ctx.getBean(EnvironmentAwareBean.class).environment, is(expectedEnv));
+ }
+
+ private static class EnvironmentAwareBean implements EnvironmentAware {
+
+ public Environment environment;
+
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
+ }
+
+ /**
+ * Mirrors the structure of beans and environment-specific config files
+ * in EnvironmentIntegrationTests-context.xml
+ */
+ @Configuration
+ @Import({DevConfig.class, ProdConfig.class})
+ static class Config {
+ @Bean
+ public EnvironmentAwareBean envAwareBean() {
+ return new EnvironmentAwareBean();
+ }
+ }
+
+ @Profile(DEV_ENV_NAME)
+ @Configuration
+ @Import(TransitiveConfig.class)
+ static class DevConfig {
+ @Bean
+ public Object devBean() {
+ return new Object();
+ }
+ }
+
+ @Profile(PROD_ENV_NAME)
+ @Configuration
+ static class ProdConfig {
+ @Bean
+ public Object prodBean() {
+ return new Object();
+ }
+ }
+
+ @Configuration
+ static class TransitiveConfig {
+ @Bean
+ public Object transitiveBean() {
+ return new Object();
+ }
+ }
+
+ @Profile(DERIVED_DEV_ENV_NAME)
+ @Configuration
+ static class DerivedDevConfig extends DevConfig {
+ @Bean
+ public Object derivedDevBean() {
+ return new Object();
+ }
+ }
+}
diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/core/env/scan1/package-info.java b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/scan1/package-info.java
new file mode 100644
index 00000000000..d2a554752a9
--- /dev/null
+++ b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/scan1/package-info.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2010 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.
+ */
+
+/**
+ * Mirrors the structure of beans and environment-specific config files
+ * in EnvironmentIntegrationTests-context.xml
+ */
+package org.springframework.core.env.scan1;
+
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_ENV_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_ENV_NAME;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Import({DevConfig.class, ProdConfig.class})
+class Config {
+}
+
+@Profile(DEV_ENV_NAME)
+@Configuration
+class DevConfig {
+ @Bean
+ public Object devBean() {
+ return new Object();
+ }
+}
+
+@Profile(PROD_ENV_NAME)
+@Configuration
+class ProdConfig {
+ @Bean
+ public Object prodBean() {
+ return new Object();
+ }
+}
diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/core/env/scan2/package-info.java b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/scan2/package-info.java
new file mode 100644
index 00000000000..be66aa076a1
--- /dev/null
+++ b/org.springframework.integration-tests/src/test/java/org/springframework/core/env/scan2/package-info.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2010 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.
+ */
+
+/**
+ * Mirrors the structure of beans and environment-specific config files
+ * in EnvironmentIntegrationTests-context.xml
+ */
+package org.springframework.core.env.scan2;
+
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_BEAN_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_ENV_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_BEAN_NAME;
+import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_ENV_NAME;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+@Profile(DEV_ENV_NAME)
+@Component(DEV_BEAN_NAME)
+class DevBean { }
+
+@Profile(PROD_ENV_NAME)
+@Component(PROD_BEAN_NAME)
+class ProdBean { }
diff --git a/org.springframework.integration-tests/src/test/resources/log4j.xml b/org.springframework.integration-tests/src/test/resources/log4j.xml
index 767b96d6206..f8aeb053a52 100644
--- a/org.springframework.integration-tests/src/test/resources/log4j.xml
+++ b/org.springframework.integration-tests/src/test/resources/log4j.xml
@@ -15,6 +15,10 @@
+
+
+
+
@@ -25,4 +29,4 @@
-
\ No newline at end of file
+
diff --git a/org.springframework.jdbc/.settings/org.eclipse.jdt.core.prefs b/org.springframework.jdbc/.settings/org.eclipse.jdt.core.prefs
index 5a5d4fe0932..51fbd353764 100644
--- a/org.springframework.jdbc/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.jdbc/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.jdbc/pom.xml b/org.springframework.jdbc/pom.xml
index b658fd195ce..d27a822aa82 100644
--- a/org.springframework.jdbc/pom.xml
+++ b/org.springframework.jdbc/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-jdbc
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java
index 4b984e7f577..30f7a55dc8b 100644
--- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java
+++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java
@@ -103,6 +103,7 @@ public class SQLErrorCodesFactory {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
lbf.setBeanClassLoader(getClass().getClassLoader());
XmlBeanDefinitionReader bdr = new XmlBeanDefinitionReader(lbf);
+ // TODO: SPR-7508 consider setEnvironment() here
// Load default SQL error codes.
Resource resource = loadResource(SQL_ERROR_CODE_DEFAULT_PATH);
diff --git a/org.springframework.jdbc/src/main/resources/META-INF/spring.schemas b/org.springframework.jdbc/src/main/resources/META-INF/spring.schemas
index 0b9d1bae079..5db9fd4b2b4 100644
--- a/org.springframework.jdbc/src/main/resources/META-INF/spring.schemas
+++ b/org.springframework.jdbc/src/main/resources/META-INF/spring.schemas
@@ -1,2 +1,3 @@
http\://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd=org/springframework/jdbc/config/spring-jdbc-3.0.xsd
-http\://www.springframework.org/schema/jdbc/spring-jdbc.xsd=org/springframework/jdbc/config/spring-jdbc-3.0.xsd
\ No newline at end of file
+http\://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd=org/springframework/jdbc/config/spring-jdbc-3.1.xsd
+http\://www.springframework.org/schema/jdbc/spring-jdbc.xsd=org/springframework/jdbc/config/spring-jdbc-3.1.xsd
diff --git a/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.1.xsd b/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.1.xsd
new file mode 100644
index 00000000000..269e08a8a12
--- /dev/null
+++ b/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.1.xsd
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ elements.
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Is this bean "enabled", meaning the scripts will be executed?
+ Defaults to true, but can be used to switch on and off the initialization depending on the environment.
+
+
+
+
+
+
+ Should failed SQL statements be ignored during initialization?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.jms/.settings/org.eclipse.jdt.core.prefs b/org.springframework.jms/.settings/org.eclipse.jdt.core.prefs
index 75d5c65c971..792acc823a3 100644
--- a/org.springframework.jms/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.jms/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:30 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=do not generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.jms/pom.xml b/org.springframework.jms/pom.xml
index 073b6e79f52..7bbc1d7bca2 100644
--- a/org.springframework.jms/pom.xml
+++ b/org.springframework.jms/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-jms
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.jms/src/main/resources/META-INF/spring.schemas b/org.springframework.jms/src/main/resources/META-INF/spring.schemas
index cee622f1872..64d6c75c6ff 100644
--- a/org.springframework.jms/src/main/resources/META-INF/spring.schemas
+++ b/org.springframework.jms/src/main/resources/META-INF/spring.schemas
@@ -1,3 +1,4 @@
http\://www.springframework.org/schema/jms/spring-jms-2.5.xsd=org/springframework/jms/config/spring-jms-2.5.xsd
http\://www.springframework.org/schema/jms/spring-jms-3.0.xsd=org/springframework/jms/config/spring-jms-3.0.xsd
-http\://www.springframework.org/schema/jms/spring-jms.xsd=org/springframework/jms/config/spring-jms-3.0.xsd
+http\://www.springframework.org/schema/jms/spring-jms-3.1.xsd=org/springframework/jms/config/spring-jms-3.1.xsd
+http\://www.springframework.org/schema/jms/spring-jms.xsd=org/springframework/jms/config/spring-jms-3.1.xsd
diff --git a/org.springframework.jms/src/main/resources/org/springframework/jms/config/spring-jms-3.1.xsd b/org.springframework.jms/src/main/resources/org/springframework/jms/config/spring-jms-3.1.xsd
new file mode 100644
index 00000000000..b4cfb626ed3
--- /dev/null
+++ b/org.springframework.jms/src/main/resources/org/springframework/jms/config/spring-jms-3.1.xsd
@@ -0,0 +1,472 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.orm/.settings/org.eclipse.jdt.core.prefs b/org.springframework.orm/.settings/org.eclipse.jdt.core.prefs
index 0e29d554498..7a583ba283d 100644
--- a/org.springframework.orm/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.orm/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.orm/pom.xml b/org.springframework.orm/pom.xml
index 3c7375b7e98..542321ea173 100644
--- a/org.springframework.orm/pom.xml
+++ b/org.springframework.orm/pom.xml
@@ -6,12 +6,12 @@
org.springframework
spring-orm
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.oxm/pom.xml b/org.springframework.oxm/pom.xml
index 8131e2ea157..701b405249b 100644
--- a/org.springframework.oxm/pom.xml
+++ b/org.springframework.oxm/pom.xml
@@ -6,12 +6,12 @@
org.springframework
spring-oxm
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.oxm/src/main/resources/META-INF/spring.schemas b/org.springframework.oxm/src/main/resources/META-INF/spring.schemas
index ea48a6fa429..e746146264a 100644
--- a/org.springframework.oxm/src/main/resources/META-INF/spring.schemas
+++ b/org.springframework.oxm/src/main/resources/META-INF/spring.schemas
@@ -1,2 +1,3 @@
http\://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd=org/springframework/oxm/config/spring-oxm-3.0.xsd
-http\://www.springframework.org/schema/oxm/spring-oxm.xsd=org/springframework/oxm/config/spring-oxm-3.0.xsd
\ No newline at end of file
+http\://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd=org/springframework/oxm/config/spring-oxm-3.1.xsd
+http\://www.springframework.org/schema/oxm/spring-oxm.xsd=org/springframework/oxm/config/spring-oxm-3.1.xsd
diff --git a/org.springframework.oxm/src/main/resources/org/springframework/oxm/config/spring-oxm-3.1.xsd b/org.springframework.oxm/src/main/resources/org/springframework/oxm/config/spring-oxm-3.1.xsd
new file mode 100644
index 00000000000..67325c70b90
--- /dev/null
+++ b/org.springframework.oxm/src/main/resources/org/springframework/oxm/config/spring-oxm-3.1.xsd
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+ Defines the elements used in Spring's Object/XML Mapping integration.
+
+
+
+
+
+
+
+ Defines a JAXB2 Marshaller.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The JAXB Context path
+
+
+
+
+
+
+
+
+
+
+
+ Defines a JiBX Marshaller.
+
+
+
+
+
+
+
+
+
+
+
+
+ The binding name used by this marshaller.
+
+
+
+
+
+
+
+
+
+
+
+ Defines a XMLBeans Marshaller.
+
+
+
+
+
+
+
+
+
+
+
+
+ The bean name of the XmlOptions that is to be used for this marshaller. Typically a
+ XmlOptionsFactoryBean definition.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A class supported by a marshaller.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.spring-library/pom.xml b/org.springframework.spring-library/pom.xml
index 5e9b592fe33..37e9857c3fa 100644
--- a/org.springframework.spring-library/pom.xml
+++ b/org.springframework.spring-library/pom.xml
@@ -14,7 +14,7 @@
org.springframework
spring-library
libd
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
Spring Framework
Spring is a layered Java/J2EE application platform, based on code published in Expert
One-on-One J2EE Design and Development by Rod Johnson (Wrox, 2002).
diff --git a/org.springframework.spring-parent/pom.xml b/org.springframework.spring-parent/pom.xml
index 9d38c6e85d6..f407bc490fa 100644
--- a/org.springframework.spring-parent/pom.xml
+++ b/org.springframework.spring-parent/pom.xml
@@ -14,7 +14,7 @@
spring-parent
pom
Spring Framework - Parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
Spring Framework Parent
https://fisheye.springframework.org/browse/spring-framework
diff --git a/org.springframework.test/.settings/org.eclipse.jdt.core.prefs b/org.springframework.test/.settings/org.eclipse.jdt.core.prefs
index b96e8d13cd6..1cbe5a3ebee 100644
--- a/org.springframework.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=20
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.test/pom.xml b/org.springframework.test/pom.xml
index d933ee82d81..79787997adf 100644
--- a/org.springframework.test/pom.xml
+++ b/org.springframework.test/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-test
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.transaction/.settings/org.eclipse.jdt.core.prefs b/org.springframework.transaction/.settings/org.eclipse.jdt.core.prefs
index 0e29d554498..7a583ba283d 100644
--- a/org.springframework.transaction/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.transaction/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.transaction/pom.xml b/org.springframework.transaction/pom.xml
index ac19a8335f5..9fed17f6faa 100644
--- a/org.springframework.transaction/pom.xml
+++ b/org.springframework.transaction/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-tx
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.transaction/src/main/java/org/springframework/jca/context/SpringContextResourceAdapter.java b/org.springframework.transaction/src/main/java/org/springframework/jca/context/SpringContextResourceAdapter.java
index ae041d3934e..e9af714e540 100644
--- a/org.springframework.transaction/src/main/java/org/springframework/jca/context/SpringContextResourceAdapter.java
+++ b/org.springframework.transaction/src/main/java/org/springframework/jca/context/SpringContextResourceAdapter.java
@@ -166,6 +166,7 @@ public class SpringContextResourceAdapter implements ResourceAdapter {
new ResourceAdapterApplicationContext(bootstrapContext);
// Set ResourceAdapter's ClassLoader as bean class loader.
applicationContext.setClassLoader(getClass().getClassLoader());
+ // TODO: SPR-7508 consider setEnvironment() here
// Extract individual config locations.
String[] configLocations =
StringUtils.tokenizeToStringArray(getContextConfigLocation(), CONFIG_LOCATION_DELIMITERS);
@@ -184,6 +185,7 @@ public class SpringContextResourceAdapter implements ResourceAdapter {
* @see #setContextConfigLocation
*/
protected void loadBeanDefinitions(BeanDefinitionRegistry registry, String[] configLocations) {
+ // TODO: SPR-7508 consider setEnvironment() here
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(configLocations);
}
diff --git a/org.springframework.transaction/src/main/resources/META-INF/spring.schemas b/org.springframework.transaction/src/main/resources/META-INF/spring.schemas
index 6fb4116d0b5..acf00109446 100644
--- a/org.springframework.transaction/src/main/resources/META-INF/spring.schemas
+++ b/org.springframework.transaction/src/main/resources/META-INF/spring.schemas
@@ -1,4 +1,5 @@
http\://www.springframework.org/schema/tx/spring-tx-2.0.xsd=org/springframework/transaction/config/spring-tx-2.0.xsd
http\://www.springframework.org/schema/tx/spring-tx-2.5.xsd=org/springframework/transaction/config/spring-tx-2.5.xsd
http\://www.springframework.org/schema/tx/spring-tx-3.0.xsd=org/springframework/transaction/config/spring-tx-3.0.xsd
-http\://www.springframework.org/schema/tx/spring-tx.xsd=org/springframework/transaction/config/spring-tx-3.0.xsd
+http\://www.springframework.org/schema/tx/spring-tx-3.1.xsd=org/springframework/transaction/config/spring-tx-3.1.xsd
+http\://www.springframework.org/schema/tx/spring-tx.xsd=org/springframework/transaction/config/spring-tx-3.1.xsd
diff --git a/org.springframework.transaction/src/main/resources/org/springframework/transaction/config/spring-tx-3.1.xsd b/org.springframework.transaction/src/main/resources/org/springframework/transaction/config/spring-tx-3.1.xsd
new file mode 100644
index 00000000000..8d76ee3a43b
--- /dev/null
+++ b/org.springframework.transaction/src/main/resources/org/springframework/transaction/config/spring-tx-3.1.xsd
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.web.portlet/.settings/org.eclipse.jdt.core.prefs b/org.springframework.web.portlet/.settings/org.eclipse.jdt.core.prefs
index 7b0e30db0ed..13ebdb03704 100644
--- a/org.springframework.web.portlet/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.web.portlet/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:32 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.web.portlet/pom.xml b/org.springframework.web.portlet/pom.xml
index f415286cc55..ac6678b3f4f 100644
--- a/org.springframework.web.portlet/pom.xml
+++ b/org.springframework.web.portlet/pom.xml
@@ -4,12 +4,12 @@
org.springframework
spring-webmvc-portlet
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/GenericPortletBean.java b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/GenericPortletBean.java
index 3ace247159f..f73ce1b6db4 100644
--- a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/GenericPortletBean.java
+++ b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/GenericPortletBean.java
@@ -27,13 +27,14 @@ import javax.portlet.PortletException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
+import org.springframework.core.env.DefaultWebEnvironment;
+import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
@@ -74,7 +75,12 @@ public abstract class GenericPortletBean extends GenericPortlet {
*/
private final Set requiredProperties = new HashSet();
-
+ /**
+ * TODO SPR-7508: think about making this overridable {@link EnvironmentAware}?
+ */
+ private Environment environment = new DefaultWebEnvironment();
+
+
/**
* Subclasses can invoke this method to specify that this property
* (which must match a JavaBean property they expose) is mandatory,
@@ -103,7 +109,7 @@ public abstract class GenericPortletBean extends GenericPortlet {
PropertyValues pvs = new PortletConfigPropertyValues(getPortletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new PortletContextResourceLoader(getPortletContext());
- bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader));
+ bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
diff --git a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/AbstractRefreshablePortletApplicationContext.java b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/AbstractRefreshablePortletApplicationContext.java
index db136444e57..39ad0bdb735 100644
--- a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/AbstractRefreshablePortletApplicationContext.java
+++ b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/AbstractRefreshablePortletApplicationContext.java
@@ -21,6 +21,7 @@ import javax.portlet.PortletContext;
import javax.servlet.ServletContext;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractRefreshableConfigApplicationContext;
import org.springframework.core.io.Resource;
@@ -167,4 +168,8 @@ public abstract class AbstractRefreshablePortletApplicationContext extends Abstr
return new PortletContextResourcePatternResolver(this);
}
+ @Override
+ protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
+ super.customizeBeanFactory(beanFactory);
+ }
}
diff --git a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/StaticPortletApplicationContext.java b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/StaticPortletApplicationContext.java
index ecaf20061f1..2746d8a1138 100644
--- a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/StaticPortletApplicationContext.java
+++ b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/StaticPortletApplicationContext.java
@@ -23,6 +23,7 @@ import javax.servlet.ServletContext;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.core.env.DefaultWebEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.context.WebApplicationContext;
@@ -60,6 +61,7 @@ public class StaticPortletApplicationContext extends StaticApplicationContext
public StaticPortletApplicationContext() {
setDisplayName("Root Portlet ApplicationContext");
+ setEnvironment(new DefaultWebEnvironment()); // TODO SPR-7508: create custom portlet env?
}
diff --git a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/XmlPortletApplicationContext.java b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/XmlPortletApplicationContext.java
index 6cb6e91f287..83769628ac1 100644
--- a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/XmlPortletApplicationContext.java
+++ b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/context/XmlPortletApplicationContext.java
@@ -83,6 +83,7 @@ public class XmlPortletApplicationContext extends AbstractRefreshablePortletAppl
// Configure the bean definition reader with this context's
// resource loading environment.
+ beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
diff --git a/org.springframework.web.portlet/src/test/java/org/springframework/web/portlet/context/XmlPortletApplicationContextTests.java b/org.springframework.web.portlet/src/test/java/org/springframework/web/portlet/context/XmlPortletApplicationContextTests.java
index 283340c8046..d968e5fd3fb 100644
--- a/org.springframework.web.portlet/src/test/java/org/springframework/web/portlet/context/XmlPortletApplicationContextTests.java
+++ b/org.springframework.web.portlet/src/test/java/org/springframework/web/portlet/context/XmlPortletApplicationContextTests.java
@@ -118,7 +118,7 @@ public class XmlPortletApplicationContextTests extends AbstractXmlWebApplication
public void testCount() {
assertTrue("should have 16 beans, not "+ this.applicationContext.getBeanDefinitionCount(),
- this.applicationContext.getBeanDefinitionCount() == 16);
+ this.applicationContext.getBeanDefinitionCount() == 16);
}
public void testPortletContextAwareBean() {
diff --git a/org.springframework.web.servlet/.settings/org.eclipse.jdt.core.prefs b/org.springframework.web.servlet/.settings/org.eclipse.jdt.core.prefs
index 0e29d554498..7a583ba283d 100644
--- a/org.springframework.web.servlet/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.web.servlet/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.web.servlet/pom.xml b/org.springframework.web.servlet/pom.xml
index d28b484d3b5..44a99a6f8af 100644
--- a/org.springframework.web.servlet/pom.xml
+++ b/org.springframework.web.servlet/pom.xml
@@ -6,12 +6,12 @@
org.springframework
spring-webmvc
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/HttpServletBean.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/HttpServletBean.java
index 1d994096ed7..f166bdbc96b 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/HttpServletBean.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/HttpServletBean.java
@@ -34,6 +34,9 @@ import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.core.env.DefaultWebEnvironment;
+import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
@@ -83,6 +86,11 @@ public abstract class HttpServletBean extends HttpServlet {
*/
private final Set requiredProperties = new HashSet();
+ /**
+ * TODO SPR-7508: think about making this overridable {@link EnvironmentAware}?
+ */
+ private Environment environment = new DefaultWebEnvironment();
+
/**
* Subclasses can invoke this method to specify that this property
@@ -114,7 +122,7 @@ public abstract class HttpServletBean extends HttpServlet {
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
- bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader));
+ bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/XmlViewResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/XmlViewResolver.java
index 0cbe725b9b0..35dc231f508 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/XmlViewResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/XmlViewResolver.java
@@ -136,6 +136,7 @@ public class XmlViewResolver extends AbstractCachingViewResolver
// Load XML resource with context-aware entity resolver.
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
+ reader.setEnvironment(getApplicationContext().getEnvironment());
reader.setEntityResolver(new ResourceEntityResolver(getApplicationContext()));
reader.loadBeanDefinitions(actualLocation);
diff --git a/org.springframework.web.servlet/src/main/resources/META-INF/spring.schemas b/org.springframework.web.servlet/src/main/resources/META-INF/spring.schemas
index d1b483ddb0f..3dfc9eed6f5 100644
--- a/org.springframework.web.servlet/src/main/resources/META-INF/spring.schemas
+++ b/org.springframework.web.servlet/src/main/resources/META-INF/spring.schemas
@@ -1,2 +1,3 @@
http\://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd=org/springframework/web/servlet/config/spring-mvc-3.0.xsd
-http\://www.springframework.org/schema/mvc/spring-mvc.xsd=org/springframework/web/servlet/config/spring-mvc-3.0.xsd
\ No newline at end of file
+http\://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd=org/springframework/web/servlet/config/spring-mvc-3.1.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc.xsd=org/springframework/web/servlet/config/spring-mvc-3.1.xsd
diff --git a/org.springframework.web.servlet/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.1.xsd b/org.springframework.web.servlet/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.1.xsd
new file mode 100644
index 00000000000..02c6e7ebad7
--- /dev/null
+++ b/org.springframework.web.servlet/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.1.xsd
@@ -0,0 +1,204 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.web.struts/.settings/org.eclipse.jdt.core.prefs b/org.springframework.web.struts/.settings/org.eclipse.jdt.core.prefs
index 0e29d554498..7a583ba283d 100644
--- a/org.springframework.web.struts/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.web.struts/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.web.struts/pom.xml b/org.springframework.web.struts/pom.xml
index 0609ca3b9c4..a82f148510e 100644
--- a/org.springframework.web.struts/pom.xml
+++ b/org.springframework.web.struts/pom.xml
@@ -6,12 +6,12 @@
org.springframework
spring-struts
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.web/.settings/org.eclipse.jdt.core.prefs b/org.springframework.web/.settings/org.eclipse.jdt.core.prefs
index a15f738edcd..4655eeb423f 100644
--- a/org.springframework.web/.settings/org.eclipse.jdt.core.prefs
+++ b/org.springframework.web/.settings/org.eclipse.jdt.core.prefs
@@ -1,15 +1,15 @@
#Wed Jul 15 00:01:30 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
diff --git a/org.springframework.web/pom.xml b/org.springframework.web/pom.xml
index c1840271c3f..5f9bb413b6d 100644
--- a/org.springframework.web/pom.xml
+++ b/org.springframework.web/pom.xml
@@ -6,12 +6,12 @@
org.springframework
spring-web
jar
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
org.springframework
spring-parent
../org.springframework.spring-parent
- 3.0.5.BUILD-SNAPSHOT
+ 3.1.0.BUILD-SNAPSHOT
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java
index 58d2a081825..8cf8d01646e 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java
@@ -21,6 +21,7 @@ import javax.servlet.ServletContext;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.AbstractRefreshableConfigApplicationContext;
+import org.springframework.core.env.DefaultWebEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.ui.context.Theme;
@@ -92,11 +93,14 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR
public AbstractRefreshableWebApplicationContext() {
setDisplayName("Root WebApplicationContext");
+ setEnvironment(new DefaultWebEnvironment());
}
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
+ // TODO: SPR-7508 extract createEnvironment() method; do also in GWAC
+ this.getEnvironment().getPropertySources().push(new ServletContextPropertySource(this.servletContext));
}
public ServletContext getServletContext() {
@@ -106,8 +110,10 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR
public void setServletConfig(ServletConfig servletConfig) {
this.servletConfig = servletConfig;
if (servletConfig != null && this.servletContext == null) {
- this.servletContext = servletConfig.getServletContext();
+ this.setServletContext(servletConfig.getServletContext());
}
+ // TODO: SPR-7508 extract createEnvironment() method; do also in GWAC
+ this.getEnvironment().getPropertySources().push(new ServletConfigPropertySource(servletConfig));
}
public ServletConfig getServletConfig() {
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java
index e47c26fa9d9..b126cb3ec33 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java
@@ -71,7 +71,11 @@ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWe
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);
+ reader.setEnvironment(this.getEnvironment());
+
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
+ scanner.setEnvironment(this.getEnvironment());
+
BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
if (beanNameGenerator != null) {
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java
index 69293d20803..daf5b5805a0 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java
@@ -21,6 +21,7 @@ import javax.servlet.ServletContext;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.env.DefaultWebEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.ui.context.Theme;
@@ -60,6 +61,11 @@ public class GenericWebApplicationContext extends GenericApplicationContext
private ThemeSource themeSource;
+ // override superclass definition of environment
+ // TODO SPR-7508: polish
+ {
+ this.setEnvironment(new DefaultWebEnvironment());
+ }
/**
* Create a new GenericWebApplicationContext.
@@ -154,6 +160,7 @@ public class GenericWebApplicationContext extends GenericApplicationContext
@Override
protected void onRefresh() {
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
+ this.getEnvironment().getPropertySources().push(new ServletContextPropertySource(servletContext));
}
public Theme getTheme(String themeName) {
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletConfigPropertySource.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletConfigPropertySource.java
new file mode 100644
index 00000000000..61d8658d200
--- /dev/null
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletConfigPropertySource.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002-2010 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.web.context.support;
+
+import java.util.Enumeration;
+
+import javax.servlet.ServletConfig;
+
+import org.springframework.core.env.DefaultWebEnvironment;
+import org.springframework.core.env.PropertySource;
+
+
+/**
+ * TODO SPR-7508: document
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see ServletContextPropertySource
+ */
+public class ServletConfigPropertySource extends PropertySource {
+
+ public ServletConfigPropertySource(ServletConfig servletConfig) {
+ this(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME, servletConfig);
+ }
+
+ public ServletConfigPropertySource(String name, ServletConfig servletConfig) {
+ super(name, servletConfig);
+ }
+
+ @Override
+ public boolean containsProperty(String name) {
+ Enumeration> initParamNames = this.source.getInitParameterNames();
+ while (initParamNames.hasMoreElements()) {
+ if (initParamNames.nextElement().equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getProperty(String name) {
+ return this.source.getInitParameter(name);
+ }
+
+ @Override
+ public int size() {
+ int size=0;
+ Enumeration> initParamNames = this.source.getInitParameterNames();
+ while (initParamNames.hasMoreElements()) {
+ initParamNames.nextElement();
+ size++;
+ }
+ return size;
+ }
+}
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextPropertyPlaceholderConfigurer.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextPropertyPlaceholderConfigurer.java
index 0e7254f68e0..3a35563168b 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextPropertyPlaceholderConfigurer.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextPropertyPlaceholderConfigurer.java
@@ -21,8 +21,10 @@ import java.util.Properties;
import javax.servlet.ServletContext;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.support.EnvironmentAwarePropertyPlaceholderConfigurer;
import org.springframework.web.context.ServletContextAware;
+
/**
* Subclass of PropertyPlaceholderConfigurer that resolves placeholders as
* ServletContext init parameters (that is, web.xml context-param
@@ -57,7 +59,10 @@ import org.springframework.web.context.ServletContextAware;
* @see #setSearchContextAttributes
* @see javax.servlet.ServletContext#getInitParameter(String)
* @see javax.servlet.ServletContext#getAttribute(String)
+ * @deprecated in Spring 3.1 in favor of {@link EnvironmentAwarePropertyPlaceholderConfigurer}
+ * in conjunction with {@link org.springframework.core.env.DefaultWebEnvironment}.
*/
+@Deprecated
public class ServletContextPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer
implements ServletContextAware {
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextPropertySource.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextPropertySource.java
new file mode 100644
index 00000000000..8bcad5ab2f8
--- /dev/null
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextPropertySource.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002-2010 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.web.context.support;
+
+import java.util.Enumeration;
+
+import javax.servlet.ServletContext;
+
+import org.springframework.core.env.DefaultWebEnvironment;
+import org.springframework.core.env.PropertySource;
+
+
+/**
+ * TODO SPR-7508: document
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see ServletConfigPropertySource
+ */
+public class ServletContextPropertySource extends PropertySource {
+
+ public ServletContextPropertySource(ServletContext servletContext) {
+ this(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME, servletContext);
+ }
+
+ public ServletContextPropertySource(String name, ServletContext servletContext) {
+ super(name, servletContext);
+ }
+
+ @Override
+ public boolean containsProperty(String name) {
+ Enumeration> initParamNames = this.source.getInitParameterNames();
+ while (initParamNames.hasMoreElements()) {
+ if (initParamNames.nextElement().equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getProperty(String name) {
+ return this.source.getInitParameter(name);
+ }
+
+ @Override
+ public int size() {
+ int size=0;
+ Enumeration> initParamNames = this.source.getInitParameterNames();
+ while (initParamNames.hasMoreElements()) {
+ initParamNames.nextElement();
+ size++;
+ }
+ return size;
+ }
+}
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java
index 740fb880203..60ff3d6655a 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java
@@ -16,11 +16,15 @@
package org.springframework.web.context.support;
+import java.util.LinkedList;
+
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.core.env.DefaultWebEnvironment;
+import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.ui.context.Theme;
@@ -66,6 +70,7 @@ public class StaticWebApplicationContext extends StaticApplicationContext
public StaticWebApplicationContext() {
setDisplayName("Root WebApplicationContext");
+ setEnvironment(new DefaultWebEnvironment()); // TODO SPR-7508: see GenericWebApplicationContext, AbstractRefreshableWebApplicationContext
}
@@ -164,6 +169,9 @@ public class StaticWebApplicationContext extends StaticApplicationContext
@Override
protected void onRefresh() {
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
+ LinkedList> propertySources = this.getEnvironment().getPropertySources();
+ propertySources.push(new ServletContextPropertySource(servletContext));
+ propertySources.push(new ServletConfigPropertySource(servletConfig));
}
public Theme getTheme(String themeName) {
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java
index 0290cb668a8..84d4b38f3cc 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/XmlWebApplicationContext.java
@@ -84,6 +84,7 @@ public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationC
// Configure the bean definition reader with this context's
// resource loading environment.
+ beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
diff --git a/org.springframework.web/src/main/java/org/springframework/web/filter/GenericFilterBean.java b/org.springframework.web/src/main/java/org/springframework/web/filter/GenericFilterBean.java
index 1572d63f3f7..288532600b8 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/filter/GenericFilterBean.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/filter/GenericFilterBean.java
@@ -37,6 +37,9 @@ import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.core.env.DefaultWebEnvironment;
+import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
@@ -74,7 +77,7 @@ import org.springframework.web.util.NestedServletException;
* @see #doFilter
*/
public abstract class GenericFilterBean implements
- Filter, BeanNameAware, ServletContextAware, InitializingBean, DisposableBean {
+ Filter, BeanNameAware, EnvironmentAware, ServletContextAware, InitializingBean, DisposableBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@@ -88,9 +91,15 @@ public abstract class GenericFilterBean implements
/* The FilterConfig of this filter */
private FilterConfig filterConfig;
-
private String beanName;
+ /**
+ * TODO SPR-7508: document
+ * Defaults to {@link DefaultWebEnvironment}; can be overriden if deployed
+ * as a spring bean by {@link #setEnvironment(Environment)}
+ */
+ private Environment environment = new DefaultWebEnvironment();
+
private ServletContext servletContext;
@@ -105,6 +114,13 @@ public abstract class GenericFilterBean implements
this.beanName = beanName;
}
+ /**
+ * TODO SPR-7508: document
+ */
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
/**
* Stores the ServletContext that the bean factory runs in.
* Only relevant in case of initialization as bean, to have a ServletContext
@@ -164,7 +180,7 @@ public abstract class GenericFilterBean implements
PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
- bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader));
+ bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
diff --git a/spring-framework.ipr b/spring-framework.ipr
index b0aec2604d9..3b638343cda 100644
--- a/spring-framework.ipr
+++ b/spring-framework.ipr
@@ -953,6 +953,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/test/java/org/springframework/core/env/PropertyPlaceholderConfigurerEnvironmentIntegrationTests.java b/src/test/java/org/springframework/core/env/PropertyPlaceholderConfigurerEnvironmentIntegrationTests.java
new file mode 100644
index 00000000000..89010245486
--- /dev/null
+++ b/src/test/java/org/springframework/core/env/PropertyPlaceholderConfigurerEnvironmentIntegrationTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2010 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.core.env;
+
+import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
+
+import org.junit.Test;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.support.GenericApplicationContext;
+
+public class PropertyPlaceholderConfigurerEnvironmentIntegrationTests {
+ @Test
+ public void test() {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.registerBeanDefinition("ppc",
+ rootBeanDefinition(PropertyPlaceholderConfigurer.class)
+ .addPropertyValue("searchSystemEnvironment", false)
+ .getBeanDefinition());
+ ctx.refresh();
+ ctx.getBean("ppc");
+ }
+}