KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > components > uuid > SimpleUUIDGen


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Axis" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55
56 /**
57  *
58  * UUIDGen adopted from the juddi project
59  * (http://sourceforge.net/projects/juddi/)
60  *
61  */

62
63 package org.jboss.axis.components.uuid;
64
65 import java.math.BigInteger JavaDoc;
66 import java.security.SecureRandom JavaDoc;
67 import java.util.Random JavaDoc;
68
69 /**
70  * Used to create new universally unique identifiers or UUID's (sometimes called
71  * GUID's). UDDI UUID's are allways formmated according to DCE UUID conventions.
72  *
73  * @author Maarten Coene
74  * @author Steve Viens
75  * @version 0.3.2 3/25/2001
76  * @since JDK1.2.2
77  */

78 public class SimpleUUIDGen implements UUIDGen
79 {
80    private static final BigInteger JavaDoc countStart = new BigInteger JavaDoc("-12219292800000"); // 15 October 1582
81
private static final int clock_sequence = (new Random JavaDoc()).nextInt(16384);
82
83    /**
84     * Creates a new UUID. The algorithm used is described by The Open Group.
85     * See <a HREF="http://www.opengroup.org/onlinepubs/009629399/apdxa.htm">
86     * Universal Unique Identifier</a> for more details.
87     * <p/>
88     * Due to a lack of functionality in Java, a part of the UUID is a secure
89     * random. This results in a long processing time when this method is called
90     * for the first time.
91     */

92    public String JavaDoc nextUUID()
93    {
94       // TODO: this method has to be checked for it's correctness. I'm not sure the standard is
95
// implemented correctly.
96

97       // the count of 100-nanosecond intervals since 00:00:00.00 15 October 1582
98
BigInteger JavaDoc count;
99
100       // the number of milliseconds since 1 January 1970
101
BigInteger JavaDoc current = BigInteger.valueOf(System.currentTimeMillis());
102
103       // the number of milliseconds since 15 October 1582
104
BigInteger JavaDoc countMillis = current.subtract(countStart);
105
106       // the result
107
count = countMillis.multiply(BigInteger.valueOf(10000));
108
109       String JavaDoc bitString = count.toString(2);
110       if (bitString.length() < 60)
111       {
112          int nbExtraZeros = 60 - bitString.length();
113          String JavaDoc extraZeros = new String JavaDoc();
114          for (int i = 0; i < nbExtraZeros; i++)
115             extraZeros = extraZeros.concat("0");
116
117          bitString = extraZeros.concat(bitString);
118       }
119
120       byte[] bits = bitString.getBytes();
121
122       // the time_low field
123
byte[] time_low = new byte[32];
124       for (int i = 0; i < 32; i++)
125          time_low[i] = bits[bits.length - i - 1];
126
127       // the time_mid field
128
byte[] time_mid = new byte[16];
129       for (int i = 0; i < 16; i++)
130          time_mid[i] = bits[bits.length - 32 - i - 1];
131
132       // the time_hi_and_version field
133
byte[] time_hi_and_version = new byte[16];
134       for (int i = 0; i < 12; i++)
135          time_hi_and_version[i] = bits[bits.length - 48 - i - 1];
136
137       time_hi_and_version[12] = ((new String JavaDoc("1")).getBytes())[0];
138       time_hi_and_version[13] = ((new String JavaDoc("0")).getBytes())[0];
139       time_hi_and_version[14] = ((new String JavaDoc("0")).getBytes())[0];
140       time_hi_and_version[15] = ((new String JavaDoc("0")).getBytes())[0];
141
142       // the clock_seq_low field
143
BigInteger JavaDoc clockSequence = BigInteger.valueOf(clock_sequence);
144       String JavaDoc clockString = clockSequence.toString(2);
145       if (clockString.length() < 14)
146       {
147          int nbExtraZeros = 14 - bitString.length();
148          String JavaDoc extraZeros = new String JavaDoc();
149          for (int i = 0; i < nbExtraZeros; i++)
150             extraZeros = extraZeros.concat("0");
151
152          clockString = extraZeros.concat(bitString);
153       }
154
155       byte[] clock_bits = clockString.getBytes();
156       byte[] clock_seq_low = new byte[8];
157       for (int i = 0; i < 8; i++)
158          clock_seq_low[i] = clock_bits[clock_bits.length - i - 1];
159
160       // the clock_seq_hi_and_reserved
161
byte[] clock_seq_hi_and_reserved = new byte[8];
162       for (int i = 0; i < 6; i++)
163          clock_seq_hi_and_reserved[i] = clock_bits[clock_bits.length - 8 - i - 1];
164
165       clock_seq_hi_and_reserved[6] = ((new String JavaDoc("0")).getBytes())[0];
166       clock_seq_hi_and_reserved[7] = ((new String JavaDoc("1")).getBytes())[0];
167
168       String JavaDoc timeLow = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_low)), 2)).longValue());
169       if (timeLow.length() < 8)
170       {
171          int nbExtraZeros = 8 - timeLow.length();
172          String JavaDoc extraZeros = new String JavaDoc();
173          for (int i = 0; i < nbExtraZeros; i++)
174             extraZeros = extraZeros.concat("0");
175
176          timeLow = extraZeros.concat(timeLow);
177       }
178
179       String JavaDoc timeMid = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_mid)), 2)).longValue());
180       if (timeMid.length() < 4)
181       {
182          int nbExtraZeros = 4 - timeMid.length();
183          String JavaDoc extraZeros = new String JavaDoc();
184          for (int i = 0; i < nbExtraZeros; i++)
185             extraZeros = extraZeros.concat("0");
186          timeMid = extraZeros.concat(timeMid);
187       }
188
189       String JavaDoc timeHiAndVersion = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_hi_and_version)), 2)).longValue());
190       if (timeHiAndVersion.length() < 4)
191       {
192          int nbExtraZeros = 4 - timeHiAndVersion.length();
193          String JavaDoc extraZeros = new String JavaDoc();
194          for (int i = 0; i < nbExtraZeros; i++)
195             extraZeros = extraZeros.concat("0");
196
197          timeHiAndVersion = extraZeros.concat(timeHiAndVersion);
198       }
199
200       String JavaDoc clockSeqHiAndReserved = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(clock_seq_hi_and_reserved)), 2)).longValue());
201       if (clockSeqHiAndReserved.length() < 2)
202       {
203          int nbExtraZeros = 2 - clockSeqHiAndReserved.length();
204          String JavaDoc extraZeros = new String JavaDoc();
205          for (int i = 0; i < nbExtraZeros; i++)
206             extraZeros = extraZeros.concat("0");
207
208          clockSeqHiAndReserved = extraZeros.concat(clockSeqHiAndReserved);
209       }
210
211       String JavaDoc clockSeqLow = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(clock_seq_low)), 2)).longValue());
212       if (clockSeqLow.length() < 2)
213       {
214          int nbExtraZeros = 2 - clockSeqLow.length();
215          String JavaDoc extraZeros = new String JavaDoc();
216          for (int i = 0; i < nbExtraZeros; i++)
217             extraZeros = extraZeros.concat("0");
218
219          clockSeqLow = extraZeros.concat(clockSeqLow);
220       }
221
222       // problem: the node should be the IEEE 802 ethernet address, but can not
223
// be retrieved in Java yet.
224
// see bug ID 4173528
225
// workaround (also suggested in bug ID 4173528)
226
// If a system wants to generate UUIDs but has no IEE 802 compliant
227
// network card or other source of IEEE 802 addresses, then this section
228
// describes how to generate one.
229
// The ideal solution is to obtain a 47 bit cryptographic quality random
230
// number, and use it as the low 47 bits of the node ID, with the most
231
// significant bit of the first octet of the node ID set to 1. This bit
232
// is the unicast/multicast bit, which will never be set in IEEE 802
233
// addresses obtained from network cards; hence, there can never be a
234
// conflict between UUIDs generated by machines with and without network
235
// cards.
236
Random JavaDoc secureRandom = null;
237       try
238       {
239          secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
240       }
241       catch (Exception JavaDoc e)
242       {
243          secureRandom = new Random JavaDoc();
244       }
245
246       long nodeValue = secureRandom.nextLong();
247       nodeValue = Math.abs(nodeValue);
248       while (nodeValue > 140737488355328L)
249       {
250          nodeValue = secureRandom.nextLong();
251          nodeValue = Math.abs(nodeValue);
252       }
253
254       BigInteger JavaDoc nodeInt = BigInteger.valueOf(nodeValue);
255       String JavaDoc nodeString = nodeInt.toString(2);
256       if (nodeString.length() < 47)
257       {
258          int nbExtraZeros = 47 - nodeString.length();
259          String JavaDoc extraZeros = new String JavaDoc();
260          for (int i = 0; i < nbExtraZeros; i++)
261             extraZeros = extraZeros.concat("0");
262
263          nodeString = extraZeros.concat(nodeString);
264       }
265
266       byte[] node_bits = nodeString.getBytes();
267       byte[] node = new byte[48];
268       for (int i = 0; i < 47; i++)
269          node[i] = node_bits[node_bits.length - i - 1];
270
271       node[47] = ((new String JavaDoc("1")).getBytes())[0];
272       String JavaDoc theNode = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(node)), 2)).longValue());
273       if (theNode.length() < 12)
274       {
275          int nbExtraZeros = 12 - theNode.length();
276          String JavaDoc extraZeros = new String JavaDoc();
277          for (int i = 0; i < nbExtraZeros; i++)
278             extraZeros = extraZeros.concat("0");
279          theNode = extraZeros.concat(theNode);
280       }
281
282       String JavaDoc result = timeLow + "-" + timeMid + "-" + timeHiAndVersion + "-" + clockSeqHiAndReserved + clockSeqLow + "-" + theNode;
283
284       return result.toUpperCase();
285    }
286
287    private static byte[] reverseArray(byte[] bits)
288    {
289       byte[] result = new byte[bits.length];
290       for (int i = 0; i < result.length; i++)
291          result[i] = bits[result.length - 1 - i];
292
293       return result;
294    }
295
296    public void destroy()
297    {
298    }
299
300    public void init()
301    {
302    }
303 }
304
Popular Tags