support for default "conversionService" bean in an ApplicationContext; revised formatting package, now integrated with DataBinder and AnnotationMethodHandlerAdapter; revised AccessControlContext access from BeanFactory
This commit is contained in:
@@ -36,9 +36,11 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -326,6 +328,24 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
return null;
|
||||
}
|
||||
|
||||
public TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException {
|
||||
try {
|
||||
PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
|
||||
if (pd != null) {
|
||||
if (pd.getReadMethod() != null) {
|
||||
return new TypeDescriptor(new MethodParameter(pd.getReadMethod(), -1));
|
||||
}
|
||||
else if (pd.getWriteMethod() != null) {
|
||||
return new TypeDescriptor(new MethodParameter(pd.getWriteMethod(), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidPropertyException ex) {
|
||||
// Consider as not determinable.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isReadableProperty(String propertyName) {
|
||||
try {
|
||||
PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -86,6 +87,14 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor {
|
||||
return null;
|
||||
}
|
||||
|
||||
public TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException {
|
||||
Field field = this.fieldMap.get(propertyName);
|
||||
if (field != null) {
|
||||
return new TypeDescriptor(field);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPropertyValue(String propertyName) throws BeansException {
|
||||
Field field = this.fieldMap.get(propertyName);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,6 +18,8 @@ package org.springframework.beans;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
/**
|
||||
* Common interface for classes that can access named properties
|
||||
* (such as bean properties of an object or fields in an object)
|
||||
@@ -86,6 +88,17 @@ public interface PropertyAccessor {
|
||||
*/
|
||||
Class getPropertyType(String propertyName) throws BeansException;
|
||||
|
||||
/**
|
||||
* Return a type descriptor for the specified property.
|
||||
* @param propertyName the property to check
|
||||
* (may be a nested path and/or an indexed/mapped property)
|
||||
* @return the property type for the particular property,
|
||||
* or <code>null</code> if not determinable
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't readable
|
||||
*/
|
||||
TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException;
|
||||
|
||||
/**
|
||||
* Get the current value of the specified property.
|
||||
* @param propertyName the name of the property to get the value of
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.beans.PropertyDescriptor;
|
||||
import java.beans.PropertyEditor;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
@@ -203,8 +204,18 @@ class TypeConverterDelegate {
|
||||
convertedValue = convertToTypedMap((Map) convertedValue, propertyName, methodParam);
|
||||
}
|
||||
else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
|
||||
String strValue = ((String) convertedValue).trim();
|
||||
if (requiredType.isEnum() && "".equals(strValue)) {
|
||||
try {
|
||||
Constructor strCtor = requiredType.getConstructor(String.class);
|
||||
return (T) BeanUtils.instantiateClass(strCtor, convertedValue);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// proceed with field lookup
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
String trimmedValue = ((String) convertedValue).trim();
|
||||
if (requiredType.isEnum() && "".equals(trimmedValue)) {
|
||||
// It's an empty enum identifier: reset the enum value to null.
|
||||
return null;
|
||||
}
|
||||
@@ -212,7 +223,7 @@ class TypeConverterDelegate {
|
||||
// with values defined as static fields. Resulting value still needs
|
||||
// to be checked, hence we don't return it right away.
|
||||
try {
|
||||
Field enumField = requiredType.getField(strValue);
|
||||
Field enumField = requiredType.getField(trimmedValue);
|
||||
convertedValue = enumField.get(null);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.security.AccessControlContext;
|
||||
|
||||
import org.springframework.beans.PropertyEditorRegistrar;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
@@ -249,6 +250,12 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
|
||||
*/
|
||||
Scope getRegisteredScope(String scopeName);
|
||||
|
||||
/**
|
||||
* Provides a security access control context relevant to this factory.
|
||||
* @return the applicable AccessControlContext (never <code>null</code>)
|
||||
*/
|
||||
AccessControlContext getAccessControlContext();
|
||||
|
||||
/**
|
||||
* Copy all relevant configuration from the given other factory.
|
||||
* <p>Should include all standard configuration settings as well as
|
||||
|
||||
@@ -150,6 +150,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
/** Map from scope identifier String to corresponding Scope */
|
||||
private final Map<String, Scope> scopes = new HashMap<String, Scope>();
|
||||
|
||||
/** Security context used when running with a SecurityManager */
|
||||
private SecurityContextProvider securityContextProvider;
|
||||
|
||||
/** Map from bean name to merged RootBeanDefinition */
|
||||
private final Map<String, RootBeanDefinition> mergedBeanDefinitions =
|
||||
new ConcurrentHashMap<String, RootBeanDefinition>();
|
||||
@@ -161,9 +164,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
|
||||
new NamedThreadLocal<Object>("Prototype beans currently in creation");
|
||||
|
||||
/** security context used when running with a Security Manager */
|
||||
private volatile SecurityContextProvider securityProvider = new SimpleSecurityContextProvider();
|
||||
|
||||
/**
|
||||
* Create a new AbstractBeanFactory.
|
||||
*/
|
||||
@@ -761,6 +761,26 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return this.scopes.get(scopeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security context provider for this bean factory. If a security manager
|
||||
* is set, interaction with the user code will be executed using the privileged
|
||||
* of the provided security context.
|
||||
*/
|
||||
public void setSecurityContextProvider(SecurityContextProvider securityProvider) {
|
||||
this.securityContextProvider = securityProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate the creation of the access control context to the
|
||||
* {@link #setSecurityContextProvider SecurityContextProvider}.
|
||||
*/
|
||||
@Override
|
||||
public AccessControlContext getAccessControlContext() {
|
||||
return (this.securityContextProvider != null ?
|
||||
this.securityContextProvider.getAccessControlContext() :
|
||||
AccessController.getContext());
|
||||
}
|
||||
|
||||
public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
|
||||
Assert.notNull(otherFactory, "BeanFactory must not be null");
|
||||
setBeanClassLoader(otherFactory.getBeanClassLoader());
|
||||
@@ -776,6 +796,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
|
||||
otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
|
||||
this.scopes.putAll(otherAbstractFactory.scopes);
|
||||
this.securityContextProvider = otherAbstractFactory.securityContextProvider;
|
||||
}
|
||||
else {
|
||||
setTypeConverter(otherFactory.getTypeConverter());
|
||||
@@ -1436,37 +1457,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Delegate the creation of the security context to {@link #getSecurityContextProvider()}.
|
||||
*/
|
||||
@Override
|
||||
protected AccessControlContext getAccessControlContext() {
|
||||
SecurityContextProvider provider = getSecurityContextProvider();
|
||||
return (provider != null ? provider.getAccessControlContext(): AccessController.getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the security context provider for this bean factory.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public SecurityContextProvider getSecurityContextProvider() {
|
||||
return securityProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security context provider for this bean factory. If a security manager
|
||||
* is set, interaction with the user code will be executed using the privileged
|
||||
* of the provided security context.
|
||||
*
|
||||
* @param securityProvider
|
||||
*/
|
||||
public void setSecurityContextProvider(SecurityContextProvider securityProvider) {
|
||||
this.securityProvider = securityProvider;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Abstract methods to be implemented by subclasses
|
||||
@@ -1526,4 +1517,5 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
*/
|
||||
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
|
||||
throws BeanCreationException;
|
||||
|
||||
}
|
||||
|
||||
@@ -212,10 +212,10 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
* Returns the security context for this bean factory. If a security manager
|
||||
* is set, interaction with the user code will be executed using the privileged
|
||||
* of the security context returned by this method.
|
||||
*
|
||||
* @return
|
||||
* @see AccessController#getContext()
|
||||
*/
|
||||
protected AccessControlContext getAccessControlContext() {
|
||||
return AccessController.getContext();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,15 +20,16 @@ import java.security.AccessControlContext;
|
||||
|
||||
/**
|
||||
* Provider of the security context of the code running inside the bean factory.
|
||||
*
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface SecurityContextProvider {
|
||||
|
||||
/**
|
||||
* Provides a security access control context relevant to a bean factory.
|
||||
*
|
||||
* @return bean factory security control context
|
||||
*/
|
||||
AccessControlContext getAccessControlContext();
|
||||
|
||||
}
|
||||
|
||||
@@ -20,18 +20,19 @@ import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
|
||||
/**
|
||||
* Simple #SecurityContextProvider implementation.
|
||||
* Simple {@link SecurityContextProvider} implementation.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @since 3.0
|
||||
*/
|
||||
public class SimpleSecurityContextProvider implements SecurityContextProvider {
|
||||
|
||||
private final AccessControlContext acc;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new <code>SimpleSecurityContextProvider</code> instance.
|
||||
*
|
||||
* The security context will be retrieved on each call from the current
|
||||
* Construct a new <code>SimpleSecurityContextProvider</code> instance.
|
||||
* <p>The security context will be retrieved on each call from the current
|
||||
* thread.
|
||||
*/
|
||||
public SimpleSecurityContextProvider() {
|
||||
@@ -39,20 +40,19 @@ public class SimpleSecurityContextProvider implements SecurityContextProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>SimpleSecurityContextProvider</code> instance.
|
||||
*
|
||||
* If the given control context is null, the security context will be
|
||||
* Construct a new <code>SimpleSecurityContextProvider</code> instance.
|
||||
* <p>If the given control context is null, the security context will be
|
||||
* retrieved on each call from the current thread.
|
||||
*
|
||||
* @param acc access control context (can be <code>null</code>)
|
||||
* @see AccessController#getContext()
|
||||
* @param acc
|
||||
* access control context (can be null)
|
||||
*/
|
||||
public SimpleSecurityContextProvider(AccessControlContext acc) {
|
||||
this.acc = acc;
|
||||
}
|
||||
|
||||
|
||||
public AccessControlContext getAccessControlContext() {
|
||||
return (acc == null ? AccessController.getContext() : acc);
|
||||
return (this.acc != null ? acc : AccessController.getContext());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user