KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > aop > util > MethodHashing


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.aop.util;
23  
24 import java.io.ByteArrayOutputStream JavaDoc;
25 import java.io.DataOutputStream JavaDoc;
26 import java.lang.reflect.Constructor JavaDoc;
27 import java.lang.reflect.Method JavaDoc;
28 import java.security.DigestOutputStream JavaDoc;
29 import java.security.MessageDigest JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.WeakHashMap JavaDoc;
33
34 /**
35  * Create a unique hash for
36  *
37  * @author <a HREF="mailto:marc@jboss.org">Marc Fleury</a>
38  * @version $Revision: 45976 $
39  */

40 public class MethodHashing
41 {
42    // Constants -----------------------------------------------------
43

44    // Static --------------------------------------------------------
45
static Map JavaDoc hashMap = new WeakHashMap JavaDoc();
46
47    public static Method JavaDoc findMethodByHash(Class JavaDoc clazz, long hash) throws Exception JavaDoc
48    {
49       Method JavaDoc[] methods = SecurityActions.getDeclaredMethods(clazz);
50       for (int i = 0; i < methods.length; i++)
51       {
52          if (methodHash(methods[i]) == hash) return methods[i];
53       }
54
55       if (clazz.isInterface())
56       {
57          final Class JavaDoc[] interfaces = clazz.getInterfaces() ;
58          final int numInterfaces = interfaces.length ;
59          for(int count = 0 ; count < numInterfaces ; count++)
60          {
61             final Method JavaDoc method = findMethodByHash(interfaces[count], hash) ;
62             if (method != null)
63             {
64                return method ;
65             }
66          }
67       }
68       else if (clazz.getSuperclass() != null)
69       {
70          return findMethodByHash(clazz.getSuperclass(), hash);
71       }
72       return null;
73    }
74
75    public static Constructor JavaDoc findConstructorByHash(Class JavaDoc clazz, long hash) throws Exception JavaDoc
76    {
77       Constructor JavaDoc[] cons = SecurityActions.getDeclaredConstructors(clazz);
78       for (int i = 0; i < cons.length; i++)
79       {
80          if (constructorHash(cons[i]) == hash) return cons[i];
81       }
82       if (clazz.getSuperclass() != null)
83       {
84          return findConstructorByHash(clazz.getSuperclass(), hash);
85       }
86       return null;
87    }
88
89    public static long methodHash(Method JavaDoc method)
90       throws Exception JavaDoc
91    {
92       Class JavaDoc[] parameterTypes = method.getParameterTypes();
93       String JavaDoc methodDesc = method.getName()+"(";
94       for(int j = 0; j < parameterTypes.length; j++)
95       {
96          methodDesc += getTypeString(parameterTypes[j]);
97       }
98       methodDesc += ")"+getTypeString(method.getReturnType());
99       return createHash(methodDesc);
100    }
101    
102    public static long createHash(String JavaDoc methodDesc)
103     throws Exception JavaDoc
104    {
105       long hash = 0;
106       ByteArrayOutputStream JavaDoc bytearrayoutputstream = new ByteArrayOutputStream JavaDoc(512);
107       MessageDigest JavaDoc messagedigest = MessageDigest.getInstance("SHA");
108       DataOutputStream JavaDoc dataoutputstream = new DataOutputStream JavaDoc(new DigestOutputStream JavaDoc(bytearrayoutputstream, messagedigest));
109       dataoutputstream.writeUTF(methodDesc);
110       dataoutputstream.flush();
111       byte abyte0[] = messagedigest.digest();
112       for(int j = 0; j < Math.min(8, abyte0.length); j++)
113          hash += (long)(abyte0[j] & 0xff) << j * 8;
114       return hash;
115       
116    }
117
118    public static long constructorHash(Constructor JavaDoc method)
119       throws Exception JavaDoc
120    {
121       Class JavaDoc[] parameterTypes = method.getParameterTypes();
122       String JavaDoc methodDesc = method.getName()+"(";
123       for(int j = 0; j < parameterTypes.length; j++)
124       {
125          methodDesc += getTypeString(parameterTypes[j]);
126       }
127       methodDesc += ")";
128
129       long hash = 0;
130       ByteArrayOutputStream JavaDoc bytearrayoutputstream = new ByteArrayOutputStream JavaDoc(512);
131       MessageDigest JavaDoc messagedigest = MessageDigest.getInstance("SHA");
132       DataOutputStream JavaDoc dataoutputstream = new DataOutputStream JavaDoc(new DigestOutputStream JavaDoc(bytearrayoutputstream, messagedigest));
133       dataoutputstream.writeUTF(methodDesc);
134       dataoutputstream.flush();
135       byte abyte0[] = messagedigest.digest();
136       for(int j = 0; j < Math.min(8, abyte0.length); j++)
137          hash += (long)(abyte0[j] & 0xff) << j * 8;
138       return hash;
139    }
140
141    /**
142    * Calculate method hashes. This algo is taken from RMI.
143    *
144    * @param intf
145    * @return
146    */

147    public static Map JavaDoc getInterfaceHashes(Class JavaDoc intf)
148    {
149       // Create method hashes
150
Method JavaDoc[] methods = SecurityActions.getDeclaredMethods(intf);
151       HashMap JavaDoc map = new HashMap JavaDoc();
152       for (int i = 0; i < methods.length; i++)
153       {
154          Method JavaDoc method = methods[i];
155          try
156          {
157             long hash = methodHash(method);
158             map.put(method.toString(), new Long JavaDoc(hash));
159          }
160          catch (Exception JavaDoc e)
161          {
162          }
163       }
164       
165       return map;
166    }
167    
168    static String JavaDoc getTypeString(Class JavaDoc cl)
169    {
170       if (cl == Byte.TYPE)
171       {
172          return "B";
173       } else if (cl == Character.TYPE)
174       {
175          return "C";
176       } else if (cl == Double.TYPE)
177       {
178          return "D";
179       } else if (cl == Float.TYPE)
180       {
181          return "F";
182       } else if (cl == Integer.TYPE)
183       {
184          return "I";
185       } else if (cl == Long.TYPE)
186       {
187          return "J";
188       } else if (cl == Short.TYPE)
189       {
190          return "S";
191       } else if (cl == Boolean.TYPE)
192       {
193          return "Z";
194       } else if (cl == Void.TYPE)
195       {
196          return "V";
197       } else if (cl.isArray())
198       {
199          return "["+getTypeString(cl.getComponentType());
200       } else
201       {
202          return "L"+cl.getName().replace('.','/')+";";
203       }
204    }
205    
206    /*
207    * The use of hashCode is not enough to differenciate methods
208    * we override the hashCode
209    *
210    * The hashes are cached in a static for efficiency
211    * RO: WeakHashMap needed to support undeploy
212    */

213    public static long calculateHash(Method JavaDoc method)
214    {
215       Map JavaDoc methodHashes = (Map JavaDoc)hashMap.get(method.getDeclaringClass());
216       
217       if (methodHashes == null)
218       {
219          methodHashes = getInterfaceHashes(method.getDeclaringClass());
220          
221          // Copy and add
222
WeakHashMap JavaDoc newHashMap = new WeakHashMap JavaDoc();
223          newHashMap.putAll(hashMap);
224          newHashMap.put(method.getDeclaringClass(), methodHashes);
225          hashMap = newHashMap;
226       }
227       
228       return ((Long JavaDoc)methodHashes.get(method.toString())).longValue();
229    }
230
231 }
232
Popular Tags