1 package org.hibernate.ejb.callback; 2 3 import java.io.ByteArrayOutputStream ; 4 import java.io.DataOutputStream ; 5 import java.lang.reflect.Constructor ; 6 import java.lang.reflect.Method ; 7 import java.security.DigestOutputStream ; 8 import java.security.MessageDigest ; 9 import java.util.HashMap ; 10 import java.util.Map ; 11 import java.util.WeakHashMap ; 12 13 19 public final class MethodHashing { 20 private MethodHashing() {} 21 static Map hashMap = new WeakHashMap (); 22 23 public static Method findMethodByHash(Class clazz, long hash) throws Exception { 24 Method [] methods = clazz.getDeclaredMethods(); 25 for ( int i = 0 ; i < methods.length ; i++ ) { 26 if ( methodHash( methods[i] ) == hash ) return methods[i]; 27 } 28 29 if ( clazz.isInterface() ) { 30 final Class [] interfaces = clazz.getInterfaces(); 31 final int numInterfaces = interfaces.length; 32 for ( int count = 0 ; count < numInterfaces ; count++ ) { 33 final Method method = findMethodByHash( interfaces[count], hash ); 34 if ( method != null ) { 35 return method; 36 } 37 } 38 } 39 else if ( clazz.getSuperclass() != null ) { 40 return findMethodByHash( clazz.getSuperclass(), hash ); 41 } 42 return null; 43 } 44 45 public static Constructor findConstructorByHash(Class clazz, long hash) throws Exception { 46 Constructor [] cons = clazz.getDeclaredConstructors(); 47 for ( int i = 0 ; i < cons.length ; i++ ) { 48 if ( constructorHash( cons[i] ) == hash ) return cons[i]; 49 } 50 if ( clazz.getSuperclass() != null ) { 51 return findConstructorByHash( clazz.getSuperclass(), hash ); 52 } 53 return null; 54 } 55 56 public static long methodHash(Method method) 57 throws Exception { 58 Class [] parameterTypes = method.getParameterTypes(); 59 String methodDesc = method.getName() + "("; 60 for ( int j = 0 ; j < parameterTypes.length ; j++ ) { 61 methodDesc += getTypeString( parameterTypes[j] ); 62 } 63 methodDesc += ")" + getTypeString( method.getReturnType() ); 64 return createHash( methodDesc ); 65 } 66 67 public static long createHash(String methodDesc) 68 throws Exception { 69 long hash = 0; 70 ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream ( 512 ); 71 MessageDigest messagedigest = MessageDigest.getInstance( "SHA" ); 72 DataOutputStream dataoutputstream = new DataOutputStream ( 73 new DigestOutputStream ( bytearrayoutputstream, messagedigest ) 74 ); 75 dataoutputstream.writeUTF( methodDesc ); 76 dataoutputstream.flush(); 77 byte abyte0[] = messagedigest.digest(); 78 for ( int j = 0 ; j < Math.min( 8, abyte0.length ) ; j++ ) { 79 hash += (long) ( abyte0[j] & 0xff ) << j * 8; 80 } 81 return hash; 82 83 } 84 85 public static long constructorHash(Constructor method) 86 throws Exception { 87 Class [] parameterTypes = method.getParameterTypes(); 88 String methodDesc = method.getName() + "("; 89 for ( int j = 0 ; j < parameterTypes.length ; j++ ) { 90 methodDesc += getTypeString( parameterTypes[j] ); 91 } 92 methodDesc += ")"; 93 94 long hash = 0; 95 ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream ( 512 ); 96 MessageDigest messagedigest = MessageDigest.getInstance( "SHA" ); 97 DataOutputStream dataoutputstream = new DataOutputStream ( 98 new DigestOutputStream ( bytearrayoutputstream, messagedigest ) 99 ); 100 dataoutputstream.writeUTF( methodDesc ); 101 dataoutputstream.flush(); 102 byte abyte0[] = messagedigest.digest(); 103 for ( int j = 0 ; j < Math.min( 8, abyte0.length ) ; j++ ) { 104 hash += (long) ( abyte0[j] & 0xff ) << j * 8; 105 } 106 return hash; 107 } 108 109 115 public static Map getInterfaceHashes(Class intf) { 116 Method [] methods = intf.getDeclaredMethods(); 118 HashMap map = new HashMap (); 119 for ( int i = 0 ; i < methods.length ; i++ ) { 120 Method method = methods[i]; 121 try { 122 long hash = methodHash( method ); 123 map.put( method.toString(), new Long ( hash ) ); 124 } 125 catch (Exception e) { 126 } 127 } 128 129 return map; 130 } 131 132 static String getTypeString(Class cl) { 133 if ( cl == Byte.TYPE ) { 134 return "B"; 135 } 136 else if ( cl == Character.TYPE ) { 137 return "C"; 138 } 139 else if ( cl == Double.TYPE ) { 140 return "D"; 141 } 142 else if ( cl == Float.TYPE ) { 143 return "F"; 144 } 145 else if ( cl == Integer.TYPE ) { 146 return "I"; 147 } 148 else if ( cl == Long.TYPE ) { 149 return "J"; 150 } 151 else if ( cl == Short.TYPE ) { 152 return "S"; 153 } 154 else if ( cl == Boolean.TYPE ) { 155 return "Z"; 156 } 157 else if ( cl == Void.TYPE ) { 158 return "V"; 159 } 160 else if ( cl.isArray() ) { 161 return "[" + getTypeString( cl.getComponentType() ); 162 } 163 else { 164 return "L" + cl.getName().replace( '.', '/' ) + ";"; 165 } 166 } 167 168 175 public static long calculateHash(Method method) { 176 Map methodHashes = (Map ) hashMap.get( method.getDeclaringClass() ); 177 178 if ( methodHashes == null ) { 179 methodHashes = getInterfaceHashes( method.getDeclaringClass() ); 180 181 WeakHashMap newHashMap = new WeakHashMap (); 183 newHashMap.putAll( hashMap ); 184 newHashMap.put( method.getDeclaringClass(), methodHashes ); 185 hashMap = newHashMap; 186 } 187 188 return ( (Long ) methodHashes.get( method.toString() ) ).longValue(); 189 } 190 191 } 192 | Popular Tags |