1 package org.hibernate.util; 3 4 import java.lang.reflect.Constructor ; 5 import java.lang.reflect.Member ; 6 import java.lang.reflect.Method ; 7 import java.lang.reflect.Modifier ; 8 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 12 import net.sf.cglib.beans.BulkBean; 13 import net.sf.cglib.beans.BulkBeanException; 14 import net.sf.cglib.reflect.FastClass; 15 import org.hibernate.AssertionFailure; 16 import org.hibernate.MappingException; 17 import org.hibernate.PropertyNotFoundException; 18 import org.hibernate.property.BasicPropertyAccessor; 19 import org.hibernate.property.DirectPropertyAccessor; 20 import org.hibernate.property.Getter; 21 import org.hibernate.property.PropertyAccessor; 22 import org.hibernate.type.PrimitiveType; 23 import org.hibernate.type.Type; 24 25 26 public final class ReflectHelper { 27 28 private static final Log log = LogFactory.getLog(ReflectHelper.class); 29 private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor(); 31 private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor(); 32 33 private static final Class [] NO_CLASSES = new Class [0]; 34 private static final Class [] OBJECT = new Class [] { Object .class }; 35 private static final Method OBJECT_EQUALS; 36 private static final Class [] NO_PARAM = new Class [] { }; 37 38 private static final Method OBJECT_HASHCODE; 39 static { 40 Method eq; 41 Method hash; 42 try { 43 eq = Object .class.getMethod("equals", OBJECT); 44 hash = Object .class.getMethod("hashCode", NO_PARAM); 45 } 46 catch (Exception e) { 47 throw new AssertionFailure("Could not find Object.equals() or Object.hashCode()", e); 48 } 49 OBJECT_EQUALS = eq; 50 OBJECT_HASHCODE = hash; 51 } 52 53 public static boolean overridesEquals(Class clazz) { 54 Method equals; 55 try { 56 equals = clazz.getMethod("equals", OBJECT); 57 } 58 catch (NoSuchMethodException nsme) { 59 return false; } 61 return !OBJECT_EQUALS.equals(equals); 62 } 63 64 public static boolean overridesHashCode(Class clazz) { 65 Method hashCode; 66 try { 67 hashCode = clazz.getMethod("hashCode", NO_PARAM); 68 } 69 catch (NoSuchMethodException nsme) { 70 return false; } 72 return !OBJECT_HASHCODE.equals(hashCode); 73 } 74 75 public static Class reflectedPropertyClass(String className, String name) throws MappingException { 76 try { 77 Class clazz = ReflectHelper.classForName(className); 78 return getter(clazz, name).getReturnType(); 79 } 80 catch (ClassNotFoundException cnfe) { 81 throw new MappingException("class " + className + " not found while looking for property: " + name, cnfe); 82 } 83 } 84 85 private static Getter getter(Class clazz, String name) throws MappingException { 86 try { 87 return BASIC_PROPERTY_ACCESSOR.getGetter(clazz, name); 88 } 89 catch (PropertyNotFoundException pnfe) { 90 return DIRECT_PROPERTY_ACCESSOR.getGetter(clazz, name); 91 } 92 } 93 94 public static Getter getGetter(Class theClass, String name) throws MappingException { 95 return BASIC_PROPERTY_ACCESSOR.getGetter(theClass, name); 96 } 97 98 public static Class classForName(String name) throws ClassNotFoundException { 99 try { 100 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 101 if (contextClassLoader!=null) { 102 return contextClassLoader.loadClass(name); 103 } 104 else { 105 return Class.forName(name); 106 } 107 } 108 catch (Exception e) { 109 return Class.forName(name); 110 } 111 } 112 113 public static boolean isPublic(Class clazz, Member member) { 114 return Modifier.isPublic( member.getModifiers() ) && Modifier.isPublic( clazz.getModifiers() ); 115 } 116 117 public static Object getConstantValue(String name) { 118 Class clazz; 119 try { 120 clazz = classForName( StringHelper.qualifier(name) ); 121 } 122 catch(ClassNotFoundException cnfe) { 123 return null; 124 } 125 try { 126 return clazz.getField( StringHelper.unqualify(name) ).get(null); 127 } 128 catch (Exception e) { 129 return null; 130 } 131 } 132 133 public static Constructor getDefaultConstructor(Class clazz) throws PropertyNotFoundException { 134 135 if ( isAbstractClass(clazz) ) return null; 136 137 try { 138 Constructor constructor = clazz.getDeclaredConstructor(NO_CLASSES); 139 if ( !isPublic(clazz, constructor) ) { 140 constructor.setAccessible(true); 141 } 142 return constructor; 143 } 144 catch (NoSuchMethodException nme) { 145 throw new PropertyNotFoundException( 146 "Object class " + clazz.getName() + 147 " must declare a default (no-argument) constructor" 148 ); 149 } 150 151 } 152 153 public static boolean isAbstractClass(Class clazz) { 154 int modifier = clazz.getModifiers(); 155 return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier); 156 } 157 158 public static boolean isFinalClass(Class clazz) { 159 return Modifier.isFinal( clazz.getModifiers() ); 160 } 161 162 public static FastClass getFastClass(Class clazz) { 163 try { 164 return FastClass.create(clazz); 165 } 166 catch (Throwable t) { 167 return null; 168 } 169 } 170 171 public static BulkBean getBulkBean( 172 Class clazz, 173 String [] getterNames, 174 String [] setterNames, 175 Class [] types, 176 FastClass fastClass 177 ) { 178 try { 179 BulkBean optimizer = BulkBean.create(clazz, getterNames, setterNames, types); 180 if ( !clazz.isInterface() && !Modifier.isAbstract( clazz.getModifiers() ) ) { 181 if (fastClass==null) return null; 182 Object instance = fastClass.newInstance(); 184 optimizer.setPropertyValues( instance, optimizer.getPropertyValues(instance) ); 185 } 186 return optimizer; 188 } 189 catch (Throwable t) { 190 191 String message = 192 "reflection optimizer disabled for: " + 193 clazz.getName() + 194 ", " + 195 StringHelper.unqualify( t.getClass().getName() ) + 196 ": " + 197 t.getMessage(); 198 199 if (t instanceof BulkBeanException) { 200 int index = ( (BulkBeanException) t ).getIndex(); 201 if (index >= 0) { 202 message += " (property " + setterNames[index] + ")"; 203 } 204 } 205 206 log.debug(message); 207 return null; 208 209 } 210 } 211 212 public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException { 213 final Constructor [] candidates = clazz.getConstructors(); 214 for ( int i=0; i<candidates.length; i++ ) { 215 final Constructor constructor = candidates[i]; 216 final Class [] params = constructor.getParameterTypes(); 217 if ( params.length==types.length ) { 218 boolean found = true; 219 for ( int j=0; j<params.length; j++ ) { 220 final boolean ok = params[j].isAssignableFrom( types[j].getReturnedClass() ) || ( 221 types[j] instanceof PrimitiveType && 222 params[j] == ( (PrimitiveType) types[j] ).getPrimitiveClass() 223 ); 224 if (!ok) { 225 found = false; 226 break; 227 } 228 } 229 if (found) { 230 if ( !isPublic(clazz, constructor) ) constructor.setAccessible(true); 231 return constructor; 232 } 233 } 234 } 235 throw new PropertyNotFoundException( "no appropriate constructor in class: " + clazz.getName() ); 236 } 237 238 public static String getPropertyName(Throwable t, BulkBean optimizer) { 239 if (t instanceof BulkBeanException) { 240 return optimizer.getSetters()[ ( (BulkBeanException) t ).getIndex() ]; 241 } 242 else { 243 return "?"; 244 } 245 } 246 247 public static Method getMethod(Class clazz, Method method) { 248 try { 249 return clazz.getMethod( method.getName(), method.getParameterTypes() ); 250 } 251 catch (Exception e) { 252 return null; 253 } 254 } 255 256 private ReflectHelper() {} 257 258 public static final String PROPERTY_GET_EXCEPTION = 259 "exception getting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info)"; 260 261 public static final String PROPERTY_SET_EXCEPTION = 262 "exception setting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info)"; 263 264 } 265 | Popular Tags |