HHH-2268 - Skip bridge methods during getter determination (JDK Bug 5062759)

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19624 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2010-05-26 22:08:33 +00:00
parent 39c75a50c6
commit 6d01dd07b0
2 changed files with 145 additions and 37 deletions

View File

@ -63,7 +63,7 @@ private BasicSetter(Class clazz, Method method, String propertyName) {
public void set(Object target, Object value, SessionFactoryImplementor factory) public void set(Object target, Object value, SessionFactoryImplementor factory)
throws HibernateException { throws HibernateException {
try { try {
method.invoke( target, new Object[] { value } ); method.invoke( target, value );
} }
catch (NullPointerException npe) { catch (NullPointerException npe) {
if ( value==null && method.getParameterTypes()[0].isPrimitive() ) { if ( value==null && method.getParameterTypes()[0].isPrimitive() ) {
@ -169,7 +169,7 @@ private BasicGetter(Class clazz, Method method, String propertyName) {
*/ */
public Object get(Object target) throws HibernateException { public Object get(Object target) throws HibernateException {
try { try {
return method.invoke(target, null); return method.invoke( target, (Object[]) null );
} }
catch (InvocationTargetException ite) { catch (InvocationTargetException ite) {
throw new PropertyAccessException( throw new PropertyAccessException(
@ -299,15 +299,15 @@ private static Method setterMethod(Class theClass, String propertyName) {
Method[] methods = theClass.getDeclaredMethods(); Method[] methods = theClass.getDeclaredMethods();
Method potentialSetter = null; Method potentialSetter = null;
for (int i=0; i<methods.length; i++) { for ( Method method : methods ) {
String methodName = methods[i].getName(); final String methodName = method.getName();
if ( methods[i].getParameterTypes().length==1 && methodName.startsWith("set") ) { if ( method.getParameterTypes().length == 1 && methodName.startsWith( "set" ) ) {
String testStdMethod = Introspector.decapitalize( methodName.substring(3) ); String testStdMethod = Introspector.decapitalize( methodName.substring( 3 ) );
String testOldMethod = methodName.substring(3); String testOldMethod = methodName.substring( 3 );
if ( testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName) ) { if ( testStdMethod.equals( propertyName ) || testOldMethod.equals( propertyName ) ) {
potentialSetter = methods[i]; potentialSetter = method;
if ( returnType==null || methods[i].getParameterTypes()[0].equals(returnType) ) { if ( returnType == null || method.getParameterTypes()[0].equals( returnType ) ) {
return potentialSetter; return potentialSetter;
} }
} }
@ -316,13 +316,11 @@ private static Method setterMethod(Class theClass, String propertyName) {
return potentialSetter; return potentialSetter;
} }
public Getter getGetter(Class theClass, String propertyName) public Getter getGetter(Class theClass, String propertyName) throws PropertyNotFoundException {
throws PropertyNotFoundException {
return createGetter(theClass, propertyName); return createGetter(theClass, propertyName);
} }
public static Getter createGetter(Class theClass, String propertyName) public static Getter createGetter(Class theClass, String propertyName) throws PropertyNotFoundException {
throws PropertyNotFoundException {
BasicGetter result = getGetterOrNull(theClass, propertyName); BasicGetter result = getGetterOrNull(theClass, propertyName);
if (result==null) { if (result==null) {
throw new PropertyNotFoundException( throw new PropertyNotFoundException(
@ -333,17 +331,19 @@ public static Getter createGetter(Class theClass, String propertyName)
); );
} }
return result; return result;
} }
private static BasicGetter getGetterOrNull(Class theClass, String propertyName) { private static BasicGetter getGetterOrNull(Class theClass, String propertyName) {
if (theClass==Object.class || theClass==null) {
if (theClass==Object.class || theClass==null) return null; return null;
}
Method method = getterMethod(theClass, propertyName); Method method = getterMethod(theClass, propertyName);
if (method!=null) { if (method!=null) {
if ( !ReflectHelper.isPublic(theClass, method) ) method.setAccessible(true); if ( !ReflectHelper.isPublic(theClass, method) ) {
method.setAccessible(true);
}
return new BasicGetter(theClass, method, propertyName); return new BasicGetter(theClass, method, propertyName);
} }
else { else {
@ -359,33 +359,38 @@ private static BasicGetter getGetterOrNull(Class theClass, String propertyName)
} }
private static Method getterMethod(Class theClass, String propertyName) { private static Method getterMethod(Class theClass, String propertyName) {
Method[] methods = theClass.getDeclaredMethods(); Method[] methods = theClass.getDeclaredMethods();
for (int i=0; i<methods.length; i++) { for ( Method method : methods ) {
// only carry on if the method has no parameters // if the method has parameters, skip it
if ( methods[i].getParameterTypes().length == 0 ) { if ( method.getParameterTypes().length != 0 ) {
String methodName = methods[i].getName(); continue;
}
// try "get" // if the method is a "bridge", skip it
if ( methodName.startsWith("get") ) { if ( method.isBridge() ) {
String testStdMethod = Introspector.decapitalize( methodName.substring(3) ); continue;
String testOldMethod = methodName.substring(3);
if ( testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName) ) {
return methods[i];
} }
final String methodName = method.getName();
// try "get"
if ( methodName.startsWith( "get" ) ) {
String testStdMethod = Introspector.decapitalize( methodName.substring( 3 ) );
String testOldMethod = methodName.substring( 3 );
if ( testStdMethod.equals( propertyName ) || testOldMethod.equals( propertyName ) ) {
return method;
}
} }
// if not "get", then try "is" // if not "get", then try "is"
if ( methodName.startsWith("is") ) { if ( methodName.startsWith( "is" ) ) {
String testStdMethod = Introspector.decapitalize( methodName.substring(2) ); String testStdMethod = Introspector.decapitalize( methodName.substring( 2 ) );
String testOldMethod = methodName.substring(2); String testOldMethod = methodName.substring( 2 );
if ( testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName) ) { if ( testStdMethod.equals( propertyName ) || testOldMethod.equals( propertyName ) ) {
return methods[i]; return method;
}
} }
} }
} }
return null; return null;
} }

View File

@ -0,0 +1,103 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.property;
import junit.framework.TestCase;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class BasicPropertyAccessorTest extends TestCase {
public static abstract class Super {
public abstract Object getIt();
public abstract void setIt(Object it);
}
public static class Duper extends Super {
private String it;
public Duper(String it) {
this.it = it;
}
public String getIt() {
return it;
}
@Override
public void setIt(Object it) {
this.it = ( it == null || String.class.isInstance( it ) )
? (String) it
: it.toString();
}
}
public static class Duper2 extends Super {
private String it;
public Duper2(String it) {
this.it = it;
}
public String getIt() {
return it;
}
public void setIt(String it) {
this.it = it;
}
@Override
public void setIt(Object it) {
if ( it == null || String.class.isInstance( it ) ) {
setIt( (String) it );
}
else {
setIt( it.toString() );
}
}
}
public void testBridgeMethodDisregarded() {
BasicPropertyAccessor accessor = new BasicPropertyAccessor();
{
BasicPropertyAccessor.BasicGetter getter = (BasicPropertyAccessor.BasicGetter) accessor.getGetter( Duper.class, "it" );
assertEquals( String.class, getter.getReturnType() );
BasicPropertyAccessor.BasicSetter setter = (BasicPropertyAccessor.BasicSetter) accessor.getSetter( Duper.class, "it" );
assertEquals( Object.class, setter.getMethod().getParameterTypes()[0] );
}
{
BasicPropertyAccessor.BasicGetter getter = (BasicPropertyAccessor.BasicGetter) accessor.getGetter( Duper2.class, "it" );
assertEquals( String.class, getter.getReturnType() );
BasicPropertyAccessor.BasicSetter setter = (BasicPropertyAccessor.BasicSetter) accessor.getSetter( Duper2.class, "it" );
assertEquals( String.class, setter.getMethod().getParameterTypes()[0] );
}
}
}