Browse Source

resolveFactoryMethodIfPossible considers nonPublicAccessAllowed and SecurityManager

Issue: SPR-11422
(cherry picked from commit 603cdea)
pull/465/head
Juergen Hoeller 12 years ago
parent
commit
0972582880
  1. 82
      spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java

82
spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -54,12 +54,9 @@ import org.springframework.util.ReflectionUtils; @@ -54,12 +54,9 @@ import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
* Helper class for resolving constructors and factory methods.
* Delegate for resolving constructors and factory methods.
* Performs constructor resolution through argument matching.
*
* <p>Operates on an {@link AbstractBeanFactory} and an {@link InstantiationStrategy}.
* Used by {@link AbstractAutowireCapableBeanFactory}.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @author Mark Fisher
@ -103,12 +100,12 @@ class ConstructorResolver { @@ -103,12 +100,12 @@ class ConstructorResolver {
* @return a BeanWrapper for the new instance
*/
public BeanWrapper autowireConstructor(
final String beanName, final RootBeanDefinition mbd, Constructor[] chosenCtors, final Object[] explicitArgs) {
final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor constructorToUse = null;
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
@ -118,7 +115,7 @@ class ConstructorResolver { @@ -118,7 +115,7 @@ class ConstructorResolver {
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
argsToUse = mbd.resolvedConstructorArguments;
@ -149,7 +146,7 @@ class ConstructorResolver { @@ -149,7 +146,7 @@ class ConstructorResolver {
}
// Take specified constructors, if any.
Constructor[] candidates = chosenCtors;
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
@ -164,7 +161,7 @@ class ConstructorResolver { @@ -164,7 +161,7 @@ class ConstructorResolver {
}
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor> ambiguousConstructors = null;
Set<Constructor<?>> ambiguousConstructors = null;
List<Exception> causes = null;
for (int i = 0; i < candidates.length; i++) {
@ -185,7 +182,7 @@ class ConstructorResolver { @@ -185,7 +182,7 @@ class ConstructorResolver {
try {
String[] paramNames = null;
if (constructorPropertiesAnnotationAvailable) {
paramNames = ConstructorPropertiesChecker.evaluateAnnotation(candidate, paramTypes.length);
paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
}
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
@ -239,7 +236,7 @@ class ConstructorResolver { @@ -239,7 +236,7 @@ class ConstructorResolver {
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<Constructor>();
ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
@ -267,7 +264,7 @@ class ConstructorResolver { @@ -267,7 +264,7 @@ class ConstructorResolver {
Object beanInstance;
if (System.getSecurityManager() != null) {
final Constructor ctorToUse = constructorToUse;
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
@ -295,18 +292,22 @@ class ConstructorResolver { @@ -295,18 +292,22 @@ class ConstructorResolver {
* @param mbd the bean definition to check
*/
public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
Class factoryClass;
Class<?> factoryClass;
boolean isStatic;
if (mbd.getFactoryBeanName() != null) {
factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
isStatic = false;
}
else {
factoryClass = mbd.getBeanClass();
isStatic = true;
}
factoryClass = ClassUtils.getUserClass(factoryClass);
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
Method[] candidates = getCandidateMethods(factoryClass, mbd);
Method uniqueCandidate = null;
for (Method candidate : candidates) {
if (mbd.isFactoryMethod(candidate)) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
if (uniqueCandidate == null) {
uniqueCandidate = candidate;
}
@ -321,6 +322,27 @@ class ConstructorResolver { @@ -321,6 +322,27 @@ class ConstructorResolver {
}
}
/**
* Retrieve all candidate methods for the given class, considering
* the {@link RootBeanDefinition#isNonPublicAccessAllowed()} flag.
* Called as the starting point for factory method determination.
*/
private Method[] getCandidateMethods(final Class<?> factoryClass, final RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
@Override
public Method[] run() {
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
}
});
}
else {
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
}
}
/**
* Instantiate the bean using a named factory method. The method may be static, if the
* bean definition parameter specifies a class, rather than a "factory-bean", or
@ -336,7 +358,9 @@ class ConstructorResolver { @@ -336,7 +358,9 @@ class ConstructorResolver {
* method, or {@code null} if none (-> use constructor argument values from bean definition)
* @return a BeanWrapper for the new instance
*/
public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
public BeanWrapper instantiateUsingFactoryMethod(
final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
@ -397,27 +421,11 @@ class ConstructorResolver { @@ -397,27 +421,11 @@ class ConstructorResolver {
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
factoryClass = ClassUtils.getUserClass(factoryClass);
Method[] rawCandidates;
final Class<?> factoryClazz = factoryClass;
if (System.getSecurityManager() != null) {
rawCandidates = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
public Method[] run() {
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
}
});
}
else {
rawCandidates = (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
}
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
List<Method> candidateSet = new ArrayList<Method>();
for (Method candidate : rawCandidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
candidate.getName().equals(mbd.getFactoryMethodName()) &&
mbd.isFactoryMethod(candidate)) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidateSet.add(candidate);
}
}
@ -759,7 +767,7 @@ class ConstructorResolver { @@ -759,7 +767,7 @@ class ConstructorResolver {
String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
((Method) methodOrCtor).getParameterTypes() : ((Constructor) methodOrCtor).getParameterTypes());
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
BeanDefinitionValueResolver valueResolver =
@ -881,7 +889,7 @@ class ConstructorResolver { @@ -881,7 +889,7 @@ class ConstructorResolver {
*/
private static class ConstructorPropertiesChecker {
public static String[] evaluateAnnotation(Constructor<?> candidate, int paramCount) {
public static String[] evaluate(Constructor<?> candidate, int paramCount) {
ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
if (cp != null) {
String[] names = cp.value();

Loading…
Cancel
Save