Skip to content

Commit

Permalink
Sync with 3.1.x
Browse files Browse the repository at this point in the history
* 3.1.x: (61 commits)
  Compensate for changes in JDK 7 Introspector
  Avoid 'type mismatch' errors in ExtendedBeanInfo
  Polish ExtendedBeanInfo and tests
  Infer AnnotationAttributes method return types
  Minor fix in MVC reference doc chapter
  Hibernate 4.1 etc
  TypeDescriptor equals implementation accepts annotations in any order
  "setBasenames" uses varargs now (for programmatic setup; SPR-9106)
  @activeprofiles mechanism works with @ImportResource as well (SPR-8992
  polishing
  clarified Resource's "getFilename" method to consistently return null
  substituteNamedParameters detects and unwraps SqlParameterValue object
  Replace spaces with tabs
  Consider security in ClassUtils#getMostSpecificMethod
  Adding null check for username being null.
  Improvements for registering custom SQL exception translators in app c
  SPR-7680 Adding QueryTimeoutException to the DataAccessException hiera
  Minor polish in WebMvcConfigurationSupport
  Detect overridden boolean getters in ExtendedBeanInfo
  Polish ExtendedBeanInfoTests
  ...
  • Loading branch information
cbeams committed Feb 13, 2012
2 parents 3eff364 + 0a5392e commit ee36c80
Show file tree
Hide file tree
Showing 134 changed files with 3,551 additions and 1,470 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
Expand Down Expand Up @@ -35,6 +35,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

Expand Down Expand Up @@ -74,12 +75,6 @@ class ExtendedBeanInfo implements BeanInfo {
public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
this.delegate = delegate;

// PropertyDescriptor instances from the delegate object are never added directly, but always
// copied to the local collection of #propertyDescriptors and returned by calls to
// #getPropertyDescriptors(). this algorithm iterates through all methods (method descriptors)
// in the wrapped BeanInfo object, copying any existing PropertyDescriptor or creating a new
// one for any non-standard setter methods found.

ALL_METHODS:
for (MethodDescriptor md : delegate.getMethodDescriptors()) {
Method method = md.getMethod();
Expand Down Expand Up @@ -136,19 +131,13 @@ public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
Method indexedReadMethod = ipd.getIndexedReadMethod();
Method indexedWriteMethod = ipd.getIndexedWriteMethod();
// has the setter already been found by the wrapped BeanInfo?
if (indexedWriteMethod != null
&& indexedWriteMethod.getName().equals(method.getName())) {
// yes -> copy it, including corresponding getter method (if any -- may be null)
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod);
continue ALL_METHODS;
}
// has a getter corresponding to this setter already been found by the wrapped BeanInfo?
if (indexedReadMethod != null
&& indexedReadMethod.getName().equals(getterMethodNameFor(propertyName))
&& indexedReadMethod.getReturnType().equals(method.getParameterTypes()[1])) {
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, method);
continue ALL_METHODS;
if (!(indexedWriteMethod != null
&& indexedWriteMethod.getName().equals(method.getName()))) {
indexedWriteMethod = method;
}
// yes -> copy it, including corresponding getter method (if any -- may be null)
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod);
continue ALL_METHODS;
}
// the INDEXED setter method was not found by the wrapped BeanInfo -> add a new PropertyDescriptor
// for it. no corresponding INDEXED getter was detected, so the 'indexed read method' parameter is null.
Expand All @@ -159,24 +148,27 @@ public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
// the method is not a setter, but is it a getter?
for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) {
// have we already copied this read method to a property descriptor locally?
String propertyName = pd.getName();
Method readMethod = pd.getReadMethod();
Method mostSpecificReadMethod = ClassUtils.getMostSpecificMethod(readMethod, method.getDeclaringClass());
for (PropertyDescriptor existingPD : this.propertyDescriptors) {
if (method.equals(pd.getReadMethod())
&& existingPD.getName().equals(pd.getName())) {
if (method.equals(mostSpecificReadMethod)
&& existingPD.getName().equals(propertyName)) {
if (existingPD.getReadMethod() == null) {
// no -> add it now
this.addOrUpdatePropertyDescriptor(pd, pd.getName(), method, pd.getWriteMethod());
this.addOrUpdatePropertyDescriptor(pd, propertyName, method, pd.getWriteMethod());
}
// yes -> do not add a duplicate
continue ALL_METHODS;
}
}
if (method == pd.getReadMethod()
|| (pd instanceof IndexedPropertyDescriptor && method == ((IndexedPropertyDescriptor) pd).getIndexedReadMethod())) {
if (method.equals(mostSpecificReadMethod)
|| (pd instanceof IndexedPropertyDescriptor && method.equals(((IndexedPropertyDescriptor) pd).getIndexedReadMethod()))) {
// yes -> copy it, including corresponding setter method (if any -- may be null)
if (pd instanceof IndexedPropertyDescriptor) {
this.addOrUpdatePropertyDescriptor(pd, pd.getName(), pd.getReadMethod(), pd.getWriteMethod(), ((IndexedPropertyDescriptor)pd).getIndexedReadMethod(), ((IndexedPropertyDescriptor)pd).getIndexedWriteMethod());
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, pd.getWriteMethod(), ((IndexedPropertyDescriptor)pd).getIndexedReadMethod(), ((IndexedPropertyDescriptor)pd).getIndexedWriteMethod());
} else {
this.addOrUpdatePropertyDescriptor(pd, pd.getName(), pd.getReadMethod(), pd.getWriteMethod());
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, pd.getWriteMethod());
}
continue ALL_METHODS;
}
Expand Down Expand Up @@ -221,7 +213,9 @@ private void addOrUpdatePropertyDescriptor(PropertyDescriptor pd, String propert
}
}
// update the existing descriptor's write method
if (writeMethod != null) {
if (writeMethod != null
&& !(existingPD instanceof IndexedPropertyDescriptor &&
!writeMethod.getParameterTypes()[0].isArray())) {
existingPD.setWriteMethod(writeMethod);
}

Expand Down Expand Up @@ -278,7 +272,7 @@ private void addOrUpdatePropertyDescriptor(PropertyDescriptor pd, String propert
}
this.propertyDescriptors.add(pd);
} catch (IntrospectionException ex) {
logger.warn(format("Could not create new PropertyDescriptor for readMethod [%s] writeMethod [%s] " +
logger.debug(format("Could not create new PropertyDescriptor for readMethod [%s] writeMethod [%s] " +
"indexedReadMethod [%s] indexedWriteMethod [%s] for property [%s]. Reason: %s",
readMethod, writeMethod, indexedReadMethod, indexedWriteMethod, propertyName, ex.getMessage()));
// suppress exception and attempt to continue
Expand All @@ -289,10 +283,20 @@ private void addOrUpdatePropertyDescriptor(PropertyDescriptor pd, String propert
try {
pd.setWriteMethod(writeMethod);
} catch (IntrospectionException ex) {
logger.warn(format("Could not add write method [%s] for property [%s]. Reason: %s",
logger.debug(format("Could not add write method [%s] for property [%s]. Reason: %s",
writeMethod, propertyName, ex.getMessage()));
// fall through -> add property descriptor as best we can
}
if (pd instanceof IndexedPropertyDescriptor) {
((IndexedPropertyDescriptor)pd).setIndexedReadMethod(indexedReadMethod);
try {
((IndexedPropertyDescriptor)pd).setIndexedWriteMethod(indexedWriteMethod);
} catch (IntrospectionException ex) {
logger.debug(format("Could not add indexed write method [%s] for property [%s]. Reason: %s",
indexedWriteMethod, propertyName, ex.getMessage()));
// fall through -> add property descriptor as best we can
}
}
this.propertyDescriptors.add(pd);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implem
*/
public AnnotatedGenericBeanDefinition(Class beanClass) {
setBeanClass(beanClass);
this.annotationMetadata = new StandardAnnotationMetadata(beanClass);
this.annotationMetadata = new StandardAnnotationMetadata(beanClass, true);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2012 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.
Expand All @@ -21,6 +21,7 @@
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.springframework.core.GenericCollectionTypeResolver;
Expand Down Expand Up @@ -56,6 +57,8 @@ public class DependencyDescriptor implements Serializable {

private final boolean eager;

private int nestingLevel = 1;

private transient Annotation[] fieldAnnotations;


Expand Down Expand Up @@ -153,6 +156,13 @@ public boolean isEager() {
}


public void increaseNestingLevel() {
this.nestingLevel++;
if (this.methodParameter != null) {
this.methodParameter.increaseNestingLevel();
}
}

/**
* Initialize parameter name discovery for the underlying method parameter, if any.
* <p>This method does not actually try to retrieve the parameter name at
Expand All @@ -178,15 +188,30 @@ public String getDependencyName() {
* @return the declared type (never <code>null</code>)
*/
public Class<?> getDependencyType() {
return (this.field != null ? this.field.getType() : this.methodParameter.getParameterType());
}

/**
* Determine the generic type of the wrapped parameter/field.
* @return the generic type (never <code>null</code>)
*/
public Type getGenericDependencyType() {
return (this.field != null ? this.field.getGenericType() : this.methodParameter.getGenericParameterType());
if (this.field != null) {
if (this.nestingLevel > 1) {
Type type = this.field.getGenericType();
if (type instanceof ParameterizedType) {
Type arg = ((ParameterizedType) type).getActualTypeArguments()[0];
if (arg instanceof Class) {
return (Class) arg;
}
else if (arg instanceof ParameterizedType) {
arg = ((ParameterizedType) arg).getRawType();
if (arg instanceof Class) {
return (Class) arg;
}
}
}
return Object.class;
}
else {
return this.field.getType();
}
}
else {
return this.methodParameter.getNestedParameterType();
}
}

/**
Expand All @@ -195,7 +220,7 @@ public Type getGenericDependencyType() {
*/
public Class<?> getCollectionType() {
return (this.field != null ?
GenericCollectionTypeResolver.getCollectionFieldType(this.field) :
GenericCollectionTypeResolver.getCollectionFieldType(this.field, this.nestingLevel) :
GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter));
}

Expand All @@ -205,7 +230,7 @@ public Class<?> getCollectionType() {
*/
public Class<?> getMapKeyType() {
return (this.field != null ?
GenericCollectionTypeResolver.getMapKeyFieldType(this.field) :
GenericCollectionTypeResolver.getMapKeyFieldType(this.field, this.nestingLevel) :
GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter));
}

Expand All @@ -215,7 +240,7 @@ public Class<?> getMapKeyType() {
*/
public Class<?> getMapValueType() {
return (this.field != null ?
GenericCollectionTypeResolver.getMapValueFieldType(this.field) :
GenericCollectionTypeResolver.getMapValueFieldType(this.field, this.nestingLevel) :
GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter));
}

Expand Down Expand Up @@ -248,13 +273,18 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound
if (this.fieldName != null) {
this.field = this.declaringClass.getDeclaredField(this.fieldName);
}
else if (this.methodName != null) {
this.methodParameter = new MethodParameter(
this.declaringClass.getDeclaredMethod(this.methodName, this.parameterTypes), this.parameterIndex);
}
else {
this.methodParameter = new MethodParameter(
this.declaringClass.getDeclaredConstructor(this.parameterTypes), this.parameterIndex);
if (this.methodName != null) {
this.methodParameter = new MethodParameter(
this.declaringClass.getDeclaredMethod(this.methodName, this.parameterTypes), this.parameterIndex);
}
else {
this.methodParameter = new MethodParameter(
this.declaringClass.getDeclaredConstructor(this.parameterTypes), this.parameterIndex);
}
for (int i = 1; i < this.nestingLevel; i++) {
this.methodParameter.increaseNestingLevel();
}
}
}
catch (Throwable ex) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
Expand Down Expand Up @@ -1328,8 +1328,9 @@ protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Clas
* @param mbd the corresponding bean definition
*/
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
Class<?> beanClass = predictBeanType(beanName, mbd, FactoryBean.class);
return (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass));
Class<?> predictedType = predictBeanType(beanName, mbd, FactoryBean.class);
return (predictedType != null && FactoryBean.class.isAssignableFrom(predictedType)) ||
(mbd.hasBeanClass() && FactoryBean.class.isAssignableFrom(mbd.getBeanClass()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
Expand Down Expand Up @@ -1000,27 +1000,14 @@ private class DependencyObjectFactory implements ObjectFactory, Serializable {

private final String beanName;

private final Class type;

public DependencyObjectFactory(DependencyDescriptor descriptor, String beanName) {
this.descriptor = descriptor;
this.beanName = beanName;
this.type = determineObjectFactoryType();
}

private Class determineObjectFactoryType() {
Type type = this.descriptor.getGenericDependencyType();
if (type instanceof ParameterizedType) {
Type arg = ((ParameterizedType) type).getActualTypeArguments()[0];
if (arg instanceof Class) {
return (Class) arg;
}
}
return Object.class;
this.descriptor.increaseNestingLevel();
}

public Object getObject() throws BeansException {
return doResolveDependency(this.descriptor, this.type, this.beanName, null, null);
return doResolveDependency(this.descriptor, this.descriptor.getDependencyType(), this.beanName, null, null);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2012 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.
Expand All @@ -16,11 +16,12 @@

package org.springframework.beans;

import static org.junit.Assert.*;
import org.junit.Test;
import test.beans.CustomEnum;
import test.beans.GenericBean;

import static org.junit.Assert.*;

/**
* @author Juergen Hoeller
* @author Chris Beams
Expand Down Expand Up @@ -109,4 +110,14 @@ public void testCustomEnumSetWithMultipleValuesAsCsv() {
assertTrue(gb.getCustomEnumSet().contains(CustomEnum.VALUE_2));
}

@Test
public void testCustomEnumSetWithGetterSetterMismatch() {
GenericBean<?> gb = new GenericBean<Object>();
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("customEnumSetMismatch", new String[] {"VALUE_1", "VALUE_2"});
assertEquals(2, gb.getCustomEnumSet().size());
assertTrue(gb.getCustomEnumSet().contains(CustomEnum.VALUE_1));
assertTrue(gb.getCustomEnumSet().contains(CustomEnum.VALUE_2));
}

}
Loading

0 comments on commit ee36c80

Please sign in to comment.