KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > 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.util;
23  
24 import java.io.ByteArrayOutputStream JavaDoc;
25 import java.io.DataOutputStream JavaDoc;
26 import java.lang.reflect.Method JavaDoc;
27 import java.lang.reflect.Constructor 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: 1958 $
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 = clazz.getDeclaredMethods();
50       for (int i = 0; i < methods.length; i++)
51       {
52          if (methodHash(methods[i]) == hash) return methods[i];
53       }
54       if (clazz.getSuperclass() != null)
55       {
56          return findMethodByHash(clazz.getSuperclass(), hash);
57       }
58       return null;
59    }
60
61    public static Constructor JavaDoc findConstructorByHash(Class JavaDoc clazz, long hash) throws Exception JavaDoc
62    {
63       Constructor JavaDoc[] cons = clazz.getDeclaredConstructors();
64       for (int i = 0; i < cons.length; i++)
65       {
66          if (constructorHash(cons[i]) == hash) return cons[i];
67       }
68       if (clazz.getSuperclass() != null)
69       {
70          return findConstructorByHash(clazz.getSuperclass(), hash);
71       }
72       return null;
73    }
74
75    public static long methodHash(Method JavaDoc method)
76       throws Exception JavaDoc
77    {
78       Class JavaDoc[] parameterTypes = method.getParameterTypes();
79       String JavaDoc methodDesc = method.getName()+"(";
80       for(int j = 0; j < parameterTypes.length; j++)
81       {
82          methodDesc += getTypeString(parameterTypes[j]);
83       }
84       methodDesc += ")"+getTypeString(method.getReturnType());
85       
86       long hash = 0;
87       ByteArrayOutputStream JavaDoc bytearrayoutputstream = new ByteArrayOutputStream JavaDoc(512);
88       MessageDigest JavaDoc messagedigest = MessageDigest.getInstance("SHA");
89       DataOutputStream JavaDoc dataoutputstream = new DataOutputStream JavaDoc(new DigestOutputStream JavaDoc(bytearrayoutputstream, messagedigest));
90       dataoutputstream.writeUTF(methodDesc);
91       dataoutputstream.flush();
92       byte abyte0[] = messagedigest.digest();
93       for(int j = 0; j < Math.min(8, abyte0.length); j++)
94          hash += (long)(abyte0[j] & 0xff) << j * 8;
95       return hash;
96    }
97
98    public static long constructorHash(Constructor JavaDoc method)
99       throws Exception JavaDoc
100    {
101       Class JavaDoc[] parameterTypes = method.getParameterTypes();
102       String JavaDoc methodDesc = method.getName()+"(";
103       for(int j = 0; j < parameterTypes.length; j++)
104       {
105          methodDesc += getTypeString(parameterTypes[j]);
106       }
107       methodDesc += ")";
108
109       long hash = 0;
110       ByteArrayOutputStream JavaDoc bytearrayoutputstream = new ByteArrayOutputStream JavaDoc(512);
111       MessageDigest JavaDoc messagedigest = MessageDigest.getInstance("SHA");
112       DataOutputStream JavaDoc dataoutputstream = new DataOutputStream JavaDoc(new DigestOutputStream JavaDoc(bytearrayoutputstream, messagedigest));
113       dataoutputstream.writeUTF(methodDesc);
114       dataoutputstream.flush();
115       byte abyte0[] = messagedigest.digest();
116       for(int j = 0; j < Math.min(8, abyte0.length); j++)
117          hash += (long)(abyte0[j] & 0xff) << j * 8;
118       return hash;
119    }
120
121    /**
122    * Calculate method hashes. This algo is taken from RMI.
123    *
124    * @param intf
125    * @return
126    */

127    public static Map JavaDoc getInterfaceHashes(Class JavaDoc intf)
128    {
129       // Create method hashes
130
Method JavaDoc[] methods = intf.getDeclaredMethods();
131       HashMap JavaDoc map = new HashMap JavaDoc();
132       for (int i = 0; i < methods.length; i++)
133       {
134          Method JavaDoc method = methods[i];
135          try
136          {
137             long hash = methodHash(method);
138             map.put(method.toString(), new Long JavaDoc(hash));
139          }
140          catch (Exception JavaDoc e)
141          {
142          }
143       }
144       
145       return map;
146    }
147    
148    static String JavaDoc getTypeString(Class JavaDoc cl)
149    {
150       if (cl == Byte.TYPE)
151       {
152          return "B";
153       } else if (cl == Character.TYPE)
154       {
155          return "C";
156       } else if (cl == Double.TYPE)
157       {
158          return "D";
159       } else if (cl == Float.TYPE)
160       {
161          return "F";
162       } else if (cl == Integer.TYPE)
163       {
164          return "I";
165       } else if (cl == Long.TYPE)
166       {
167          return "J";
168       } else if (cl == Short.TYPE)
169       {
170          return "S";
171       } else if (cl == Boolean.TYPE)
172       {
173          return "Z";
174       } else if (cl == Void.TYPE)
175       {
176          return "V";
177       } else if (cl.isArray())
178       {
179          return "["+getTypeString(cl.getComponentType());
180       } else
181       {
182          return "L"+cl.getName().replace('.','/')+";";
183       }
184    }
185    
186    /*
187    * The use of hashCode is not enough to differenciate methods
188    * we override the hashCode
189    *
190    * The hashes are cached in a static for efficiency
191    * RO: WeakHashMap needed to support undeploy
192    */

193    public static long calculateHash(Method JavaDoc method)
194    {
195       Map JavaDoc methodHashes = (Map JavaDoc)hashMap.get(method.getDeclaringClass());
196       
197       if (methodHashes == null)
198       {
199          methodHashes = getInterfaceHashes(method.getDeclaringClass());
200          
201          // Copy and add
202
WeakHashMap JavaDoc newHashMap = new WeakHashMap JavaDoc();
203          newHashMap.putAll(hashMap);
204          newHashMap.put(method.getDeclaringClass(), methodHashes);
205          hashMap = newHashMap;
206       }
207       
208       return ((Long JavaDoc)methodHashes.get(method.toString())).longValue();
209    }
210
211 }
212
Popular Tags