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