Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/axis/components/uuid/FastUUIDGen.java


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;
19  import java.security.SecureRandom;
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 secureRandom;
29  
30      private static String 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 e) {
53              secureRandom = new Random();
54          }
55  
56          nodeStr = getNodeHexValue();
57          clockSequence = getClockSequence();
58      }
59  
60      private static String 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 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 timeLowStr = leftZeroPadString(Long.toHexString(timeLow), 8);
96          String timeMidStr = leftZeroPadString(Long.toHexString(timeMid), 4);
97          String timeHiStr = leftZeroPadString(Long.toHexString(timeHi), 4);
98  
99          String clockSeqHiStr = leftZeroPadString(Long.toHexString(clockSeqHi), 2);
100         String clockSeqLowStr = leftZeroPadString(Long.toHexString(clockSeqLow), 2);
101 
102         StringBuffer result = new StringBuffer(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 leftZeroPadString(String bitString, int len) {
117         if (bitString.length() < len) {
118             int nbExtraZeros = len - bitString.length();
119             StringBuffer extraZeros = new StringBuffer();
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 }