KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > ejb > callback > MethodHashing


1 package org.hibernate.ejb.callback;
2
3 import java.io.ByteArrayOutputStream JavaDoc;
4 import java.io.DataOutputStream JavaDoc;
5 import java.lang.reflect.Constructor JavaDoc;
6 import java.lang.reflect.Method JavaDoc;
7 import java.security.DigestOutputStream JavaDoc;
8 import java.security.MessageDigest JavaDoc;
9 import java.util.HashMap JavaDoc;
10 import java.util.Map JavaDoc;
11 import java.util.WeakHashMap JavaDoc;
12
13 /**
14  * Create a unique hash for
15  *
16  * @author <a HREF="mailto:marc@jboss.org">Marc Fleury</a>
17  * @version $Revision: 1.5 $
18  */

19 public final class MethodHashing {
20     private MethodHashing() {}
21     static Map JavaDoc hashMap = new WeakHashMap JavaDoc();
22
23     public static Method JavaDoc findMethodByHash(Class JavaDoc clazz, long hash) throws Exception JavaDoc {
24         Method JavaDoc[] 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 JavaDoc[] interfaces = clazz.getInterfaces();
31             final int numInterfaces = interfaces.length;
32             for ( int count = 0 ; count < numInterfaces ; count++ ) {
33                 final Method JavaDoc 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 JavaDoc findConstructorByHash(Class JavaDoc clazz, long hash) throws Exception JavaDoc {
46         Constructor JavaDoc[] 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 JavaDoc method)
57             throws Exception JavaDoc {
58         Class JavaDoc[] parameterTypes = method.getParameterTypes();
59         String JavaDoc 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 JavaDoc methodDesc)
68             throws Exception JavaDoc {
69         long hash = 0;
70         ByteArrayOutputStream JavaDoc bytearrayoutputstream = new ByteArrayOutputStream JavaDoc( 512 );
71         MessageDigest JavaDoc messagedigest = MessageDigest.getInstance( "SHA" );
72         DataOutputStream JavaDoc dataoutputstream = new DataOutputStream JavaDoc(
73                 new DigestOutputStream JavaDoc( 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 JavaDoc method)
86             throws Exception JavaDoc {
87         Class JavaDoc[] parameterTypes = method.getParameterTypes();
88         String JavaDoc 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 JavaDoc bytearrayoutputstream = new ByteArrayOutputStream JavaDoc( 512 );
96         MessageDigest JavaDoc messagedigest = MessageDigest.getInstance( "SHA" );
97         DataOutputStream JavaDoc dataoutputstream = new DataOutputStream JavaDoc(
98                 new DigestOutputStream JavaDoc( 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     /**
110      * Calculate method hashes. This algo is taken from RMI.
111      *
112      * @param intf
113      * @return
114      */

115     public static Map JavaDoc getInterfaceHashes(Class JavaDoc intf) {
116         // Create method hashes
117
Method JavaDoc[] methods = intf.getDeclaredMethods();
118         HashMap JavaDoc map = new HashMap JavaDoc();
119         for ( int i = 0 ; i < methods.length ; i++ ) {
120             Method JavaDoc method = methods[i];
121             try {
122                 long hash = methodHash( method );
123                 map.put( method.toString(), new Long JavaDoc( hash ) );
124             }
125             catch (Exception JavaDoc e) {
126             }
127         }
128
129         return map;
130     }
131
132     static String JavaDoc getTypeString(Class JavaDoc 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     /*
169     * The use of hashCode is not enough to differenciate methods
170     * we override the hashCode
171     *
172     * The hashes are cached in a static for efficiency
173     * RO: WeakHashMap needed to support undeploy
174     */

175     public static long calculateHash(Method JavaDoc method) {
176         Map JavaDoc methodHashes = (Map JavaDoc) hashMap.get( method.getDeclaringClass() );
177
178         if ( methodHashes == null ) {
179             methodHashes = getInterfaceHashes( method.getDeclaringClass() );
180
181             // Copy and add
182
WeakHashMap JavaDoc newHashMap = new WeakHashMap JavaDoc();
183             newHashMap.putAll( hashMap );
184             newHashMap.put( method.getDeclaringClass(), methodHashes );
185             hashMap = newHashMap;
186         }
187
188         return ( (Long JavaDoc) methodHashes.get( method.toString() ) ).longValue();
189     }
190
191 }
192
Popular Tags