KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > nutch > io > MD5Hash


1 /* Copyright (c) 2003 The Nutch Organization. All rights reserved. */
2 /* Use subject to the conditions in http://www.nutch.org/LICENSE.txt. */
3
4 package net.nutch.io;
5
6 import java.io.IOException JavaDoc;
7 import java.io.DataInput JavaDoc;
8 import java.io.DataOutput JavaDoc;
9 import java.util.Arrays JavaDoc;
10 import java.security.*;
11
12 /** A Writable for MD5 hash values.
13  *
14  * @author Doug Cutting
15  */

16 public class MD5Hash implements WritableComparable {
17   public static final int MD5_LEN = 16;
18   private static final MessageDigest DIGESTER;
19   static {
20     try {
21       DIGESTER = MessageDigest.getInstance("MD5");
22     } catch (NoSuchAlgorithmException e) {
23       throw new RuntimeException JavaDoc(e);
24     }
25   }
26
27   private byte[] digest;
28
29   /** Constructs an MD5Hash. */
30   public MD5Hash() {
31     this.digest = new byte[MD5_LEN];
32   }
33
34   /** Constructs an MD5Hash from a hex string. */
35   public MD5Hash(String JavaDoc hex) {
36     setDigest(hex);
37   }
38   
39   /** Constructs an MD5Hash with a specified value. */
40   public MD5Hash(byte[] digest) {
41     if (digest.length != MD5_LEN)
42       throw new IllegalArgumentException JavaDoc("Wrong length: " + digest.length);
43     this.digest = digest;
44   }
45   
46   // javadoc from Writable
47
public void readFields(DataInput JavaDoc in) throws IOException JavaDoc {
48     in.readFully(digest);
49   }
50
51   /** Constructs, reads and returns an instance. */
52   public static MD5Hash read(DataInput JavaDoc in) throws IOException JavaDoc {
53     MD5Hash result = new MD5Hash();
54     result.readFields(in);
55     return result;
56   }
57
58   // javadoc from Writable
59
public void write(DataOutput JavaDoc out) throws IOException JavaDoc {
60     out.write(digest);
61   }
62
63   /** Copy the contents of another instance into this instance. */
64   public void set(MD5Hash that) {
65     System.arraycopy(that.digest, 0, this.digest, 0, MD5_LEN);
66   }
67
68   /** Returns the digest bytes. */
69   public byte[] getDigest() { return digest; }
70
71   /** Construct a hash value for a byte array. */
72   public static MD5Hash digest(byte[] data) {
73     return digest(data, 0, data.length);
74   }
75
76   /** Construct a hash value for a byte array. */
77   public static MD5Hash digest(byte[] data, int start, int len) {
78     byte[] digest;
79     synchronized (DIGESTER) {
80       DIGESTER.update(data, start, len);
81       digest = DIGESTER.digest();
82     }
83     return new MD5Hash(digest);
84   }
85
86   /** Construct a hash value for a String. */
87   public static MD5Hash digest(String JavaDoc string) {
88     return digest(UTF8.getBytes(string));
89   }
90
91   /** Construct a hash value for a String. */
92   public static MD5Hash digest(UTF8 utf8) {
93     return digest(utf8.getBytes(), 0, utf8.getLength());
94   }
95
96   /** Construct a half-sized version of this MD5. Fits in a long **/
97   public long halfDigest() {
98     long value = 0;
99     for (int i = 0; i < 8; i++)
100       value |= ((digest[i] & 0xffL) << (8*(7-i)));
101     return value;
102   }
103
104   /** Returns true iff <code>o</code> is an MD5Hash whose digest contains the
105    * same values. */

106   public boolean equals(Object JavaDoc o) {
107     if (!(o instanceof MD5Hash))
108       return false;
109     MD5Hash other = (MD5Hash)o;
110     return Arrays.equals(this.digest, other.digest);
111   }
112
113   /** Returns a hash code value for this object.*/
114   public int hashCode() {
115     return // xor four ints
116
(digest[ 0] | (digest[ 1]<<8) | (digest[ 2]<<16) | (digest[ 3]<<24)) ^
117       (digest[ 4] | (digest[ 5]<<8) | (digest[ 6]<<16) | (digest[ 7]<<24)) ^
118       (digest[ 8] | (digest[ 9]<<8) | (digest[10]<<16) | (digest[11]<<24)) ^
119       (digest[12] | (digest[13]<<8) | (digest[14]<<16) | (digest[15]<<24));
120   }
121
122
123   /** Compares this object with the specified object for order.*/
124   public int compareTo(Object JavaDoc o) {
125     MD5Hash that = (MD5Hash)o;
126     return WritableComparator.compareBytes(this.digest, 0, MD5_LEN,
127                                            that.digest, 0, MD5_LEN);
128   }
129
130   /** A WritableComparator optimized for MD5Hash keys. */
131   public static class Comparator extends WritableComparator {
132     public Comparator() {
133       super(MD5Hash.class);
134     }
135
136     public int compare(byte[] b1, int s1, int l1,
137                        byte[] b2, int s2, int l2) {
138       return compareBytes(b1, s1, MD5_LEN, b2, s2, MD5_LEN);
139     }
140   }
141
142
143   private static final char[] HEX_DIGITS =
144   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
145
146   /** Returns a string representation of this object. */
147   public String JavaDoc toString() {
148     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(MD5_LEN*2);
149     for (int i = 0; i < MD5_LEN; i++) {
150       int b = digest[i];
151       buf.append(HEX_DIGITS[(b >> 4) & 0xf]);
152       buf.append(HEX_DIGITS[b & 0xf]);
153     }
154     return buf.toString();
155   }
156
157   /** Sets the digest value from a hex string. */
158   public void setDigest(String JavaDoc hex) {
159     if (hex.length() != MD5_LEN*2)
160       throw new IllegalArgumentException JavaDoc("Wrong length: " + hex.length());
161     byte[] digest = new byte[MD5_LEN];
162     for (int i = 0; i < MD5_LEN; i++) {
163       int j = i << 1;
164       digest[i] = (byte)(charToNibble(hex.charAt(j)) << 4 |
165                          charToNibble(hex.charAt(j+1)));
166     }
167     this.digest = digest;
168   }
169
170   private static final int charToNibble(char c) {
171     if (c >= '0' && c <= '9') {
172       return c - '0';
173     } else if (c >= 'a' && c <= 'f') {
174       return 0xa + (c - 'a');
175     } else if (c >= 'A' && c <= 'F') {
176       return 0xA + (c - 'A');
177     } else {
178       throw new RuntimeException JavaDoc("Not a hex character: " + c);
179     }
180   }
181
182
183 }
184
Popular Tags