comparison src/org/tmatesoft/hg/core/Nodeid.java @ 500:465316bf97e8

Tailored subclass of IAE for malformed Nodeids:HgBadNodeidFormatException
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Mon, 29 Oct 2012 18:16:21 +0100
parents 85b8efde5586
children d9c07e1432c4
comparison
equal deleted inserted replaced
499:899a1b68ef03 500:465316bf97e8
42 private final byte[] binaryData; 42 private final byte[] binaryData;
43 43
44 /** 44 /**
45 * @param binaryRepresentation - array of exactly 20 bytes 45 * @param binaryRepresentation - array of exactly 20 bytes
46 * @param shallClone - true if array is subject to future modification and shall be copied, not referenced 46 * @param shallClone - true if array is subject to future modification and shall be copied, not referenced
47 * @throws IllegalArgumentException if supplied binary representation doesn't correspond to 20 bytes of sha1 digest 47 * @throws HgBadNodeidFormatException custom {@link IllegalArgumentException} subclass if supplied binary representation doesn't correspond to 20 bytes of sha1 digest
48 */ 48 */
49 public Nodeid(byte[] binaryRepresentation, boolean shallClone) { 49 public Nodeid(byte[] binaryRepresentation, boolean shallClone) {
50 // 5 int fields => 32 bytes 50 // 5 int fields => 32 bytes
51 // byte[20] => 48 bytes (16 bytes is Nodeid with one field, 32 bytes for byte[20] 51 // byte[20] => 48 bytes (16 bytes is Nodeid with one field, 32 bytes for byte[20]
52 if (binaryRepresentation == null || binaryRepresentation.length != 20) { 52 if (binaryRepresentation == null || binaryRepresentation.length != 20) {
53 throw new IllegalArgumentException(); 53 throw new HgBadNodeidFormatException(String.format("Bad value: %s", String.valueOf(binaryRepresentation)));
54 } 54 }
55 /* 55 /*
56 * byte[].clone() is not reflected when ran with -agentlib:hprof=heap=sites 56 * byte[].clone() is not reflected when ran with -agentlib:hprof=heap=sites
57 * thus not to get puzzled why there are N Nodeids and much less byte[] instances, 57 * thus not to get puzzled why there are N Nodeids and much less byte[] instances,
58 * may use following code to see N byte[] as well. 58 * may use following code to see N byte[] as well.
138 * Factory for {@link Nodeid Nodeids}. 138 * Factory for {@link Nodeid Nodeids}.
139 * Primary difference with cons is handling of NULL id (this method returns constant) and control over array 139 * Primary difference with cons is handling of NULL id (this method returns constant) and control over array
140 * duplication - this method always makes a copy of an array passed 140 * duplication - this method always makes a copy of an array passed
141 * @param binaryRepresentation - byte array of a length at least offset + 20 141 * @param binaryRepresentation - byte array of a length at least offset + 20
142 * @param offset - index in the array to start from 142 * @param offset - index in the array to start from
143 * @throws IllegalArgumentException when arguments don't select 20 bytes 143 * @throws HgBadNodeidFormatException custom {@link IllegalArgumentException} subclass when arguments don't select 20 bytes
144 */ 144 */
145 public static Nodeid fromBinary(byte[] binaryRepresentation, int offset) { 145 public static Nodeid fromBinary(byte[] binaryRepresentation, int offset) {
146 if (binaryRepresentation == null || binaryRepresentation.length - offset < 20) { 146 if (binaryRepresentation == null || binaryRepresentation.length - offset < 20) {
147 throw new IllegalArgumentException(); 147 throw new HgBadNodeidFormatException(String.format("Bad value: %s", String.valueOf(binaryRepresentation)));
148 } 148 }
149 int i = 0; 149 int i = 0;
150 while (i < 20 && binaryRepresentation[offset+i] == 0) i++; 150 while (i < 20 && binaryRepresentation[offset+i] == 0) i++;
151 if (i == 20) { 151 if (i == 20) {
152 return NULL; 152 return NULL;
162 /** 162 /**
163 * Parse encoded representation. 163 * Parse encoded representation.
164 * 164 *
165 * @param asciiRepresentation - encoded form of the Nodeid. 165 * @param asciiRepresentation - encoded form of the Nodeid.
166 * @return object representation 166 * @return object representation
167 * @throws IllegalArgumentException when argument doesn't match encoded form of 20-bytes sha1 digest. 167 * @throws HgBadNodeidFormatException custom {@link IllegalArgumentException} subclass when argument doesn't match encoded form of 20-bytes sha1 digest.
168 */ 168 */
169 public static Nodeid fromAscii(String asciiRepresentation) { 169 public static Nodeid fromAscii(String asciiRepresentation) {
170 if (asciiRepresentation.length() != 40) { 170 if (asciiRepresentation.length() != 40) {
171 throw new IllegalArgumentException(); 171 throw new HgBadNodeidFormatException(String.format("Bad value: %s", asciiRepresentation));
172 } 172 }
173 // XXX is better impl for String possible? 173 // XXX is better impl for String possible?
174 return fromAscii(asciiRepresentation.toCharArray(), 0, 40); 174 return fromAscii(asciiRepresentation.toCharArray(), 0, 40);
175 } 175 }
176 176
177 /** 177 /**
178 * Parse encoded representation. Similar to {@link #fromAscii(String)}. 178 * Parse encoded representation. Similar to {@link #fromAscii(String)}.
179 * @throws HgBadNodeidFormatException custom {@link IllegalArgumentException} subclass when bytes are not hex digits or number of bytes != 40 (160 bits)
179 */ 180 */
180 public static Nodeid fromAscii(byte[] asciiRepresentation, int offset, int length) { 181 public static Nodeid fromAscii(byte[] asciiRepresentation, int offset, int length) {
181 if (length != 40) { 182 if (length != 40) {
182 throw new IllegalArgumentException(); 183 throw new IllegalArgumentException();
183 } 184 }
184 byte[] data = new byte[20]; 185 try {
185 boolean zeroBytes = DigestHelper.ascii2bin(asciiRepresentation, offset, length, data); 186 byte[] data = new byte[20];
186 if (zeroBytes) { 187 boolean zeroBytes = DigestHelper.ascii2bin(asciiRepresentation, offset, length, data);
187 return NULL; 188 if (zeroBytes) {
188 } 189 return NULL;
189 return new Nodeid(data, false); 190 }
191 return new Nodeid(data, false);
192 } catch (IllegalArgumentException ex) {
193 throw new HgBadNodeidFormatException(ex.getMessage());
194 }
190 } 195 }
191 196
192 public static Nodeid fromAscii(char[] asciiRepresentation, int offset, int length) { 197 public static Nodeid fromAscii(char[] asciiRepresentation, int offset, int length) {
193 byte[] b = new byte[length]; 198 byte[] b = new byte[length];
194 for (int i = 0; i < b.length; i++) { 199 for (int i = 0; i < b.length; i++) {