KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > easybeans > rpc > util > Hash


1 /**
2  * EasyBeans
3  * Copyright (C) 2006 Bull S.A.S.
4  * Contact: easybeans@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: Hash.java 203 2006-03-15 17:53:41Z benoitf $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.easybeans.rpc.util;
27
28 import java.io.ByteArrayOutputStream JavaDoc;
29 import java.io.DataOutputStream JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.lang.reflect.Method JavaDoc;
32 import java.security.DigestOutputStream JavaDoc;
33 import java.security.MessageDigest JavaDoc;
34 import java.security.NoSuchAlgorithmException JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.Map JavaDoc;
37
38 import org.objectweb.asm.Type;
39
40 import org.objectweb.easybeans.log.JLog;
41 import org.objectweb.easybeans.log.JLogFactory;
42
43 /**
44  * Utility class providing some hashing methods on java.lang.reflect.Method or
45  * java.lang.Class.
46  * @author Florent Benoit
47  */

48 public final class Hash {
49
50     /**
51      * Logger.
52      */

53     private static JLog logger = JLogFactory.getLog(Hash.class);
54
55     /**
56      * Length of hash of a method (eight byte sequence).
57      */

58     private static final int BYTES_LENGTH = 8;
59
60     /**
61      * Mask for hashing algorithm.
62      */

63     private static final int BYTE_MASK = 0xFF;
64
65
66     /**
67      * Utility class, no public constructor.
68      */

69     private Hash() {
70
71     }
72
73     /**
74      * Computes the hash for a given method.<br>
75      * The method hash to be used for the opnum parameter is a 64-bit (long)
76      * integer computed from the first two 32-bit values of the message digest
77      * of a particular byte stream using the National Institute of Standards and
78      * Technology (NIST) Secure Hash Algorithm (SHA-1). This byte stream
79      * contains a string as if it was written using the
80      * java.io.DataOutput.writeUTF method, consisting of the remote method's
81      * name followed by its method descriptor (see section 4.3.3 of The Java
82      * Virtual Machine Specification (JVMS) for a description of method
83      * descriptors). The 64-bit hash value is the little-endian composition of
84      * an eight byte sequence where the first four bytes are the first 32-bit
85      * value of the message digest in big-endian byte order and the last four
86      * bytes are the second 32-bit value of the message digest in big-endian
87      * byte order.
88      * @param method the given method.
89      * @return the computed hash.
90      * @see <a
91      * HREF="http://java.sun.com/j2se/1.5.0/docs/guide/rmi/spec/rmi-stubs24.html">Method
92      * hashing of RMI</a>
93      */

94     public static long hashMethod(final Method JavaDoc method) {
95
96         MessageDigest JavaDoc md;
97         try {
98             md = MessageDigest.getInstance("SHA-1");
99         } catch (NoSuchAlgorithmException JavaDoc e) {
100             throw new IllegalStateException JavaDoc("Algorithm SHA-1 is not available", e);
101         }
102         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
103         DigestOutputStream JavaDoc dos = new DigestOutputStream JavaDoc(baos, md);
104         DataOutputStream JavaDoc das = new DataOutputStream JavaDoc(dos);
105
106         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
107         sb.append(method.getName());
108         sb.append(Type.getMethodDescriptor(method));
109         try {
110             das.writeUTF(sb.toString());
111         } catch (IOException JavaDoc e) {
112             throw new IllegalStateException JavaDoc("Cannot write data for method '" + method.getName() + "'.", e);
113         }
114         try {
115             das.flush();
116         } catch (IOException JavaDoc e) {
117             logger.warn("Cannot flush the stream", e);
118         }
119         try {
120             das.close();
121         } catch (IOException JavaDoc e) {
122             logger.warn("Cannot flush the stream", e);
123         }
124
125         byte[] digest = md.digest();
126         long hash = 0;
127         int size = Math.min(digest.length, BYTES_LENGTH);
128         for (int i = 0; i < size; i++) {
129             hash += (long) (digest[i] & BYTE_MASK) << (BYTES_LENGTH * i);
130         }
131         return hash;
132     }
133
134
135     /**
136      * Gets a map between an hash and its associated method.
137      * @param clz the class to analyze.
138      * @return a map with an hash and its associated method.
139      */

140     public static Map JavaDoc<Long JavaDoc, Method JavaDoc> hashClass(final Class JavaDoc clz) {
141         Map JavaDoc<Long JavaDoc, Method JavaDoc> map = new HashMap JavaDoc<Long JavaDoc, Method JavaDoc>();
142         Method JavaDoc[] methods = clz.getMethods();
143         for (Method JavaDoc m : methods) {
144             map.put(Long.valueOf(hashMethod(m)), m);
145         }
146         return map;
147     }
148
149 }
150
Popular Tags