KickJava   Java API By Example, From Geeks To Geeks.

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


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.axis.components.uuid;
17
18 import java.util.Random JavaDoc;
19 import java.security.SecureRandom JavaDoc;
20
21 /**
22  * Creates time-based UUID's. See the <a HREF="http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-03.txt">UUID Internet Draft</a> for details.
23  *
24  * @author Jarek Gawor (gawor@apache.org)
25  */

26 public class FastUUIDGen implements UUIDGen {
27
28     private static Random JavaDoc secureRandom;
29
30     private static String JavaDoc nodeStr;
31     private static int clockSequence;
32
33     private long lastTime = 0;
34
35     static {
36         // problem: the node should be the IEEE 802 ethernet address, but can not
37
// be retrieved in Java yet.
38
// see bug ID 4173528
39
// workaround (also suggested in bug ID 4173528)
40
// If a system wants to generate UUIDs but has no IEE 802 compliant
41
// network card or other source of IEEE 802 addresses, then this section
42
// describes how to generate one.
43
// The ideal solution is to obtain a 47 bit cryptographic quality random
44
// number, and use it as the low 47 bits of the node ID, with the most
45
// significant bit of the first octet of the node ID set to 1. This bit
46
// is the unicast/multicast bit, which will never be set in IEEE 802
47
// addresses obtained from network cards; hence, there can never be a
48
// conflict between UUIDs generated by machines with and without network
49
// cards.
50
try {
51             secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
52         } catch (Exception JavaDoc e) {
53             secureRandom = new Random JavaDoc();
54         }
55
56         nodeStr = getNodeHexValue();
57         clockSequence = getClockSequence();
58     }
59
60     private static String JavaDoc getNodeHexValue() {
61         long node = 0;
62         long nodeValue = 0;
63         while ( (node = getBitsValue(nodeValue, 47, 47)) == 0 ) {
64             nodeValue = secureRandom.nextLong();
65         }
66         node = node | 0x800000000000L;
67         return leftZeroPadString(Long.toHexString(node), 12);
68     }
69
70     private static int getClockSequence() {
71         return secureRandom.nextInt(16384);
72     }
73
74     public String JavaDoc nextUUID() {
75         long time = System.currentTimeMillis();
76
77         long timestamp = time * 10000;
78         timestamp += 0x01b21dd2L << 32;
79         timestamp += 0x13814000;
80         
81         synchronized(this) {
82             if (time - lastTime <= 0) {
83                 clockSequence = ((clockSequence + 1) & 16383);
84             }
85             lastTime = time;
86         }
87
88         long timeLow = getBitsValue(timestamp, 32, 32);
89         long timeMid = getBitsValue(timestamp, 48, 16);
90         long timeHi = getBitsValue(timestamp, 64, 16) | 0x1000;
91
92         long clockSeqLow = getBitsValue(clockSequence, 8, 8);
93         long clockSeqHi = getBitsValue(clockSequence, 16, 8) | 0x80;
94         
95         String JavaDoc timeLowStr = leftZeroPadString(Long.toHexString(timeLow), 8);
96         String JavaDoc timeMidStr = leftZeroPadString(Long.toHexString(timeMid), 4);
97         String JavaDoc timeHiStr = leftZeroPadString(Long.toHexString(timeHi), 4);
98
99         String JavaDoc clockSeqHiStr = leftZeroPadString(Long.toHexString(clockSeqHi), 2);
100         String JavaDoc clockSeqLowStr = leftZeroPadString(Long.toHexString(clockSeqLow), 2);
101
102         StringBuffer JavaDoc result = new StringBuffer JavaDoc(36);
103         result.append(timeLowStr).append("-");
104         result.append(timeMidStr).append("-");
105         result.append(timeHiStr).append("-");
106         result.append(clockSeqHiStr).append(clockSeqLowStr);
107         result.append("-").append(nodeStr);
108
109         return result.toString();
110     }
111
112     private static long getBitsValue(long value, int startBit, int bitLen) {
113         return ((value << (64-startBit)) >>> (64-bitLen));
114     }
115
116     private static final String JavaDoc leftZeroPadString(String JavaDoc bitString, int len) {
117         if (bitString.length() < len) {
118             int nbExtraZeros = len - bitString.length();
119             StringBuffer JavaDoc extraZeros = new StringBuffer JavaDoc();
120             for (int i = 0; i < nbExtraZeros; i++) {
121                 extraZeros.append("0");
122             }
123             extraZeros.append(bitString);
124             bitString = extraZeros.toString();
125         }
126         return bitString;
127     }
128
129 }
130
Popular Tags