2 * Copyright (c) 2001-2007 Sun Microsystems, Inc. All rights reserved.
4 * The Sun Project JXTA(TM) Software License
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * 3. The end-user documentation included with the redistribution, if any, must
17 * include the following acknowledgment: "This product includes software
18 * developed by Sun Microsystems, Inc. for JXTA(TM) technology."
19 * Alternately, this acknowledgment may appear in the software itself, if
20 * and wherever such third-party acknowledgments normally appear.
22 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
23 * not be used to endorse or promote products derived from this software
24 * without prior written permission. For written permission, please contact
25 * Project JXTA at http://www.jxta.org.
27 * 5. Products derived from this software may not be called "JXTA", nor may
28 * "JXTA" appear in their name, without prior written permission of Sun.
30 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
32 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN
33 * MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
36 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
39 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * JXTA is a registered trademark of Sun Microsystems, Inc. in the United
42 * States and other countries.
44 * Please see the license information page at :
45 * <http://www.jxta.org/project/www/license.html> for instructions on use of
46 * the license in source files.
48 * ====================================================================
50 * This software consists of voluntary contributions made by many individuals
51 * on behalf of Project JXTA. For more information on Project JXTA, please see
52 * http://www.jxta.org.
54 * This license is based on the BSD license adopted by the Apache Foundation.
57 package net.jxta.impl.id.binaryID;
60 import java.util.logging.Level;
61 import net.jxta.logging.Logging;
62 import java.util.logging.Logger;
64 import java.io.Serializable;
68 * A <code>BinaryID</code> is a 256-byte, identifier.
69 * This class should be immutable so that it is thread safe.
71 * @author Daniel Brookshier <a HREF="mailto:turbogeek@cluck.com">turbogeek@cluck.com</a>
73 * @see net.jxta.id.IDFactory
76 public class BinaryID implements Serializable {
78 private final static transient Logger LOG = Logger.getLogger(BinaryID.class.getName());
79 public static String UUIDEncoded = "uuid";
80 public final static int flagsSize = 1;
82 public final static byte flagPeerGroupID = 'a';
83 public final static byte flagPeerID = 'b';
84 public final static byte flagPipeID = 'c';
86 public final static byte flagModuleClassID = 'd';
87 public final static byte flagModuleClassRoleID = 'e';
89 public final static byte flagModuleSpecID = 'f';
90 public final static byte flagCodatID = 'g';
91 public final static byte flagGenericID = 'z';
94 * location of the byte designating its type.
96 public final static int flagsOffset = 0;
99 * location of the byte where the data starts.
101 public final static int dataOffset = 1;
106 private static final byte[] nullID = { 0};
107 public static final BinaryID nullBinaryID = new BinaryID(flagGenericID, nullID, true);
110 * Array that holds the length and the value of the id in base64 format. This is the default format
111 * rather than binary byte because it saves time converting. Odds of returning the actual binary are
112 * low so it is done on demand only. Callers of the toByteArray() method should consider the cost of
113 * decoding if it is to be called often.
115 protected String encodedValue = null;
118 * Creates a null value ID.
121 this.encodedValue = nullBinaryID.encodedValue; // (flagGenericID, nullID, true);
125 * Creates zero content ID of a specific type.
127 public BinaryID(byte id) {
128 this(id, nullID, true);
132 * Creates a ID from a string. Note that the ID is not currently validated.
134 * @param encodedValue Value to convert ID.
136 protected BinaryID(String encodedValue) {
137 this.encodedValue = encodedValue;
141 * Simple constructor that takes a binary array to signify the contents of the array.
143 * @param type The Type of ID. Valid values: flagPeerGroupID,flagPeerID,flagPipeID,flagGenericID
144 * @param data the array of up to 256 bytes. Max is 256 if lengthIncluded is true or 255 if the first byte is the length-1.
145 * @param lengthIncluded Boolean that signifies if the first byte is the length of the bytes to follow.
146 * @throws RuntimeException Runtime exception trhown if array is not correct or if included, the array length does not match actual size.
149 public BinaryID(byte type, byte data[], boolean lengthIncluded) {
150 if (lengthIncluded && data.length < 256 && data.length > 1) {
151 if (data[0] == data.length - 1) {
153 java.io.StringWriter base64 = new java.io.StringWriter();
154 net.jxta.impl.util.BASE64OutputStream encoder = new net.jxta.impl.util.BASE64OutputStream(base64);
159 encodedValue = ((char) type) + base64.toString();
160 } catch (Exception e) {
161 LOG.log(Level.SEVERE, "Unable to encode binary value.", e);
162 throw new RuntimeException("Unable to encode binary value.");
165 throw new RuntimeException(
166 "Length of data section is " + (data.length - 1) + " but byte zero says length is:" + data[0] + ".");
168 } else if (!lengthIncluded && data.length > 0) {
169 byte temp[] = new byte[data.length + 1];
171 temp[0] = (byte) data.length;
172 System.arraycopy(data, 0, temp, 1, data.length);
174 java.io.StringWriter base64 = new java.io.StringWriter();
175 net.jxta.impl.util.BASE64OutputStream encoder = new net.jxta.impl.util.BASE64OutputStream(base64);
180 encodedValue = ((char) type) + base64.toString();
181 } catch (Exception e) {
182 LOG.log(Level.SEVERE, "Unable to encode binary value.", e);
183 throw new RuntimeException("Unable to encode binary value.");
185 } else if (lengthIncluded && (data.length > 256 || data.length == 0)) {
186 throw new RuntimeException("Length of 'data' is " + data.length + " must be >0 and less or equal to 256.");
187 } else if (!lengthIncluded && data.length > 255) {
188 throw new RuntimeException("Length of 'data' is " + data.length + " must be less than 256. ");
193 * Returns the value of the ID as a binary array. This is always decoded from the base64
194 * string rather than caching of the binary array. Callers of the toByteArray() method
195 * should consider the cost of decoding if the method is called often.
197 * @return returns the data part of the array.
199 public byte[] toByteArray() {
201 java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
202 net.jxta.impl.util.BASE64InputStream decoder = new net.jxta.impl.util.BASE64InputStream(
203 new java.io.StringReader(encodedValue.substring(1)));
206 int c = decoder.read();
215 return bos.toByteArray();
216 } catch (Exception e) {
217 LOG.log(Level.SEVERE, "Unable to decode binary value.", e);
218 throw new RuntimeException("Unable to encode binary value.");
224 * Returns the value of the ID as a binary array without the size in byte zero. This is always decoded from the base64
225 * string rather than caching of the binary array. Callers of the toByteArray() method
226 * should consider the cost of decoding if the method is called often.<p>
228 * Note that we assume the array size-1 equals the contents of byte zero.
230 * @return returns the array with the first byte as the length of the remaining bytes.
232 public byte[] toSizeIncludedByteArray() {
233 byte[] data = toByteArray();
235 byte temp[] = new byte[data.length - 1];
237 System.arraycopy(data, 1, temp, 0, temp.length);
243 * @return The ID which consists of a character designating type, followed by the base64 encoded value of the size and array of bytes.
245 public String encodedValue() {
250 * Returns the hash code of the BinaryID<p>
252 * WARNING: Do not use this hash as a network ID. Use a stronger digest hash like SHA-1 to get the hash of the contents.
254 * @return int hashcode
258 public int hashCode() {
259 return encodedValue.hashCode();
263 * Compares two BinaryIDs for equality.<p>
264 * true: taget == this<p>
265 * false: target == null<p>
266 * true: taget.encodedValue == this.encodedValue<p>
267 * true: target instance of ID && ID==ID.nullID && nullBinaryID.encodedValue().equals( encodedValue())<p>
268 * false: all other posibilities<p>
270 * @param target the BidaryID to be compared against.
271 * @return boolean true if IDs are equal, false otherwise.
274 public boolean equals(Object target) {
275 boolean result = false;
277 if (target == this) {
279 } else if (target == null) {
281 } else if (target instanceof BinaryID) {
282 result = encodedValue().equals(((BinaryID) target).encodedValue());
283 LOG.fine("((BinaryID)target).encodedValue():" + ((BinaryID) target).encodedValue());
284 } else if (target instanceof net.jxta.id.ID && ((net.jxta.id.ID) target) == net.jxta.id.ID.nullID
285 && nullBinaryID.encodedValue().equals(encodedValue())) {
288 // LOG.error("this:"+encodedValue()+" type:"+target.getClass().getName()+" target:"+target+" equals:"+result,new RuntimeException("test exception"));
293 * Return the type of ID.
295 * @return byte value designating type.
299 return (byte) encodedValue.charAt(0);
303 * Returns base 64 encoded value.
305 * @return String return value
309 public String toString() {
314 * returns the raw encoded value. Not cloned because it is a string.
316 public String getID() {