KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > juddi > uuidgen > DefaultUUIDGen


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.juddi.uuidgen;
17
18 import java.math.BigInteger JavaDoc;
19 import java.util.Random JavaDoc;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 /**
25  * Used to create new universally unique identifiers or UUID's (sometimes called
26  * GUID's). UDDI UUID's are allways formmated according to DCE UUID conventions.
27  *
28  * @author Maarten Coene
29  * @author Steve Viens (sviens@apache.org)
30  */

31 public class DefaultUUIDGen implements UUIDGen
32 {
33   // private reference to the jUDDI logger
34
private static Log log = LogFactory.getLog(DefaultUUIDGen.class);
35
36   private static final BigInteger JavaDoc COUNT_START = new BigInteger JavaDoc("-12219292800000"); // 15 October 1582
37
private static final int CLOCK_SEQUENCE = (new Random JavaDoc()).nextInt(16384);
38   
39   private Random JavaDoc random;
40
41   /**
42    *
43    */

44   public DefaultUUIDGen()
45   {
46     try {
47       random = new Random JavaDoc();
48       random.setSeed(System.currentTimeMillis());
49     } catch (Exception JavaDoc e) {
50       random = new Random JavaDoc();
51     }
52   }
53
54   /**
55    *
56    */

57   public String JavaDoc uuidgen()
58   {
59     return nextUUID();
60   }
61
62   /**
63    *
64    */

65   public String JavaDoc[] uuidgen(int nmbr)
66   {
67     String JavaDoc[] uuids = new String JavaDoc[nmbr];
68
69     for (int i=0; i<uuids.length; i++)
70       uuids[i] = nextUUID();
71
72     return uuids;
73   }
74
75   /**
76    * Creates a new UUID. The algorithm used is described by The Open Group.
77    * See <a HREF="http://www.opengroup.org/onlinepubs/009629399/apdxa.htm">
78    * Universal Unique Identifier</a> for more details.
79    *
80    * Due to a lack of functionality in Java, a part of the UUID is a secure
81    * random. This results in a long processing time when this method is called
82    * for the first time.
83    */

84   private String JavaDoc nextUUID()
85   {
86     // the number of milliseconds since 1 January 1970
87
BigInteger JavaDoc current = BigInteger.valueOf(System.currentTimeMillis());
88
89     // the number of milliseconds since 15 October 1582
90
BigInteger JavaDoc countMillis = current.subtract(COUNT_START);
91
92     // the count of 100-nanosecond intervals since 00:00:00.00 15 October 1582
93
BigInteger JavaDoc count = countMillis.multiply(BigInteger.valueOf(10000));
94
95     String JavaDoc bitString = count.toString(2);
96     if (bitString.length() < 60)
97     {
98       int nbExtraZeros = 60 - bitString.length();
99       String JavaDoc extraZeros = new String JavaDoc();
100       for (int i=0; i<nbExtraZeros; i++)
101         extraZeros = extraZeros.concat("0");
102
103       bitString = extraZeros.concat(bitString);
104     }
105
106     byte[] bits = bitString.getBytes();
107
108     // the time_low field
109
byte[] time_low = new byte[32];
110     for (int i=0; i<32; i++)
111       time_low[i] = bits[bits.length - i - 1];
112
113     // the time_mid field
114
byte[] time_mid = new byte[16];
115     for (int i=0; i<16; i++)
116       time_mid[i] = bits[bits.length - 32 - i - 1];
117
118     // the time_hi_and_version field
119
byte[] time_hi_and_version = new byte[16];
120     for (int i=0; i<12; i++)
121       time_hi_and_version[i] = bits[bits.length - 48 - i - 1];
122
123     time_hi_and_version[12] = ((new String JavaDoc("1")).getBytes())[0];
124     time_hi_and_version[13] = ((new String JavaDoc("0")).getBytes())[0];
125     time_hi_and_version[14] = ((new String JavaDoc("0")).getBytes())[0];
126     time_hi_and_version[15] = ((new String JavaDoc("0")).getBytes())[0];
127
128     // the clock_seq_low field
129
BigInteger JavaDoc clockSequence = BigInteger.valueOf(CLOCK_SEQUENCE);
130     String JavaDoc clockString = clockSequence.toString(2);
131     if (clockString.length() < 14)
132     {
133       int nbExtraZeros = 14 - bitString.length();
134       String JavaDoc extraZeros = new String JavaDoc();
135       for (int i=0; i<nbExtraZeros; i++)
136         extraZeros = extraZeros.concat("0");
137
138       clockString = extraZeros.concat(bitString);
139     }
140
141     byte[] clock_bits = clockString.getBytes();
142     byte[] clock_seq_low = new byte[8];
143     for (int i=0; i<8; i++)
144       clock_seq_low[i] = clock_bits[clock_bits.length - i - 1];
145
146     // the clock_seq_hi_and_reserved
147
byte[] clock_seq_hi_and_reserved = new byte[8];
148     for (int i=0; i<6; i++)
149       clock_seq_hi_and_reserved[i] = clock_bits[clock_bits.length - 8 - i - 1];
150
151     clock_seq_hi_and_reserved[6] = ((new String JavaDoc("0")).getBytes())[0];
152     clock_seq_hi_and_reserved[7] = ((new String JavaDoc("1")).getBytes())[0];
153
154     String JavaDoc timeLow = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_low)), 2)).longValue());
155     if (timeLow.length() < 8)
156     {
157       int nbExtraZeros = 8 - timeLow.length();
158       String JavaDoc extraZeros = new String JavaDoc();
159       for (int i=0; i<nbExtraZeros; i++)
160         extraZeros = extraZeros.concat("0");
161
162       timeLow = extraZeros.concat(timeLow);
163     }
164
165     String JavaDoc timeMid = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_mid)), 2)).longValue());
166     if (timeMid.length() < 4)
167     {
168       int nbExtraZeros = 4 - timeMid.length();
169       String JavaDoc extraZeros = new String JavaDoc();
170       for (int i=0; i<nbExtraZeros; i++)
171         extraZeros = extraZeros.concat("0");
172
173       timeMid = extraZeros.concat(timeMid);
174     }
175
176     String JavaDoc timeHiAndVersion = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_hi_and_version)), 2)).longValue());
177     if (timeHiAndVersion.length() < 4)
178     {
179       int nbExtraZeros = 4 - timeHiAndVersion.length();
180       String JavaDoc extraZeros = new String JavaDoc();
181       for (int i=0; i<nbExtraZeros; i++)
182         extraZeros = extraZeros.concat("0");
183
184       timeHiAndVersion = extraZeros.concat(timeHiAndVersion);
185     }
186
187     String JavaDoc clockSeqHiAndReserved = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(clock_seq_hi_and_reserved)), 2)).longValue());
188     if (clockSeqHiAndReserved.length() < 2)
189     {
190       int nbExtraZeros = 2 - clockSeqHiAndReserved.length();
191       String JavaDoc extraZeros = new String JavaDoc();
192       for (int i=0; i<nbExtraZeros; i++)
193         extraZeros = extraZeros.concat("0");
194
195       clockSeqHiAndReserved = extraZeros.concat(clockSeqHiAndReserved);
196     }
197
198     String JavaDoc clockSeqLow = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(clock_seq_low)), 2)).longValue());
199     if (clockSeqLow.length() < 2)
200     {
201       int nbExtraZeros = 2 - clockSeqLow.length();
202       String JavaDoc extraZeros = new String JavaDoc();
203       for (int i=0; i<nbExtraZeros; i++)
204         extraZeros = extraZeros.concat("0");
205
206       clockSeqLow = extraZeros.concat(clockSeqLow);
207     }
208
209     // problem: the node should be the IEEE 802 ethernet address, but can not
210
// be retrieved in Java yet.
211
// see bug ID 4173528
212
// workaround (also suggested in bug ID 4173528)
213
// If a system wants to generate UUIDs but has no IEE 802 compliant
214
// network card or other source of IEEE 802 addresses, then this section
215
// describes how to generate one.
216
// The ideal solution is to obtain a 47 bit cryptographic quality random
217
// number, and use it as the low 47 bits of the node ID, with the most
218
// significant bit of the first octet of the node ID set to 1. This bit
219
// is the unicast/multicast bit, which will never be set in IEEE 802
220
// addresses obtained from network cards; hence, there can never be a
221
// conflict between UUIDs generated by machines with and without network
222
// cards.
223

