001: /*
002:
003: Derby - Class org.apache.derby.impl.services.uuid.BasicUUID
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.services.uuid;
023:
024: import org.apache.derby.iapi.services.io.FormatIdUtil;
025: import org.apache.derby.iapi.services.io.StoredFormatIds;
026: import org.apache.derby.iapi.services.io.Formatable;
027:
028: import org.apache.derby.catalog.UUID;
029:
030: import java.io.ObjectOutput;
031: import java.io.ObjectInput;
032: import java.io.IOException;
033:
034: import java.io.StringReader;
035:
036: public class BasicUUID implements UUID, Formatable {
037: /*
038: ** Fields of BasicUUID
039: */
040:
041: private long majorId; // only using 48 bits
042: private long timemillis;
043: private int sequence;
044:
045: /*
046: ** Methods of BasicUUID
047: */
048:
049: /**
050: Constructor only called by BasicUUIDFactory.
051: **/
052: public BasicUUID(long majorId, long timemillis, int sequence) {
053: this .majorId = majorId;
054: this .timemillis = timemillis;
055: this .sequence = sequence;
056: }
057:
058: /**
059: Constructor only called by BasicUUIDFactory.
060: Constructs a UUID from the string representation
061: produced by toString.
062: @see BasicUUID#toString
063: **/
064: public BasicUUID(String uuidstring) {
065: StringReader sr = new StringReader(uuidstring);
066: sequence = (int) readMSB(sr);
067:
068: long ltimemillis = readMSB(sr) << 32;
069: ltimemillis += readMSB(sr) << 16;
070: ltimemillis += readMSB(sr);
071: timemillis = ltimemillis;
072: majorId = readMSB(sr);
073: }
074:
075: /**
076: Constructor only called by BasicUUIDFactory.
077: Constructs a UUID from the byte array representation
078: produced by toByteArrayio.
079: @see BasicUUID#toByteArray
080: **/
081: public BasicUUID(byte[] b) {
082: int lsequence = 0;
083: for (int ix = 0; ix < 4; ix++) {
084: lsequence = lsequence << 8;
085: lsequence = lsequence | (0xff & b[ix]);
086: }
087:
088: long ltimemillis = 0;
089: for (int ix = 4; ix < 10; ix++) {
090: ltimemillis = ltimemillis << 8;
091: ltimemillis = ltimemillis | (0xff & b[ix]);
092: }
093:
094: long linetaddr = 0;
095: for (int ix = 10; ix < 16; ix++) {
096: linetaddr = linetaddr << 8;
097: linetaddr = linetaddr | (0xff & b[ix]);
098: }
099:
100: sequence = lsequence;
101: timemillis = ltimemillis;
102: majorId = linetaddr;
103: }
104:
105: /*
106: * Formatable methods
107: */
108:
109: // no-arg constructor, required by Formatable
110: public BasicUUID() {
111: super ();
112: }
113:
114: /**
115: Write this out.
116: @exception IOException error writing to log stream
117: */
118: public void writeExternal(ObjectOutput out) throws IOException {
119: // RESOLVE: write out the byte array instead?
120: out.writeLong(majorId);
121: out.writeLong(timemillis);
122: out.writeInt(sequence);
123: }
124:
125: /**
126: Read this in
127: @exception IOException error reading from log stream
128: */
129: public void readExternal(ObjectInput in) throws IOException {
130: majorId = in.readLong();
131: timemillis = in.readLong();
132: sequence = in.readInt();
133: }
134:
135: /**
136: Return my format identifier.
137: */
138: public int getTypeFormatId() {
139: return StoredFormatIds.BASIC_UUID;
140: }
141:
142: private static void writeMSB(char[] data, int offset, long value,
143: int nbytes) {
144: for (int i = nbytes - 1; i >= 0; i--) {
145: long b = (value & (255L << (8 * i))) >>> (8 * i);
146:
147: int c = (int) ((b & 0xf0) >> 4);
148: data[offset++] = (char) (c < 10 ? c + '0' : (c - 10) + 'a');
149: c = (int) (b & 0x0f);
150: data[offset++] = (char) (c < 10 ? c + '0' : (c - 10) + 'a');
151: }
152: }
153:
154: /**
155: Read a long value, msb first, from its character
156: representation in the string reader, using '-' or
157: end of string to delimit.
158: **/
159: private static long readMSB(StringReader sr) {
160: long value = 0;
161:
162: try {
163: int c;
164: while ((c = sr.read()) != -1) {
165: if (c == '-')
166: break;
167: value <<= 4;
168:
169: int nibble;
170: if (c <= '9')
171: nibble = c - '0';
172: else if (c <= 'F')
173: nibble = c - 'A' + 10;
174: else
175: nibble = c - 'a' + 10;
176: value += nibble;
177: }
178: } catch (Exception e) {
179: }
180:
181: return value;
182: }
183:
184: /*
185: ** Methods of UUID
186: */
187:
188: /**
189: Implement value equality.
190:
191: **/
192: public boolean equals(Object otherObject) {
193: if (!(otherObject instanceof BasicUUID))
194: return false;
195:
196: BasicUUID other = (BasicUUID) otherObject;
197:
198: return (this .sequence == other.sequence)
199: && (this .timemillis == other.timemillis)
200: && (this .majorId == other.majorId);
201: }
202:
203: /**
204: Provide a hashCode which is compatible with
205: the equals() method.
206: **/
207: public int hashCode() {
208: long hc = majorId ^ timemillis;
209:
210: return sequence ^ ((int) (hc >> 4));
211: }
212:
213: /**
214: Produce a string representation of this UUID which
215: can be passed to UUIDFactory.recreateUUID later on
216: to reconstruct it. The funny representation is
217: designed to (sort of) match the format of Microsoft's
218: UUIDGEN utility.
219: */
220: public String toString() {
221: return stringWorkhorse('-');
222: }
223:
224: /**
225: Produce a string representation of this UUID which
226: is suitable for use as a unique ANSI identifier.
227: */
228: public String toANSIidentifier() {
229: return "U" + stringWorkhorse('X');
230: }
231:
232: /**
233: * Private workhorse of the string making routines.
234: *
235: * @param separator Character to separate number blocks.
236: * Null means do not include a separator.
237: *
238: * @return string representation of UUID.
239: */
240: public String stringWorkhorse(char separator) {
241: char[] data = new char[36];
242:
243: writeMSB(data, 0, (long) sequence, 4);
244:
245: int offset = 8;
246: if (separator != 0)
247: data[offset++] = separator;
248:
249: long ltimemillis = timemillis;
250: writeMSB(data, offset,
251: (ltimemillis & 0x0000ffff00000000L) >>> 32, 2);
252: offset += 4;
253: if (separator != 0)
254: data[offset++] = separator;
255: writeMSB(data, offset,
256: (ltimemillis & 0x00000000ffff0000L) >>> 16, 2);
257: offset += 4;
258: if (separator != 0)
259: data[offset++] = separator;
260: writeMSB(data, offset, (ltimemillis & 0x000000000000ffffL), 2);
261: offset += 4;
262: if (separator != 0)
263: data[offset++] = separator;
264: writeMSB(data, offset, majorId, 6);
265: offset += 12;
266:
267: return new String(data, 0, offset);
268: }
269:
270: /**
271: Store this UUID in a byte array. Arrange the bytes in the UUID
272: in the same order the code which stores a UUID in a string
273: does.
274:
275: @see org.apache.derby.catalog.UUID#toByteArray
276: */
277: public byte[] toByteArray() {
278: byte[] result = new byte[16];
279:
280: int lsequence = sequence;
281: result[0] = (byte) (lsequence >>> 24);
282: result[1] = (byte) (lsequence >>> 16);
283: result[2] = (byte) (lsequence >>> 8);
284: result[3] = (byte) lsequence;
285:
286: long ltimemillis = timemillis;
287: result[4] = (byte) (ltimemillis >>> 40);
288: result[5] = (byte) (ltimemillis >>> 32);
289: result[6] = (byte) (ltimemillis >>> 24);
290: result[7] = (byte) (ltimemillis >>> 16);
291: result[8] = (byte) (ltimemillis >>> 8);
292: result[9] = (byte) ltimemillis;
293:
294: long linetaddr = majorId;
295: result[10] = (byte) (linetaddr >>> 40);
296: result[11] = (byte) (linetaddr >>> 32);
297: result[12] = (byte) (linetaddr >>> 24);
298: result[13] = (byte) (linetaddr >>> 16);
299: result[14] = (byte) (linetaddr >>> 8);
300: result[15] = (byte) linetaddr;
301:
302: return result;
303: }
304:
305: /**
306: Clone this UUID.
307:
308: @return a copy of this UUID
309: */
310: public UUID cloneMe() {
311: return new BasicUUID(majorId, timemillis, sequence);
312: }
313:
314: public String toHexString() {
315: return stringWorkhorse((char) 0);
316: }
317: }
|