KickJava   Java API By Example, From Geeks To Geeks.

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


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
17 /**
18  *
19  * UUIDGen adopted from the juddi project
20  * (http://sourceforge.net/projects/juddi/)
21  *
22  */

23
24 package org.apache.axis.components.uuid;
25
26 import java.math.BigInteger JavaDoc;
27 import java.security.SecureRandom JavaDoc;
28 import java.util.Random JavaDoc;
29
30 /**
31  * Used to create new universally unique identifiers or UUID's (sometimes called
32  * GUID's). UDDI UUID's are allways formmated according to DCE UUID conventions.
33  *
34  * @author Maarten Coene
35  * @author Steve Viens
36  * @version 0.3.2 3/25/2001
37  * @since JDK1.2.2
38  */

39 public class SimpleUUIDGen implements UUIDGen {
40     private static final BigInteger JavaDoc countStart = new BigInteger JavaDoc("-12219292800000"); // 15 October 1582
41
private static final int clock_sequence = (new Random JavaDoc()).nextInt(16384);
42     private static final byte ZERO = (byte) 48; // "0"
43
private static final byte ONE = (byte) 49; // "1"
44
private static Random JavaDoc secureRandom = null;
45
46     static {
47         // problem: the node should be the IEEE 802 ethernet address, but can not
48
// be retrieved in Java yet.
49
// see bug ID 4173528
50
// workaround (also suggested in bug ID 4173528)
51
// If a system wants to generate UUIDs but has no IEE 802 compliant
52
// network card or other source of IEEE 802 addresses, then this section
53
// describes how to generate one.
54
// The ideal solution is to obtain a 47 bit cryptographic quality random
55
// number, and use it as the low 47 bits of the node ID, with the most
56
// significant bit of the first octet of the node ID set to 1. This bit
57
// is the unicast/multicast bit, which will never be set in IEEE 802
58
// addresses obtained from network cards; hence, there can never be a
59
// conflict between UUIDs generated by machines with and without network
60
// cards.
61
try {
62             secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
63         } catch (Exception JavaDoc e) {
64             secureRandom = new Random JavaDoc();
65         }
66     }
67
68     /**
69      * utility method which returns a bitString with left zero padding
70      * for as many places as necessary to reach <tt>len</tt>; otherwise
71      * returns bitString unaltered.
72      *
73      * @return a left zero padded string of at least <tt>len</tt> chars
74      * @param bitString a String to pad
75      * @param len the length under which bitString needs padding
76      */

77     private static final String JavaDoc leftZeroPadString(String JavaDoc bitString, int len) {
78         if (bitString.length() < len) {
79             int nbExtraZeros = len - bitString.length();
80             StringBuffer JavaDoc extraZeros = new StringBuffer JavaDoc();
81             for (int i = 0; i < nbExtraZeros; i++) {
82                 extraZeros.append("0");
83             }
84             extraZeros.append(bitString);
85             bitString = extraZeros.toString();
86         }
87         return bitString;
88     }
89
90     /**
91      * Creates a new UUID. The algorithm used is described by The Open Group.
92      * See <a HREF="http://www.opengroup.org/onlinepubs/009629399/apdxa.htm">
93      * Universal Unique Identifier</a> for more details.
94      * <p>
95      * Due to a lack of functionality in Java, a part of the UUID is a secure
96      * random. This results in a long processing time when this method is called
97      * for the first time.
98      */

99     public String JavaDoc nextUUID() {
100         // TODO: this method has to be checked for it's correctness. I'm not sure the standard is
101
// implemented correctly.
102

103         // the count of 100-nanosecond intervals since 00:00:00.00 15 October 1582
104
BigInteger JavaDoc count;
105
106         // the number of milliseconds since 1 January 1970
107
BigInteger JavaDoc current = BigInteger.valueOf(System.currentTimeMillis());
108
109         // the number of milliseconds since 15 October 1582
110
BigInteger JavaDoc countMillis = current.subtract(countStart);
111
112         // the result
113
count = countMillis.multiply(BigInteger.valueOf(10000));
114         byte[] bits = leftZeroPadString(count.toString(2), 60).getBytes();
115
116         // the time_low field
117
byte[] time_low = new byte[32];
118         for (int i = 0; i < 32; i++)
119             time_low[i] = bits[bits.length - i - 1];
120
121         // the time_mid field
122
byte[] time_mid = new byte[16];
123         for (int i = 0; i < 16; i++)
124             time_mid[i] = bits[bits.length - 32 - i - 1];
125
126         // the time_hi_and_version field
127
byte[] time_hi_and_version = new byte[16];
128         for (int i = 0; i < 12; i++)
129             time_hi_and_version[i] = bits[bits.length - 48 - i - 1];
130
131         time_hi_and_version[12] = ONE;
132         time_hi_and_version[13] = ZERO;
133         time_hi_and_version[14] = ZERO;
134         time_hi_and_version[15] = ZERO;
135
136         // the clock_seq_low field
137
BigInteger JavaDoc clockSequence = BigInteger.valueOf(clock_sequence);
138         byte[] clock_bits = leftZeroPadString(clockSequence.toString(2), 14).getBytes();
139         byte[] clock_seq_low = new byte[8];
140         for (int i = 0; i < 8; i++) {
141             clock_seq_low[i] = clock_bits[clock_bits.length - i - 1];
142         }
143
144         // the clock_seq_hi_and_reserved
145
byte[] clock_seq_hi_and_reserved = new byte[8];
146         for (int i = 0; i < 6; i++)
147             clock_seq_hi_and_reserved[i] = clock_bits[clock_bits.length - 8 - i - 1];
148
149         clock_seq_hi_and_reserved[6] = ZERO;
150         clock_seq_hi_and_reserved[7] = ONE;
151
152         String JavaDoc timeLow = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_low)), 2)).longValue());
153         timeLow = leftZeroPadString(timeLow, 8);
154
155         String JavaDoc timeMid = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_mid)), 2)).longValue());
156         timeMid = leftZeroPadString(timeMid, 4);
157
158         String JavaDoc timeHiAndVersion = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_hi_and_version)), 2)).longValue());
159         timeHiAndVersion = leftZeroPadString(timeHiAndVersion, 4);
160
161         String JavaDoc clockSeqHiAndReserved = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(clock_seq_hi_and_reserved)), 2)).longValue());
162         clockSeqHiAndReserved = leftZeroPadString(clockSeqHiAndReserved, 2);
163
164         String JavaDoc clockSeqLow = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(clock_seq_low)), 2)).longValue());
165         clockSeqLow = leftZeroPadString(clockSeqLow, 2);
166
167         long nodeValue = secureRandom.nextLong();
168         nodeValue = Math.abs(nodeValue);
169         while (nodeValue > 140737488355328L) {
170             nodeValue = secureRandom.nextLong();
171             nodeValue = Math.abs(nodeValue);
172         }
173
174         BigInteger JavaDoc nodeInt = BigInteger.valueOf(nodeValue);
175
176         byte[] node_bits = leftZeroPadString(nodeInt.toString(2), 47).getBytes();
177         byte[] node = new byte[48];
178         for (int i = 0; i < 47; i++)
179             node[i] = node_bits[node_bits.length - i - 1];
180
181         node[47] = ONE;
182         String JavaDoc theNode = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(node)), 2)).longValue());
183         theNode = leftZeroPadString(theNode, 12);
184
185         StringBuffer JavaDoc result = new StringBuffer JavaDoc(timeLow);
186         result.append("-");
187         result.append(timeMid);
188         result.append("-");
189         result.append(timeHiAndVersion);
190         result.append("-");
191         result.append(clockSeqHiAndReserved);
192         result.append(clockSeqLow);
193         result.append("-");
194         result.append(theNode);
195         return result.toString().toUpperCase();
196     }
197
198     private static byte[] reverseArray(byte[] bits) {
199         byte[] result = new byte[bits.length];
200         for (int i = 0; i < result.length; i++)
201             result[i] = bits[result.length - 1 - i];
202
203         return result;
204     }
205 }
206
Popular Tags