+ interaction with user code uses now dedicated privileged when running under a security manager
This commit is contained in:
parent
fe5b5022f0
commit
d5d3104b7b
|
|
@ -22,6 +22,10 @@ import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
@ -31,7 +35,6 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.core.GenericCollectionTypeResolver;
|
import org.springframework.core.GenericCollectionTypeResolver;
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
@ -102,6 +105,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
*/
|
*/
|
||||||
private Map<String, BeanWrapperImpl> nestedBeanWrappers;
|
private Map<String, BeanWrapperImpl> nestedBeanWrappers;
|
||||||
|
|
||||||
|
/** The security context used for invoking the property methods */
|
||||||
|
private AccessControlContext acc;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards.
|
* Create new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards.
|
||||||
|
|
@ -198,6 +204,16 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
setIntrospectionClass(object.getClass());
|
setIntrospectionClass(object.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the security context used during the invocation of the wrapped instance methods.
|
||||||
|
* Can be null.
|
||||||
|
*
|
||||||
|
* @param acc
|
||||||
|
*/
|
||||||
|
public void setSecurityContext(AccessControlContext acc) {
|
||||||
|
this.acc = acc;
|
||||||
|
}
|
||||||
|
|
||||||
public final Object getWrappedInstance() {
|
public final Object getWrappedInstance() {
|
||||||
return this.object;
|
return this.object;
|
||||||
}
|
}
|
||||||
|
|
@ -539,12 +555,29 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
if (pd == null || pd.getReadMethod() == null) {
|
if (pd == null || pd.getReadMethod() == null) {
|
||||||
throw new NotReadablePropertyException(getRootClass(), this.nestedPath + propertyName);
|
throw new NotReadablePropertyException(getRootClass(), this.nestedPath + propertyName);
|
||||||
}
|
}
|
||||||
Method readMethod = pd.getReadMethod();
|
final Method readMethod = pd.getReadMethod();
|
||||||
try {
|
try {
|
||||||
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
||||||
readMethod.setAccessible(true);
|
readMethod.setAccessible(true);
|
||||||
}
|
}
|
||||||
Object value = readMethod.invoke(this.object, (Object[]) null);
|
|
||||||
|
Object value = null;
|
||||||
|
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
try {
|
||||||
|
value = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
public Object run() throws Exception {
|
||||||
|
return readMethod.invoke(object, (Object[]) null);
|
||||||
|
}
|
||||||
|
},acc);
|
||||||
|
} catch (PrivilegedActionException pae) {
|
||||||
|
throw pae.getException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = readMethod.invoke(object, (Object[]) null);
|
||||||
|
}
|
||||||
|
|
||||||
if (tokens.keys != null) {
|
if (tokens.keys != null) {
|
||||||
// apply indexes and map keys
|
// apply indexes and map keys
|
||||||
for (int i = 0; i < tokens.keys.length; i++) {
|
for (int i = 0; i < tokens.keys.length; i++) {
|
||||||
|
|
@ -602,7 +635,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||||
"Getter for property '" + actualName + "' threw exception", ex);
|
"Getter for property '" + actualName + "' threw exception", ex);
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException ex) {
|
|
||||||
|
catch(IllegalAccessException ex) {
|
||||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||||
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
|
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
|
||||||
}
|
}
|
||||||
|
|
@ -614,6 +648,10 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||||
"Invalid index in property path '" + propertyName + "'", ex);
|
"Invalid index in property path '" + propertyName + "'", ex);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||||
|
"Invalid index in property path '" + propertyName + "'", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -813,14 +851,26 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {
|
if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {
|
||||||
Method readMethod = pd.getReadMethod();
|
final Method readMethod = pd.getReadMethod();
|
||||||
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
||||||
readMethod.setAccessible(true);
|
readMethod.setAccessible(true);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
oldValue = readMethod.invoke(this.object);
|
if (System.getSecurityManager() != null) {
|
||||||
|
oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
public Object run() throws Exception {
|
||||||
|
return readMethod.invoke(object);
|
||||||
|
}
|
||||||
|
},acc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oldValue = readMethod.invoke(object);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex instanceof PrivilegedActionException) {
|
||||||
|
ex = ((PrivilegedActionException) ex).getException();
|
||||||
|
}
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Could not read previous value of property '" +
|
logger.debug("Could not read previous value of property '" +
|
||||||
this.nestedPath + propertyName + "'", ex);
|
this.nestedPath + propertyName + "'", ex);
|
||||||
|
|
@ -831,11 +881,28 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
}
|
}
|
||||||
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
|
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
|
||||||
}
|
}
|
||||||
Method writeMethod = pd.getWriteMethod();
|
final Method writeMethod = pd.getWriteMethod();
|
||||||
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
|
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
|
||||||
writeMethod.setAccessible(true);
|
writeMethod.setAccessible(true);
|
||||||
}
|
}
|
||||||
writeMethod.invoke(this.object, valueToApply);
|
final Object value = valueToApply;
|
||||||
|
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
try {
|
||||||
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
public Object run() throws Exception {
|
||||||
|
writeMethod.invoke(object, value);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},acc);
|
||||||
|
} catch (PrivilegedActionException ex) {
|
||||||
|
throw ex.getException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writeMethod.invoke(object, value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (InvocationTargetException ex) {
|
catch (InvocationTargetException ex) {
|
||||||
PropertyChangeEvent propertyChangeEvent =
|
PropertyChangeEvent propertyChangeEvent =
|
||||||
|
|
@ -862,6 +929,11 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||||
throw new MethodInvocationException(pce, ex);
|
throw new MethodInvocationException(pce, ex);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
PropertyChangeEvent pce =
|
||||||
|
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||||
|
throw new MethodInvocationException(pce, ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ import java.lang.reflect.Modifier;
|
||||||
import java.security.AccessControlContext;
|
import java.security.AccessControlContext;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -330,13 +332,27 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
|
|
||||||
public Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
public Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||||
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
|
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
|
||||||
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
|
final RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
|
||||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||||
if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) {
|
if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) {
|
||||||
return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance();
|
return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object bean = getInstantiationStrategy().instantiate(bd, null, this);
|
Object bean = null;
|
||||||
|
final BeanFactory parent = this;
|
||||||
|
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
bean = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
|
||||||
|
public Object run() {
|
||||||
|
return getInstantiationStrategy().instantiate(bd, null, parent);
|
||||||
|
}
|
||||||
|
}, getAccessControlContext());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bean = getInstantiationStrategy().instantiate(bd, null, parent);
|
||||||
|
}
|
||||||
|
|
||||||
populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
|
populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
@ -403,9 +419,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
|
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
|
||||||
throws BeanCreationException {
|
throws BeanCreationException {
|
||||||
|
|
||||||
AccessControlContext acc = AccessController.getContext();
|
|
||||||
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
|
||||||
public Object run() {
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Creating instance of bean '" + beanName + "'");
|
logger.debug("Creating instance of bean '" + beanName + "'");
|
||||||
}
|
}
|
||||||
|
|
@ -438,8 +451,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
logger.debug("Finished creating instance of bean '" + beanName + "'");
|
logger.debug("Finished creating instance of bean '" + beanName + "'");
|
||||||
}
|
}
|
||||||
return beanInstance;
|
return beanInstance;
|
||||||
}
|
|
||||||
}, acc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -904,9 +915,22 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
* @param mbd the bean definition for the bean
|
* @param mbd the bean definition for the bean
|
||||||
* @return BeanWrapper for the new instance
|
* @return BeanWrapper for the new instance
|
||||||
*/
|
*/
|
||||||
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
|
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
|
||||||
try {
|
try {
|
||||||
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
|
Object beanInstance = null;
|
||||||
|
final BeanFactory parent = this;
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
|
||||||
|
public Object run() {
|
||||||
|
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
|
||||||
|
}
|
||||||
|
}, getAccessControlContext());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
|
||||||
|
}
|
||||||
|
|
||||||
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
|
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
|
||||||
initBeanWrapper(bw);
|
initBeanWrapper(bw);
|
||||||
return bw;
|
return bw;
|
||||||
|
|
@ -1230,6 +1254,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
MutablePropertyValues mpvs = null;
|
MutablePropertyValues mpvs = null;
|
||||||
List<PropertyValue> original;
|
List<PropertyValue> original;
|
||||||
|
|
||||||
|
if (System.getSecurityManager()!= null) {
|
||||||
|
if (bw instanceof BeanWrapperImpl) {
|
||||||
|
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pvs instanceof MutablePropertyValues) {
|
if (pvs instanceof MutablePropertyValues) {
|
||||||
mpvs = (MutablePropertyValues) pvs;
|
mpvs = (MutablePropertyValues) pvs;
|
||||||
if (mpvs.isConverted()) {
|
if (mpvs.isConverted()) {
|
||||||
|
|
@ -1337,17 +1367,18 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
* @see #invokeInitMethods
|
* @see #invokeInitMethods
|
||||||
* @see #applyBeanPostProcessorsAfterInitialization
|
* @see #applyBeanPostProcessorsAfterInitialization
|
||||||
*/
|
*/
|
||||||
protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
|
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
|
||||||
if (bean instanceof BeanNameAware) {
|
|
||||||
((BeanNameAware) bean).setBeanName(beanName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bean instanceof BeanClassLoaderAware) {
|
if (System.getSecurityManager() != null) {
|
||||||
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
public Object run() {
|
||||||
|
invokeAwareMethods(beanName, bean);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, getAccessControlContext());
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if (bean instanceof BeanFactoryAware) {
|
invokeAwareMethods(beanName, bean);
|
||||||
((BeanFactoryAware) bean).setBeanFactory(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object wrappedBean = bean;
|
Object wrappedBean = bean;
|
||||||
|
|
@ -1370,6 +1401,20 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
return wrappedBean;
|
return wrappedBean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void invokeAwareMethods(final String beanName, final Object bean) {
|
||||||
|
if (bean instanceof BeanNameAware) {
|
||||||
|
((BeanNameAware) bean).setBeanName(beanName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bean instanceof BeanClassLoaderAware) {
|
||||||
|
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bean instanceof BeanFactoryAware) {
|
||||||
|
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Give a bean a chance to react now all its properties are set,
|
* Give a bean a chance to react now all its properties are set,
|
||||||
* and a chance to know about its owning bean factory (this object).
|
* and a chance to know about its owning bean factory (this object).
|
||||||
|
|
@ -1382,7 +1427,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
* @throws Throwable if thrown by init methods or by the invocation process
|
* @throws Throwable if thrown by init methods or by the invocation process
|
||||||
* @see #invokeCustomInitMethod
|
* @see #invokeCustomInitMethod
|
||||||
*/
|
*/
|
||||||
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)
|
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
|
|
||||||
boolean isInitializingBean = (bean instanceof InitializingBean);
|
boolean isInitializingBean = (bean instanceof InitializingBean);
|
||||||
|
|
@ -1390,7 +1435,22 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
|
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
|
||||||
}
|
}
|
||||||
((InitializingBean) bean).afterPropertiesSet();
|
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
try {
|
||||||
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
public Object run() throws Exception {
|
||||||
|
((InitializingBean) bean).afterPropertiesSet();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},getAccessControlContext());
|
||||||
|
} catch (PrivilegedActionException pae) {
|
||||||
|
throw pae.getException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
((InitializingBean) bean).afterPropertiesSet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mbd != null) {
|
if (mbd != null) {
|
||||||
|
|
@ -1413,9 +1473,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
* @param enforceInitMethod indicates whether the defined init method needs to exist
|
* @param enforceInitMethod indicates whether the defined init method needs to exist
|
||||||
* @see #invokeInitMethods
|
* @see #invokeInitMethods
|
||||||
*/
|
*/
|
||||||
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable {
|
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
|
||||||
String initMethodName = mbd.getInitMethodName();
|
String initMethodName = mbd.getInitMethodName();
|
||||||
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
|
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
|
||||||
BeanUtils.findMethod(bean.getClass(), initMethodName) :
|
BeanUtils.findMethod(bean.getClass(), initMethodName) :
|
||||||
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
|
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
|
||||||
if (initMethod == null) {
|
if (initMethod == null) {
|
||||||
|
|
@ -1437,11 +1497,23 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
|
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
|
||||||
}
|
}
|
||||||
ReflectionUtils.makeAccessible(initMethod);
|
ReflectionUtils.makeAccessible(initMethod);
|
||||||
try {
|
if (System.getSecurityManager() != null) {
|
||||||
initMethod.invoke(bean, (Object[]) null);
|
try {
|
||||||
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
|
||||||
|
public Object run() throws Exception {
|
||||||
|
initMethod.invoke(bean, (Object[]) null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, getAccessControlContext());
|
||||||
|
}
|
||||||
|
catch (PrivilegedActionException pae) {
|
||||||
|
InvocationTargetException ex = (InvocationTargetException) pae.getException();
|
||||||
|
throw ex.getTargetException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (InvocationTargetException ex) {
|
else {
|
||||||
throw ex.getTargetException();
|
initMethod.invoke(bean, (Object[]) null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,11 @@
|
||||||
package org.springframework.beans.factory.support;
|
package org.springframework.beans.factory.support;
|
||||||
|
|
||||||
import java.beans.PropertyEditor;
|
import java.beans.PropertyEditor;
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -151,6 +156,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
|
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
|
||||||
new NamedThreadLocal<Object>("Prototype beans currently in creation");
|
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.
|
* Create a new AbstractBeanFactory.
|
||||||
*/
|
*/
|
||||||
|
|
@ -196,6 +204,16 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
return doGetBean(name, requiredType, args, false);
|
return doGetBean(name, requiredType, args, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected <T> T doGetBean(
|
||||||
|
final String name, final Class<T> requiredType, final Object[] args, final boolean typeCheckOnly)
|
||||||
|
throws BeansException {
|
||||||
|
return AccessController.doPrivileged(new PrivilegedAction<T>() {
|
||||||
|
|
||||||
|
public T run() {
|
||||||
|
return doGetBeanRaw(name, requiredType, args, typeCheckOnly);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Return an instance, which may be shared or independent, of the specified bean.
|
* Return an instance, which may be shared or independent, of the specified bean.
|
||||||
* @param name the name of the bean to retrieve
|
* @param name the name of the bean to retrieve
|
||||||
|
|
@ -208,7 +226,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
* @throws BeansException if the bean could not be created
|
* @throws BeansException if the bean could not be created
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> T doGetBean(
|
private <T> T doGetBeanRaw(
|
||||||
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
|
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
|
||||||
throws BeansException {
|
throws BeansException {
|
||||||
|
|
||||||
|
|
@ -409,9 +427,19 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isFactoryBean(beanName, mbd)) {
|
if (isFactoryBean(beanName, mbd)) {
|
||||||
FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
|
final FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
|
||||||
return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean) factoryBean).isPrototype()) ||
|
if (System.getSecurityManager() != null) {
|
||||||
!factoryBean.isSingleton());
|
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||||
|
public Boolean run() {
|
||||||
|
return Boolean.valueOf(((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean) factoryBean).isPrototype()) ||
|
||||||
|
!factoryBean.isSingleton()));
|
||||||
|
}
|
||||||
|
}, getAccessControlContext()).booleanValue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean) factoryBean).isPrototype()) ||
|
||||||
|
!factoryBean.isSingleton());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -861,7 +889,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
* @param mbd the merged bean definition
|
* @param mbd the merged bean definition
|
||||||
*/
|
*/
|
||||||
protected void destroyBean(String beanName, Object beanInstance, RootBeanDefinition mbd) {
|
protected void destroyBean(String beanName, Object beanInstance, RootBeanDefinition mbd) {
|
||||||
new DisposableBeanAdapter(beanInstance, beanName, mbd, getBeanPostProcessors()).destroy();
|
new DisposableBeanAdapter(beanInstance, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroyScopedBean(String beanName) {
|
public void destroyScopedBean(String beanName) {
|
||||||
|
|
@ -1136,35 +1164,55 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
* @return the resolved bean class (or <code>null</code> if none)
|
* @return the resolved bean class (or <code>null</code> if none)
|
||||||
* @throws CannotLoadBeanClassException if we failed to load the class
|
* @throws CannotLoadBeanClassException if we failed to load the class
|
||||||
*/
|
*/
|
||||||
protected Class resolveBeanClass(RootBeanDefinition mbd, String beanName, Class[] typesToMatch)
|
protected Class resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class[] typesToMatch)
|
||||||
throws CannotLoadBeanClassException {
|
throws CannotLoadBeanClassException {
|
||||||
try {
|
try {
|
||||||
if (mbd.hasBeanClass()) {
|
if (mbd.hasBeanClass()) {
|
||||||
return mbd.getBeanClass();
|
return mbd.getBeanClass();
|
||||||
}
|
}
|
||||||
if (typesToMatch != null) {
|
|
||||||
ClassLoader tempClassLoader = getTempClassLoader();
|
if (System.getSecurityManager() != null) {
|
||||||
if (tempClassLoader != null) {
|
return AccessController.doPrivileged(new PrivilegedExceptionAction<Class>() {
|
||||||
if (tempClassLoader instanceof DecoratingClassLoader) {
|
|
||||||
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
|
public Class run() throws Exception {
|
||||||
for (Class typeToMatch : typesToMatch) {
|
return doResolveBeanClass(mbd, typesToMatch);
|
||||||
dcl.excludeClass(typeToMatch.getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
String className = mbd.getBeanClassName();
|
}, getAccessControlContext());
|
||||||
return (className != null ? ClassUtils.forName(className, tempClassLoader) : null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return mbd.resolveBeanClass(getBeanClassLoader());
|
else {
|
||||||
|
return doResolveBeanClass(mbd, typesToMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (PrivilegedActionException pae) {
|
||||||
|
ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
|
||||||
|
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), (ClassNotFoundException) ex);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException ex) {
|
catch (ClassNotFoundException ex) {
|
||||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
|
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), (ClassNotFoundException) ex);
|
||||||
}
|
}
|
||||||
catch (LinkageError err) {
|
catch (LinkageError err) {
|
||||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
|
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Class doResolveBeanClass(final RootBeanDefinition mbd, final Class[] typesToMatch)
|
||||||
|
throws ClassNotFoundException {
|
||||||
|
if (typesToMatch != null) {
|
||||||
|
ClassLoader tempClassLoader = getTempClassLoader();
|
||||||
|
if (tempClassLoader != null) {
|
||||||
|
if (tempClassLoader instanceof DecoratingClassLoader) {
|
||||||
|
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
|
||||||
|
for (Class<?> typeToMatch : typesToMatch) {
|
||||||
|
dcl.excludeClass(typeToMatch.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String className = mbd.getBeanClassName();
|
||||||
|
return (className != null ? ClassUtils.forName(className, tempClassLoader) : null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mbd.resolveBeanClass(getBeanClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate the given String as contained in a bean definition,
|
* Evaluate the given String as contained in a bean definition,
|
||||||
* potentially resolving it as an expression.
|
* potentially resolving it as an expression.
|
||||||
|
|
@ -1363,13 +1411,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
* @see #registerDependentBean
|
* @see #registerDependentBean
|
||||||
*/
|
*/
|
||||||
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
|
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
|
||||||
|
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
|
||||||
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
|
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
|
||||||
if (mbd.isSingleton()) {
|
if (mbd.isSingleton()) {
|
||||||
// Register a DisposableBean implementation that performs all destruction
|
// Register a DisposableBean implementation that performs all destruction
|
||||||
// work for the given bean: DestructionAwareBeanPostProcessors,
|
// work for the given bean: DestructionAwareBeanPostProcessors,
|
||||||
// DisposableBean interface, custom destroy method.
|
// DisposableBean interface, custom destroy method.
|
||||||
registerDisposableBean(beanName,
|
registerDisposableBean(beanName,
|
||||||
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors()));
|
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// A bean with a custom scope...
|
// A bean with a custom scope...
|
||||||
|
|
@ -1378,11 +1427,41 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");
|
throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");
|
||||||
}
|
}
|
||||||
scope.registerDestructionCallback(beanName,
|
scope.registerDestructionCallback(beanName,
|
||||||
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors()));
|
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* Delegate the creation of the security context to {@link #getSecurityContextProvider()}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected AccessControlContext getAccessControlContext() {
|
||||||
|
SecurityContextProvider provider = getSecurityContextProvider();
|
||||||
|
return (provider != null ? provider.getAccessControlContext(): null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
// Abstract methods to be implemented by subclasses
|
||||||
|
|
@ -1442,5 +1521,4 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
*/
|
*/
|
||||||
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
|
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
|
||||||
throws BeanCreationException;
|
throws BeanCreationException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@ import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
@ -99,7 +102,7 @@ class ConstructorResolver {
|
||||||
* @return a BeanWrapper for the new instance
|
* @return a BeanWrapper for the new instance
|
||||||
*/
|
*/
|
||||||
public BeanWrapper autowireConstructor(
|
public BeanWrapper autowireConstructor(
|
||||||
String beanName, RootBeanDefinition mbd, Constructor[] chosenCtors, Object[] explicitArgs) {
|
final String beanName, final RootBeanDefinition mbd, Constructor[] chosenCtors, final Object[] explicitArgs) {
|
||||||
|
|
||||||
BeanWrapperImpl bw = new BeanWrapperImpl();
|
BeanWrapperImpl bw = new BeanWrapperImpl();
|
||||||
this.beanFactory.initBeanWrapper(bw);
|
this.beanFactory.initBeanWrapper(bw);
|
||||||
|
|
@ -256,8 +259,25 @@ class ConstructorResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Object beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
|
Object beanInstance = null;
|
||||||
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
|
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
final Constructor ctorToUse = constructorToUse;
|
||||||
|
final Object[] argumentsToUse = argsToUse;
|
||||||
|
|
||||||
|
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
|
||||||
|
public Object run() {
|
||||||
|
return beanFactory.getInstantiationStrategy().instantiate(
|
||||||
|
mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
|
||||||
|
}
|
||||||
|
}, beanFactory.getAccessControlContext());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
beanInstance = beanFactory.getInstantiationStrategy().instantiate(
|
||||||
|
mbd, beanName, beanFactory, constructorToUse, argsToUse);
|
||||||
|
}
|
||||||
|
|
||||||
bw.setWrappedInstance(beanInstance);
|
bw.setWrappedInstance(beanInstance);
|
||||||
return bw;
|
return bw;
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +331,7 @@ class ConstructorResolver {
|
||||||
* method, or <code>null</code> if none (-> use constructor argument values from bean definition)
|
* method, or <code>null</code> if none (-> use constructor argument values from bean definition)
|
||||||
* @return a BeanWrapper for the new instance
|
* @return a BeanWrapper for the new instance
|
||||||
*/
|
*/
|
||||||
public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {
|
public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
|
||||||
BeanWrapperImpl bw = new BeanWrapperImpl();
|
BeanWrapperImpl bw = new BeanWrapperImpl();
|
||||||
this.beanFactory.initBeanWrapper(bw);
|
this.beanFactory.initBeanWrapper(bw);
|
||||||
|
|
||||||
|
|
@ -491,8 +511,27 @@ class ConstructorResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Object beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
|
|
||||||
mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
|
Object beanInstance = null;
|
||||||
|
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
final Object fb = factoryBean;
|
||||||
|
final Method factoryMethod = factoryMethodToUse;
|
||||||
|
final Object[] args = argsToUse;
|
||||||
|
|
||||||
|
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
|
||||||
|
public Object run() {
|
||||||
|
return beanFactory.getInstantiationStrategy().instantiate(
|
||||||
|
mbd, beanName, beanFactory, fb, factoryMethod, args);
|
||||||
|
}
|
||||||
|
}, beanFactory.getAccessControlContext());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
beanInstance = beanFactory.getInstantiationStrategy().instantiate(
|
||||||
|
mbd, beanName, beanFactory, factoryBean, factoryMethodToUse, argsToUse);
|
||||||
|
}
|
||||||
|
|
||||||
if (beanInstance == null) {
|
if (beanInstance == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -808,5 +847,4 @@ class ConstructorResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -21,6 +21,8 @@ import java.io.Serializable;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -179,10 +181,21 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
* when deciding whether a bean definition should be considered as a
|
* when deciding whether a bean definition should be considered as a
|
||||||
* candidate for autowiring.
|
* candidate for autowiring.
|
||||||
*/
|
*/
|
||||||
public void setAutowireCandidateResolver(AutowireCandidateResolver autowireCandidateResolver) {
|
public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
|
||||||
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
|
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
|
||||||
if (autowireCandidateResolver instanceof BeanFactoryAware) {
|
if (autowireCandidateResolver instanceof BeanFactoryAware) {
|
||||||
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
|
if (System.getSecurityManager() != null) {
|
||||||
|
final BeanFactory target = this;
|
||||||
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
public Object run() {
|
||||||
|
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(target);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, getAccessControlContext());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.autowireCandidateResolver = autowireCandidateResolver;
|
this.autowireCandidateResolver = autowireCandidateResolver;
|
||||||
}
|
}
|
||||||
|
|
@ -493,8 +506,20 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
|
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
|
||||||
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
|
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
|
||||||
if (isFactoryBean(beanName)) {
|
if (isFactoryBean(beanName)) {
|
||||||
FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
|
final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
|
||||||
if (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()) {
|
boolean isEagerInit = false;
|
||||||
|
|
||||||
|
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
|
||||||
|
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||||
|
public Boolean run() {
|
||||||
|
return Boolean.valueOf(((SmartFactoryBean) factory).isEagerInit());
|
||||||
|
}
|
||||||
|
}, getAccessControlContext()).booleanValue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();
|
||||||
|
}
|
||||||
|
if (isEagerInit) {
|
||||||
getBean(beanName);
|
getBean(beanName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ package org.springframework.beans.factory.support;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -66,6 +70,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
|
|
||||||
private List<DestructionAwareBeanPostProcessor> beanPostProcessors;
|
private List<DestructionAwareBeanPostProcessor> beanPostProcessors;
|
||||||
|
|
||||||
|
private final AccessControlContext acc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new DisposableBeanAdapter for the given bean.
|
* Create a new DisposableBeanAdapter for the given bean.
|
||||||
|
|
@ -76,7 +81,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
* (potentially DestructionAwareBeanPostProcessor), if any
|
* (potentially DestructionAwareBeanPostProcessor), if any
|
||||||
*/
|
*/
|
||||||
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
|
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
|
||||||
List<BeanPostProcessor> postProcessors) {
|
List<BeanPostProcessor> postProcessors, AccessControlContext acc) {
|
||||||
|
|
||||||
Assert.notNull(bean, "Bean must not be null");
|
Assert.notNull(bean, "Bean must not be null");
|
||||||
this.bean = bean;
|
this.bean = bean;
|
||||||
|
|
@ -84,6 +89,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
this.invokeDisposableBean =
|
this.invokeDisposableBean =
|
||||||
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
|
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
|
||||||
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
|
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
|
||||||
|
this.acc = acc;
|
||||||
|
|
||||||
String destroyMethodName = beanDefinition.getDestroyMethodName();
|
String destroyMethodName = beanDefinition.getDestroyMethodName();
|
||||||
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
|
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
|
||||||
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
|
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
|
||||||
|
|
@ -131,6 +138,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
|
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
|
||||||
this.destroyMethodName = destroyMethodName;
|
this.destroyMethodName = destroyMethodName;
|
||||||
this.beanPostProcessors = postProcessors;
|
this.beanPostProcessors = postProcessors;
|
||||||
|
this.acc = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -169,7 +177,18 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
|
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
((DisposableBean) this.bean).destroy();
|
if (System.getSecurityManager() != null) {
|
||||||
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
|
||||||
|
public Object run() throws Exception {
|
||||||
|
((DisposableBean) bean).destroy();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, acc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
((DisposableBean) bean).destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
|
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
|
||||||
|
|
@ -199,9 +218,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
* for a method with a single boolean argument (passing in "true",
|
* for a method with a single boolean argument (passing in "true",
|
||||||
* assuming a "force" parameter), else logging an error.
|
* assuming a "force" parameter), else logging an error.
|
||||||
*/
|
*/
|
||||||
private void invokeCustomDestroyMethod(Method destroyMethod) {
|
private void invokeCustomDestroyMethod(final Method destroyMethod) {
|
||||||
Class[] paramTypes = destroyMethod.getParameterTypes();
|
Class[] paramTypes = destroyMethod.getParameterTypes();
|
||||||
Object[] args = new Object[paramTypes.length];
|
final Object[] args = new Object[paramTypes.length];
|
||||||
if (paramTypes.length == 1) {
|
if (paramTypes.length == 1) {
|
||||||
args[0] = Boolean.TRUE;
|
args[0] = Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -211,9 +230,22 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
}
|
}
|
||||||
ReflectionUtils.makeAccessible(destroyMethod);
|
ReflectionUtils.makeAccessible(destroyMethod);
|
||||||
try {
|
try {
|
||||||
destroyMethod.invoke(this.bean, args);
|
if (System.getSecurityManager() != null) {
|
||||||
}
|
try {
|
||||||
catch (InvocationTargetException ex) {
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
public Object run() throws Exception {
|
||||||
|
destroyMethod.invoke(bean, args);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, acc);
|
||||||
|
} catch (PrivilegedActionException pax) {
|
||||||
|
throw (InvocationTargetException) pax.getException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
destroyMethod.invoke(bean, args);
|
||||||
|
}
|
||||||
|
} catch (InvocationTargetException ex) {
|
||||||
String msg = "Invocation of destroy method '" + this.destroyMethodName +
|
String msg = "Invocation of destroy method '" + this.destroyMethodName +
|
||||||
"' failed on bean with name '" + this.beanName + "'";
|
"' failed on bean with name '" + this.beanName + "'";
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ package org.springframework.beans.factory.support;
|
||||||
import java.security.AccessControlContext;
|
import java.security.AccessControlContext;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
|
@ -50,9 +52,18 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||||
* @return the FactoryBean's object type,
|
* @return the FactoryBean's object type,
|
||||||
* or <code>null</code> if the type cannot be determined yet
|
* or <code>null</code> if the type cannot be determined yet
|
||||||
*/
|
*/
|
||||||
protected Class getTypeForFactoryBean(FactoryBean factoryBean) {
|
protected Class getTypeForFactoryBean(final FactoryBean factoryBean) {
|
||||||
try {
|
try {
|
||||||
return factoryBean.getObjectType();
|
if (System.getSecurityManager() != null) {
|
||||||
|
return AccessController.doPrivileged(new PrivilegedAction<Class>() {
|
||||||
|
public Class run() {
|
||||||
|
return factoryBean.getObjectType();
|
||||||
|
}
|
||||||
|
}, getAccessControlContext());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return factoryBean.getObjectType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
// Thrown from the FactoryBean's getObjectType implementation.
|
// Thrown from the FactoryBean's getObjectType implementation.
|
||||||
|
|
@ -112,40 +123,51 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||||
final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
|
final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
|
||||||
throws BeanCreationException {
|
throws BeanCreationException {
|
||||||
|
|
||||||
AccessControlContext acc = AccessController.getContext();
|
|
||||||
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
|
||||||
public Object run() {
|
|
||||||
Object object;
|
|
||||||
|
|
||||||
|
|
||||||
|
Object object;
|
||||||
|
try {
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
AccessControlContext acc = getAccessControlContext();
|
||||||
try {
|
try {
|
||||||
object = factory.getObject();
|
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
public Object run() throws Exception {
|
||||||
|
return factory.getObject();
|
||||||
|
}
|
||||||
|
}, acc);
|
||||||
|
} catch (PrivilegedActionException pae) {
|
||||||
|
throw pae.getException();
|
||||||
}
|
}
|
||||||
catch (FactoryBeanNotInitializedException ex) {
|
|
||||||
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
|
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not accept a null value for a FactoryBean that's not fully
|
|
||||||
// initialized yet: Many FactoryBeans just return null then.
|
|
||||||
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
|
|
||||||
throw new BeanCurrentlyInCreationException(
|
|
||||||
beanName, "FactoryBean which is currently in creation returned null from getObject");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (object != null && shouldPostProcess) {
|
|
||||||
try {
|
|
||||||
object = postProcessObjectFromFactoryBean(object, beanName);
|
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
}, acc);
|
else {
|
||||||
|
object = factory.getObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FactoryBeanNotInitializedException ex) {
|
||||||
|
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Do not accept a null value for a FactoryBean that's not fully
|
||||||
|
// initialized yet: Many FactoryBeans just return null then.
|
||||||
|
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
|
||||||
|
throw new BeanCurrentlyInCreationException(
|
||||||
|
beanName, "FactoryBean which is currently in creation returned null from getObject");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object != null && shouldPostProcess) {
|
||||||
|
try {
|
||||||
|
object = postProcessObjectFromFactoryBean(object, beanName);
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -186,4 +208,14 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||||
this.factoryBeanObjectCache.remove(beanName);
|
this.factoryBeanObjectCache.remove(beanName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
protected AccessControlContext getAccessControlContext() {
|
||||||
|
return AccessController.getContext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support;
|
||||||
|
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider of the security context of the code running inside the bean factory.
|
||||||
|
*
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public interface SecurityContextProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a security access control context relevant to a bean factory.
|
||||||
|
*
|
||||||
|
* @return bean factory security control context
|
||||||
|
*/
|
||||||
|
AccessControlContext getAccessControlContext();
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,9 @@ package org.springframework.beans.factory.support;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
|
||||||
import org.springframework.beans.BeanInstantiationException;
|
import org.springframework.beans.BeanInstantiationException;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
@ -46,12 +49,17 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||||
if (beanDefinition.getMethodOverrides().isEmpty()) {
|
if (beanDefinition.getMethodOverrides().isEmpty()) {
|
||||||
Constructor constructorToUse = (Constructor) beanDefinition.resolvedConstructorOrFactoryMethod;
|
Constructor constructorToUse = (Constructor) beanDefinition.resolvedConstructorOrFactoryMethod;
|
||||||
if (constructorToUse == null) {
|
if (constructorToUse == null) {
|
||||||
Class clazz = beanDefinition.getBeanClass();
|
final Class clazz = beanDefinition.getBeanClass();
|
||||||
if (clazz.isInterface()) {
|
if (clazz.isInterface()) {
|
||||||
throw new BeanInstantiationException(clazz, "Specified class is an interface");
|
throw new BeanInstantiationException(clazz, "Specified class is an interface");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
|
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {
|
||||||
|
|
||||||
|
public Constructor run() throws Exception {
|
||||||
|
return clazz.getDeclaredConstructor((Class[]) null);
|
||||||
|
}
|
||||||
|
});
|
||||||
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
|
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
|
@ -107,11 +115,17 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||||
|
|
||||||
public Object instantiate(
|
public Object instantiate(
|
||||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||||
Object factoryBean, Method factoryMethod, Object[] args) {
|
Object factoryBean, final Method factoryMethod, Object[] args) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// It's a static method if the target is null.
|
// It's a static method if the target is null.
|
||||||
ReflectionUtils.makeAccessible(factoryMethod);
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
|
||||||
|
public Object run() {
|
||||||
|
ReflectionUtils.makeAccessible(factoryMethod);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
return factoryMethod.invoke(factoryBean, args);
|
return factoryMethod.invoke(factoryBean, args);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException ex) {
|
catch (IllegalArgumentException ex) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support;
|
||||||
|
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
import java.security.AccessController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple #SecurityContextProvider implementation.
|
||||||
|
*
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* thread.
|
||||||
|
*/
|
||||||
|
public SimpleSecurityContextProvider() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new <code>SimpleSecurityContextProvider</code> instance.
|
||||||
|
*
|
||||||
|
* If the given control context is null, the security context will be
|
||||||
|
* retrieved on each call from the current thread.
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support.security;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.Permissions;
|
||||||
|
import java.security.Policy;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.PropertyPermission;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanCreationException;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanFactory;
|
||||||
|
import org.springframework.beans.factory.support.SecurityContextProvider;
|
||||||
|
import org.springframework.beans.factory.support.security.support.ConstructorBean;
|
||||||
|
import org.springframework.beans.factory.support.security.support.CustomCallbackBean;
|
||||||
|
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public class CallbacksSecurityTest extends TestCase {
|
||||||
|
|
||||||
|
private XmlBeanFactory beanFactory;
|
||||||
|
private SecurityContextProvider provider;
|
||||||
|
|
||||||
|
public CallbacksSecurityTest() {
|
||||||
|
// setup security
|
||||||
|
if (System.getSecurityManager() == null) {
|
||||||
|
Policy policy = Policy.getPolicy();
|
||||||
|
URL policyURL = getClass().getResource("/org/springframework/beans/factory/support/security/policy.all");
|
||||||
|
System.setProperty("java.security.policy", policyURL.toString());
|
||||||
|
System.setProperty("policy.allowSystemProperty", "true");
|
||||||
|
policy.refresh();
|
||||||
|
|
||||||
|
System.setSecurityManager(new SecurityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
|
||||||
|
final ProtectionDomain empty = new ProtectionDomain(null, new Permissions());
|
||||||
|
|
||||||
|
provider = new SecurityContextProvider() {
|
||||||
|
private final AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] { empty });
|
||||||
|
|
||||||
|
public AccessControlContext getAccessControlContext() {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DefaultResourceLoader drl = new DefaultResourceLoader();
|
||||||
|
Resource config = drl.getResource("/org/springframework/beans/factory/support/security/callbacks.xml");
|
||||||
|
beanFactory = new XmlBeanFactory(config);
|
||||||
|
|
||||||
|
beanFactory.setSecurityContextProvider(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSecuritySanity() throws Exception {
|
||||||
|
AccessControlContext acc = provider.getAccessControlContext();
|
||||||
|
try {
|
||||||
|
acc.checkPermission(new PropertyPermission("*", "read"));
|
||||||
|
fail("Acc should not have any permissions");
|
||||||
|
} catch (SecurityException se) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
|
final CustomCallbackBean bean = new CustomCallbackBean();
|
||||||
|
final Method method = bean.getClass().getMethod("destroy", null);
|
||||||
|
method.setAccessible(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||||
|
|
||||||
|
public Object run() throws Exception {
|
||||||
|
method.invoke(bean, null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, acc);
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
final Class<ConstructorBean> cl = ConstructorBean.class;
|
||||||
|
try {
|
||||||
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||||
|
|
||||||
|
public Object run() throws Exception {
|
||||||
|
return cl.newInstance();
|
||||||
|
}
|
||||||
|
}, acc);
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSpringInitBean() throws Exception {
|
||||||
|
try {
|
||||||
|
beanFactory.getBean("spring-init");
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (BeanCreationException ex) {
|
||||||
|
assertTrue(ex.getCause() instanceof SecurityException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCustomInitBean() throws Exception {
|
||||||
|
try {
|
||||||
|
beanFactory.getBean("custom-init");
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (BeanCreationException ex) {
|
||||||
|
assertTrue(ex.getCause() instanceof SecurityException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSpringDestroyBean() throws Exception {
|
||||||
|
beanFactory.getBean("spring-destroy");
|
||||||
|
beanFactory.destroySingletons();
|
||||||
|
assertNull(System.getProperty("security.destroy"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCustomDestroyBean() throws Exception {
|
||||||
|
beanFactory.getBean("custom-destroy");
|
||||||
|
beanFactory.destroySingletons();
|
||||||
|
assertNull(System.getProperty("security.destroy"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCustomFactoryObject() throws Exception {
|
||||||
|
try {
|
||||||
|
beanFactory.getBean("spring-factory");
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (BeanCreationException ex) {
|
||||||
|
assertTrue(ex.getCause() instanceof SecurityException);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCustomFactoryType() throws Exception {
|
||||||
|
assertNull(beanFactory.getType("spring-factory"));
|
||||||
|
assertNull(System.getProperty("factory.object.type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCustomStaticFactoryMethod() throws Exception {
|
||||||
|
try {
|
||||||
|
beanFactory.getBean("custom-static-factory-method");
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (BeanCreationException ex) {
|
||||||
|
assertTrue(ex.getMostSpecificCause() instanceof SecurityException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCustomInstanceFactoryMethod() throws Exception {
|
||||||
|
try {
|
||||||
|
beanFactory.getBean("custom-factory-method");
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (BeanCreationException ex) {
|
||||||
|
assertTrue(ex.getMostSpecificCause() instanceof SecurityException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTrustedFactoryMethod() throws Exception {
|
||||||
|
try {
|
||||||
|
beanFactory.getBean("trusted-factory-method");
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (BeanCreationException ex) {
|
||||||
|
assertTrue(ex.getMostSpecificCause() instanceof SecurityException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConstructor() throws Exception {
|
||||||
|
try {
|
||||||
|
beanFactory.getBean("constructor");
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (BeanCreationException ex) {
|
||||||
|
// expected
|
||||||
|
assertTrue(ex.getMostSpecificCause() instanceof SecurityException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testContainerPriviledges() throws Exception {
|
||||||
|
AccessControlContext acc = provider.getAccessControlContext();
|
||||||
|
|
||||||
|
AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||||
|
|
||||||
|
public Object run() throws Exception {
|
||||||
|
beanFactory.getBean("working-factory-method");
|
||||||
|
beanFactory.getBean("container-execution");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPropertyInjection() throws Exception {
|
||||||
|
try {
|
||||||
|
beanFactory.getBean("property-injection");
|
||||||
|
fail("expected security exception");
|
||||||
|
} catch (BeanCreationException ex) {
|
||||||
|
assertTrue(ex.getMessage().contains("security"));
|
||||||
|
}
|
||||||
|
|
||||||
|
beanFactory.getBean("working-property-injection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
|
||||||
|
default-lazy-init="true">
|
||||||
|
|
||||||
|
<bean name="spring-init" class="org.springframework.beans.factory.support.security.support.InitBean"/>
|
||||||
|
|
||||||
|
<bean name="spring-destroy" class="org.springframework.beans.factory.support.security.support.DestroyBean"/>
|
||||||
|
|
||||||
|
<bean name="custom-init" class="org.springframework.beans.factory.support.security.support.CustomCallbackBean"
|
||||||
|
init-method="init"/>
|
||||||
|
|
||||||
|
<bean name="custom-destroy" class="org.springframework.beans.factory.support.security.support.CustomCallbackBean"
|
||||||
|
destroy-method="destroy"/>
|
||||||
|
|
||||||
|
<bean name="spring-factory" class="org.springframework.beans.factory.support.security.support.CustomFactoryBean"/>
|
||||||
|
|
||||||
|
<bean name="custom-static-factory-method" class="org.springframework.beans.factory.support.security.support.FactoryBean" factory-method="makeStaticInstance"/>
|
||||||
|
|
||||||
|
<bean name="factory-bean" class="org.springframework.beans.factory.support.security.support.FactoryBean"/>
|
||||||
|
|
||||||
|
<bean name="custom-factory-method" factory-bean="factory-bean" factory-method="makeInstance"/>
|
||||||
|
|
||||||
|
<bean name="trusted-factory-method" class="java.lang.System" factory-method="getProperties"/>
|
||||||
|
|
||||||
|
<bean name="constructor" class="org.springframework.beans.factory.support.security.support.ConstructorBean"/>
|
||||||
|
|
||||||
|
<bean name="working-factory-method" class="org.springframework.beans.factory.support.security.support.FactoryBean" factory-method="protectedStaticInstance"/>
|
||||||
|
|
||||||
|
<bean name="container-execution" class="org.springframework.beans.factory.support.security.support.ConstructorBean">
|
||||||
|
<constructor-arg ref="working-factory-method"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="property-injection" class="org.springframework.beans.factory.support.security.support.PropertyBean">
|
||||||
|
<property name="securityProperty" value="value"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="working-property-injection" class="org.springframework.beans.factory.support.security.support.PropertyBean">
|
||||||
|
<property name="property">
|
||||||
|
<array>
|
||||||
|
<ref bean="working-factory-method"/>
|
||||||
|
</array>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
grant {
|
||||||
|
permission java.security.AllPermission;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support.security.support;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public class ConstructorBean {
|
||||||
|
|
||||||
|
public ConstructorBean() {
|
||||||
|
System.getProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstructorBean(Object obj) {
|
||||||
|
System.out.println("Received object " + obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support.security.support;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public class CustomCallbackBean {
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
System.getProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
System.setProperty("security.destroy", "true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support.security.support;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public class CustomFactoryBean implements FactoryBean<Object> {
|
||||||
|
|
||||||
|
public Object getObject() throws Exception {
|
||||||
|
return System.getProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getObjectType() {
|
||||||
|
System.setProperty("factory.object.type", "true");
|
||||||
|
return Properties.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSingleton() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support.security.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public class DestroyBean implements DisposableBean {
|
||||||
|
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
System.setProperty("security.destroy", "true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support.security.support;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public class FactoryBean {
|
||||||
|
|
||||||
|
public static Object makeStaticInstance() {
|
||||||
|
System.getProperties();
|
||||||
|
return new Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Object protectedStaticInstance() {
|
||||||
|
return "protectedStaticInstance";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object makeInstance() {
|
||||||
|
System.getProperties();
|
||||||
|
return new Object();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support.security.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public class InitBean implements InitializingBean {
|
||||||
|
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
System.getProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006-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.beans.factory.support.security.support;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Costin Leau
|
||||||
|
*/
|
||||||
|
public class PropertyBean {
|
||||||
|
|
||||||
|
public void setSecurityProperty(Object property) {
|
||||||
|
System.getProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperty(Object property) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,11 +16,18 @@
|
||||||
|
|
||||||
package org.springframework.context.support;
|
package org.springframework.context.support;
|
||||||
|
|
||||||
|
import java.security.AccessControlContext;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanFactory;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.context.ApplicationEventPublisherAware;
|
import org.springframework.context.ApplicationEventPublisherAware;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.MessageSourceAware;
|
import org.springframework.context.MessageSourceAware;
|
||||||
import org.springframework.context.ResourceLoaderAware;
|
import org.springframework.context.ResourceLoaderAware;
|
||||||
|
|
||||||
|
|
@ -56,7 +63,35 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
|
||||||
|
AccessControlContext acc = null;
|
||||||
|
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
if (applicationContext instanceof ConfigurableApplicationContext) {
|
||||||
|
ConfigurableListableBeanFactory factory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
|
||||||
|
if (factory instanceof AbstractBeanFactory) {
|
||||||
|
acc = ((AbstractBeanFactory) factory).getSecurityContextProvider().getAccessControlContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// optimize - check the bean class before creating the inner class + native call
|
||||||
|
if (bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware
|
||||||
|
|| bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware) {
|
||||||
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
public Object run() {
|
||||||
|
doProcess(bean);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
doProcess(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doProcess(Object bean) {
|
||||||
if (bean instanceof ResourceLoaderAware) {
|
if (bean instanceof ResourceLoaderAware) {
|
||||||
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
|
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
|
||||||
}
|
}
|
||||||
|
|
@ -69,11 +104,9 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||||
if (bean instanceof ApplicationContextAware) {
|
if (bean instanceof ApplicationContextAware) {
|
||||||
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
|
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
|
||||||
}
|
}
|
||||||
return bean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object postProcessAfterInitialization(Object bean, String name) {
|
public Object postProcessAfterInitialization(Object bean, String name) {
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue