/*  
 *  
 * The ObjectStyle Group Software License, version 1.1 
 * ObjectStyle Group - http://objectstyle.org/ 
 *  
 * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors 
 * of the software. All rights reserved. 
 *  
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 *  
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 *  
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in 
 *    the documentation and/or other materials provided with the 
 *    distribution. 
 *  
 * 3. The end-user documentation included with the redistribution, if any, 
 *    must include the following acknowlegement: 
 *    "This product includes software developed by independent contributors 
 *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)." 
 *    Alternately, this acknowlegement may appear in the software itself, 
 *    if and wherever such third-party acknowlegements normally appear. 
 *  
 * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse 
 *    or promote products derived from this software without prior written 
 *    permission. For written permission, email 
 *    "andrus at objectstyle dot org". 
 *  
 * 5. Products derived from this software may not be called "ObjectStyle" 
 *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their 
 *    names without prior written permission. 
 *  
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR 
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE. 
 *  
 *  
 * This software consists of voluntary contributions made by many 
 * individuals and hosted on ObjectStyle Group web site.  For more 
 * information on the ObjectStyle Group, please see 
 * <http://objectstyle.org/>. 
 */ 
 
import java.net.UnknownHostException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
 
 
/** 
 * helper class to generate pseudo-GUID sequences. 
 *  
 * @author Andrus Adamchik 
 */ 
public class IDUtil { 
     
    private static final int BITMASK_0 = 0xff; 
    private static final int BITMASK_1 = 0xff << 8; 
    private static final int BITMASK_2 = 0xff << 16; 
    private static final int BITMASK_3 = 0xff << 24; 
    private static final int BITMASK_4 = 0xff << 32; 
    private static final int BITMASK_5 = 0xff << 40; 
    private static final int BITMASK_6 = 0xff << 48; 
    private static final int BITMASK_7 = 0xff << 56; 
 
    // this id sequence needs to be long enough to feel 
    // the gap within the same timestamp millisecond 
    private static volatile int currentId; 
 
    private static MessageDigest md; 
    private static byte[] ipAddress; 
 
    static { 
        try { 
            md = MessageDigest.getInstance("MD5"); 
        } 
        catch (NoSuchAlgorithmException e) { 
            throw new RuntimeException("Can't initialize MessageDigest.", e); 
        } 
 
        try { 
            ipAddress = java.net.InetAddress.getLocalHost().getAddress(); 
        } 
        catch (UnknownHostException e) { 
            // use loopback interface 
            ipAddress = new byte[] { 
                    127, 0, 0, 1 
            }; 
        } 
    } 
 
    /** 
     * Prints a byte value to a StringBuffer as a double digit hex value. 
     *  
     * @since 1.2 
     */ 
    public static void appendFormattedByte(StringBuffer buffer, byte byteValue) { 
        final String digits = "0123456789ABCDEF"; 
 
        buffer.append(digits.charAt((byteValue >>> 4) & 0xF)); 
        buffer.append(digits.charAt(byteValue & 0xF)); 
    } 
 
    /** 
     * @param length the length of returned byte[] 
     * @return A pseudo-unique byte array of the specified length. Length must be at least 
     *         16 bytes, or an exception is thrown. 
     * @since 1.0.2 
     */ 
    public synchronized static byte[] pseudoUniqueByteSequence(int length) { 
        if (length < 16) { 
            throw new IllegalArgumentException( 
                    "Can't generate unique byte sequence shorter than 16 bytes: " 
                            + length); 
        } 
 
        if (length == 16) { 
            return pseudoUniqueByteSequence16(); 
        } 
 
        byte[] bytes = new byte[length]; 
        for (int i = 0; i <= length - 16; i += 16) { 
            byte[] nextSequence = pseudoUniqueByteSequence16(); 
            System.arraycopy(nextSequence, 0, bytes, i, 16); 
        } 
 
        // leftovers? 
        int leftoverLen = length % 16; 
        if (leftoverLen > 0) { 
            byte[] nextSequence = pseudoUniqueByteSequence16(); 
            System.arraycopy(nextSequence, 0, bytes, length - leftoverLen, leftoverLen); 
        } 
 
        return bytes; 
    } 
 
