SystemEnvironmentPropertySource uses regular property names check instead of optimized Map lookup (for defensiveness in SecurityManager scenarios)

Issue: SPR-12224
This commit is contained in:
Juergen Hoeller 2014-09-19 00:11:44 +02:00
parent 7f8d611598
commit 65cc57dabb
3 changed files with 27 additions and 47 deletions

View File

@ -16,10 +16,7 @@
package org.springframework.core.env; package org.springframework.core.env;
import org.apache.commons.logging.Log; import org.springframework.util.ObjectUtils;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
/** /**
* A {@link PropertySource} implementation capable of interrogating its * A {@link PropertySource} implementation capable of interrogating its
@ -41,24 +38,16 @@ import org.springframework.util.Assert;
* or not. * or not.
* *
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller
* @since 3.1 * @since 3.1
*/ */
public abstract class EnumerablePropertySource<T> extends PropertySource<T> { public abstract class EnumerablePropertySource<T> extends PropertySource<T> {
protected final Log logger = LogFactory.getLog(getClass());
public EnumerablePropertySource(String name, T source) { public EnumerablePropertySource(String name, T source) {
super(name, source); super(name, source);
} }
/**
* Return the names of all properties contained by the
* {@linkplain #getSource() source} object (never {@code null}).
*/
public abstract String[] getPropertyNames();
/** /**
* Return whether this {@code PropertySource} contains a property with the given name. * Return whether this {@code PropertySource} contains a property with the given name.
* <p>This implementation checks for the presence of the given name within the * <p>This implementation checks for the presence of the given name within the
@ -67,19 +56,13 @@ public abstract class EnumerablePropertySource<T> extends PropertySource<T> {
*/ */
@Override @Override
public boolean containsProperty(String name) { public boolean containsProperty(String name) {
Assert.notNull(name, "Property name must not be null"); return ObjectUtils.containsElement(getPropertyNames(), name);
for (String candidate : getPropertyNames()) {
if (candidate.equals(name)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("PropertySource [%s] contains '%s'", getName(), name));
}
return true;
}
}
if (logger.isTraceEnabled()) {
logger.trace(String.format("PropertySource [%s] does not contain '%s'", getName(), name));
}
return false;
} }
/**
* Return the names of all properties contained by the
* {@linkplain #getSource() source} object (never {@code null}).
*/
public abstract String[] getPropertyNames();
} }

View File

@ -18,13 +18,13 @@ package org.springframework.core.env;
import java.util.Map; import java.util.Map;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* {@link PropertySource} that reads keys and values from a {@code Map} object. * {@link PropertySource} that reads keys and values from a {@code Map} object.
* *
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller
* @since 3.1 * @since 3.1
* @see PropertiesPropertySource * @see PropertiesPropertySource
*/ */
@ -34,25 +34,20 @@ public class MapPropertySource extends EnumerablePropertySource<Map<String, Obje
super(name, source); super(name, source);
} }
@Override @Override
public Object getProperty(String name) { public Object getProperty(String name) {
return this.source.get(name); return this.source.get(name);
} }
@Override
public boolean containsProperty(String name) {
return this.source.containsKey(name);
}
@Override @Override
public String[] getPropertyNames() { public String[] getPropertyNames() {
return StringUtils.toStringArray(this.source.keySet()); return StringUtils.toStringArray(this.source.keySet());
} }
@Override
public boolean containsProperty(String name) {
Assert.notNull(name, "Property name must not be null");
boolean containsProperty = this.source.containsKey(name);
if (logger.isDebugEnabled()) {
logger.debug(String.format("PropertySource [%s] %s '%s'", getName(),
(containsProperty ? "contains" : "does not contain"), name));
}
return containsProperty;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ package org.springframework.core.env;
import java.util.Map; import java.util.Map;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/** /**
* Specialization of {@link MapPropertySource} designed for use with * Specialization of {@link MapPropertySource} designed for use with
@ -70,8 +71,9 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
super(name, source); super(name, source);
} }
/** /**
* Return true if a property with the given name or any underscore/uppercase variant * Return {@link true} if a property with the given name or any underscore/uppercase variant
* thereof exists in this property source. * thereof exists in this property source.
*/ */
@Override @Override
@ -80,13 +82,11 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
} }
/** /**
* {@inheritDoc} * This implementation returns {@code true} if a property with the given name or
* <p>This implementation returns {@code true} if a property with the given name or
* any underscore/uppercase variant thereof exists in this property source. * any underscore/uppercase variant thereof exists in this property source.
*/ */
@Override @Override
public Object getProperty(String name) { public Object getProperty(String name) {
Assert.notNull(name, "property name must not be null");
String actualName = resolvePropertyName(name); String actualName = resolvePropertyName(name);
if (logger.isDebugEnabled() && !name.equals(actualName)) { if (logger.isDebugEnabled() && !name.equals(actualName)) {
logger.debug(String.format("PropertySource [%s] does not contain '%s', but found equivalent '%s'", logger.debug(String.format("PropertySource [%s] does not contain '%s', but found equivalent '%s'",
@ -101,23 +101,24 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
* found or otherwise the original name. Never returns {@code null}. * found or otherwise the original name. Never returns {@code null}.
*/ */
private String resolvePropertyName(String name) { private String resolvePropertyName(String name) {
if (super.containsProperty(name)) { Assert.notNull(name, "Property name must not be null");
if (ObjectUtils.containsElement(getPropertyNames(), name)) {
return name; return name;
} }
String usName = name.replace('.', '_'); String usName = name.replace('.', '_');
if (!name.equals(usName) && super.containsProperty(usName)) { if (!name.equals(usName) && ObjectUtils.containsElement(getPropertyNames(), usName)) {
return usName; return usName;
} }
String ucName = name.toUpperCase(); String ucName = name.toUpperCase();
if (!name.equals(ucName)) { if (!name.equals(ucName)) {
if (super.containsProperty(ucName)) { if (ObjectUtils.containsElement(getPropertyNames(), ucName)) {
return ucName; return ucName;
} }
else { else {
String usUcName = ucName.replace('.', '_'); String usUcName = ucName.replace('.', '_');
if (!ucName.equals(usUcName) && super.containsProperty(usUcName)) { if (!ucName.equals(usUcName) && ObjectUtils.containsElement(getPropertyNames(), usUcName)) {
return usUcName; return usUcName;
} }
} }
@ -125,4 +126,5 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
return name; return name;
} }
} }