/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC. * * 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.internal.util; /** * Utility class for various reflection operations. * * @author Gavin King * @author Steve Ebersole */ @SuppressWarnings("unchecked") public final class ReflectHelper { // // //TODO: this dependency is kinda Bad // private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor(); // private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor(); // public static final Class[] NO_PARAM_SIGNATURE = new Class[0]; public static final Object[] NO_PARAMS = new Object[0]; // // public static final Class[] SINGLE_OBJECT_PARAM_SIGNATURE = new Class[] { Object.class }; // // private static final Method OBJECT_EQUALS; // private static final Method OBJECT_HASHCODE; // // static { // Method eq; // Method hash; // try { // eq = extractEqualsMethod( Object.class ); // hash = extractHashCodeMethod( Object.class ); // } // catch ( Exception e ) { // throw new AssertionFailure( "Could not find Object.equals() or Object.hashCode()", e ); // } // OBJECT_EQUALS = eq; // OBJECT_HASHCODE = hash; // } // // /** // * Disallow instantiation of ReflectHelper. // */ // private ReflectHelper() { // } // // /** // * Encapsulation of getting hold of a class's {@link Object#equals equals} method. // * // * @param clazz The class from which to extract the equals method. // * @return The equals method reference // * @throws NoSuchMethodException Should indicate an attempt to extract equals method from interface. // */ // public static Method extractEqualsMethod(Class clazz) throws NoSuchMethodException { // return clazz.getMethod( "equals", SINGLE_OBJECT_PARAM_SIGNATURE ); // } // // /** // * Encapsulation of getting hold of a class's {@link Object#hashCode hashCode} method. // * // * @param clazz The class from which to extract the hashCode method. // * @return The hashCode method reference // * @throws NoSuchMethodException Should indicate an attempt to extract hashCode method from interface. // */ // public static Method extractHashCodeMethod(Class clazz) throws NoSuchMethodException { // return clazz.getMethod( "hashCode", NO_PARAM_SIGNATURE ); // } // // /** // * Determine if the given class defines an {@link Object#equals} override. // * // * @param clazz The class to check // * @return True if clazz defines an equals override. // */ // public static boolean overridesEquals(Class clazz) { // Method equals; // try { // equals = extractEqualsMethod( clazz ); // } // catch ( NoSuchMethodException nsme ) { // return false; //its an interface so we can't really tell anything... // } // return !OBJECT_EQUALS.equals( equals ); // } // // /** // * Determine if the given class defines a {@link Object#hashCode} override. // * // * @param clazz The class to check // * @return True if clazz defines an hashCode override. // */ // public static boolean overridesHashCode(Class clazz) { // Method hashCode; // try { // hashCode = extractHashCodeMethod( clazz ); // } // catch ( NoSuchMethodException nsme ) { // return false; //its an interface so we can't really tell anything... // } // return !OBJECT_HASHCODE.equals( hashCode ); // } // // /** // * Determine if the given class implements the given interface. // * // * @param clazz The class to check // * @param intf The interface to check it against. // * @return True if the class does implement the interface, false otherwise. // */ // public static boolean implementsInterface(Class clazz, Class intf) { // assert intf.isInterface() : "Interface to check was not an interface"; // return intf.isAssignableFrom( clazz ); // } // /** * Perform resolution of a class name. * <p/> * Here we first check the context classloader, if one, before delegating to * {@link Class#forName(String, boolean, ClassLoader)} using the caller's classloader * * @param name The class name * @param caller The class from which this call originated (in order to access that class's loader). * @return The class reference. * @throws ClassNotFoundException From {@link Class#forName(String, boolean, ClassLoader)}. */ public static Class classForName(String name, Class caller) throws ClassNotFoundException { try { ClassLoader classLoader = ClassLoaderHelper.getContextClassLoader(); if ( classLoader != null ) { return classLoader.loadClass( name ); } } catch ( Throwable ignore ) { } return Class.forName( name, true, caller.getClassLoader() ); } /** * Perform resolution of a class name. * <p/> * Same as {@link #classForName(String, Class)} except that here we delegate to * {@link Class#forName(String)} if the context classloader lookup is unsuccessful. * * @param name The class name * @return The class reference. * @throws ClassNotFoundException From {@link Class#forName(String)}. */ public static Class classForName(String name) throws ClassNotFoundException { try { ClassLoader classLoader = ClassLoaderHelper.getContextClassLoader(); if ( classLoader != null ) { return classLoader.loadClass(name); } } catch ( Throwable ignore ) { } return Class.forName( name ); } // /** // * Is this member publicly accessible. // * <p/> // * Short-hand for {@link #isPublic(Class, Member)} passing the member + {@link Member#getDeclaringClass()} // * // * @param member The member to check // * @return True if the member is publicly accessible. // */ // public static boolean isPublic(Member member) { // return isPublic( member.getDeclaringClass(), member ); // } // // /** // * Is this member publicly accessible. // * // * @param clazz The class which defines the member // * @param member The memeber. // * @return True if the member is publicly accessible, false otherwise. // */ // public static boolean isPublic(Class clazz, Member member) { // return Modifier.isPublic( member.getModifiers() ) && Modifier.isPublic( clazz.getModifiers() ); // } // // /** // * Attempt to resolve the specified property type through reflection. // * // * @param className The name of the class owning the property. // * @param name The name of the property. // * @return The type of the property. // * @throws MappingException Indicates we were unable to locate the property. // */ // public static Class reflectedPropertyClass(String className, String name) throws MappingException { // try { // Class clazz = ReflectHelper.classForName( className ); // return getter( clazz, name ).getReturnType(); // } // catch ( ClassNotFoundException cnfe ) { // throw new MappingException( "class " + className + " not found while looking for property: " + name, cnfe ); // } // } // // /** // * Attempt to resolve the specified property type through reflection. // * // * @param clazz The class owning the property. // * @param name The name of the property. // * @return The type of the property. // * @throws MappingException Indicates we were unable to locate the property. // */ // public static Class reflectedPropertyClass(Class clazz, String name) throws MappingException { // return getter( clazz, name ).getReturnType(); // } // // private static Getter getter(Class clazz, String name) throws MappingException { // try { // return BASIC_PROPERTY_ACCESSOR.getGetter( clazz, name ); // } // catch ( PropertyNotFoundException pnfe ) { // return DIRECT_PROPERTY_ACCESSOR.getGetter( clazz, name ); // } // } // // /** // * Directly retrieve the {@link Getter} reference via the {@link BasicPropertyAccessor}. // * // * @param theClass The class owning the property // * @param name The name of the property // * @return The getter. // * @throws MappingException Indicates we were unable to locate the property. // */ // public static Getter getGetter(Class theClass, String name) throws MappingException { // return BASIC_PROPERTY_ACCESSOR.getGetter( theClass, name ); // } // // /** // * Resolve a constant to its actual value. // * // * @param name The name // * @return The value // */ // public static Object getConstantValue(String name) { // Class clazz; // try { // clazz = classForName( StringHelper.qualifier( name ) ); // } // catch ( Throwable t ) { // return null; // } // try { // return clazz.getField( StringHelper.unqualify( name ) ).get( null ); // } // catch ( Throwable t ) { // return null; // } // } // // /** // * Retrieve the default (no arg) constructor from the given class. // * // * @param clazz The class for which to retrieve the default ctor. // * @return The default constructor. // * @throws PropertyNotFoundException Indicates there was not publicly accessible, no-arg constructor (todo : why PropertyNotFoundException???) // */ // public static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) throws PropertyNotFoundException { // if ( isAbstractClass( clazz ) ) { // return null; // } // // try { // Constructor<T> constructor = clazz.getDeclaredConstructor( NO_PARAM_SIGNATURE ); // constructor.setAccessible( true ); // return constructor; // } // catch ( NoSuchMethodException nme ) { // throw new PropertyNotFoundException( // "Object class [" + clazz.getName() + "] must declare a default (no-argument) constructor" // ); // } // } // // /** // * Determine if the given class is declared abstract. // * // * @param clazz The class to check. // * @return True if the class is abstract, false otherwise. // */ // public static boolean isAbstractClass(Class clazz) { // int modifier = clazz.getModifiers(); // return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier); // } // // /** // * Determine is the given class is declared final. // * // * @param clazz The class to check. // * @return True if the class is final, flase otherwise. // */ // public static boolean isFinalClass(Class clazz) { // return Modifier.isFinal( clazz.getModifiers() ); // } // // /** // * Retrieve a constructor for the given class, with arguments matching the specified Hibernate mapping // * {@link Type types}. // * // * @param clazz The class needing instantiation // * @param types The types representing the required ctor param signature // * @return The matching constructor. // * @throws PropertyNotFoundException Indicates we could not locate an appropriate constructor (todo : again with PropertyNotFoundException???) // */ // public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException { // final Constructor[] candidates = clazz.getConstructors(); // for ( int i = 0; i < candidates.length; i++ ) { // final Constructor constructor = candidates[i]; // final Class[] params = constructor.getParameterTypes(); // if ( params.length == types.length ) { // boolean found = true; // for ( int j = 0; j < params.length; j++ ) { // final boolean ok = params[j].isAssignableFrom( types[j].getReturnedClass() ) || ( // types[j] instanceof PrimitiveType && // params[j] == ( ( PrimitiveType ) types[j] ).getPrimitiveClass() // ); // if ( !ok ) { // found = false; // break; // } // } // if ( found ) { // constructor.setAccessible( true ); // return constructor; // } // } // } // throw new PropertyNotFoundException( "no appropriate constructor in class: " + clazz.getName() ); // } // // public static Method getMethod(Class clazz, Method method) { // try { // return clazz.getMethod( method.getName(), method.getParameterTypes() ); // } // catch (Exception e) { // return null; // } // } }