    public synchronized static byte[] pseudoUniqueSecureByteSequence(int length) { 
        if (length < 16) { 
            throw new IllegalArgumentException( 
                    "Can't generate unique byte sequence shorter than 16 bytes: " 
                            + length); 
        } 
 
        if (length == 16) { 
            return pseudoUniqueSecureByteSequence16(); 
        } 
 
        byte[] bytes = new byte[length]; 
        for (int i = 0; i <= length - 16; i += 16) { 
            byte[] nextSequence = pseudoUniqueSecureByteSequence16(); 
            System.arraycopy(nextSequence, 0, bytes, i, 16); 
        } 
 
        // leftovers? 
        int leftoverLen = length % 16; 
        if (leftoverLen > 0) { 
            byte[] nextSequence = pseudoUniqueSecureByteSequence16(); 
            System.arraycopy(nextSequence, 0, bytes, length - leftoverLen, leftoverLen); 
        } 
 
        return bytes; 
    } 
 
    public static final byte[] pseudoUniqueByteSequence8() { 
        byte[] bytes = new byte[8]; 
 
        // bytes 0..2 - incrementing # 
        // bytes 3..5 - timestamp high bytes 
        // bytes 6..7 - IP address 
 
        int nextInt = nextInt(); 
 
        bytes[0] = (byte) ((nextInt & (0xff << 16)) >>> 16); 
        bytes[1] = (byte) ((nextInt & (0xff << 8)) >>> 8); 
        bytes[2] = (byte) (nextInt & 0xff); 
 
        // append 3 high bytes of timestamp 
 
        long t = System.currentTimeMillis(); 
 
        bytes[3] = (byte) ((t & BITMASK_2) >>> 16); 
        bytes[4] = (byte) ((t & BITMASK_1) >>> 8); 
        bytes[5] = (byte) (t & BITMASK_0); 
 
        // append 2 last bytes of IP address 
        System.arraycopy(ipAddress, 2, bytes, 6, 2); 
        return bytes; 
    } 
 
    /** 
     * @return A pseudo unique 16-byte array. 
     */ 
    public static final byte[] pseudoUniqueByteSequence16() { 
        byte[] bytes = new byte[16]; 
 
        // bytes 0..3 - incrementing # 
        // bytes 4..11 - timestamp 
        // bytes 12..15 - IP address 
 
        int nextInt = nextInt(); 
 
        bytes[0] = (byte) ((nextInt & BITMASK_3) >>> 24); 
        bytes[1] = (byte) ((nextInt & BITMASK_2) >>> 16); 
        bytes[2] = (byte) ((nextInt & BITMASK_1) >>> 8); 
        bytes[3] = (byte) (nextInt & BITMASK_0); 
 
        long t = System.currentTimeMillis(); 
 
        bytes[4] = (byte) ((t & BITMASK_7) >>> 56); 
        bytes[5] = (byte) ((t & BITMASK_6) >>> 48); 
        bytes[6] = (byte) ((t & BITMASK_5) >>> 40); 
        bytes[7] = (byte) ((t & BITMASK_4) >>> 32); 
        bytes[8] = (byte) ((t & BITMASK_3) >>> 24); 
        bytes[9] = (byte) ((t & BITMASK_2) >>> 16); 
        bytes[10] = (byte) ((t & BITMASK_1) >>> 8); 
        bytes[11] = (byte) (t & BITMASK_0); 
 
        System.arraycopy(ipAddress, 0, bytes, 12, 4); 
        return bytes; 
    } 
 
    /** 
     * @return A pseudo unique digested 16-byte array. 
     */ 
    public static byte[] pseudoUniqueSecureByteSequence16() { 
        byte[] bytes = pseudoUniqueByteSequence16(); 
 
        synchronized (md) { 
            return md.digest(bytes); 
        } 
    } 
 
    private static final int nextInt() { 
        if (currentId == Integer.MAX_VALUE) { 
            currentId = 0; 
        } 
 
        return currentId++; 
    } 
 
    private IDUtil() { 
    } 
} 
 
    
     
     
     
     
  
  |