Source code: jsdsi/Hash.java
1 /*
2 * Copyright 2002 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this program for any
5 * purpose and without fee is hereby granted, provided that this
6 * copyright and permission notice appear on all copies and supporting
7 * documentation, the name of M.I.T. not be used in advertising or
8 * publicity pertaining to distribution of the program without specific
9 * prior permission, and notice be given in supporting documentation that
10 * copying and distribution is by permission of M.I.T. M.I.T. makes no
11 * representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 */
14 package jsdsi;
15
16 import jsdsi.sexp.*;
17 import java.net.URL;
18 import java.security.MessageDigest;
19 import java.security.NoSuchAlgorithmException;
20 import java.util.ArrayList;
21 import java.util.Iterator;
22 import java.util.List;
23
24 /**
25 * A cryptographic hash value. Specifies the hash algorithm, the value
26 * to hash, and an optional set of URIs that specify where the hashed
27 * object is located.
28 *
29 * @author Sameer Ajmani
30 * @version $Revision: 1.3 $ $Date: 2003/08/02 18:35:48 $
31 */
32 public class Hash extends Obj {
33 /**
34 * Name of the hash algorithm used.
35 */
36 private final String algo;
37
38 /**
39 * Hash value.
40 */
41 private final byte[] data;
42
43 /**
44 * URLs assigned to this <code>Hash</code> (may be <code>null</code>).
45 */
46 private final URL[] urls;
47
48 /**
49 * Creates a new <code>Hash</code> from a given algorithm name, a
50 * value to hash, and an array of URLs.
51 *
52 * @param a name of the hash algorithm used.
53 * @param d value to hash.
54 * @param u an array of URLs assigned to this <code>Hash</code>.
55 */
56 public Hash(String a, byte[] d, URL[] u) {
57 assert(a != null) : "null algo";
58 assert(d != null) : "null data";
59 algo = a;
60 data = d;
61 urls = u;
62 }
63
64 /**
65 * Creates a new <code>Hash</code> from a given algorithm name, object
66 * to hash, and an array of URLs.
67 *
68 * @param a name of the hash algorithm used.
69 * @param o object to calculate the hash value from.
70 * @param u an array of URLs assigned to this <code>Hash</code>.
71 */
72 public Hash(String a, Obj o, URL[] u) {
73 assert(a != null) : "null algo";
74 assert(o != null) : "null object";
75 algo = a;
76 try {
77 data = MessageDigest.getInstance(a).digest(o.toByteArray());
78 } catch (NoSuchAlgorithmException e) {
79 throw new Error(e);
80 }
81 urls = u;
82 }
83
84 /**
85 * Creates a new <code>Hash</code> from an algorithm name and a byte array
86 * that contains a hash value.
87 *
88 * @param a name of the hash algorithm used.
89 * @param d byte array containing the value to hash.
90 */
91 public Hash(String a, byte[] d) {
92 this(a, d, null);
93 }
94
95 /**
96 * Creates a new <code>Hash</code> from an algorithm name and an object.
97 *
98 * @param a name of the hash algorithm used.
99 * @param o object to calculate the hash value from.
100 */
101 public Hash(String a, Obj o) {
102 this(a, o, null);
103 }
104
105 /**
106 * Returns the name of the algorithm used.
107 *
108 * @return the name of the algorithm used.
109 */
110 public String getAlgorithm() {
111 return algo;
112 }
113
114 /**
115 * Returns the hash value as a byte array.
116 *
117 * @return a byte array that stores the has value.
118 */
119 public byte[] getData() {
120 return data;
121 }
122
123 /**
124 * Returns an array of URLs assigned to this <code>Hash</code>.
125 *
126 * @return an array of URLs assigned to this <code>Hash</code>.
127 */
128 public URL[] getURLs() {
129 return urls;
130 }
131
132 /**
133 * @see java.lang.Object#equals(Object)
134 */
135 public boolean equals(Object o) {
136 if (o instanceof Hash) {
137 Hash h = (Hash) o;
138 return algo.equals(h.algo)
139 && java.util.Arrays.equals(data, h.data)
140 && Util.equals(urls, h.urls);
141 }
142 return false;
143 }
144
145 /**
146 * @see java.lang.Object#hashCode()
147 */
148 public int hashCode() {
149 return algo.hashCode() ^ data.hashCode() ^ Util.hashCode(urls);
150 }
151
152 /**
153 * Returns an <code>SexpList</code> that holds this <code>Hash</code>.
154 *
155 * @return an <code>SexpList</code> that holds this <code>Hash</code>.
156 */
157 public SexpList toSexp() {
158 List l = new ArrayList(3);
159 l.add(SexpUtil.toSexp(getAlgorithm()));
160 l.add(SexpUtil.toSexp(getData()));
161 if (getURLs() != null) {
162 l.add(SexpUtil.toSexp(getURLs()));
163 }
164 return SexpUtil.toSexp("hash", l);
165 }
166
167 /**
168 * Parses an <code>SexpList</code> that holds a <code>Hash</code>
169 * and returns a <code>Hash</code> of this.
170 *
171 * @param l the <code>SexpList</code> to parse.
172 * @return the <code>Hash</code> created from the
173 * <code>SexList</code>.
174 * @throws SexpParseException
175 */
176 public static Hash parseHash(SexpList l) throws SexpParseException {
177 Iterator hbody = SexpUtil.getBody(l);
178 String algo = SexpUtil.getNextString(hbody, "hash algo");
179 byte[] data = SexpUtil.getNextByteArray(hbody, "hash data");
180 SexpUtil.checkDone(hbody, "hash"); // TODO: support URIs
181 return new Hash(algo, data);
182 }
183 }