224     long nodeValue = random.nextLong();
225     nodeValue = Math.abs(nodeValue);
226     while (nodeValue > 140737488355328L)
227     {
228       nodeValue = random.nextLong();
229       nodeValue = Math.abs(nodeValue);
230     }
231
232     BigInteger JavaDoc nodeInt = BigInteger.valueOf(nodeValue);
233     String JavaDoc nodeString = nodeInt.toString(2);
234     if (nodeString.length() < 47)
235     {
236       int nbExtraZeros = 47 - nodeString.length();
237       String JavaDoc extraZeros = new String JavaDoc();
238       for (int i=0; i<nbExtraZeros; i++)
239         extraZeros = extraZeros.concat("0");
240
241       nodeString = extraZeros.concat(nodeString);
242     }
243
244     byte[] node_bits = nodeString.getBytes();
245     byte[] node = new byte[48];
246     for (int i=0; i<47; i++)
247       node[i] = node_bits[node_bits.length - i - 1];
248
249     node[47] = ((new String JavaDoc("1")).getBytes())[0];
250     String JavaDoc theNode = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(node)), 2)).longValue());
251     if (theNode.length() < 12)
252     {
253       int nbExtraZeros = 12 - theNode.length();
254       String JavaDoc extraZeros = new String JavaDoc();
255       for (int i=0; i<nbExtraZeros; i++)
256         extraZeros = extraZeros.concat("0");
257       theNode = extraZeros.concat(theNode);
258     }
259
260     String JavaDoc result = timeLow + "-" + timeMid +"-" + timeHiAndVersion + "-" + clockSeqHiAndReserved + clockSeqLow + "-" + theNode;
261
262     return result.toUpperCase();
263   }
264
265   /**
266    *
267    */

268   private static byte[] reverseArray(byte[] bits)
269   {
270     byte[] result = new byte[bits.length];
271     for (int i=0; i<result.length; i++)
272       result[i] = bits[result.length - 1 - i];
273
274     return result;
275   }
276
277
278   /***************************************************************************/
279   /***************************** TEST DRIVER *********************************/
280   /***************************************************************************/
281
282
283   public static void main(String JavaDoc args[])
284   {
285     DefaultUUIDGen generator = new DefaultUUIDGen();
286
287     long start = System.currentTimeMillis();
288
289     for (int i = 1; i <= 100; ++i)
290       generator.uuidgen();
291
292     long end = System.currentTimeMillis();
293
294     System.out.println("DefaultUUIDGen: Generation of 100 UUID's took "+(end-start)+" milliseconds.");
295   }
296 }
Popular Tags