Skip to content

Commit

Permalink
+ interaction with user code uses now dedicated privileged when runni…
Browse files Browse the repository at this point in the history
…ng under a security manager
  • Loading branch information
Costin Leau committed Aug 6, 2009
1 parent fe5b502 commit d5d3104
Show file tree
Hide file tree
Showing 21 changed files with 1,099 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
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.HashMap;
import java.util.Iterator;
Expand All @@ -31,7 +35,6 @@

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.util.Assert;
Expand Down Expand Up @@ -102,6 +105,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
*/
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.
Expand Down Expand Up @@ -198,6 +204,16 @@ public void setWrappedInstance(Object object, String nestedPath, Object rootObje
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() {
return this.object;
}
Expand Down Expand Up @@ -539,12 +555,29 @@ private Object getPropertyValue(PropertyTokenHolder tokens) throws BeansExceptio
if (pd == null || pd.getReadMethod() == null) {
throw new NotReadablePropertyException(getRootClass(), this.nestedPath + propertyName);
}
Method readMethod = pd.getReadMethod();
final Method readMethod = pd.getReadMethod();
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
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) {
// apply indexes and map keys
for (int i = 0; i < tokens.keys.length; i++) {
Expand Down Expand Up @@ -602,7 +635,8 @@ else if (value instanceof Map) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Getter for property '" + actualName + "' threw exception", ex);
}
catch (IllegalAccessException ex) {

catch(IllegalAccessException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
}
Expand All @@ -614,6 +648,10 @@ else if (value instanceof Map) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"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
Expand Down Expand Up @@ -813,14 +851,26 @@ else if (propValue instanceof Map) {
}
else {
if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {
Method readMethod = pd.getReadMethod();
final Method readMethod = pd.getReadMethod();
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
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) {
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" +
this.nestedPath + propertyName + "'", ex);
Expand All @@ -831,11 +881,28 @@ else if (propValue instanceof Map) {
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
Method writeMethod = pd.getWriteMethod();
final Method writeMethod = pd.getWriteMethod();
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
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) {
PropertyChangeEvent propertyChangeEvent =
Expand All @@ -862,6 +929,11 @@ else if (propValue instanceof Map) {
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
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);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
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.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -330,13 +332,27 @@ public Object createBean(Class beanClass, int autowireMode, boolean dependencyCh

public Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
// 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);
if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) {
return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance();
}
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));
return bean;
}
Expand Down Expand Up @@ -403,9 +419,6 @@ public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, St
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {

AccessControlContext acc = AccessController.getContext();
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
Expand Down Expand Up @@ -438,8 +451,6 @@ public Object run() {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
}, acc);
}

/**
Expand Down Expand Up @@ -904,9 +915,22 @@ protected Constructor[] determineConstructorsFromBeanPostProcessors(Class beanCl
* @param mbd the bean definition for the bean
* @return BeanWrapper for the new instance
*/
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
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);
initBeanWrapper(bw);
return bw;
Expand Down Expand Up @@ -1229,6 +1253,12 @@ protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrap

MutablePropertyValues mpvs = null;
List<PropertyValue> original;

if (System.getSecurityManager()!= null) {
if (bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}

if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
Expand Down Expand Up @@ -1337,19 +1367,20 @@ private Object convertForProperty(Object value, String propertyName, BeanWrapper
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}

if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {

if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}

if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
else {
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
Expand All @@ -1369,6 +1400,20 @@ protected Object initializeBean(String beanName, Object bean, RootBeanDefinition
}
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,
Expand All @@ -1382,15 +1427,30 @@ protected Object initializeBean(String beanName, Object bean, RootBeanDefinition
* @throws Throwable if thrown by init methods or by the invocation process
* @see #invokeCustomInitMethod
*/
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {

boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
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) {
Expand All @@ -1413,9 +1473,9 @@ protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinitio
* @param enforceInitMethod indicates whether the defined init method needs to exist
* @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();
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
Expand All @@ -1437,11 +1497,23 @@ protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefi
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
ReflectionUtils.makeAccessible(initMethod);
try {
initMethod.invoke(bean, (Object[]) null);
if (System.getSecurityManager() != 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) {
throw ex.getTargetException();
else {
initMethod.invoke(bean, (Object[]) null);
}
}

Expand Down
Loading

0 comments on commit d5d3104

Please sign in to comment.