Merge 3.1.0 development branch into trunk
Branch in question is 'env' branch from git://git.springsource.org/sandbox/cbeams.git; merged into
git-svn repository with:
git merge -s recursive -Xtheirs --no-commit env
No merge conflicts, but did need to
git rm spring-build
prior to committing.
With this change, Spring 3.1.0 development is now happening on SVN
trunk. Further commits to the 3.0.x line will happen in an as-yet
uncreated SVN branch. 3.1.0 snapshots will be available
per the usual nightly CI build from trunk.
This commit is contained in:
284
org.springframework.core/src/main/java/org/springframework/core/env/AbstractEnvironment.java
vendored
Normal file
284
org.springframework.core/src/main/java/org/springframework/core/env/AbstractEnvironment.java
vendored
Normal file
@@ -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<String> activeProfiles = new LinkedHashSet<String>();
|
||||
private LinkedList<PropertySource<?>> propertySources = new LinkedList<PropertySource<?>>();
|
||||
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<String, String> propertiesMap) {
|
||||
addPropertySource(new MapPropertySource(name, propertiesMap));
|
||||
}
|
||||
|
||||
public LinkedList<PropertySource<?>> 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> T getProperty(String key, Class<T> 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> T getRequiredProperty(String key, Class<T> 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<PropertySource<?>> 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<String> 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<String, String> getSystemEnvironment() {
|
||||
Map<String,String> 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<String, String> 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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
32
org.springframework.core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java
vendored
Normal file
32
org.springframework.core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java
vendored
Normal file
@@ -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);
|
||||
|
||||
}
|
||||
39
org.springframework.core/src/main/java/org/springframework/core/env/DefaultEnvironment.java
vendored
Normal file
39
org.springframework.core/src/main/java/org/springframework/core/env/DefaultEnvironment.java
vendored
Normal file
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
31
org.springframework.core/src/main/java/org/springframework/core/env/DefaultWebEnvironment.java
vendored
Normal file
31
org.springframework.core/src/main/java/org/springframework/core/env/DefaultWebEnvironment.java
vendored
Normal file
@@ -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";
|
||||
|
||||
}
|
||||
101
org.springframework.core/src/main/java/org/springframework/core/env/Environment.java
vendored
Normal file
101
org.springframework.core/src/main/java/org/springframework/core/env/Environment.java
vendored
Normal file
@@ -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<String> getActiveProfiles();
|
||||
|
||||
/**
|
||||
* TODO SPR-7508: document
|
||||
*/
|
||||
boolean containsProperty(String key);
|
||||
|
||||
/**
|
||||
* TODO SPR-7508: document
|
||||
*/
|
||||
String getProperty(String key);
|
||||
|
||||
/**
|
||||
* TODO SPR-7508: document
|
||||
*/
|
||||
<T> T getProperty(String key, Class<T> targetType);
|
||||
|
||||
/**
|
||||
* TODO SPR-7508: document
|
||||
*/
|
||||
String getRequiredProperty(String key);
|
||||
|
||||
/**
|
||||
* TODO SPR-7508: document
|
||||
*/
|
||||
<T> T getRequiredProperty(String key, Class<T> 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<String, String> 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<String, String> 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);
|
||||
|
||||
}
|
||||
32
org.springframework.core/src/main/java/org/springframework/core/env/EnvironmentCapable.java
vendored
Normal file
32
org.springframework.core/src/main/java/org/springframework/core/env/EnvironmentCapable.java
vendored
Normal file
@@ -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();
|
||||
|
||||
}
|
||||
53
org.springframework.core/src/main/java/org/springframework/core/env/MapPropertySource.java
vendored
Normal file
53
org.springframework.core/src/main/java/org/springframework/core/env/MapPropertySource.java
vendored
Normal file
@@ -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<Map<String, String>> {
|
||||
|
||||
protected MapPropertySource(String name, Map<String, String> 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Properties> {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
139
org.springframework.core/src/main/java/org/springframework/core/env/PropertySource.java
vendored
Normal file
139
org.springframework.core/src/main/java/org/springframework/core/env/PropertySource.java
vendored
Normal file
@@ -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<T> {
|
||||
|
||||
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<Void>{
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> 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<PropertySource<?>> getPropertySources();
|
||||
|
||||
}
|
||||
118
org.springframework.core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java
vendored
Normal file
118
org.springframework.core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Read-only {@code Map<String, String>} implementation that is backed by system properties or environment
|
||||
* variables.
|
||||
*
|
||||
* <p>Used by {@link AbstractApplicationContext} when a {@link SecurityManager} prohibits access to {@link
|
||||
* System#getProperties()} or {@link System#getenv()}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Chris Beams
|
||||
* @since 3.0
|
||||
*/
|
||||
abstract class ReadOnlySystemAttributesMap implements Map<String, String> {
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
public String get(Object key) {
|
||||
if (key instanceof String) {
|
||||
String attributeName = (String) key;
|
||||
return getSystemAttribute(attributeName);
|
||||
}
|
||||
else {
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method that returns the underlying system attribute.
|
||||
*
|
||||
* <p>Implementations typically call {@link System#getProperty(String)} or {@link System#getenv(String)} here.
|
||||
*/
|
||||
protected abstract String getSystemAttribute(String attributeName);
|
||||
|
||||
// Unsupported
|
||||
|
||||
public int size() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String put(String key, String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String remove(Object key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Set<String> keySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends String, ? extends String> m) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Collection<String> values() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Set<Entry<String, String>> entrySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
* <code>"classpath:myfile.txt"</code>) to <code>Resource</code>
|
||||
* properties instead of using a <code>String</code> location property.
|
||||
*
|
||||
* <p>The path may contain <code>${...}</code> placeholders,
|
||||
* to be resolved as system properties: e.g. <code>${user.dir}</code>.
|
||||
* Unresolvable placeholder are ignored by default.
|
||||
* <p>The path may contain <code>${...}</code> placeholders, to be
|
||||
* resolved as {@link Environment} properties: e.g. <code>${user.dir}</code>.
|
||||
* Unresolvable placeholders are ignored by default.
|
||||
*
|
||||
* <p>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 <code>ResourceLoader</code> 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 <code>ResourceLoader</code> 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 <code>ResourceLoader</code> 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 <code>ResourceLoader</code> to use
|
||||
* @param environment the <code>Environment</code> to use
|
||||
* @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
|
||||
* if no corresponding property could be found in the given <code>environment</code>
|
||||
*/
|
||||
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 <code>environment</code> 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,12 @@ import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
||||
* <code>${user.dir}</code>. 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
|
||||
|
||||
75
org.springframework.core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java
vendored
Normal file
75
org.springframework.core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java
vendored
Normal file
@@ -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
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
452
org.springframework.core/src/test/java/org/springframework/core/env/DefaultEnvironmentTests.java
vendored
Normal file
452
org.springframework.core/src/test/java/org/springframework/core/env/DefaultEnvironmentTests.java
vendored
Normal file
@@ -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<PropertySource<?>> 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<PropertySource<?>> 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<String, String> nullableProperties = new HashMap<String, String>();
|
||||
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<String> 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<String, String> 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<String, String> 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<Collection<?>> isEmpty() {
|
||||
|
||||
return new TypeSafeMatcher<Collection<?>>() {
|
||||
|
||||
@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<String, String> getModifiableSystemEnvironment() throws Exception {
|
||||
Class<?>[] classes = Collections.class.getDeclaredClasses();
|
||||
Map<String, String> 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<String, String>) obj;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> 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<String, String> getModifiableSystemEnvironment() throws Exception {
|
||||
Class<?>[] classes = Collections.class.getDeclaredClasses();
|
||||
Map<String, String> 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<String, String>) obj;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
}
|
||||
120
org.springframework.core/src/test/java/org/springframework/core/env/PropertySourceTests.java
vendored
Normal file
120
org.springframework.core/src/test/java/org/springframework/core/env/PropertySourceTests.java
vendored
Normal file
@@ -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<String, String> map1 = new HashMap<String, String>() {{ put("a", "b"); }};
|
||||
Map<String, String> map2 = new HashMap<String, String>() {{ 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<String, String> map1 = new HashMap<String, String>() {{ put("a", "b"); }};
|
||||
Map<String, String> map2 = new HashMap<String, String>() {{ put("c", "d"); }};
|
||||
|
||||
PropertySource<?> ps1 = new MapPropertySource("ps1", map1);
|
||||
ps1.getSource();
|
||||
LinkedList<PropertySource<?>> propertySources = new LinkedList<PropertySource<?>>();
|
||||
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<String, String> map = new HashMap<String, String>() {{ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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}");
|
||||
|
||||
Reference in New Issue
Block a user