squash some warnings in ReflectHelper + cleanups

This commit is contained in:
Gavin King 2024-10-08 09:06:05 +02:00
parent 9166d73f36
commit 2e2d2948b0
1 changed files with 140 additions and 166 deletions

View File

@ -4,7 +4,6 @@
*/ */
package org.hibernate.internal.util; package org.hibernate.internal.util;
import java.beans.Introspector;
import java.lang.reflect.AccessibleObject; import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -29,6 +28,9 @@ import org.hibernate.property.access.spi.Getter;
import jakarta.persistence.Transient; import jakarta.persistence.Transient;
import static java.beans.Introspector.decapitalize;
import static java.lang.Thread.currentThread;
/** /**
* Utility class for various reflection operations. * Utility class for various reflection operations.
* *
@ -120,12 +122,12 @@ public final class ReflectHelper {
if ( clazz.isRecord() || clazz.isEnum() ) { if ( clazz.isRecord() || clazz.isEnum() ) {
return true; return true;
} }
Method equals; final Method equals;
try { try {
equals = extractEqualsMethod( clazz ); equals = extractEqualsMethod( clazz );
} }
catch ( NoSuchMethodException nsme ) { catch ( NoSuchMethodException nsme ) {
return false; //its an interface so we can't really tell anything... return false; //it's an interface so we can't really tell anything
} }
return !OBJECT_EQUALS.equals( equals ); return !OBJECT_EQUALS.equals( equals );
} }
@ -140,12 +142,12 @@ public final class ReflectHelper {
if ( clazz.isRecord() || clazz.isEnum() ) { if ( clazz.isRecord() || clazz.isEnum() ) {
return true; return true;
} }
Method hashCode; final Method hashCode;
try { try {
hashCode = extractHashCodeMethod( clazz ); hashCode = extractHashCodeMethod( clazz );
} }
catch ( NoSuchMethodException nsme ) { catch ( NoSuchMethodException nsme ) {
return false; //its an interface so we can't really tell anything... return false; //it's an interface so we can't really tell anything
} }
return !OBJECT_HASHCODE.equals( hashCode ); return !OBJECT_HASHCODE.equals( hashCode );
} }
@ -156,7 +158,10 @@ public final class ReflectHelper {
* @param clazz The class to check * @param clazz The class to check
* @param intf The interface to check it against. * @param intf The interface to check it against.
* @return True if the class does implement the interface, false otherwise. * @return True if the class does implement the interface, false otherwise.
*
* @deprecated No longer used
*/ */
@Deprecated(since = "7", forRemoval = true)
public static boolean implementsInterface(Class<?> clazz, Class<?> intf) { public static boolean implementsInterface(Class<?> clazz, Class<?> intf) {
assert intf.isInterface() : "Interface to check was not an interface"; assert intf.isInterface() : "Interface to check was not an interface";
return intf.isAssignableFrom( clazz ); return intf.isAssignableFrom( clazz );
@ -175,7 +180,7 @@ public final class ReflectHelper {
*/ */
public static Class<?> classForName(String name, Class<?> caller) throws ClassNotFoundException { public static Class<?> classForName(String name, Class<?> caller) throws ClassNotFoundException {
try { try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); final ClassLoader classLoader = currentThread().getContextClassLoader();
if ( classLoader != null ) { if ( classLoader != null ) {
return classLoader.loadClass( name ); return classLoader.loadClass( name );
} }
@ -202,7 +207,7 @@ public final class ReflectHelper {
@Deprecated @Deprecated
public static Class<?> classForName(String name) throws ClassNotFoundException { public static Class<?> classForName(String name) throws ClassNotFoundException {
try { try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); final ClassLoader classLoader = currentThread().getContextClassLoader();
if ( classLoader != null ) { if ( classLoader != null ) {
return classLoader.loadClass(name); return classLoader.loadClass(name);
} }
@ -220,7 +225,8 @@ public final class ReflectHelper {
* @return True if the member is publicly accessible, false otherwise. * @return True if the member is publicly accessible, false otherwise.
*/ */
public static boolean isPublic(Class<?> clazz, Member member) { public static boolean isPublic(Class<?> clazz, Member member) {
return Modifier.isPublic( member.getModifiers() ) && Modifier.isPublic( clazz.getModifiers() ); return Modifier.isPublic( member.getModifiers() )
&& Modifier.isPublic( clazz.getModifiers() );
} }
/** /**
@ -239,7 +245,7 @@ public final class ReflectHelper {
String name, String name,
ClassLoaderService classLoaderService) throws MappingException { ClassLoaderService classLoaderService) throws MappingException {
try { try {
Class<?> clazz = classLoaderService.classForName( className ); final Class<?> clazz = classLoaderService.classForName( className );
return getter( clazz, name ).getReturnTypeClass(); return getter( clazz, name ).getReturnTypeClass();
} }
catch ( ClassLoadingException e ) { catch ( ClassLoadingException e ) {
@ -252,7 +258,7 @@ public final class ReflectHelper {
String name, String name,
ClassLoaderService classLoaderService) throws MappingException { ClassLoaderService classLoaderService) throws MappingException {
try { try {
Class<?> clazz = classLoaderService.classForName( className ); final Class<?> clazz = classLoaderService.classForName( className );
return getter( clazz, name ).getReturnType(); return getter( clazz, name ).getReturnType();
} }
catch ( ClassLoadingException e ) { catch ( ClassLoadingException e ) {
@ -289,7 +295,7 @@ public final class ReflectHelper {
} }
try { try {
Constructor<T> constructor = clazz.getDeclaredConstructor( NO_PARAM_SIGNATURE ); final Constructor<T> constructor = clazz.getDeclaredConstructor( NO_PARAM_SIGNATURE );
ensureAccessibility( constructor ); ensureAccessibility( constructor );
return constructor; return constructor;
} }
@ -336,7 +342,7 @@ public final class ReflectHelper {
* @return True if the class is abstract, false otherwise. * @return True if the class is abstract, false otherwise.
*/ */
public static boolean isAbstractClass(Class<?> clazz) { public static boolean isAbstractClass(Class<?> clazz) {
int modifier = clazz.getModifiers(); final int modifier = clazz.getModifiers();
return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier); return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier);
} }
@ -403,9 +409,8 @@ public final class ReflectHelper {
else if ( containerClass == Object.class ) { else if ( containerClass == Object.class ) {
throw new IllegalArgumentException( "Illegal attempt to locate field [" + propertyName + "] on Object.class" ); throw new IllegalArgumentException( "Illegal attempt to locate field [" + propertyName + "] on Object.class" );
} }
else {
Field field = locateField( containerClass, propertyName ); final Field field = locateField( containerClass, propertyName );
if ( field == null ) { if ( field == null ) {
throw new PropertyNotFoundException( throw new PropertyNotFoundException(
String.format( String.format(
@ -416,11 +421,10 @@ public final class ReflectHelper {
) )
); );
} }
ensureAccessibility( field ); ensureAccessibility( field );
return field; return field;
} }
}
public static void ensureAccessibility(AccessibleObject accessibleObject) { public static void ensureAccessibility(AccessibleObject accessibleObject) {
if ( !accessibleObject.isAccessible() ) { if ( !accessibleObject.isAccessible() ) {
@ -434,11 +438,10 @@ public final class ReflectHelper {
} }
try { try {
Field field = clazz.getDeclaredField( propertyName ); final Field field = clazz.getDeclaredField( propertyName );
if ( !isStaticField( field ) ) { return !isStaticField( field )
return field; ? field
} : locateField( clazz.getSuperclass(), propertyName );
return locateField( clazz.getSuperclass(), propertyName );
} }
catch ( NoSuchFieldException nsfe ) { catch ( NoSuchFieldException nsfe ) {
return locateField( clazz.getSuperclass(), propertyName ); return locateField( clazz.getSuperclass(), propertyName );
@ -467,17 +470,15 @@ public final class ReflectHelper {
if ( checkClass.equals( Object.class ) ) { if ( checkClass.equals( Object.class ) ) {
break; break;
} }
else {
getter = getGetterOrNull( checkClass, propertyName ); getter = getGetterOrNull( checkClass, propertyName );
// if no getter found yet, check all implemented interfaces // if no getter found yet, check all implemented interfaces
if ( getter == null ) { if ( getter == null ) {
getter = getGetterOrNull( checkClass.getInterfaces(), propertyName ); getter = getGetterOrNull( checkClass.getInterfaces(), propertyName );
} }
checkClass = checkClass.getSuperclass(); checkClass = checkClass.getSuperclass();
} }
}
if ( getter == null ) { if ( getter == null ) {
throw new PropertyNotFoundException( throw new PropertyNotFoundException(
@ -499,15 +500,14 @@ public final class ReflectHelper {
Method getter = null; Method getter = null;
for ( int i = 0; getter == null && i < interfaces.length; ++i ) { for ( int i = 0; getter == null && i < interfaces.length; ++i ) {
final Class<?> anInterface = interfaces[i]; final Class<?> anInterface = interfaces[i];
if ( shouldSkipInterfaceCheck( anInterface ) ) { if ( !shouldSkipInterfaceCheck( anInterface ) ) {
continue;
}
getter = getGetterOrNull( anInterface, propertyName ); getter = getGetterOrNull( anInterface, propertyName );
if ( getter == null ) { if ( getter == null ) {
// if no getter found yet, check all implemented interfaces of interface // if no getter found yet, check all implemented interfaces of interface
getter = getGetterOrNull( anInterface.getInterfaces(), propertyName ); getter = getGetterOrNull( anInterface.getInterfaces(), propertyName );
} }
} }
}
return getter; return getter;
} }
@ -532,31 +532,18 @@ public final class ReflectHelper {
} }
for ( Method method : containerClass.getDeclaredMethods() ) { for ( Method method : containerClass.getDeclaredMethods() ) {
// if the method has parameters, skip it if ( method.getParameterCount() == 0 // if the method has parameters, skip it
if ( method.getParameterCount() != 0 ) { && !Modifier.isStatic( method.getModifiers() )
continue; && !method.isBridge()
} && method.getAnnotation( Transient.class ) == null ) {
// if the method is a "bridge", skip it
if ( method.isBridge() ) {
continue;
}
if ( method.getAnnotation( Transient.class ) != null ) {
continue;
}
if ( Modifier.isStatic( method.getModifiers() ) ) {
continue;
}
final String methodName = method.getName(); final String methodName = method.getName();
// try "get" // try "get"
if ( methodName.startsWith( "get" ) ) { if ( methodName.startsWith( "get" ) ) {
final String stemName = methodName.substring( 3 ); final String stemName = methodName.substring( 3 );
final String decapitalizedStemName = Introspector.decapitalize( stemName ); if ( stemName.equals( propertyName )
if ( stemName.equals( propertyName ) || decapitalizedStemName.equals( propertyName ) ) { || decapitalize( stemName ).equals( propertyName ) ) {
verifyNoIsVariantExists( containerClass, propertyName, method, stemName ); verifyNoIsVariantExists( containerClass, propertyName, method, stemName );
return method; return method;
} }
@ -566,8 +553,8 @@ public final class ReflectHelper {
// if not "get", then try "is" // if not "get", then try "is"
if ( methodName.startsWith( "is" ) ) { if ( methodName.startsWith( "is" ) ) {
final String stemName = methodName.substring( 2 ); final String stemName = methodName.substring( 2 );
String decapitalizedStemName = Introspector.decapitalize( stemName ); if ( stemName.equals( propertyName )
if ( stemName.equals( propertyName ) || decapitalizedStemName.equals( propertyName ) ) { || decapitalize( stemName ).equals( propertyName ) ) {
// not sure that this can ever really happen given the handling of "get" above. // not sure that this can ever really happen given the handling of "get" above.
// but be safe // but be safe
verifyNoGetVariantExists( containerClass, propertyName, method, stemName ); verifyNoGetVariantExists( containerClass, propertyName, method, stemName );
@ -575,6 +562,7 @@ public final class ReflectHelper {
} }
} }
} }
}
return null; return null;
} }
@ -629,7 +617,8 @@ public final class ReflectHelper {
final Method getMethod = containerClass.getDeclaredMethod( "get" + stemName ); final Method getMethod = containerClass.getDeclaredMethod( "get" + stemName );
// No such method should throw the caught exception. So if we get here, there was // No such method should throw the caught exception. So if we get here, there was
// such a method. // such a method.
if ( !Modifier.isStatic( getMethod.getModifiers() ) && getMethod.getAnnotation( Transient.class ) == null ) { if ( !Modifier.isStatic( getMethod.getModifiers() )
&& getMethod.getAnnotation( Transient.class ) == null ) {
checkGetAndIsVariants( containerClass, propertyName, getMethod, isMethod ); checkGetAndIsVariants( containerClass, propertyName, getMethod, isMethod );
} }
} }
@ -672,9 +661,8 @@ public final class ReflectHelper {
if ( checkClass.equals( Object.class ) ) { if ( checkClass.equals( Object.class ) ) {
break; break;
} }
else {
setter = setterOrNull( checkClass, propertyName, propertyType, likelyMethodName ); setter = setterOrNull( checkClass, propertyName, propertyType, likelyMethodName );
// if no setter found yet, check all implemented interfaces // if no setter found yet, check all implemented interfaces
if ( setter == null ) { if ( setter == null ) {
setter = setterOrNull( checkClass.getInterfaces(), propertyName, propertyType, likelyMethodName ); setter = setterOrNull( checkClass.getInterfaces(), propertyName, propertyType, likelyMethodName );
@ -682,9 +670,9 @@ public final class ReflectHelper {
else { else {
ensureAccessibility( setter ); ensureAccessibility( setter );
} }
checkClass = checkClass.getSuperclass(); checkClass = checkClass.getSuperclass();
} }
}
return setter; // might be null return setter; // might be null
} }
@ -697,9 +685,8 @@ public final class ReflectHelper {
if ( checkClass.equals( Object.class ) ) { if ( checkClass.equals( Object.class ) ) {
break; break;
} }
else {
setter = setterOrNullBySetterName( checkClass, setterName, propertyType ); setter = setterOrNullBySetterName( checkClass, setterName, propertyType );
// if no setter found yet, check all implemented interfaces // if no setter found yet, check all implemented interfaces
if ( setter == null ) { if ( setter == null ) {
setter = setterOrNullBySetterName( checkClass.getInterfaces(), setterName, propertyType ); setter = setterOrNullBySetterName( checkClass.getInterfaces(), setterName, propertyType );
@ -707,9 +694,9 @@ public final class ReflectHelper {
else { else {
ensureAccessibility( setter ); ensureAccessibility( setter );
} }
checkClass = checkClass.getSuperclass(); checkClass = checkClass.getSuperclass();
} }
}
return setter; // might be null return setter; // might be null
} }
@ -717,22 +704,21 @@ public final class ReflectHelper {
Method setter = null; Method setter = null;
for ( int i = 0; setter == null && i < interfaces.length; ++i ) { for ( int i = 0; setter == null && i < interfaces.length; ++i ) {
final Class<?> anInterface = interfaces[i]; final Class<?> anInterface = interfaces[i];
if ( shouldSkipInterfaceCheck( anInterface ) ) { if ( !shouldSkipInterfaceCheck( anInterface ) ) {
continue;
}
setter = setterOrNullBySetterName( anInterface, setterName, propertyType ); setter = setterOrNullBySetterName( anInterface, setterName, propertyType );
if ( setter == null ) { if ( setter == null ) {
// if no setter found yet, check all implemented interfaces of interface // if no setter found yet, check all implemented interfaces of interface
setter = setterOrNullBySetterName( anInterface.getInterfaces(), setterName, propertyType ); setter = setterOrNullBySetterName( anInterface.getInterfaces(), setterName, propertyType );
} }
} }
}
return setter; return setter;
} }
private static boolean shouldSkipInterfaceCheck(final Class anInterface) { private static boolean shouldSkipInterfaceCheck(final Class<?> anInterface) {
final String interfaceName = anInterface.getName(); final String interfaceName = anInterface.getName();
//Skip checking any interface that we've added ourself via bytecode enhancement: //Skip checking any interface that we've added via bytecode enhancement:
//there's many of those and it's pointless to look there. //there's many of those, and it's pointless to look there.
if ( interfaceName.startsWith( "org.hibernate.engine." ) ) { if ( interfaceName.startsWith( "org.hibernate.engine." ) ) {
return true; return true;
} }
@ -779,19 +765,18 @@ public final class ReflectHelper {
Method setter = null; Method setter = null;
for ( int i = 0; setter == null && i < interfaces.length; ++i ) { for ( int i = 0; setter == null && i < interfaces.length; ++i ) {
final Class<?> anInterface = interfaces[i]; final Class<?> anInterface = interfaces[i];
if ( shouldSkipInterfaceCheck( anInterface ) ) { if ( !shouldSkipInterfaceCheck( anInterface ) ) {
continue;
}
setter = setterOrNull( anInterface, propertyName, propertyType, likelyMethodName ); setter = setterOrNull( anInterface, propertyName, propertyType, likelyMethodName );
if ( setter == null ) { if ( setter == null ) {
// if no setter found yet, check all implemented interfaces of interface // if no setter found yet, check all implemented interfaces of interface
setter = setterOrNull( anInterface.getInterfaces(), propertyName, propertyType, likelyMethodName ); setter = setterOrNull( anInterface.getInterfaces(), propertyName, propertyType, likelyMethodName );
} }
} }
}
return setter; return setter;
} }
private static Method setterOrNull(Class<?> theClass, String propertyName, Class propertyType, String likelyMethodName) { private static Method setterOrNull(Class<?> theClass, String propertyName, Class<?> propertyType, String likelyMethodName) {
try { try {
return theClass.getDeclaredMethod( likelyMethodName, propertyType ); return theClass.getDeclaredMethod( likelyMethodName, propertyType );
} }
@ -803,7 +788,7 @@ public final class ReflectHelper {
final String methodName = method.getName(); final String methodName = method.getName();
if ( method.getParameterCount() == 1 && methodName.startsWith( "set" ) ) { if ( method.getParameterCount() == 1 && methodName.startsWith( "set" ) ) {
final String testOldMethod = methodName.substring( 3 ); final String testOldMethod = methodName.substring( 3 );
final String testStdMethod = Introspector.decapitalize( testOldMethod ); final String testStdMethod = decapitalize( testOldMethod );
if ( testStdMethod.equals( propertyName ) || testOldMethod.equals( propertyName ) ) { if ( testStdMethod.equals( propertyName ) || testOldMethod.equals( propertyName ) ) {
potentialSetter = method; potentialSetter = method;
if ( propertyType == null || method.getParameterTypes()[0].equals( propertyType ) ) { if ( propertyType == null || method.getParameterTypes()[0].equals( propertyType ) ) {
@ -818,12 +803,9 @@ public final class ReflectHelper {
private static String likelySetterMethodNameForProperty(final String propertyName) { private static String likelySetterMethodNameForProperty(final String propertyName) {
final char firstCharacter = propertyName.charAt( 0 ); final char firstCharacter = propertyName.charAt( 0 );
if ( Character.isLowerCase( firstCharacter ) ) { return Character.isLowerCase( firstCharacter )
return "set" + Character.toUpperCase( firstCharacter ) + propertyName.substring( 1 ); ? "set" + Character.toUpperCase( firstCharacter ) + propertyName.substring( 1 )
} : "set" + propertyName;
else {
return "set" + propertyName;
}
} }
/** /**
@ -835,26 +817,17 @@ public final class ReflectHelper {
*/ */
public static Method findGetterMethodForFieldAccess(Field field, String propertyName) { public static Method findGetterMethodForFieldAccess(Field field, String propertyName) {
for ( Method method : field.getDeclaringClass().getDeclaredMethods() ) { for ( Method method : field.getDeclaringClass().getDeclaredMethods() ) {
// if the method has parameters, skip it if ( method.getParameterCount() == 0 // if the method has parameters, skip it
if ( method.getParameterCount() != 0 ) { && !Modifier.isStatic( method.getModifiers() )
continue; && method.getReturnType().isAssignableFrom( field.getType() ) ) {
}
if ( Modifier.isStatic( method.getModifiers() ) ) {
continue;
}
if ( ! method.getReturnType().isAssignableFrom( field.getType() ) ) {
continue;
}
final String methodName = method.getName(); final String methodName = method.getName();
// try "get" // try "get"
if ( methodName.startsWith( "get" ) ) { if ( methodName.startsWith( "get" ) ) {
final String stemName = methodName.substring( 3 ); final String stemName = methodName.substring( 3 );
final String decapitalizedStemName = Introspector.decapitalize( stemName ); if ( stemName.equals( propertyName )
if ( stemName.equals( propertyName ) || decapitalizedStemName.equals( propertyName ) ) { || decapitalize( stemName ).equals( propertyName ) ) {
return method; return method;
} }
@ -863,12 +836,13 @@ public final class ReflectHelper {
// if not "get", then try "is" // if not "get", then try "is"
if ( methodName.startsWith( "is" ) ) { if ( methodName.startsWith( "is" ) ) {
final String stemName = methodName.substring( 2 ); final String stemName = methodName.substring( 2 );
String decapitalizedStemName = Introspector.decapitalize( stemName ); if ( stemName.equals( propertyName )
if ( stemName.equals( propertyName ) || decapitalizedStemName.equals( propertyName ) ) { || decapitalize( stemName ).equals( propertyName ) ) {
return method; return method;
} }
} }
} }
}
if ( isRecord( field.getDeclaringClass() ) ) { if ( isRecord( field.getDeclaringClass() ) ) {
try { try {
return field.getDeclaringClass().getMethod( field.getName(), NO_PARAM_SIGNATURE ); return field.getDeclaringClass().getMethod( field.getName(), NO_PARAM_SIGNATURE );
@ -926,24 +900,24 @@ public final class ReflectHelper {
else if ( type instanceof Class<?> ) { else if ( type instanceof Class<?> ) {
return (Class<T>) type; return (Class<T>) type;
} }
else if ( type instanceof ParameterizedType ) { else if ( type instanceof ParameterizedType parameterizedType ) {
return (Class<T>) ( (ParameterizedType) type ).getRawType(); return (Class<T>) parameterizedType.getRawType();
} }
else if ( type instanceof TypeVariable ) { else if ( type instanceof TypeVariable<?> typeVariable ) {
return getClass( ( (TypeVariable<?>) type ).getBounds()[0] ); return getClass( typeVariable.getBounds()[0] );
} }
else if ( type instanceof WildcardType ) { else if ( type instanceof WildcardType wildcardType ) {
return getClass( ( (WildcardType) type ).getUpperBounds()[0] ); return getClass( wildcardType.getUpperBounds()[0] );
} }
throw new UnsupportedOperationException( "Can't get java type class from type: " + type ); throw new UnsupportedOperationException( "Can't get java type class from type: " + type );
} }
public static Class<?> getPropertyType(Member member) { public static Class<?> getPropertyType(Member member) {
if (member instanceof Field) { if (member instanceof Field field) {
return ( (Field) member ).getType(); return field.getType();
} }
else if (member instanceof Method) { else if (member instanceof Method method) {
return ( (Method) member ).getReturnType(); return method.getReturnType();
} }
else { else {
throw new AssertionFailure("member should have been a method or field"); throw new AssertionFailure("member should have been a method or field");