/******************************************************************************* * Copyright (c) 2009 MATERNA Information & Communications. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html. For further * project-related information visit http://www.ws4d.org. The most recent * version of the JMEDS framework can be obtained from * http://sourceforge.net/projects/ws4d-javame. ******************************************************************************/ package org.ws4d.java.util; import java.util.Random; import org.ws4d.java.types.URI; /** * This class can be used to create RFC-4122 time based Universally Unique * Identifiers with random host node part. Portions adopted from the JUG UUID * generator. Also offers methods for generating random numbers. * * @see <a href="http://jug.safehaus.org/">http://jug.safehaus.org/</a> * @see <a * href="http://www.faqs.org/rfcs/rfc4122.html">http://www.faqs.org/rfcs/rfc4122.html</a> */ public final class IDGenerator { public static final String UUID_PREFIX = "uuid"; /** * the prefix to be used for DPWS. */ public static final String URI_UUID_PREFIX = "urn:" + UUID_PREFIX + ":"; /** * Start of the Gregorian calendar. */ private static final long CLOCK_OFFSET = 0x01b21dd213814000L; private static final String HEX_CHARS = "0123456789abcdef"; private static final byte INDEX_CLOCK_HI = 6; private static final byte INDEX_CLOCK_MID = 4; private static final byte INDEX_CLOCK_LOW = 0; private static final byte INDEX_CLOCK_SEQUENCE = 8; private static final byte INDEX_VARIANT = 8; private static final byte INDEX_NODE = 10; private static byte[] nodeIdentifier = new byte[6]; private static short clockSequence; private static long commonSequenceNumber = 1; /** static internal message counter */ private static int lastUsedInternalMsgId = 0; static { // initialize that nodeidentifier Random r = Math.getRandom(); long rand = r.nextLong(); for (int i = 0; i < 6; i++) { nodeIdentifier[i] = (byte) (rand >>> (56 - i * 8)); } // initialize clock sequence clockSequence = (short) (r.nextInt() & 0xffff); } /** * Utility class. Hides default constructor. */ private IDGenerator() { } /** * Returns a RFC-4122 conformant UUID, normal form. * * @return a RFC-4122 conformant UUID, normal form. */ public static String getUUID() { StringBuffer uuidString = new StringBuffer(36); byte[] uuidData = new byte[16]; /* get the time in 100 nano seconds intervalls since 1582/15/10 */ long systime = System.currentTimeMillis(); systime *= 10000L; // 100 nano seconds resolution systime += CLOCK_OFFSET; int clockHi = (int) (systime >>> 32); int clockLo = (int) systime; uuidData[INDEX_CLOCK_LOW] = (byte) (clockLo >>> 24); uuidData[INDEX_CLOCK_LOW + 1] = (byte) (clockLo >>> 16); uuidData[INDEX_CLOCK_LOW + 2] = (byte) (clockLo >>> 8); uuidData[INDEX_CLOCK_LOW + 3] = (byte) (clockLo); uuidData[INDEX_CLOCK_HI] = (byte) (clockHi >>> 24); uuidData[INDEX_CLOCK_HI + 1] = (byte) (clockHi >>> 16); // set version uuidData[INDEX_CLOCK_HI] &= 0x0f; uuidData[INDEX_CLOCK_HI] |= (1 << 4); uuidData[INDEX_CLOCK_MID] = (byte) (clockHi >>> 8); uuidData[INDEX_CLOCK_MID + 1] = (byte) (clockHi); uuidData[INDEX_CLOCK_SEQUENCE] = (byte) (clockSequence >> 16); uuidData[INDEX_CLOCK_SEQUENCE + 1] = (byte) (clockSequence); clockSequence++; uuidData[INDEX_VARIANT] &= (byte) 0x3f; uuidData[INDEX_VARIANT] |= (byte) 0x80; for (int i = 0; i < 6; i++) { uuidData[INDEX_NODE + i] = nodeIdentifier[i]; } for (int i = 0; i < 16; i++) { switch (i) { case 4: case 6: case 8: case 10: uuidString.append("-"); } int hex = uuidData[i] & 0xff; uuidString.append(HEX_CHARS.charAt(hex >> 4)); uuidString.append(HEX_CHARS.charAt(hex & 0xf)); } return uuidString.toString(); } /** * Returns the UUID as URI. e.g. * "urn:uuid:550e8400-e29b-11d4-a716-446655440000". URI schemas: * http://www.iana.org/assignments/uri-schemes.html URN namespaces: * http://www.iana.org/assignments/urn-namespaces/ * * @return the UUID URI. */ public static URI getUUIDasURI() { return new URI(URI_UUID_PREFIX + getUUID()); } /** * Returns a sequence number that is unique within a single VM until this VM * is restarted. * * @return the sequence number */ public static synchronized long getSequenceNumber() { return commonSequenceNumber++; } /** * Increment static message id. * * @return internal message id */ public static synchronized int getStaticMsgId() { return ++lastUsedInternalMsgId; } }