You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by ga...@apache.org on 2004/11/04 22:05:07 UTC

cvs commit: ws-axis/java/src/org/apache/axis/components/uuid FastUUIDGen.java UUIDGenFactory.java

gawor       2004/11/04 13:05:07

  Modified:    java/src/org/apache/axis/components/uuid UUIDGenFactory.java
  Added:       java/src/org/apache/axis/components/uuid FastUUIDGen.java
  Log:
  faster time-based uuid generator implementation. switched as default
  
  Revision  Changes    Path
  1.7       +2 -2      ws-axis/java/src/org/apache/axis/components/uuid/UUIDGenFactory.java
  
  Index: UUIDGenFactory.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/java/src/org/apache/axis/components/uuid/UUIDGenFactory.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- UUIDGenFactory.java	25 Feb 2004 14:02:33 -0000	1.6
  +++ UUIDGenFactory.java	4 Nov 2004 21:05:07 -0000	1.7
  @@ -42,7 +42,7 @@
   
       static {
           AxisProperties.setClassOverrideProperty(Compiler.class, "axis.UUIDGenerator");
  -        AxisProperties.setClassDefault(UUIDGen.class, "org.apache.axis.components.uuid.SimpleUUIDGen");
  +        AxisProperties.setClassDefault(UUIDGen.class, "org.apache.axis.components.uuid.FastUUIDGen");
       }
   
       /**
  @@ -53,4 +53,4 @@
           log.debug("axis.UUIDGenerator:" + uuidgen.getClass().getName());
           return uuidgen;
       }
  -}
  \ No newline at end of file
  +}
  
  
  
  1.1                  ws-axis/java/src/org/apache/axis/components/uuid/FastUUIDGen.java
  
  Index: FastUUIDGen.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.axis.components.uuid;
  
  import java.util.Random;
  import java.security.SecureRandom;
  
  /**
   * 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.
   *
   * @author Jarek Gawor (gawor@apache.org)
   */
  public class FastUUIDGen implements UUIDGen {
  
      private static Random secureRandom;
  
      private static String nodeStr;
      private static int clockSequence;
  
      private long lastTime = 0;
  
      static {
          // problem: the node should be the IEEE 802 ethernet address, but can not
          // be retrieved in Java yet.
          // see bug ID 4173528
          // workaround (also suggested in bug ID 4173528)
          // If a system wants to generate UUIDs but has no IEE 802 compliant
          // network card or other source of IEEE 802 addresses, then this section
          // describes how to generate one.
          // The ideal solution is to obtain a 47 bit cryptographic quality random
          // number, and use it as the low 47 bits of the node ID, with the most
          // significant bit of the first octet of the node ID set to 1. This bit
          // is the unicast/multicast bit, which will never be set in IEEE 802
          // addresses obtained from network cards; hence, there can never be a
          // conflict between UUIDs generated by machines with and without network
          // cards.
          try {
              secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
          } catch (Exception e) {
              secureRandom = new Random();
          }
  
          nodeStr = getNodeHexValue();
          clockSequence = getClockSequence();
      }
  
      private static String getNodeHexValue() {
          long node = 0;
          long nodeValue = 0;
          while ( (node = getBitsValue(nodeValue, 47, 47)) == 0 ) {
              nodeValue = secureRandom.nextLong();
          }
          node = node | 0x800000000000L;
          return leftZeroPadString(Long.toHexString(node), 12);
      }
  
      private static int getClockSequence() {
          return secureRandom.nextInt(16384);
      }
  
      public String nextUUID() {
          long time = System.currentTimeMillis();
  
          long timestamp = time * 10000;
          timestamp += 0x01b21dd2L << 32;
          timestamp += 0x13814000;
          
          synchronized(this) {
              if (time - lastTime <= 0) {
                  int oldClockSequence = clockSequence;
                  while ( oldClockSequence == clockSequence) {
                      clockSequence = getClockSequence();
                  }
              }
              lastTime = time;
          }
  
          long timeLow = getBitsValue(timestamp, 32, 32);
          long timeMid = getBitsValue(timestamp, 48, 16);
          long timeHi = getBitsValue(timestamp, 64, 16) | 0x1000;
  
          long clockSeqLow = getBitsValue(clockSequence, 8, 8);
          long clockSeqHi = getBitsValue(clockSequence, 16, 8) | 0x80;
          
          String timeLowStr = leftZeroPadString(Long.toHexString(timeLow), 8);
          String timeMidStr = leftZeroPadString(Long.toHexString(timeMid), 4);
          String timeHiStr = leftZeroPadString(Long.toHexString(timeHi), 4);
  
          String clockSeqHiStr = leftZeroPadString(Long.toHexString(clockSeqHi), 2);
          String clockSeqLowStr = leftZeroPadString(Long.toHexString(clockSeqLow), 2);
  
          StringBuffer result = new StringBuffer(36);
          result.append(timeLowStr).append("-");
          result.append(timeMidStr).append("-");
          result.append(timeHiStr).append("-");
          result.append(clockSeqHiStr).append(clockSeqLowStr);
          result.append("-").append(nodeStr);
  
          return result.toString();
      }
  
      private static long getBitsValue(long value, int startBit, int bitLen) {
          return ((value << (64-startBit)) >>> (64-bitLen));
      }
  
      private static final String leftZeroPadString(String bitString, int len) {
          if (bitString.length() < len) {
              int nbExtraZeros = len - bitString.length();
              StringBuffer extraZeros = new StringBuffer();
              for (int i = 0; i < nbExtraZeros; i++) {
                  extraZeros.append("0");
              }
              extraZeros.append(bitString);
              bitString = extraZeros.toString();
          }
          return bitString;
      }
  
      public static void main(String [] args) throws Exception {
          String current = null;
          String prev = null;
          
          FastUUIDGen g = new FastUUIDGen();
          for (int i=0;i<1000;i++) {
              current = g.nextUUID();
              if (current.equals(prev)) {
                  throw new Exception(current + " " + prev);
              }
              prev = current;
          }
      }
  }