Java Uuid Generator (JUG) is a library for generating all (3) types of UUIDs on Java. And perhaps .NET/Mono as well: MUG is in the making!
Apache License 2.0 or LGPL 2.1
+Tatu Saloranta
+Tatu Saloranta (tsaloranta@gmail.com)
+ You can download this project in either + zip or + tar formats. +
+You can also clone the project with Git + by running: +
$ git clone git://github.com/cowtowncoder/java-uuid-generator+ + + + +
The {@link EthernetAddress} class provides several methods to - * construct ethernet address objects from. If one passes a bad - * parameter to these methods, this type of exception might occur. - * - * @version $Revision: 1.1 $ - * - * @since 1.0 - * - * @author $Author: pkb $ - * - * @see EthernetAddress */ -//---------------------------------------------------------------- - -public final class BadAddressException extends IllegalArgumentException { - - //---------------------------------------------------------------- - /** Construct exception with a particular message. - * - * @param text - * - * Text message to associate with exception - * - * @since 1.0 */ - //---------------------------------------------------------------- - - BadAddressException(String message) { - super(message); - } - -} diff -Nru jug-2.0.0/src/java/com/ccg/net/ethernet/EthernetAddress.java jug-3.1.5/src/java/com/ccg/net/ethernet/EthernetAddress.java --- jug-2.0.0/src/java/com/ccg/net/ethernet/EthernetAddress.java 2005-07-21 05:25:50.000000000 +0000 +++ jug-3.1.5/src/java/com/ccg/net/ethernet/EthernetAddress.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,558 +0,0 @@ -/*---------------------------------------------------------------- - * $Id: EthernetAddress.java,v 1.2 2001/10/11 21:13:28 pkb Exp $ - * - * (c)2001 - Paul Blankenbaker - * - * Revision Log - * - * $Log: EthernetAddress.java,v $ - * Revision 1.2 2001/10/11 21:13:28 pkb - * Changed organization of native code - moved binaries to - * $COMHOME/native/OS/ARCH directories - * - * Revision 1.1 2001/10/04 19:42:33 pkb - * - * Added package related to Ethernet addresses (turns out to be a - * non-trivial exercise to get a ethernet address in a cross platform - * manner). Currently uses native code (as I don't know of another way) - * and supports Windows, Linux, Solaris. Tested on (Windows 98, RedHat - * 7.1 and Solaris 8). - * - * - */ -//---------------------------------------------------------------- - -package com.ccg.net.ethernet; - -import java.util.*; - - -//---------------------------------------------------------------- -/** Manage ethernet address objects and provide a means to determine - * the ethernet address of the machine the JVM is running on. - * - *
This class is used to examine (work with) ethernet addresses. It - * was primarily created to provide a means to determine the ethernet - * address(es) of the local machine (which turned out to be a - * non-trivial project). - * - *
IMPORTANT INSTALLATION INSTRUCTIONS
- * - *This class relies on native code when determining the ethernet - * address. Because of this, a shared library module needs to be - * installed BEFORE you will be able to use the methods in this class - * related to the local ethernet address of the machine. - * - *
To do the installation, you need to: - * - *
It is important to note that the shared libraries need to be - * copied to a location that is within the library search path for - * your environment. I've found that the $(JREHOME)/bin directory - * tends to always be in the search path (at least for - * Linux/Windows). For Sun's JRE installation, look for - * $(JREHOME)/lib/ARCH (like "/opt/jdk/jre/lib/sparc"). If you are - * unable to copy the library to this location, you may need to update - * your library search path before executing code. - * - *
The source code for each of the libraries is available, however, - * it is often easier not to have to locate a compiler and simply use - * one of the pre-compiled binary files. The following binary files - * are available: - * - *
- * cp $COMHOME/ccg/native/linux/x86/libEthernetAddress.so \ - * $JREHOME/bin/libEthernetAddress.so
- * cp $COMHOME/ccg/native/solaris/sparc/libEthernetAddress.so \ - * $JREHOME/lib/sparc/libEthernetAddress.so
- * copy %COMHOME%/ccg/native/win/x86/EthernetAddress.dll \ - * %JREHOME%/bin/EthernetAddress.dll
Developer Notes:
- * - *If you need to add support for additional platforms (such as a - * Mac/Beos/etc), you should take one of the source 'C' files (like - * EthernetAddress_linux.c) as your starting point and create a new - * 'C' source file for the native platform you'd like to support. - * - * @version $Revision: 1.2 $ - * - * @since 1.0 - * - * @author $Author: pkb $ - * - * @see #getPrimaryAdapter - * @see PrintMAC.java */ -//---------------------------------------------------------------- - -public final class EthernetAddress { - - //---------------------------------------------------------------- - /** Native method to look up the ethernet address for a adapter. - * - * @param i - * - * ID of the next ethernet address you want to check. - * - * @param ea - * - * Byte array which is at least 6 bytes long to store the - * ethernet address in. - * - * @return - * - * true if able to determine address for adapter, false if not. - * - * @since 1.0 */ - //---------------------------------------------------------------- - - private static native boolean getLocalEthernet(int i, byte[] ea); - - - - //---------------------------------------------------------------- - /** Tries to create a EthernetAddress object for adapter N. - * - * @param n - * - * ID of adapter you want to get address of (start at 0). - * - * @return - * - * EthernetAddress object if able to determine, or null if not. - * - * @since 1.0 */ - //---------------------------------------------------------------- - - private static EthernetAddress getLocalEthernetAddress(int i) { - // load native code - - // load ALL adapters we can find on the system - byte[] ea = new byte[6]; - - if (!getLocalEthernet(i,ea)) return null; - - return fromBytes(ea); - - } - - - //---------------------------------------------------------------- - /** Check to see if all bytes of the ethernet address are zero. - * - *
This method checks all of the bytes of a ethernet address to - * see if they are zero. If they are, then the ethernet address is - * "0:0:0:0:0:0", which we consider the "null" ethernet address. - * - * @return - * - * true if all bytes of the ethernet address are 0. - * - * @since 1.0 - * - * @see #NULL */ - //---------------------------------------------------------------- - - public boolean isNull() { - for (int i = 0; i < _Bytes.length; i++) if (_Bytes[i] != 0) return false; - return true; - } - - - //---------------------------------------------------------------- - /** Constant ethernet address object which has the "null address". - * - *
This constant can be used when you want a non-null - * EthernetAddress object reference, but want a invalid (or null) - * ethernet address contained. - * - *
The {@link #isNull isNull()} method will ALWAYS return true - * for this constant. - * - * @serial - * - * @since 1.0 - * - * @see #isNull */ - //---------------------------------------------------------------- - - public static final EthernetAddress NULL=new EthernetAddress(); - - - //---------------------------------------------------------------- - /** Try to determine the primary ethernet address of the machine. - * - *
This method will try to return the primary ethernet address of - * the machine. In order for this to succeed: - * - *
This method will try and find ALL of the ethernet adapters - * which are currently available on the system. This is heavily OS - * dependent and may not be supported on all platforms. When not - * supported, you should still get back a collection with the {@link - * #getPrimaryAdapter primary adapter} in it. - * - * @throws UnsatisfiedLinkError - * - * This exception is thrown if we are unable to load the native - * library (like: libEthernetAddress.so or EthernetAddress.dll) - * which is required to query the system for the ethernet - * address. - * - * @return - * - * Array of all ethernet adapters (never returns null, but may - * return a 0 length array if no adapters could be found). - * - * @see #getPrimaryAdapter */ - //---------------------------------------------------------------- - - public static Collection getAllAdapters() - throws UnsatisfiedLinkError { - - // allocate vector to hold info - Vector av = new Vector(); - EthernetAddress ea=null; - for (int i = 0; (ea = getLocalEthernetAddress(i)) != null; i++) { - av.addElement(ea); - } - - return av; - } - - - //---------------------------------------------------------------- - /** Constructs object with "null values" (address of "0:0:0:0:0:0"). - * - * @since 1.0 */ - //---------------------------------------------------------------- - - EthernetAddress() { - _Bytes = new byte[6]; - } - - - //---------------------------------------------------------------- - /** Holds the binary ID of your ethernet adapter. - * - * @serial - * - * @since 1.0 */ - //---------------------------------------------------------------- - - private byte[] _Bytes; - - - //---------------------------------------------------------------- - /** Set the binary ID of your ethernet adapter. - * - * @param val - * - * New byte[] value to assign. - * - * @see #getBytes */ - //---------------------------------------------------------------- - - public static EthernetAddress fromBytes(byte[] val) - throws BadAddressException { - if (val == null || val.length != 6) { - throw new BadAddressException("ethernet address not 6 bytes long"); - } - - EthernetAddress ea = new EthernetAddress(); - for (int i = 0; i < val.length; i++) ea._Bytes[i] = val[i]; - return ea; - } - - - //---------------------------------------------------------------- - /** Get the binary ID of your ethernet adapter. - * - * @return - * - * Copy of the current byte[] value assigned. - * - * @see #fromBytes */ - //---------------------------------------------------------------- - - public byte[] getBytes() { - return (byte[]) _Bytes.clone(); - } - - - //---------------------------------------------------------------- - /** Parse a ethernet address object from a string. - * - *
Ethernet addresses are typically shown as 6 hexadecimal values - * (range: [0,ff]) separated by colons. They have the form: - * - *
- * x:x:x:x:x:x - *- * - *
This method is fairly lenient in its parsing. It allows any - * character (and omission) of the separator (shown above). And each - * hex value may be one or two digits long and upper or lower case. - * - *
The following shows several different ways to list the same - * ethernet address: - * - *
- * 00:E0:98:06:92:0E - * 0:e0:98:6:92:e - * 0-e0-98 6-92-e - * 00e0980692e0 - *- * - * @param sval - * String value to try and parse a ethernet address from (must - * not be null). - * - * @throws BadAddressException - * If we could not parse a ethernet address from the string you - * passed. - * - * @see #toString */ - //---------------------------------------------------------------- - - public static EthernetAddress fromString(String sval) - throws BadAddressException { - - byte[] eab = new byte[6]; - int ei = 0; - boolean needHiNyb = true; - - boolean lastWasSep = true; - - int val = -1; - - int slen = sval.length(); - for (int i = 0; i < slen; i++) { - char c = sval.charAt(i); - int cval = Character.digit(c,16); - - if (cval == -1) { // if not hex digit - if (lastWasSep) { // if last char was separator - ei = 0; // reset to zero bytes - } - else if (val != -1) { // if we have value to store - if (ei >= eab.length) { - throw new BadAddressException("too many bytes in \""+sval+"\""); - } - eab[ei++] = (byte) val; - val = -1; - needHiNyb = true; - } - } - else { // got hex digit - lastWasSep = false; - if (needHiNyb) { // if need hi-nybble, save value - val = cval; - needHiNyb = false; - } - else { // if lo-nybble, then update array - val <<= 4; - val += cval; - needHiNyb = true; - if (ei >= eab.length) { - throw new BadAddressException("too many bytes in \""+sval+"\""); - } - eab[ei++] = (byte) val; - val = -1; - } - } - } - - // if last byte value is single digit, - // catch it here outside of loop - if ((val != -1) && !needHiNyb) { - if (ei >= eab.length) { - throw new BadAddressException("too many bytes in \""+sval+"\""); - } - eab[ei++] = (byte) val; - } - - if (ei != eab.length) { - throw new BadAddressException("not enough bytes in \""+sval+"\""); - } - - EthernetAddress ea = new EthernetAddress(); - ea._Bytes = eab; - return ea; - - } - - - //---------------------------------------------------------------- - /** Get a hash code for the object. - * - *
This method obeys the hash code contract and returns a hash - * value that will try to be random, but will be identical for - * objects which are {@link #equals equal}. - * - * @return - * - * A reasonable hash code for the object. - * - * @since 1.0 */ - //---------------------------------------------------------------- - - public int hashCode() { - - int blen = _Bytes.length; - - if (blen == 0) return 0; - - int hc = _Bytes[0]; - for (int i = 1; i < blen; i++) { - hc *= 37; - hc += _Bytes[i]; - } - - return hc; - - } - - - //---------------------------------------------------------------- - /** Determine if two ethernet address objects are "equal". - * - * @param o - * - * Other object to compare to (you can pass null). - * - * @return - * - * true if two objects have same Ethernet address, false if not. - * - * @since 1.0 */ - //---------------------------------------------------------------- - - public boolean equals(Object o) { - - if (!(o instanceof EthernetAddress)) return false; - - byte[] bao = ((EthernetAddress) o)._Bytes; - if (bao.length != _Bytes.length) return false; - - for (int i = 0; i < bao.length; i++) if (bao[i] != _Bytes[i]) return false; - return true; - } - - - //---------------------------------------------------------------- - /** Get the string representation of the ethernet address. - * - * @return - * - * String representation of ehternet address in form: - * "xx:xx:xx:xx:xx:xx". - * - * @see #fromString */ - //---------------------------------------------------------------- - - public String toString() { - int blen = _Bytes.length; - StringBuffer sb = new StringBuffer(blen*3); - for (int i = 0; i < blen; i++) { - int lo = _Bytes[i]; - int hi = ((lo >> 4) & 0xF); - lo &= 0xF; - if (i != 0) sb.append(':'); - sb.append(Character.forDigit(hi,16)); - sb.append(Character.forDigit(lo,16)); - } - return sb.toString(); - } - - //---------------------------------------------------------------- - // Static class method to load native library first time class is - // loaded - //---------------------------------------------------------------- - - /* 08-Sep-2002, TSa: Commented out to allow for alternative - * dynamic library loading (loading is handled from outside this - * class now, to allow dynamically choosing the correct lib as well - * as catching possible exceptions) - */ - /* - static { - try { - System.loadLibrary("EthernetAddress"); - } catch (Throwable t) { - com.ccg.util.Log.error("problem loading \"EthernetAddress"+ - "\" native library",t); - } - } - */ -} diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/EthernetAddress.java jug-3.1.5/src/java/org/safehaus/uuid/EthernetAddress.java --- jug-2.0.0/src/java/org/safehaus/uuid/EthernetAddress.java 2005-08-10 03:34:06.000000000 +0000 +++ jug-3.1.5/src/java/org/safehaus/uuid/EthernetAddress.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,418 +0,0 @@ -/* JUG Java Uuid Generator - * - * Copyright (c) 2002 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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.safehaus.uuid; - -import java.io.Serializable; - -/** - * EthernetAddress encapsulates the 6-byte Mac address defined in - * IEEE 802.1 standard. - */ - -public class EthernetAddress - implements Serializable, Cloneable, Comparable -{ - private final static String kHexChars = "0123456789abcdefABCDEF"; - - private final byte[] mAddress = new byte[6]; - - /* *** Creation methods *** */ - - /** - * String constructor; given a 'standard' ethernet MAC address string - * (like '00:C0:F0:3D:5B:7C'), constructs an EthernetAddress instance. - * - * Note that string is case-insensitive, and also that leading zeroes - * may be omitted. Thus '00:C0:F0:3D:5B:7C' and '0:c0:f0:3d:5b:7c' are - * equivalent, and a 'null' address could be passed as ':::::' as well - * as '00:00:00:00:00:00' (or any other intermediate combination). - * - * @param addrStr String representation of the ethernet address - */ - public EthernetAddress(String addrStr) - throws NumberFormatException - { - byte[] addr = mAddress; - int len = addrStr.length(); - - /* Ugh. Although the most logical format would be the 17-char one - * (12 hex digits separated by colons), apparently leading zeroes - * can be omitted. Thus... Can't just check string length. :-/ - */ - for (int i = 0, j = 0; j < 6; ++j) { - if (i >= len) { - // Is valid if this would have been the last byte: - if (j == 5) { - addr[5] = (byte) 0; - break; - } - throw new NumberFormatException("Incomplete ethernet address (missing one or more digits"); - } - - char c = addrStr.charAt(i); - ++i; - int value; - - // The whole number may be omitted (if it was zero): - if (c == ':') { - value = 0; - } else { - // No, got at least one digit? - if (c >= '0' && c <= '9') { - value = (c - '0'); - } else if (c >= 'a' && c <= 'f') { - value = (c - 'a' + 10); - } else if (c >= 'A' && c <= 'F') { - value = (c - 'A' + 10); - } else { - throw new NumberFormatException("Non-hex character '"+c+"'"); - } - - // How about another one? - if (i < len) { - c = addrStr.charAt(i); - ++i; - if (c != ':') { - value = (value << 4); - if (c >= '0' && c <= '9') { - value |= (c - '0'); - } else if (c >= 'a' && c <= 'f') { - value |= (c - 'a' + 10); - } else if (c >= 'A' && c <= 'F') { - value |= (c - 'A' + 10); - } else { - throw new NumberFormatException("Non-hex character '"+c+"'"); - } - } - } - } - - addr[j] = (byte) value; - - if (c != ':') { - if (i < len) { - if (addrStr.charAt(i) != ':') { - throw new NumberFormatException("Expected ':', got ('" - + addrStr.charAt(i) - +"')"); - } - ++i; - } else if (j < 5) { - throw new NumberFormatException("Incomplete ethernet address (missing one or more digits"); - } - } - } - } - - /** - * Binary constructor that constructs an instance given the 6 byte - * (48-bit) address. Useful if an address is saved in binary format - * (for saving space for example). - */ - public EthernetAddress(byte [] addr) - throws NumberFormatException - { - if (addr.length != 6) { - throw new NumberFormatException("Ethernet address has to consist of 6 bytes"); - } - for (int i = 0; i < 6; ++i) { - mAddress[i] = addr[i]; - } - } - - /** - * Another binary constructor; constructs an instance from the given - * long argument; the lowest 6 bytes contain the address. - * - * @param addr long that contains the MAC address in 6 least significant - * bytes. - */ - public EthernetAddress(long addr) - { - for (int i = 0; i < 6; ++i) { - mAddress[5 - i] = (byte) addr; - addr >>>= 8; - } - } - - /** - * Package internal constructor for creating an 'empty' ethernet address - */ - EthernetAddress() - { - byte z = (byte) 0; - for (int i = 0; i < 6; ++i) { - mAddress[i] = z; - } - } - - /** - * Default cloning behaviour (bitwise copy) is just fine... - */ - public Object clone() - { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - // shouldn't happen - return null; - } - } - - /* *** Comparison methods *** */ - - public boolean equals(Object o) - { - if (!(o instanceof EthernetAddress)) { - return false; - } - byte[] otherAddress = ((EthernetAddress) o).mAddress; - byte[] thisAddress = mAddress; - for (int i = 0; i < 6; ++i) { - if (otherAddress[i] != thisAddress[i]) { - return false; - } - } - return true; - } - - /** - * Method that compares this EthernetAddress to one passed in as - * argument. Comparison is done simply by comparing individual - * address bytes in the order. - * - * @return -1 if this EthernetAddress should be sorted before the - * one passed in, 1 if after and 0 if they are equal. - */ - public int compareTo(Object o) - { - byte[] thatA = ((EthernetAddress) o).mAddress; - byte[] thisA = mAddress; - - for (int i = 0; i < 6; ++i) { - int cmp = (((int) thisA[i]) & 0xFF) - - (((int) thatA[i]) & 0xFF); - if (cmp != 0) { - return cmp; - } - } - - return 0; - } - - /* *** Type conversion *** */ - - /** - * Returns the canonical string representation of this ethernet address. - * Canonical means that all characters are lower-case and string length - * is always 17 characters (ie. leading zeroes are not omitted). - * - * @return Canonical string representation of this ethernet address. - */ - public String toString() - { - /* Let's not cache the output here (unlike with UUID), assuming - * this won't be called as often: - */ - StringBuffer b = new StringBuffer(17); - byte[] addr = mAddress; - - for (int i = 0; i < 6; ++i) { - if (i > 0) { - b.append(":"); - } - int hex = addr[i] & 0xFF; - b.append(kHexChars.charAt(hex >> 4)); - b.append(kHexChars.charAt(hex & 0x0f)); - } - return b.toString(); - } - - /** - * Returns 6 byte byte array that contains the binary representation - * of this ethernet address; byte 0 is the most significant byte - * (and so forth) - * - * @return 6 byte byte array that contains the binary representation - */ - public byte[] asByteArray() - { - byte[] result = new byte[6]; - - toByteArray(result); - - return result; - } - - /** - * Synonym to 'asByteArray()' - * - * @return 6 byte byte array that contains the binary representation - */ - public byte[] toByteArray() { return asByteArray(); } - - public void toByteArray(byte[] array) { toByteArray(array, 0); } - - public void toByteArray(byte[] array, int pos) - { - for (int i = 0; i < 6; ++i) { - array[pos+i] = mAddress[i]; - } - } - - public long toLong() - { - /* Damn Java's having signed bytes sucks... they are NEVER what - * anyone needs; and sign extension work-arounds are slow. - */ - byte[] addr = mAddress; - int hi = (((int) addr[0]) & 0xFF) << 8 - | (((int) addr[1]) & 0xFF); - int lo = ((int) addr[2]) & 0xFF; - for (int i = 3; i < 6; ++i) { - lo = (lo << 8) | (((int) addr[i]) & 0xFF); - } - - return ((long) hi) << 32 | (((long) lo) & 0xFFFFFFFFL); - } - - /** - * Constructs a new EthernetAddress given the byte array that contains - * binary representation of the address. - * - * Note that calling this method returns the same result as would - * using the matching constructor. - * - * @param addr Binary representation of the ethernet address - * - * @throws NumberFormatException if addr is invalid (less or more than - * 6 bytes in array) - */ - public static EthernetAddress valueOf(byte[] addr) - throws NumberFormatException - { - return new EthernetAddress(addr); - } - - /** - * Constructs a new EthernetAddress given the byte array that contains - * binary representation of the address. - * - * Note that calling this method returns the same result as would - * using the matching constructor. - * - * @param addr Binary representation of the ethernet address - * - * @throws NumberFormatException if addr is invalid (less or more than - * 6 ints in array) - */ - public static EthernetAddress valueOf(int[] addr) - throws NumberFormatException - { - byte[] bAddr = new byte[addr.length]; - - for (int i = 0; i < addr.length; ++i) { - bAddr[i] = (byte) addr[i]; - } - return new EthernetAddress(bAddr); - } - - /** - * Constructs a new EthernetAddress given a string representation of - * the ethernet address. - * - * Note that calling this method returns the same result as would - * using the matching constructor. - * - * @param addrStr String representation of the ethernet address - * - * @throws NumberFormatException if addr representation is invalid - */ - public static EthernetAddress valueOf(String addrStr) - throws NumberFormatException - { - return new EthernetAddress(addrStr); - } - - /** - * Constructs a new EthernetAddress given the long int value (64-bit) - * representation of the ethernet address (of which 48 LSB contain - * the definition) - * - * Note that calling this method returns the same result as would - * using the matching constructor. - * - * @param addr Long int representation of the ethernet address - */ - public static EthernetAddress valueOf(long addr) - { - return new EthernetAddress(addr); - } - - public static void main(String[] args) - { - System.out.println("EthernetAddress.main, test:"); - System.out.println("---------------------------"); - - int len; - long rnd = 0; - if (args == null || args.length == 0) { - System.out.println("[no address passed, using a random address]"); - len = 1; - rnd = System.currentTimeMillis() - ^ (long) (Math.random() * (double) 0x100000000L); - args = new String[] { new EthernetAddress(rnd).toString() }; - } - - for (int i = 0; i < args.length; ++i) { - String s = args[i]; - System.out.println("Address '"+s+"':"); - try { - EthernetAddress a = EthernetAddress.valueOf(s); - System.err.println(" Ok, comes out as '"+a.toString()+"'"); - - // EthernetAddress <-> long - System.err.print(" Converting to long, result = "); - long l = a.toLong(); - System.err.println(""+Long.toHexString(l)); - System.err.print(" Creating address from long, are equal: "); - EthernetAddress b = EthernetAddress.valueOf(l); - if (b.equals(a)) { - System.err.println("yes (OK)"); - } else { - System.err.println("no (FAIL)"); - break; - } - - // EthernetAddress <-> byte[] - System.err.println(" Converting to byte array."); - byte[] ba = a.asByteArray(); - System.err.print(" Creating address from byte[], are equal: "); - b = EthernetAddress.valueOf(ba); - if (b.equals(a)) { - System.err.println("yes (OK)"); - } else { - System.err.println("no (FAIL)"); - break; - } - } catch (NumberFormatException e) { - System.out.println(" Fail: "+e.toString()); - } - } - System.out.println("---------------------------"); - System.out.println("Done."); - } -} diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/ext/FileBasedTimestampSynchronizer.java jug-3.1.5/src/java/org/safehaus/uuid/ext/FileBasedTimestampSynchronizer.java --- jug-2.0.0/src/java/org/safehaus/uuid/ext/FileBasedTimestampSynchronizer.java 2005-08-10 03:42:06.000000000 +0000 +++ jug-3.1.5/src/java/org/safehaus/uuid/ext/FileBasedTimestampSynchronizer.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,230 +0,0 @@ -/* JUG Java Uuid Generator - * - * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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.safehaus.uuid.ext; - -import org.safehaus.uuid.Logger; -import org.safehaus.uuid.TimestampSynchronizer; - -import java.io.*; - -/** - * Implementation of {@link TimestampSynchronizer}, which uses file system - * as the storage and locking mechanism. - *
- * Synchronization is achieved by obtaining an exclusive file locks on two - * specified lock files, and by using the files to store first "safe" timestamp - * value that the generator can use; alternating between one to use to ensure - * one of them always contains a valid timestamp. Latter is needed to guard - * against system clock moving backwards after UUID generator restart. - *
- * Note: this class will only work on JDK 1.4 and above, since it requires - * NIO package to do proper file locking (as well as new opening mode for - * {@link RandomAccessFile}). - *
- * Also note that it is assumed that the caller has taken care to synchronize
- * access to method to be single-threaded. As such, none of the methods
- * is explicitly synchronized here.
- */
-public final class FileBasedTimestampSynchronizer
- extends TimestampSynchronizer
-{
- // // // Constants:
-
- /**
- * The default update interval is 10 seconds, meaning that the
- * synchronizer "reserves" next 10 secods for generation. This
- * also means that the lock files need to be accessed at most
- * once every ten second.
- */
- final static long DEFAULT_UPDATE_INTERVAL = 10L * 1000L;
-
- final static String FILENAME1 = "uuid1.lck";
-
- final static String FILENAME2 = "uuid2.lck";
-
- // // // Configuration:
-
- long mInterval = DEFAULT_UPDATE_INTERVAL;
-
- final LockedFile mLocked1, mLocked2;
-
- // // // State:
-
- /**
- * Flag used to indicate which of timestamp files has the most
- * recently succesfully updated timestamp value. True means that
- * mFile1
is more recent; false that mFile2
- * is.
- */
- boolean mFirstActive = false;
-
- /**
- * Constructor that uses default values for names of files to use
- * (files will get created in the current working directory), as
- * well as for the update frequency value (10 seconds).
- */
- public FileBasedTimestampSynchronizer()
- throws IOException
- {
- this(new File(FILENAME1), new File(FILENAME2));
- }
-
- public FileBasedTimestampSynchronizer(File f1, File f2)
- throws IOException
- {
- this(f1, f2, DEFAULT_UPDATE_INTERVAL);
- }
-
- public FileBasedTimestampSynchronizer(File f1, File f2, long interval)
- throws IOException
- {
- mInterval = interval;
- mLocked1 = new LockedFile(f1);
-
- boolean ok = false;
- try {
- mLocked2 = new LockedFile(f2);
- ok = true;
- } finally {
- if (!ok) {
- mLocked1.deactivate();
- }
- }
-
- // But let's leave reading up to initialization
- }
-
- /*
- //////////////////////////////////////////////////////////////
- // Configuration
- //////////////////////////////////////////////////////////////
- */
-
- public void setUpdateInterval(long interval)
- {
- if (interval < 1L) {
- throw new IllegalArgumentException("Illegal value ("+interval+"); has to be a positive integer value");
- }
- mInterval = interval;
- }
-
- /*
- //////////////////////////////////////////////////////////////
- // Implementation of the API
- //////////////////////////////////////////////////////////////
- */
-
- /**
- * This method is to be called only once by
- * {@link org.safehaus.uuid.UUIDTimer}. It
- * should fetch the persisted timestamp value, which indicates
- * first timestamp value that is guaranteed NOT to have used by
- * a previous incarnation. If it can not determine such value, it
- * is to return 0L as a marker.
- *
- * @return First timestamp value that was NOT locked by lock files;
- * 0L to indicate that no information was read.
- */
- protected long initialize()
- throws IOException
- {
- long ts1 = mLocked1.readStamp();
- long ts2 = mLocked2.readStamp();
- long result;
-
- if (ts1 > ts2) {
- mFirstActive = true;
- result = ts1;
- } else {
- mFirstActive = false;
- result = ts2;
- }
-
- /* Hmmh. If we didn't get a time stamp (-> 0), or if written time is
- * ahead of current time, let's log something:
- */
- if (result <= 0L) {
- Logger.logWarning("Could not determine safe timer starting point: assuming current system time is acceptable");
- } else {
- long now = System.currentTimeMillis();
- long diff = now - result;
-
- /* It's more suspicious if old time was ahead... although with
- * longer iteration values, it can be ahead without errors. So
- * let's base check on current iteration value:
- */
- if ((now + mInterval) < result) {
- Logger.logWarning("Safe timestamp read is "+(result - now)+" milliseconds in future, and is greater than the inteval ("+mInterval+")");
- }
-
- /* Hmmh. Is there any way a suspiciously old timestamp could be
- * harmful? It can obviously be useless but...
- */
- }
-
- return result;
- }
-
- public void deactivate()
- throws IOException
- {
- doDeactivate(mLocked1, mLocked2);
- }
-
- /**
- * @return Timestamp value that the caller can NOT use. That is, all
- * timestamp values prior to (less than) this value can be used
- * ok, but this value and ones after can only be used by first
- * calling update.
- */
- public long update(long now)
- throws IOException
- {
- long nextAllowed = now + mInterval;
-
- /* We have to make sure to (over)write the one that is NOT
- * actively used, to ensure that we always have fully persisted
- * timestamp value, even if the write process gets interruped
- * half-way through.
- */
-
- if (mFirstActive) {
- mLocked2.writeStamp(nextAllowed);
- } else {
- mLocked1.writeStamp(nextAllowed);
- }
-
- mFirstActive = !mFirstActive;
-
- return nextAllowed;
- }
-
- /*
- //////////////////////////////////////////////////////////////
- // Internal methods
- //////////////////////////////////////////////////////////////
- */
-
- protected static void doDeactivate(LockedFile lf1, LockedFile lf2)
- {
- if (lf1 != null) {
- lf1.deactivate();
- }
- if (lf2 != null) {
- lf2.deactivate();
- }
- }
-}
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/ext/JavaUtilLogger.java jug-3.1.5/src/java/org/safehaus/uuid/ext/JavaUtilLogger.java
--- jug-2.0.0/src/java/org/safehaus/uuid/ext/JavaUtilLogger.java 2005-09-25 19:16:19.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/ext/JavaUtilLogger.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,134 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid.ext;
-
-import java.io.*;
-
-import java.util.logging.Logger;
-
-//import org.safehaus.uuid.Logger;
-
-/**
- * Simple wrapper that allows easy connecting of JUG logging into JDK 1.4+
- * logging implementation (aka "java.util.logging" aka "JUL".
- *
- * Note: using this class requires JDK 1.4 or above.
- */
-public class JavaUtilLogger
- extends org.safehaus.uuid.Logger
-{
- private java.util.logging.Logger mPeer;
-
- private JavaUtilLogger(java.util.logging.Logger peer)
- {
- mPeer = peer;
- }
-
- /**
- * Static method to call to make JUG use to proxy all of its logging
- * through the specified j.u.l Logger
instance.
- *
- * Method will create a simple wrapper, and call
- * {@link org.safehaus.uuid.Logger#setLogger} with the wrapper as
- * the argument. This will then re-direct logging from the previously
- * defined Logger (which initially is the simple JUG logger) to the
- * new wrapper, which routes logging messages to the log4j peer Logger
- * instance.
- */
- public static void connectToJavaUtilLogging(java.util.logging.Logger peer)
- {
- JavaUtilLogger logger = new JavaUtilLogger(peer);
- // This is static method of the base class...
- setLogger(logger);
- }
-
- /**
- * Static method to call to make JUG use a log4j proxy all of its logging
- * through a j.u.l Logger
constructed to correspond with
- * org.safehaus.uuid.Logger
class (this generally determines
- * j.u.l category output etc settings).
- *
- * Method will create a simple wrapper, and call - * {@link org.safehaus.uuid.Logger#setLogger} with the wrapper as - * the argument. This will then re-direct logging from the previously - * defined Logger (which initially is the simple JUG logger) to the - * new wrapper, which routes logging messages to the j.u.l peer Logger - * instance. - */ - public static void connectToJavaUtilLogging() - { - connectToJavaUtilLogging(java.util.logging.Logger.getLogger(org.safehaus.uuid.Logger.class.getName())); - } - - /* - ///////////////////////////////////////////////////////////// - // Overridable implementation/instance methods from - // Logger base class - ///////////////////////////////////////////////////////////// - */ - - // // // Config - - // This is ok; let's just use base class functionality: - //protected void doSetLogLevel(int ll); - - /** - * Note: this method is meaningless with log4j, since it has more - * advanced output mapping and filtering mechanisms. As such, it's - * a no-op - */ - protected void doSetOutput(PrintStream str) - { - // Could also throw an Error.. but for now, let's log instead... - mPeer.warning("doSetOutput(PrintStream) called on "+getClass()+" instance, ignoring."); - } - - /** - * Note: this method is meaningless with log4j, since it has more - * advanced output mapping and filtering mechanisms. As such, it's - * a no-op - */ - protected void doSetOutput(Writer w) - { - mPeer.warning("doSetOutput(Writer) called on "+getClass()+" instance, ignoring."); - } - - // // // Logging methods - - protected void doLogInfo(String msg) - { - if (mLogLevel <= LOG_INFO_AND_ABOVE) { - mPeer.info(msg); - } - } - - protected void doLogWarning(String msg) - { - if (mLogLevel <= LOG_WARNING_AND_ABOVE) { - mPeer.warning(msg); - } - } - - protected void doLogError(String msg) - { - /* Hmmh. JUL doesn't have error... and SEVERE is bit drastic. But, - * well, let's use that for ERRORs for now. - */ - if (mLogLevel <= LOG_ERROR_AND_ABOVE) { - mPeer.severe(msg); - } - } -} diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/ext/LockedFile.java jug-3.1.5/src/java/org/safehaus/uuid/ext/LockedFile.java --- jug-2.0.0/src/java/org/safehaus/uuid/ext/LockedFile.java 2005-08-09 05:29:47.000000000 +0000 +++ jug-3.1.5/src/java/org/safehaus/uuid/ext/LockedFile.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,292 +0,0 @@ -/* JUG Java Uuid Generator - * - * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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.safehaus.uuid.ext; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; - -import org.safehaus.uuid.Logger; - -/** - * Utility class used by {@link FileBasedTimestampSynchronizer} to do - * actual file access and locking. - *
- * Class stores simple timestamp values based on system time accessed
- * using System.currentTimeMillis()
. A single timestamp
- * is stored into a file using {@link RandomAccessFile} in fully
- * synchronized mode. Value is written in ISO-Latin (ISO-8859-1)
- * encoding (superset of Ascii, 1 byte per char) as 16-digit hexadecimal
- * number, surrounded by brackets. As such, file produced should
- * always have exact size of 18 bytes. For extra robustness, slight
- * variations in number of digits are accepeted, as are white space
- * chars before and after bracketed value.
- */
-class LockedFile
-{
- /**
- * Expected file length comes from hex-timestamp (16 digits),
- * preamble "[0x",(3 chars) and trailer "]\r\n" (2 chars, linefeed
- * to help debugging -- in some environments, missing trailing linefeed
- * causes problems: also, 2-char linefeed to be compatible with all
- * standard linefeeds on MacOS, Unix and Windows).
- */
- final static int DEFAULT_LENGTH = 22;
-
- final static long READ_ERROR = 0L;
-
- // // // Configuration:
-
- final File mFile;
-
- // // // File state
-
- RandomAccessFile mRAFile;
-
- FileChannel mChannel;
-
- FileLock mLock;
-
- ByteBuffer mWriteBuffer = null;
-
- /**
- * Flag set if the original file (created before this instance was
- * created) had size other than default size and needs to be
- * truncated
- */
- boolean mWeirdSize;
-
- /**
- * Marker used to ensure that the timestamps stored are monotonously
- * increasing. Shouldn't really be needed, since caller should take
- * care of it, but let's be bit paranoid here.
- */
- long mLastTimestamp = 0L;
-
- LockedFile(File f)
- throws IOException
- {
- mFile = f;
-
- RandomAccessFile raf = null;
- FileChannel channel = null;
- FileLock lock = null;
- boolean ok = false;
-
- try { // let's just use a single block to share cleanup code
- raf = new RandomAccessFile(f, "rwd");
-
- // Then lock them, if possible; if not, let's err out
- channel = raf.getChannel();
- if (channel == null) {
- throw new IOException("Failed to access channel for '"+f+"'");
- }
- lock = channel.tryLock();
- if (lock == null) {
- throw new IOException("Failed to lock '"+f+"' (another JVM running UUIDGenerator?)");
- }
- ok = true;
- } finally {
- if (!ok) {
- doDeactivate(f, raf, lock);
- }
- }
-
- mRAFile = raf;
- mChannel = channel;
- mLock = lock;
- }
-
- public void deactivate()
- {
- RandomAccessFile raf = mRAFile;
- mRAFile = null;
- FileLock lock = mLock;
- mLock = null;
- doDeactivate(mFile, raf, lock);
- }
-
- public long readStamp()
- {
- int size;
-
- try {
- size = (int) mChannel.size();
- } catch (IOException ioe) {
- doLogError("Failed to read file size: "+ioe);
- return READ_ERROR;
- }
-
- mWeirdSize = (size != DEFAULT_LENGTH);
-
- // Let's check specifically empty files though
- if (size == 0) {
- doLogWarning("Missing or empty file, can not read timestamp value");
- return READ_ERROR;
- }
-
- // Let's also allow some slack... but just a bit
- if (size > 100) {
- size = 100;
- }
- byte[] data = new byte[size];
- try {
- mRAFile.readFully(data);
- } catch (IOException ie) {
- doLogError("Failed to read "+size+" bytes: "+ie);
- return READ_ERROR;
- }
-
- /* Ok, got data. Now, we could just directly parse the bytes (since
- * it is single-byte encoding)... but for convenience, let's create
- * the String (this is only called once per JVM session)
- */
- char[] cdata = new char[size];
- for (int i = 0; i < size; ++i) {
- cdata[i] = (char) (data[i] & 0xFF);
- }
- String dataStr = new String(cdata);
- // And let's trim leading (and trailing, who cares)
- dataStr = dataStr.trim();
-
- long result = -1;
- String err = null;
-
- if (!dataStr.startsWith("[0")
- || dataStr.length() < 3
- || Character.toLowerCase(dataStr.charAt(2)) != 'x') {
- err = "does not start with '[0x' prefix";
- } else {
- int ix = dataStr.indexOf(']', 3);
- if (ix <= 0) {
- err = "does not end with ']' marker";
- } else {
- String hex = dataStr.substring(3, ix);
- if (hex.length() > 16) {
- err = "length of the (hex) timestamp too long; expected 16, had "+hex.length()+" ('"+hex+"')";
- } else {
- try {
- result = Long.parseLong(hex, 16);
- } catch (NumberFormatException nex) {
- err = "does not contain a valid hex timestamp; got '"
- +hex+"' (parse error: "+nex+")";
- }
- }
- }
- }
-
- // Unsuccesful?
- if (result < 0L) {
- doLogError("Malformed timestamp file contents: "+err);
- return READ_ERROR;
- }
-
- mLastTimestamp = result;
- return result;
- }
-
- final static String HEX_DIGITS = "0123456789abcdef";
-
- public void writeStamp(long stamp)
- throws IOException
- {
- // Let's do sanity check first:
- if (stamp <= mLastTimestamp) {
- /* same stamp is not dangerous, but pointless... so warning,
- * not an error:
- */
- if (stamp == mLastTimestamp) {
- doLogWarning("Trying to re-write existing timestamp ("+stamp+")");
- return;
- }
- throw new IOException(""+getFileDesc()+" trying to overwrite existing value ("+mLastTimestamp+") with an earlier timestamp ("+stamp+")");
- }
-
-//System.err.println("!!!! Syncing ["+mFile+"] with "+stamp+" !!!");
-
- // Need to initialize the buffer?
- if (mWriteBuffer == null) {
- mWriteBuffer = ByteBuffer.allocate(DEFAULT_LENGTH);
- mWriteBuffer.put(0, (byte) '[');
- mWriteBuffer.put(1, (byte) '0');
- mWriteBuffer.put(2, (byte) 'x');
- mWriteBuffer.put(19, (byte) ']');
- mWriteBuffer.put(20, (byte) '\r');
- mWriteBuffer.put(21, (byte) '\n');
- }
-
- // Converting to hex is simple
- for (int i = 18; i >= 3; --i) {
- int val = (((int) stamp) & 0x0F);
- mWriteBuffer.put(i, (byte) HEX_DIGITS.charAt(val));
- stamp = (stamp >> 4);
- }
- // and off we go:
- mWriteBuffer.position(0); // to make sure we always write it all
- mChannel.write(mWriteBuffer, 0L);
- if (mWeirdSize) {
- mRAFile.setLength(DEFAULT_LENGTH);
- mWeirdSize = false;
- }
-
- // This is probably not needed (as the random access file is supposedly synced)... but let's be safe:
- mChannel.force(false);
-
- // And that's it!
- }
-
- /*
- //////////////////////////////////////////////////////////////
- // Internal methods
- //////////////////////////////////////////////////////////////
- */
-
- protected void doLogWarning(String msg)
- {
- Logger.logWarning("(file '"+getFileDesc()+"') "+msg);
- }
-
- protected void doLogError(String msg)
- {
- Logger.logError("(file '"+getFileDesc()+"') "+msg);
- }
-
- protected String getFileDesc() {
- return mFile.toString();
- }
-
- protected static void doDeactivate(File f, RandomAccessFile raf,
- FileLock lock)
- {
- if (lock != null) {
- try {
- lock.release();
- } catch (Throwable t) {
- Logger.logError("Failed to release lock (for file '"+f+"'): "+t);
- }
- }
- if (raf != null) {
- try {
- raf.close();
- } catch (Throwable t) {
- Logger.logError("Failed to close file '"+f+"':"+t);
- }
- }
- }
-}
-
-
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/ext/Log4jLogger.java jug-3.1.5/src/java/org/safehaus/uuid/ext/Log4jLogger.java
--- jug-2.0.0/src/java/org/safehaus/uuid/ext/Log4jLogger.java 2005-09-25 19:16:30.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/ext/Log4jLogger.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,132 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid.ext;
-
-import java.io.*;
-
-import org.apache.log4j.Logger;
-
-//import org.safehaus.uuid.Logger;
-
-/**
- * Simple wrapper that allows easy connecting of JUG logging into log4j
- * logging subsystem.
- *
- * Note: using this class implies all the dependencies that the log4j
- * subsystem in use requires (JDK 1.2 or above, in general)
- */
-public class Log4jLogger
- extends org.safehaus.uuid.Logger
-{
- private org.apache.log4j.Logger mPeer;
-
- private Log4jLogger(org.apache.log4j.Logger peer)
- {
- mPeer = peer;
- }
-
- /**
- * Static method to call to make JUG use to proxy all of its logging
- * through the specified log4j Logger
instance.
- *
- * Method will create a simple wrapper, and call
- * {@link org.safehaus.uuid.Logger#setLogger} with the wrapper as
- * the argument. This will then re-direct logging from the previously
- * defined Logger (which initially is the simple JUG logger) to the
- * new wrapper, which routes logging messages to the log4j peer Logger
- * instance.
- */
- public static void connectToLog4j(org.apache.log4j.Logger peer)
- {
- Log4jLogger logger = new Log4jLogger(peer);
- // This is static method of the base class...
- setLogger(logger);
- }
-
- /**
- * Static method to call to make JUG use a log4j proxy all of its logging
- * through a log4j Logger
constructed to correspond with
- * org.safehaus.uuid.Logger
class (this generally determines
- * log4j category output etc settings).
- *
- * Method will create a simple wrapper, and call - * {@link org.safehaus.uuid.Logger#setLogger} with the wrapper as - * the argument. This will then re-direct logging from the previously - * defined Logger (which initially is the simple JUG logger) to the - * new wrapper, which routes logging messages to the log4j peer Logger - * instance. - */ - public static void connectToLog4j() - { - connectToLog4j(org.apache.log4j.Logger.getLogger(org.safehaus.uuid.Logger.class)); - } - - /* - ///////////////////////////////////////////////////////////// - // Overridable implementation/instance methods from - // Logger base class - ///////////////////////////////////////////////////////////// - */ - - // // // Config - - // This is ok; let's just use base class functionality: - //protected void doSetLogLevel(int ll); - - /** - * Note: this method is meaningless with log4j, since it has more - * advanced output mapping and filtering mechanisms. As such, it's - * a no-op - */ - protected void doSetOutput(PrintStream str) - { - // Could also throw an Error.. but for now, let's log instead... - mPeer.warn("doSetOutput(PrintStream) called on "+getClass()+" instance, ignoring."); - } - - /** - * Note: this method is meaningless with log4j, since it has more - * advanced output mapping and filtering mechanisms. As such, it's - * a no-op - */ - protected void doSetOutput(Writer w) - { - mPeer.warn("doSetOutput(Writer) called on "+getClass()+" instance, ignoring."); - } - - // // // Logging methods - - protected void doLogInfo(String msg) - { - if (mLogLevel <= LOG_INFO_AND_ABOVE) { - mPeer.info(msg); - } - } - - protected void doLogWarning(String msg) - { - if (mLogLevel <= LOG_WARNING_AND_ABOVE) { - mPeer.warn(msg); - } - } - - protected void doLogError(String msg) - { - if (mLogLevel <= LOG_ERROR_AND_ABOVE) { - mPeer.error(msg); - } - } -} diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/ext/package.html jug-3.1.5/src/java/org/safehaus/uuid/ext/package.html --- jug-2.0.0/src/java/org/safehaus/uuid/ext/package.html 2005-08-10 03:54:46.000000000 +0000 +++ jug-3.1.5/src/java/org/safehaus/uuid/ext/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -
-Package that contains optional Jug classes; classes that either: -
-
-
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/Jug.java jug-3.1.5/src/java/org/safehaus/uuid/Jug.java
--- jug-2.0.0/src/java/org/safehaus/uuid/Jug.java 2005-08-02 05:15:32.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/Jug.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,370 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002 Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid;
-
-import java.io.*;
-import java.security.*;
-import java.util.*;
-
-/**
- * Class that implements command-line interface for accessing functionality
- * implemented by {@link UUIDGenerator}.
- */
-public class Jug
-{
- private final static HashMap mTypes = new HashMap();
- static {
- mTypes.put("time-based", "t");
- mTypes.put("random-based", "r");
- mTypes.put("name-based", "n");
- mTypes.put("tag-uri-no-timestamp", "u");
- mTypes.put("tag-uri-with-timestamp", "U");
- }
-
- private final static HashMap mOptions = new HashMap();
- static {
- mOptions.put("count", "c");
- mOptions.put("ethernet-address", "e");
- mOptions.put("help", "h");
- mOptions.put("namespace", "s");
- mOptions.put("name", "n");
- mOptions.put("performance", "p");
- mOptions.put("verbose", "v");
- }
-
- static void printUsage()
- {
- String clsName = Jug.class.getName();
- System.err.println("Usage: java "+clsName+" [options] type");
- System.err.println("Where options are:");
- System.err.println(" --count / -c
- * To keep things as light-weight as possible, we won't bother defining
- * separate interface or abstract class -- this class defines both API
- * and the default implementation. It can thus be extended to override
- * functionality to provide thigs like bridging to "real" logging systems.
- * For simple configuration (suppress all, redirect to another stream)
- * default implementation should be sufficient, however.
- *
- * Note: package
- * Default is to low only warnings and errors
- */
- protected int mLogLevel = LOG_ALL;
-
- /**
- * Output object to use, if defined; initialized to
- *
- * Note: exact functionality invoked depends on the logger instance:
- * sub-classes of this class may need to do mapping to some other
- * logging sub-system (log4j and JUL logging, for example, use their
- * own severity levels that while generally reasonably easy to map,
- * are nonetheless not one-to-one which the simple logger).
- */
- public static void setLogLevel(int level)
- {
- Logger l = sInstance;
- if (l != null) {
- l.doSetLogLevel(level);
- }
- }
-
- /**
- * Method that will re-direct output of the logger using the specified
- * {@link PrintStream}. Null is allowed, and signifies that all the
- * output should be suppressed.
- *
- * Note: exact functionality invoked depends on the logger instance.
- */
- public static void setOutput(PrintStream str)
- {
- Logger l = sInstance;
- if (l != null) {
- l.doSetOutput(str);
- }
- }
-
- /**
- * Method that will re-direct output of the logger using the specified
- * {@link Writer}. Null is allowed, and signifies that all the
- * output should be suppressed.
- */
- public static void setOutput(Writer w)
- {
- Logger l = sInstance;
- if (l != null) {
- l.doSetOutput(w);
- }
- }
-
- // // // Logging methods
-
- public static void logInfo(String msg)
- {
- Logger l = sInstance;
- if (l != null) {
- l.doLogInfo(msg);
- }
- }
-
- public static void logWarning(String msg)
- {
- Logger l = sInstance;
- if (l != null) {
- l.doLogWarning(msg);
- }
- }
-
- public static void logError(String msg)
- {
- Logger l = sInstance;
- if (l != null) {
- l.doLogError(msg);
- }
- }
-
- /*
- /////////////////////////////////////////////////////////////
- // Overridable implementation/instance methods
- /////////////////////////////////////////////////////////////
- */
-
- // // // Config
-
- protected void doSetLogLevel(int ll)
- {
- /* No need to sync for atomic value that's not used
- * for synced or critical things
- */
- mLogLevel = ll;
- }
-
- protected void doSetOutput(PrintStream str)
- {
- synchronized (this) {
- mOutput1 = str;
- mOutput2 = null;
- }
- }
-
- protected void doSetOutput(Writer w)
- {
- synchronized (this) {
- mOutput1 = null;
- mOutput2 = (w instanceof PrintWriter) ?
- (PrintWriter) w : new PrintWriter(w);
- }
- }
-
- // // // Logging methods
-
- protected void doLogInfo(String msg)
- {
- if (mLogLevel <= LOG_INFO_AND_ABOVE && isEnabled()) {
- synchronized (this) {
- doWrite("INFO: "+msg);
- }
- }
- }
-
- protected void doLogWarning(String msg)
- {
- if (mLogLevel <= LOG_WARNING_AND_ABOVE && isEnabled()) {
- synchronized (this) {
- doWrite("WARNING: "+msg);
- }
- }
- }
-
- protected void doLogError(String msg)
- {
- if (mLogLevel <= LOG_ERROR_AND_ABOVE && isEnabled()) {
- synchronized (this) {
- doWrite("ERROR: "+msg);
- }
- }
- }
-
- /*
- /////////////////////////////////////////////////////////////
- // Internal methods
- /////////////////////////////////////////////////////////////
- */
-
- protected void doWrite(String msg)
- {
- if (mOutput1 != null) {
- mOutput1.println(msg);
- } else if (mOutput2 != null) {
- mOutput2.println(msg);
- }
- }
-
- /**
- * Internal method used to quickly check if the Logger's output
- * is suppressed or not.
- *
- * Note: not synchronized since it's read-only method that's return
- * value can not be used for reliable syncing.
- */
- protected boolean isEnabled() {
- return (mOutput1 != null) || (mOutput2 != null);
- }
-}
-
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/NativeInterfaces.java jug-3.1.5/src/java/org/safehaus/uuid/NativeInterfaces.java
--- jug-2.0.0/src/java/org/safehaus/uuid/NativeInterfaces.java 2005-08-17 04:23:37.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/NativeInterfaces.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,261 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002-2004 Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Copyright (c) 2002 Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid;
-
-import java.io.*;
-import java.security.*;
-import java.util.*;
-
-/**
- * Proxy class that uses JNI-based functionality to obtain information
- * about local interfaces.
- *
- * Note that there are two different places where platform-dependant
- * native code libraries can be located under:
- *
- * The default implementation used by JUG is
- * {@link org.safehaus.uuid.ext.FileBasedTimestampSynchronizer}.
- */
-public abstract class TimestampSynchronizer
-{
- protected TimestampSynchronizer() { }
-
- /**
- * Initialization method is will be called on an instance by
- * {@link UUIDTimer} right after it's been configured with one.
- * At this point the implementation instance should have been properly
- * configured, and should be able to determine the first legal timestamp
- * value (return value). Method should also initialize any locking that
- * it does (if any), such as locking files it needs.
- *
- * Return value thus indicates the lowest initial time value that can
- * be used by the caller that can not have been used by previous
- * incarnations of the UUID generator (assuming instance was able to
- * find properly persisted data to figure that out).
- * However, caller also needs to make sure that it will
- * call {@link #update} when it actually needs the time stamp for the
- * first time,
- * since this method can not allocate timestamps beyond this initial
- * value at this point.
- *
- * @return First (and last) legal timestamp to use;
- * Caller needs to instantiate an instance of
- * {@link TimestampSynchronizer}; currently the only standard
- * implementation is
- * {@link org.safehaus.uuid.ext.FileBasedTimestampSynchronizer} (which
- * is JDK 1.4+).
- *
- * Note: since the generator instance is a singleton, calling this
- * method will always cause all generation to be synchronized using
- * the specified method.
- *
- * @param sync Synchronizer instance to use for synchronization.
- */
-
- public void synchronizeExternally(TimestampSynchronizer sync)
- throws IOException
- {
- synchronized (mTimerLock) {
- if (mTimer == null) {
- mTimer = new UUIDTimer(getRandomNumberGenerator());
- }
- mTimer.setSynchronizer(sync);
- }
- }
-
- /*
- /////////////////////////////////////////////////////
- // Configuration
- /////////////////////////////////////////////////////
- */
-
- /**
- * Method that returns a randomly generated dummy ethernet address.
- * To prevent collision with real addresses, the returned address has
- * the broadcast bit set, ie. it doesn't represent address of any existing
- * NIC.
- *
- * Note that this dummy address will be shared for the lifetime of
- * this UUIDGenerator, ie. only one is ever generated independent of
- * how many times this methods is called.
- *
- * @return Randomly generated dummy ethernet broadcast address.
- */
- public EthernetAddress getDummyAddress()
- {
- synchronized (mDummyAddressLock) {
- if (mDummyAddress == null) {
- Random rnd = getRandomNumberGenerator();
- byte[] dummy = new byte[6];
- rnd.nextBytes(dummy);
- /* Need to set the broadcast bit to indicate it's not a real
- * address.
- */
- /* 08-Feb-2004, TSa: Note: it's the least bit, not highest;
- * thanks to Ralf S. Engelschall for fix:
- */
- dummy[0] |= (byte) 0x01;
- try {
- mDummyAddress = new EthernetAddress(dummy);
- } catch (NumberFormatException nex) {
- /* Let's just let this cause a null-pointer exception
- * later on...
- */
- }
- }
- }
-
- return mDummyAddress;
- }
-
- /**
- * Method for getting the shared random number generator used for
- * generating the UUIDs. This way the initialization cost is only
- * taken once; access need not be synchronized (or in cases where
- * it has to, SecureRandom takes care of it); it might even be good
- * for getting really 'random' stuff to get shared access...
- */
- public Random getRandomNumberGenerator()
- {
- /* Could be synchronized, but since side effects are trivial
- * (ie. possibility of generating more than one SecureRandom,
- * of which all but one are dumped) let's not add synchronization
- * overhead:
- */
- if (mRnd == null) {
- mRnd = new SecureRandom();
- }
- return mRnd;
- }
-
- /**
- * Method that can be called to specify alternative random
- * number generator to use. This is usually done to use
- * implementation that is faster than
- * {@link SecureRandom} that is used by default.
- *
- * Note that to avoid first-time initialization penalty
- * of using {@link SecureRandom}, this method has to be called
- * before generating the first random-number based UUID.
- */
- public void setRandomNumberGenerator(Random r)
- {
- mRnd = r;
- }
-
- /* Method for getting the shared message digest (hash) algorithm.
- * Whether to use the shared one or not depends; using shared instance
- * adds synchronization overhead (access has to be sync'ed), but
- * using multiple separate digests wastes memory.
- */
- public MessageDigest getHashAlgorithm()
- {
- /* Similar to the shared random number generator, it's not necessary
- * to synchronize initialization. However, use of the hash instance
- * HAS to be synchronized by the caller to prevent problems with
- * multiple threads updating digest etc.
- */
- if (mHasher == null) {
- try {
- mHasher = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException nex) {
- throw new Error("Couldn't instantiate an MD5 MessageDigest instance: "+nex.toString());
- }
- }
- return mHasher;
- }
-
- /*
- /////////////////////////////////////////////////////
- // UUID generation methods
- /////////////////////////////////////////////////////
- */
-
- /**
- * Method for generating (pseudo-)random based UUIDs, using the
- * default (shared) SecureRandom object.
- *
- * Note that the first time
- * SecureRandom object is used, there is noticeable delay between
- * calling the method and getting the reply. This is because SecureRandom
- * has to initialize itself to reasonably random state. Thus, if you
- * want to lessen delay, it may be be a good idea to either get the
- * first random UUID asynchronously from a separate thread, or to
- * use the other generateRandomBasedUUID passing a previously initialized
- * SecureRandom instance.
- *
- * @return UUID generated using (pseudo-)random based method
- */
- public UUID generateRandomBasedUUID()
- {
- return generateRandomBasedUUID(getRandomNumberGenerator());
- }
-
- /**
- * Method for generating (pseudo-)random based UUIDs, using the
- * specified SecureRandom object. To prevent/avoid delay JDK's
- * default SecureRandom object causes when first random number
- * is generated, it may be a good idea to initialize the SecureRandom
- * instance (on a separate thread for example) when app starts.
- *
- * @param randomGenerator Random number generator to use for getting the
- * random number from which UUID will be composed.
- *
- * @return UUID generated using (pseudo-)random based method
- */
- public UUID generateRandomBasedUUID(Random randomGenerator)
- {
- byte[] rnd = new byte[16];
-
- randomGenerator.nextBytes(rnd);
-
- return new UUID(UUID.TYPE_RANDOM_BASED, rnd);
- }
-
- /**
- * Method for generating time based UUIDs. Note that this version
- * doesn't use any existing Hardware address (because none is available
- * for some reason); instead it uses randomly generated dummy broadcast
- * address.
- *
- * Note that since the dummy address is only to be created once and
- * shared from there on, there is some synchronization overhead.
- *
- * @return UUID generated using time based method
- */
- public UUID generateTimeBasedUUID()
- {
- return generateTimeBasedUUID(getDummyAddress());
- }
-
- /**
- * Method for generating time based UUIDs.
- *
- * @param addr Hardware address (802.1) to use for generating
- * spatially unique part of UUID. If system has more than one NIC,
- * any address is usable. If no NIC is available (or its address
- * not accessible; often the case with java apps), a randomly
- * generated broadcast address is acceptable. If so, use the
- * alternative method that takes no arguments.
- *
- * @return UUID generated using time based method
- */
- public UUID generateTimeBasedUUID(EthernetAddress addr)
- {
- byte[] contents = new byte[16];
-
- addr.toByteArray(contents, 10);
-
- synchronized (mTimerLock) {
- if (mTimer == null) {
- mTimer = new UUIDTimer(getRandomNumberGenerator());
- }
-
- mTimer.getTimestamp(contents);
- }
-
- return new UUID(UUID.TYPE_TIME_BASED, contents);
- }
-
- /**
- * Method for generating name-based UUIDs, using the standard
- * name-based generation method described in the UUID specs,
- * and the caller supplied hashing method.
- *
- * Note that this method is not synchronized, so caller has to make
- * sure the digest object will not be accessed from other threads.
- *
- * Note that if you call this method directly (instead of calling
- * the version with one less argument), you have to make sure that
- * access to 'hash' is synchronized; either by only generating UUIDs
- * from one single thread, or by using explicit sync'ing.
- *
- * @param nameSpaceUUID UUID of the namespace, as defined by the
- * spec. UUID has 4 pre-defined "standard" name space strings
- * that can be passed to UUID constructor (see example below).
- * Note that this argument is optional; if no namespace is needed
- * (for example when name includes namespace prefix), null may be
- * passed.
- * @param name Name to base the UUID on; for example,
- * IP-name ("www.w3c.org") of the system for UUID.NAMESPACE_DNS,
- * URL ("http://www.w3c.org/index.html") for UUID.NAMESPACE_URL
- * and so on.
- * @param digest Instance of MessageDigest to use for hashing the name
- * value. hash.reset() will be called before calculating the has
- * value, to make sure digest state is not random and UUID will
- * not be randomised.
- *
- * @return UUID generated using name-based method based on the
- * arguments given.
- *
- * Example:
- *
- * Of course, assuming UUIDs are randomized enough, even simpler
- * approach might be good enough?
- *
- * Is this a good hash? ... one of these days I better read more about
- * basic hashing techniques I swear!
- */
- private final static int[] kShifts = {
- 3, 7, 17, 21, 29, 4, 9
- };
-
- public int hashCode()
- {
- if (mHashCode == 0) {
- // Let's handle first and last byte separately:
- int result = mId[0] & 0xFF;
-
- result |= (result << 16);
- result |= (result << 8);
-
- for (int i = 1; i < 15; i += 2) {
- int curr = (mId[i] & 0xFF) << 8 | (mId[i+1] & 0xFF);
- int shift = kShifts[i >> 1];
-
- if (shift > 16) {
- result ^= (curr << shift) | (curr >>> (32 - shift));
- } else {
- result ^= (curr << shift);
- }
- }
-
- // and then the last byte:
- int last = mId[15] & 0xFF;
- result ^= (last << 3);
- result ^= (last << 13);
-
- result ^= (last << 27);
- // Let's not accept hash 0 as it indicates 'not hashed yet':
- if (result == 0) {
- mHashCode = -1;
- } else {
- mHashCode = result;
- }
- }
- return mHashCode;
- }
-
- public String toString()
- {
- /* Could be synchronized, but there isn't much harm in just taking
- * our chances (ie. in the worst case we'll form the string more
- * than once... but result is the same)
- */
-
- if (mDesc == null) {
- StringBuffer b = new StringBuffer(36);
-
- for (int i = 0; i < 16; ++i) {
- // Need to bypass hyphens:
- switch (i) {
- case 4:
- case 6:
- case 8:
- case 10:
- b.append('-');
- }
- int hex = mId[i] & 0xFF;
- b.append(kHexChars.charAt(hex >> 4));
- b.append(kHexChars.charAt(hex & 0x0f));
- }
- if (!sDescCaching) {
- return b.toString();
- }
- mDesc = b.toString();
- }
- return mDesc;
- }
-
- /* *** Comparison methods: *** */
-
- private final static int[] sTimeCompare = new int[] {
- INDEX_CLOCK_HI, INDEX_CLOCK_HI + 1,
- INDEX_CLOCK_MID, INDEX_CLOCK_MID + 1,
- INDEX_CLOCK_LO, INDEX_CLOCK_LO + 1,
- INDEX_CLOCK_LO + 2, INDEX_CLOCK_LO + 3,
- };
-
- /**
- * Let's also make UUIDs sortable. This will mostly/only be useful with
- * time-based UUIDs; they will sorted by time of creation. The order
- * will be strictly correct with UUIDs produced over one JVM's lifetime;
- * that is, if more than one JVMs create UUIDs and/or system is rebooted
- * the order may not be 100% accurate between UUIDs created under
- * different JVMs.
- *
- * For all UUIDs, type is first compared, and UUIDs of different types
- * are sorted together (ie. null UUID is before all other UUIDs, then
- * time-based UUIDs etc). If types are the same, time-based UUIDs'
- * time stamps (including additional clock counter) are compared, so
- * UUIDs created first are ordered first. For all other types (and for
- * time-based UUIDs with same time stamp, which should only occur
- * when comparing a UUID with itself, or with UUIDs created on
- * different JVMs or external systems) binary comparison is done
- * over all 16 bytes.
- *
- * @param o Object to compare this UUID to; should be a UUID
- *
- * @return -1 if this UUID should be ordered before the one passed,
- * 1 if after, and 0 if they are the same
- *
- * @throws ClassCastException if o is not a UUID.
- */
- public int compareTo(Object o)
- {
- UUID other = (UUID) o;
-
- int thisType = getType();
- int thatType = other.getType();
-
- /* Let's first order by type:
- */
- if (thisType > thatType) {
- return 1;
- } else if (thisType < thatType) {
- return -1;
- }
-
- /* And for time-based UUIDs let's compare time stamps first,
- * then the rest... For all other types, we'll just do straight
- * byte-by-byte comparison.
- */
- byte[] thisId = mId;
- byte[] thatId = other.mId;
- int i = 0;
- if (thisType == TYPE_TIME_BASED) {
- for (; i < 8; ++i) {
- int index = sTimeCompare[i];
- int cmp = (((int) thisId[index]) & 0xFF)
- - (((int) thatId[index]) & 0xFF);
- if (cmp != 0) {
- return cmp;
- }
- }
- // Let's fall down to full comparison otherwise
- }
-
- for (; i < 16; ++i) {
- int cmp = (((int) thisId[i]) & 0xFF) - (((int) thatId[i]) & 0xFF);
- if (cmp != 0) {
- return cmp;
- }
- }
-
- return 0;
- }
-
- /**
- * Checking equality of UUIDs is easy; just compare the 128-bit
- * number.
- */
- public boolean equals(Object o)
- {
- if (!(o instanceof UUID)) {
- return false;
- }
- byte[] otherId = ((UUID) o).mId;
- byte[] thisId = mId;
- for (int i = 0; i < 16; ++i) {
- if (otherId[i] != thisId[i]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Constructs a new UUID instance given the canonical string
- * representation of an UUID.
- *
- * Note that calling this method returns the same result as would
- * using the matching (1 string arg) constructor.
- *
- * @param id Canonical string representation used for constructing
- * an UUID instance
- *
- * @throws NumberFormatException if 'id' is invalid UUID
- */
- public static UUID valueOf(String id)
- throws NumberFormatException
- {
- return new UUID(id);
- }
-
- /**
- * Constructs a new UUID instance given a byte array that contains
- * the (16 byte) binary representation.
- *
- * Note that calling this method returns the same result as would
- * using the matching constructor
- *
- * @param src Byte array that contains the UUID definition
- * @param start Offset in the array where the UUID starts
- */
- public static UUID valueOf(byte[] src, int start)
- {
- return new UUID(src, start);
- }
-
- /**
- * Constructs a new UUID instance given a byte array that contains
- * the (16 byte) binary representation.
- *
- * Note that calling this method returns the same result as would
- * using the matching constructor
- *
- * @param src Byte array that contains the UUID definition
- */
- public static UUID valueOf(byte[] src)
- {
- return new UUID(src);
- }
-
- private void copyFrom(UUID src)
- {
- byte[] srcB = src.mId;
- byte[] dstB = mId;
-
- for (int i = 0; i < 16; ++i) {
- dstB[i] = srcB[i];
- }
-
- mDesc = sDescCaching ? src.mDesc : null;
- }
-
- public static void main(String[] args)
- {
- }
-}
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/UUIDTimer.java jug-3.1.5/src/java/org/safehaus/uuid/UUIDTimer.java
--- jug-2.0.0/src/java/org/safehaus/uuid/UUIDTimer.java 2005-08-08 05:44:49.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/UUIDTimer.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,363 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002 Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * UUIDTimer produces the time stamps required for time-based UUIDs.
- * It works as outlined in the UUID specification, with following
- * implementation:
- *
- *Some additional assumptions about calculating the timestamp:
- *
- * Note about synchronization: this class is assumed to always be called
- * from a synchronized context (caller locks on either this object, or
- * a similar timer lock), and so has no method synchronization.
- */
-public class UUIDTimer
-{
- // // // Constants
-
- /**
- * Since System.longTimeMillis() returns time from january 1st 1970,
- * and UUIDs need time from the beginning of gregorian calendar
- * (15-oct-1582), need to apply the offset:
- */
- private final static long kClockOffset = 0x01b21dd213814000L;
- /**
- * Also, instead of getting time in units of 100nsecs, we get something
- * with max resolution of 1 msec... and need the multiplier as well
- */
- private final static long kClockMultiplier = 10000;
- private final static long kClockMultiplierL = 10000L;
-
- /**
- * Let's allow "virtual" system time to advance at most 100 milliseconds
- * beyond actual physical system time, before adding delays.
- */
- private final static long kMaxClockAdvance = 100L;
-
- // // // Configuration
-
- private final Random mRnd;
-
- // // // Clock state:
-
- /**
- * Additional state information used to protect against anomalous
- * cases (clock time going backwards, node id getting mixed up).
- * Third byte is actually used for seeding counter on counter
- * overflow.
- */
- private final byte[] mClockSequence = new byte[3];
-
- /**
- * Last physical timestamp value
- * See {@link TimestampSynchronizer} for details.
- */
- private TimestampSynchronizer mSync = null;
-
- UUIDTimer(Random rnd)
- {
- mRnd = rnd;
- initCounters(rnd);
- mLastSystemTimestamp = 0L;
- // This may get overwritten by the synchronizer
- mLastUsedTimestamp = 0L;
- }
-
- private void initCounters(Random rnd)
- {
- /* Let's generate the clock sequence field now; as with counter,
- * this reduces likelihood of collisions (as explained in UUID specs)
- */
- rnd.nextBytes(mClockSequence);
- /* Ok, let's also initialize the counter...
- * Counter is used to make it slightly less likely that
- * two instances of UUIDGenerator (from separate JVMs as no more
- * than one can be created in one JVM) would produce colliding
- * time-based UUIDs. The practice of using multiple generators,
- * is strongly discouraged, of course, but just in case...
- */
- mClockCounter = mClockSequence[2] & 0xFF;
- }
-
- public void getTimestamp(byte[] uuidData)
- {
- // First the clock sequence:
- uuidData[UUID.INDEX_CLOCK_SEQUENCE] = mClockSequence[0];
- uuidData[UUID.INDEX_CLOCK_SEQUENCE+1] = mClockSequence[1];
-
- long systime = System.currentTimeMillis();
-
- /* Let's first verify that the system time is not going backwards;
- * independent of whether we can use it:
- */
- if (systime < mLastSystemTimestamp) {
- Logger.logWarning("System time going backwards! (got value "+systime+", last "+mLastSystemTimestamp);
- // Let's write it down, still
- mLastSystemTimestamp = systime;
- }
-
- /* But even without it going backwards, it may be less than the
- * last one used (when generating UUIDs fast with coarse clock
- * resolution; or if clock has gone backwards over reboot etc).
- */
- if (systime <= mLastUsedTimestamp) {
- /* Can we just use the last time stamp (ok if the counter
- * hasn't hit max yet)
- */
- if (mClockCounter < kClockMultiplier) { // yup, still have room
- systime = mLastUsedTimestamp;
- } else { // nope, have to roll over to next value and maybe wait
- long actDiff = mLastUsedTimestamp - systime;
- long origTime = systime;
- systime = mLastUsedTimestamp + 1L;
-
- Logger.logWarning("Timestamp over-run: need to reinitialize random sequence");
-
- /* Clock counter is now at exactly the multiplier; no use
- * just anding its value. So, we better get some random
- * numbers instead...
- */
- initCounters(mRnd);
-
- /* But do we also need to slow down? (to try to keep virtual
- * time close to physical time; ie. either catch up when
- * system clock has been moved backwards, or when coarse
- * clock resolution has forced us to advance virtual timer
- * too far)
- */
- if (actDiff >= kMaxClockAdvance) {
- slowDown(origTime, actDiff);
- }
- }
- } else {
- /* Clock has advanced normally; just need to make sure counter is
- * reset to a low value (need not be 0; good to leave a small
- * residual to further decrease collisions)
- */
- mClockCounter &= 0xFF;
- }
-
- mLastUsedTimestamp = systime;
-
- /* Ok, we have consistent clock (virtual or physical) value that
- * we can and should use.
- * But do we need to check external syncing now?
- */
- if (mSync != null && systime >= mFirstUnsafeTimestamp) {
- try {
- mFirstUnsafeTimestamp = mSync.update(systime);
- } catch (IOException ioe) {
- throw new RuntimeException("Failed to synchronize timestamp: "+ioe);
- }
- }
-
- /* Now, let's translate the timestamp to one UUID needs, 100ns
- * unit offset from the beginning of Gregorian calendar...
- */
- systime *= kClockMultiplierL;
- systime += kClockOffset;
-
- // Plus add the clock counter:
- systime += mClockCounter;
- // and then increase
- ++mClockCounter;
-
- /* Time fields are nicely split across the UUID, so can't just
- * linearly dump the stamp:
- */
- int clockHi = (int) (systime >>> 32);
- int clockLo = (int) systime;
-
- uuidData[UUID.INDEX_CLOCK_HI] = (byte) (clockHi >>> 24);
- uuidData[UUID.INDEX_CLOCK_HI+1] = (byte) (clockHi >>> 16);
- uuidData[UUID.INDEX_CLOCK_MID] = (byte) (clockHi >>> 8);
- uuidData[UUID.INDEX_CLOCK_MID+1] = (byte) clockHi;
-
- uuidData[UUID.INDEX_CLOCK_LO] = (byte) (clockLo >>> 24);
- uuidData[UUID.INDEX_CLOCK_LO+1] = (byte) (clockLo >>> 16);
- uuidData[UUID.INDEX_CLOCK_LO+2] = (byte) (clockLo >>> 8);
- uuidData[UUID.INDEX_CLOCK_LO+3] = (byte) clockLo;
- }
-
- public void setSynchronizer(TimestampSynchronizer sync)
- throws IOException
- {
- TimestampSynchronizer old = mSync;
-
- if (old != null) {
- try {
- old.deactivate();
- } catch (IOException ioe) {
- Logger.logError("Failed to deactivate the old synchronizer: "+ioe);
- }
- }
-
- mSync = sync;
-
- /* Ok, now; synchronizer can tell us what is the first timestamp
- * value that definitely was NOT used by the previous incarnation.
- * This can serve as the last used time stamp, assuming it is not
- * less than value we are using now.
- */
- if (sync != null) {
- long lastSaved = sync.initialize();
- if (lastSaved > mLastUsedTimestamp) {
- mLastUsedTimestamp = lastSaved;
- }
- }
-
- /* Also, we need to make sure there are now no safe values (since
- * synchronizer is not yet requested to allocate any):
- */
- mFirstUnsafeTimestamp = 0L; // ie. will always trigger sync.update()
- }
-
- /*
- ///////////////////////////////////////////////////////////
- // Private methods
- ///////////////////////////////////////////////////////////
- */
-
- private final static int MAX_WAIT_COUNT = 50;
-
- /**
- * Simple utility method to use to wait for couple of milliseconds,
- * to let system clock hopefully advance closer to the virtual
- * timestamps used. Delay is kept to just a millisecond or two,
- * to prevent excessive blocking; but that should be enough to
- * eventually synchronize physical clock with virtual clock values
- * used for UUIDs.
- *
- * @param msecs Number of milliseconds to wait for from current
- * time point
- */
- private final static void slowDown(long startTime, long actDiff)
- {
- /* First, let's determine how long we'd like to wait.
- * This is based on how far ahead are we as of now.
- */
- long ratio = actDiff / kMaxClockAdvance;
- long delay;
-
- if (ratio < 2L) { // 200 msecs or less
- delay = 1L;
- } else if (ratio < 10L) { // 1 second or less
- delay = 2L;
- } else if (ratio < 600L) { // 1 minute or less
- delay = 3L;
- } else {
- delay = 5L;
- }
- Logger.logWarning("Need to wait for "+delay+" milliseconds; virtual clock advanced too far in the future");
- long waitUntil = startTime + delay;
- int counter = 0;
- do {
- try {
- Thread.sleep(delay);
- } catch (InterruptedException ie) { }
- delay = 1L;
- /* This is just a sanity check: don't want an "infinite"
- * loop if clock happened to be moved backwards by, say,
- * an hour...
- */
- if (++counter > MAX_WAIT_COUNT) {
- break;
- }
- } while (System.currentTimeMillis() < waitUntil);
- }
-}
diff -Nru jug-2.0.0/src/java/test/FileSyncTest.java jug-3.1.5/src/java/test/FileSyncTest.java
--- jug-2.0.0/src/java/test/FileSyncTest.java 2005-08-09 05:29:47.000000000 +0000
+++ jug-3.1.5/src/java/test/FileSyncTest.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,42 +0,0 @@
-package test;
-
-import org.safehaus.uuid.*;
-import org.safehaus.uuid.ext.*;
-
-/**
- * Simple manual utility test class for manually checking whether file-based
- * synchronization seems to be working or not.
- */
-public class FileSyncTest
-{
- public static void main(String[] args)
- throws Exception
- {
- UUIDGenerator gen = UUIDGenerator.getInstance();
- FileBasedTimestampSynchronizer sync =
- new FileBasedTimestampSynchronizer();
- // Let's stress-test it...
- sync.setUpdateInterval(2000L);
- gen.synchronizeExternally(sync);
-
- int counter = 1;
- while (true) {
- UUID uuid = gen.generateTimeBasedUUID();
- // Default one is for convenient output
- System.out.println("#"+counter+" -> "+uuid);
-
- /* This allows lexical sorting by uuid... (not very useful,
- * since 'real' UUID ordering is not lexical)
- */
- //System.out.println(""+uuid+" (#"+counter+")");
-
- // And this can be used to ensure there are no dups:
- //System.out.println(""+uuid);
- ++counter;
-
- try {
- Thread.sleep(120L);
- } catch (InterruptedException ie) { }
- }
- }
-}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/EthernetAddress.java jug-3.1.5/src/main/java/com/fasterxml/uuid/EthernetAddress.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/EthernetAddress.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/EthernetAddress.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,497 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002 Tatu Saloranta, tatu.saloranta@iki.fi
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid;
+
+import java.io.Serializable;
+import java.net.NetworkInterface;
+import java.security.SecureRandom;
+import java.util.Enumeration;
+import java.util.Random;
+
+/**
+ * EthernetAddress encapsulates the 6-byte MAC address defined in
+ * IEEE 802.1 standard.
+ */
+public class EthernetAddress
+ implements Serializable, Cloneable, Comparable
+ * Internally a {@link SecureRandom} instance is used for generating
+ * random number to base address on.
+ */
+ public static EthernetAddress constructMulticastAddress()
+ {
+ return constructMulticastAddress(_randomNumberGenerator());
+ }
+
+ /**
+ * Factory method that can be used to construct a random multicast
+ * address; to be used in cases where there is no "real" ethernet
+ * address to use. Address to generate should be a multicase address
+ * to avoid accidental collision with real manufacturer-assigned
+ * MAC addresses.
+ *
+ * Address is created using specified random number generator.
+ */
+ public static EthernetAddress constructMulticastAddress(Random rnd)
+ {
+ byte[] dummy = new byte[6];
+ synchronized (rnd) {
+ rnd.nextBytes(dummy);
+ }
+ /* Need to set the broadcast bit to indicate it's not a real
+ * address.
+ */
+ /* 20-May-2010, tatu: Actually, we could use both second least-sig-bit
+ * ("locally administered") or the LSB (multicast), as neither is
+ * ever set for 'real' addresses.
+ * Since UUID specs recommends latter, use that.
+ */
+ dummy[0] |= (byte) 0x01;
+ return new EthernetAddress(dummy);
+ }
+
+ /*
+ /**********************************************************************
+ /* Conversions to raw types
+ /**********************************************************************
+ */
+
+ /**
+ * Returns 6 byte byte array that contains the binary representation
+ * of this ethernet address; byte 0 is the most significant byte
+ * (and so forth)
+ *
+ * @return 6 byte byte array that contains the binary representation
+ */
+ public byte[] asByteArray()
+ {
+ byte[] result = new byte[6];
+ toByteArray(result);
+ return result;
+ }
+
+ /**
+ * Synonym to 'asByteArray()'
+ *
+ * @return 6 byte byte array that contains the binary representation
+ */
+ public byte[] toByteArray() { return asByteArray(); }
+
+ public void toByteArray(byte[] array) {
+ if (array.length < 6) {
+ throw new IllegalArgumentException("Too small array, need to have space for 6 bytes");
+ }
+ toByteArray(array, 0);
+ }
+
+ public void toByteArray(byte[] array, int pos)
+ {
+ if (pos < 0 || (pos + 6) > array.length) {
+ throw new IllegalArgumentException("Illegal offset ("+pos+"), need room for 6 bytes");
+ }
+ int i = (int) (_address >> 32);
+ array[pos++] = (byte) (i >> 8);
+ array[pos++] = (byte) i;
+ i = (int) _address;
+ array[pos++] = (byte) (i >> 24);
+ array[pos++] = (byte) (i >> 16);
+ array[pos++] = (byte) (i >> 8);
+ array[pos] = (byte) i;
+ }
+
+ public long toLong() {
+ return _address;
+ }
+
+ /*
+ /**********************************************************************
+ /* Accessors
+ /**********************************************************************
+ */
+
+ /**
+ * Method that can be used to check if this address refers
+ * to a multicast address.
+ * Such addresses are never assigned to individual network
+ * cards.
+ */
+ public boolean isMulticastAddress() {
+ return (((int) (_address >> 40)) & 0x01) != 0;
+ }
+
+ /**
+ * Method that can be used to check if this address refers
+ * to a "locally administered address"
+ * (see [http://en.wikipedia.org/wiki/MAC_address] for details).
+ * Such addresses are not assigned to individual network
+ * cards.
+ */
+ public boolean isLocallyAdministeredAddress() {
+ return (((int) (_address >> 40)) & 0x02) != 0;
+ }
+
+ /*
+ /**********************************************************************
+ /* Standard methods
+ /**********************************************************************
+ */
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o == this) return true;
+ if (o == null) return false;
+ if (o.getClass() != getClass()) return false;
+ return ((EthernetAddress) o)._address == _address;
+ }
+
+ /**
+ * Method that compares this EthernetAddress to one passed in as
+ * argument. Comparison is done simply by comparing individual
+ * address bytes in the order.
+ *
+ * @return negative number if this EthernetAddress should be sorted before the
+ * parameter address if they are equal, os positive non-zero number if this address
+ * should be sorted after parameter
+ */
+ public int compareTo(EthernetAddress other)
+ {
+ long l = _address - other._address;
+ if (l < 0L) return -1;
+ return (l == 0L) ? 0 : 1;
+ }
+
+ /**
+ * Returns the canonical string representation of this ethernet address.
+ * Canonical means that all characters are lower-case and string length
+ * is always 17 characters (ie. leading zeroes are not omitted).
+ *
+ * @return Canonical string representation of this ethernet address.
+ */
+ @Override
+ public String toString()
+ {
+ String str = _asString;
+ if (str != null) {
+ return str;
+ }
+
+ /* Let's not cache the output here (unlike with UUID), assuming
+ * this won't be called as often:
+ */
+ StringBuilder b = new StringBuilder(17);
+ int i1 = (int) (_address >> 32);
+ int i2 = (int) _address;
+
+ _appendHex(b, i1 >> 8);
+ b.append(':');
+ _appendHex(b, i1);
+ b.append(':');
+ _appendHex(b, i2 >> 24);
+ b.append(':');
+ _appendHex(b, i2 >> 16);
+ b.append(':');
+ _appendHex(b, i2 >> 8);
+ b.append(':');
+ _appendHex(b, i2);
+ _asString = str = b.toString();
+ return str;
+ }
+
+ /*
+ /**********************************************************************
+ /* Internal methods
+ /**********************************************************************
+ */
+
+ /**
+ * Helper method for accessing configured random number generator
+ */
+ protected synchronized static Random _randomNumberGenerator()
+ {
+ if (_rnd == null) {
+ _rnd = new SecureRandom();
+ }
+ return _rnd;
+ }
+
+ private final void _appendHex(StringBuilder sb, int hex)
+ {
+ sb.append(HEX_CHARS[(hex >> 4) & 0xF]);
+ sb.append(HEX_CHARS[(hex & 0x0f)]);
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/FileBasedTimestampSynchronizer.java jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/FileBasedTimestampSynchronizer.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/FileBasedTimestampSynchronizer.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/FileBasedTimestampSynchronizer.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,230 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid.ext;
+
+import com.fasterxml.uuid.Logger;
+import com.fasterxml.uuid.TimestampSynchronizer;
+
+import java.io.*;
+
+/**
+ * Implementation of {@link TimestampSynchronizer}, which uses file system
+ * as the storage and locking mechanism.
+ *
+ * Synchronization is achieved by obtaining an exclusive file locks on two
+ * specified lock files, and by using the files to store first "safe" timestamp
+ * value that the generator can use; alternating between one to use to ensure
+ * one of them always contains a valid timestamp. Latter is needed to guard
+ * against system clock moving backwards after UUID generator restart.
+ *
+ * Note: this class will only work on JDK 1.4 and above, since it requires
+ * NIO package to do proper file locking (as well as new opening mode for
+ * {@link RandomAccessFile}).
+ *
+ * Also note that it is assumed that the caller has taken care to synchronize
+ * access to method to be single-threaded. As such, none of the methods
+ * is explicitly synchronized here.
+ */
+public final class FileBasedTimestampSynchronizer
+ extends TimestampSynchronizer
+{
+ // // // Constants:
+
+ /**
+ * The default update interval is 10 seconds, meaning that the
+ * synchronizer "reserves" next 10 seconds for generation. This
+ * also means that the lock files need to be accessed at most
+ * once every ten second.
+ */
+ final static long DEFAULT_UPDATE_INTERVAL = 10L * 1000L;
+
+ protected final static String DEFAULT_LOCK_FILE_NAME1 = "uuid1.lck";
+
+ protected final static String DEFAULT_LOCK_FILE_NAME2 = "uuid2.lck";
+
+ // // // Configuration:
+
+ protected long mInterval = DEFAULT_UPDATE_INTERVAL;
+
+ protected final LockedFile mLocked1, mLocked2;
+
+ // // // State:
+
+ /**
+ * Flag used to indicate which of timestamp files has the most
+ * recently succesfully updated timestamp value. True means that
+ *
+ * Note: using this class requires JDK 1.4 or above.
+ */
+public class JavaUtilLogger
+ extends com.fasterxml.uuid.Logger
+{
+ private java.util.logging.Logger mPeer;
+
+ private JavaUtilLogger(java.util.logging.Logger peer)
+ {
+ mPeer = peer;
+ }
+
+ /**
+ * Static method to call to make JUG use to proxy all of its logging
+ * through the specified j.u.l
+ * Method will create a simple wrapper, and call
+ * {@link com.fasterxml.uuid.Logger#setLogger} with the wrapper as
+ * the argument. This will then re-direct logging from the previously
+ * defined Logger (which initially is the simple JUG logger) to the
+ * new wrapper, which routes logging messages to the log4j peer Logger
+ * instance.
+ */
+ public static void connectToJavaUtilLogging(java.util.logging.Logger peer)
+ {
+ JavaUtilLogger logger = new JavaUtilLogger(peer);
+ // This is static method of the base class...
+ setLogger(logger);
+ }
+
+ /**
+ * Static method to call to make JUG use a log4j proxy all of its logging
+ * through a j.u.l
+ * Method will create a simple wrapper, and call
+ * {@link com.fasterxml.uuid.Logger#setLogger} with the wrapper as
+ * the argument. This will then re-direct logging from the previously
+ * defined Logger (which initially is the simple JUG logger) to the
+ * new wrapper, which routes logging messages to the j.u.l peer Logger
+ * instance.
+ */
+ public static void connectToJavaUtilLogging()
+ {
+ connectToJavaUtilLogging(java.util.logging.Logger.getLogger(com.fasterxml.uuid.Logger.class.getName()));
+ }
+
+ /*
+ /////////////////////////////////////////////////////////////
+ // Overridable implementation/instance methods from
+ // Logger base class
+ /////////////////////////////////////////////////////////////
+ */
+
+ // // // Config
+
+ // This is ok; let's just use base class functionality:
+ //protected void doSetLogLevel(int ll);
+
+ /**
+ * Note: this method is meaningless with log4j, since it has more
+ * advanced output mapping and filtering mechanisms. As such, it's
+ * a no-op
+ */
+ protected void doSetOutput(PrintStream str)
+ {
+ // Could also throw an Error.. but for now, let's log instead...
+ mPeer.warning("doSetOutput(PrintStream) called on "+getClass()+" instance, ignoring.");
+ }
+
+ /**
+ * Note: this method is meaningless with log4j, since it has more
+ * advanced output mapping and filtering mechanisms. As such, it's
+ * a no-op
+ */
+ protected void doSetOutput(Writer w)
+ {
+ mPeer.warning("doSetOutput(Writer) called on "+getClass()+" instance, ignoring.");
+ }
+
+ // // // Logging methods
+
+ protected void doLogInfo(String msg)
+ {
+ if (_logLevel <= LOG_INFO_AND_ABOVE) {
+ mPeer.info(msg);
+ }
+ }
+
+ protected void doLogWarning(String msg)
+ {
+ if (_logLevel <= LOG_WARNING_AND_ABOVE) {
+ mPeer.warning(msg);
+ }
+ }
+
+ protected void doLogError(String msg)
+ {
+ /* Hmmh. JUL doesn't have error... and SEVERE is bit drastic. But,
+ * well, let's use that for ERRORs for now.
+ */
+ if (_logLevel <= LOG_ERROR_AND_ABOVE) {
+ mPeer.severe(msg);
+ }
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/LockedFile.java jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/LockedFile.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/LockedFile.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/LockedFile.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,292 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid.ext;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import com.fasterxml.uuid.Logger;
+
+/**
+ * Utility class used by {@link FileBasedTimestampSynchronizer} to do
+ * actual file access and locking.
+ *
+ * Class stores simple timestamp values based on system time accessed
+ * using
+ * Note: using this class implies all the dependencies that the log4j
+ * subsystem in use requires (JDK 1.2 or above, in general)
+ */
+public class Log4jLogger
+ extends com.fasterxml.uuid.Logger
+{
+ private org.apache.log4j.Logger mPeer;
+
+ private Log4jLogger(org.apache.log4j.Logger peer)
+ {
+ mPeer = peer;
+ }
+
+ /**
+ * Static method to call to make JUG use to proxy all of its logging
+ * through the specified log4j
+ * Method will create a simple wrapper, and call
+ * {@link com.fasterxml.uuid.Logger#setLogger} with the wrapper as
+ * the argument. This will then re-direct logging from the previously
+ * defined Logger (which initially is the simple JUG logger) to the
+ * new wrapper, which routes logging messages to the log4j peer Logger
+ * instance.
+ */
+ public static void connectToLog4j(org.apache.log4j.Logger peer)
+ {
+ Log4jLogger logger = new Log4jLogger(peer);
+ // This is static method of the base class...
+ setLogger(logger);
+ }
+
+ /**
+ * Static method to call to make JUG use a log4j proxy all of its logging
+ * through a log4j
+ * Method will create a simple wrapper, and call
+ * {@link com.fasterxml.uuid.Logger#setLogger} with the wrapper as
+ * the argument. This will then re-direct logging from the previously
+ * defined Logger (which initially is the simple JUG logger) to the
+ * new wrapper, which routes logging messages to the log4j peer Logger
+ * instance.
+ */
+ public static void connectToLog4j()
+ {
+ connectToLog4j(org.apache.log4j.Logger.getLogger(com.fasterxml.uuid.Logger.class));
+ }
+
+ /*
+ /////////////////////////////////////////////////////////////
+ // Overridable implementation/instance methods from
+ // Logger base class
+ /////////////////////////////////////////////////////////////
+ */
+
+ // // // Config
+
+ // This is ok; let's just use base class functionality:
+ //protected void doSetLogLevel(int ll);
+
+ /**
+ * Note: this method is meaningless with log4j, since it has more
+ * advanced output mapping and filtering mechanisms. As such, it's
+ * a no-op
+ */
+ protected void doSetOutput(PrintStream str)
+ {
+ // Could also throw an Error.. but for now, let's log instead...
+ mPeer.warn("doSetOutput(PrintStream) called on "+getClass()+" instance, ignoring.");
+ }
+
+ /**
+ * Note: this method is meaningless with log4j, since it has more
+ * advanced output mapping and filtering mechanisms. As such, it's
+ * a no-op
+ */
+ protected void doSetOutput(Writer w)
+ {
+ mPeer.warn("doSetOutput(Writer) called on "+getClass()+" instance, ignoring.");
+ }
+
+ // // // Logging methods
+
+ protected void doLogInfo(String msg)
+ {
+ if (_logLevel <= LOG_INFO_AND_ABOVE) {
+ mPeer.info(msg);
+ }
+ }
+
+ protected void doLogWarning(String msg)
+ {
+ if (_logLevel <= LOG_WARNING_AND_ABOVE) {
+ mPeer.warn(msg);
+ }
+ }
+
+ protected void doLogError(String msg)
+ {
+ if (_logLevel <= LOG_ERROR_AND_ABOVE) {
+ mPeer.error(msg);
+ }
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/package.html jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/package.html
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/package.html 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/package.html 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,11 @@
+
+Otherwise base JDK version requirement for these classes is 1.4.
+
+ * As all JUG provided implementations, this generator is fully thread-safe; access
+ * to digester is synchronized as necessary.
+ *
+ * @since 3.0
+ */
+public class NameBasedGenerator extends StringArgGenerator
+{
+ public final static Charset _utf8;
+ static {
+ _utf8 = Charset.forName("UTF-8");
+ }
+
+ /**
+ * Namespace used when name is a DNS name.
+ */
+ public final static UUID NAMESPACE_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
+
+ /**
+ * Namespace used when name is a URL.
+ */
+ public final static UUID NAMESPACE_URL = UUID.fromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8");
+ /**
+ * Namespace used when name is an OID.
+ */
+ public final static UUID NAMESPACE_OID = UUID.fromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
+ /**
+ * Namespace used when name is an X500 identifier
+ */
+ public final static UUID NAMESPACE_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8");
+
+ /*
+ /**********************************************************************
+ /* Configuration
+ /**********************************************************************
+ */
+
+ /**
+ * Namespace to use as prefix.
+ */
+ protected final UUID _namespace;
+
+ /**
+ * Message digesster to use for hash calculation
+ */
+ protected final MessageDigest _digester;
+
+ protected final UUIDType _type;
+
+ /*
+ /**********************************************************************
+ /* Construction
+ /**********************************************************************
+ */
+
+ /**
+ * @param namespace of the namespace, as defined by the
+ * spec. UUID has 4 pre-defined "standard" name space strings
+ * that can be passed to UUID constructor (see example below).
+ * Note that this argument is optional; if no namespace is needed
+ * (for example when name includes namespace prefix), null may be passed.
+ * @param digester Hashing algorithm to use.
+
+ */
+ public NameBasedGenerator(UUID namespace, MessageDigest digester, UUIDType type)
+ {
+ _namespace = namespace;
+ // And default digester SHA-1
+ if (digester == null) {
+
+ }
+ if (type == null) {
+ String typeStr = digester.getAlgorithm();
+ if (typeStr.startsWith("MD5")) {
+ type = UUIDType.NAME_BASED_MD5;
+ } else if (typeStr.startsWith("SHA")) {
+ type = UUIDType.NAME_BASED_SHA1;
+ } else {
+ // Hmmh... error out? Let's default to SHA-1, but log a warning
+ type = UUIDType.NAME_BASED_SHA1;
+ Logger.logWarning("Could not determine type of Digester from '"+typeStr+"'; assuming 'SHA-1' type");
+ }
+ }
+ _digester = digester;
+ _type = type;
+ }
+
+ /*
+ /**********************************************************************
+ /* Access to config
+ /**********************************************************************
+ */
+
+ @Override
+ public UUIDType getType() { return _type; }
+
+ public UUID getNamespace() { return _namespace; }
+
+ /*
+ /**********************************************************************
+ /* UUID generation
+ /**********************************************************************
+ */
+
+ @Override
+ public UUID generate(String name)
+ {
+ // !!! TODO: 14-Oct-2010, tatu: can repurpose faster UTF-8 encoding from Jackson
+ return generate(name.getBytes(_utf8));
+ }
+
+ @Override
+ public UUID generate(byte[] nameBytes)
+ {
+ byte[] digest;
+ synchronized (_digester) {
+ _digester.reset();
+ if (_namespace != null) {
+ _digester.update(UUIDUtil.asByteArray(_namespace));
+ }
+ _digester.update(nameBytes);
+ digest = _digester.digest();
+ }
+ return UUIDUtil.constructUUID(_type, digest);
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/impl/RandomBasedGenerator.java jug-3.1.5/src/main/java/com/fasterxml/uuid/impl/RandomBasedGenerator.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/impl/RandomBasedGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/impl/RandomBasedGenerator.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,137 @@
+package com.fasterxml.uuid.impl;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.UUID;
+
+import com.fasterxml.uuid.NoArgGenerator;
+import com.fasterxml.uuid.UUIDType;
+
+/**
+ * Implementation of UUID generator that uses generation method 4.
+ *
+ * Note on random number generation when using {@link SecureRandom} for random number
+ * generation: the first time {@link SecureRandom} object is used, there is noticeable delay between
+ * calling the method and getting the reply. This is because SecureRandom
+ * has to initialize itself to reasonably random state. Thus, if you
+ * want to lessen delay, it may be be a good idea to either get the
+ * first random UUID asynchronously from a separate thread, or to
+ * use the other generateRandomBasedUUID passing a previously initialized
+ * SecureRandom instance.
+ *
+ * @since 3.0
+ */
+public class RandomBasedGenerator extends NoArgGenerator
+{
+ /**
+ * Default shared random number generator, used if no random number generator
+ * is explicitly specified for instance
+ */
+ protected static Random _sharedRandom = null;
+
+ /**
+ * Random number generator that this generator uses.
+ */
+ protected final Random _random;
+
+ /**
+ * Looks like {@link SecureRandom} implementation is more efficient
+ * using single call access (compared to basic {@link java.util.Random}),
+ * so let's use that knowledge to our benefit.
+ */
+ protected final boolean _secureRandom;
+
+ /**
+ * @param rnd Random number generator to use for generating UUIDs; if null,
+ * shared default generator is used. Note that it is strongly recommend to
+ * use a good (pseudo) random number generator; for example, JDK's
+ * {@link SecureRandom}.
+ */
+ public RandomBasedGenerator(Random rnd)
+ {
+ if (rnd == null) {
+ rnd = LazyRandom.sharedSecureRandom();
+ _secureRandom = true;
+ } else {
+ _secureRandom = (rnd instanceof SecureRandom);
+ }
+ _random = rnd;
+ }
+
+ /*
+ /**********************************************************************
+ /* Access to config
+ /**********************************************************************
+ */
+
+ @Override
+ public UUIDType getType() { return UUIDType.RANDOM_BASED; }
+
+ /*
+ /**********************************************************************
+ /* UUID generation
+ /**********************************************************************
+ */
+
+ @Override
+ public UUID generate()
+ {
+ /* 14-Oct-2010, tatu: Surprisingly, variant for reading byte array is
+ * tad faster for SecureRandom... so let's use that then
+ */
+ long r1, r2;
+
+ if (_secureRandom) {
+ final byte[] buffer = new byte[16];
+ _random.nextBytes(buffer);
+ r1 = _toLong(buffer, 0);
+ r2 = _toLong(buffer, 1);
+ } else {
+ r1 = _random.nextLong();
+ r2 = _random.nextLong();
+ }
+ return UUIDUtil.constructUUID(UUIDType.RANDOM_BASED, r1, r2);
+ }
+
+ /*
+ /**********************************************************************
+ /* Internal methods
+ /**********************************************************************
+ */
+
+ private final static long _toLong(byte[] buffer, int offset)
+ {
+ long l1 = _toInt(buffer, offset);
+ long l2 = _toInt(buffer, offset+4);
+ long l = (l1 << 32) + ((l2 << 32) >>> 32);
+ return l;
+ }
+
+ private final static long _toInt(byte[] buffer, int offset)
+ {
+ return (buffer[offset] << 24)
+ + ((buffer[++offset] & 0xFF) << 16)
+ + ((buffer[++offset] & 0xFF) << 8)
+ + (buffer[++offset] & 0xFF);
+ }
+
+ /*
+ /**********************************************************************
+ /* Helper classes
+ /**********************************************************************
+ */
+
+ /**
+ * Trivial helper class that uses class loading as synchronization
+ * mechanism for lazy instantation of the shared secure random
+ * instance.
+ */
+ private final static class LazyRandom
+ {
+ private final static SecureRandom shared = new SecureRandom();
+
+ public static SecureRandom sharedSecureRandom() {
+ return shared;
+ }
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/impl/TimeBasedGenerator.java jug-3.1.5/src/main/java/com/fasterxml/uuid/impl/TimeBasedGenerator.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/impl/TimeBasedGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/impl/TimeBasedGenerator.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,112 @@
+package com.fasterxml.uuid.impl;
+
+import java.util.UUID;
+
+import com.fasterxml.uuid.*;
+
+/**
+ * Implementation of UUID generator that uses time/location based generation
+ * method (variant 1).
+ *
+ * As all JUG provided implementations, this generator is fully thread-safe.
+ * Additionally it can also be made externally synchronized with other
+ * instances (even ones running on other JVMs); to do this,
+ * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
+ * (or equivalent).
+ *
+ * @since 3.0
+ */
+public class TimeBasedGenerator extends NoArgGenerator
+{
+ /*
+ /**********************************************************************
+ /* Configuration
+ /**********************************************************************
+ */
+
+ protected final EthernetAddress _ethernetAddress;
+
+ /**
+ * Object used for synchronizing access to timestamps, to guarantee
+ * that timestamps produced by this generator are unique and monotonically increasings.
+ * Some implementations offer even stronger guarantees, for example that
+ * same guarantee holds between instances running on different JVMs (or
+ * with native code).
+ */
+ protected final UUIDTimer _timer;
+
+ /**
+ * Base values for the second long (last 8 bytes) of UUID to construct
+ */
+ protected final long _uuidL2;
+
+ /*
+ /**********************************************************************
+ /* Construction
+ /**********************************************************************
+ */
+
+ /**
+ * @param ethAddr Hardware address (802.1) to use for generating
+ * spatially unique part of UUID. If system has more than one NIC,
+ */
+
+ public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
+ {
+ byte[] uuidBytes = new byte[16];
+ if (ethAddr == null) {
+ ethAddr = EthernetAddress.constructMulticastAddress();
+ }
+ // initialize baseline with MAC address info
+ _ethernetAddress = ethAddr;
+ _ethernetAddress.toByteArray(uuidBytes, 10);
+ // and add clock sequence
+ int clockSeq = timer.getClockSequence();
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
+ long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
+ _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
+ _timer = timer;
+ }
+
+ /*
+ /**********************************************************************
+ /* Access to config
+ /**********************************************************************
+ */
+
+ @Override
+ public UUIDType getType() { return UUIDType.TIME_BASED; }
+
+ public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
+
+ /*
+ /**********************************************************************
+ /* UUID generation
+ /**********************************************************************
+ */
+
+ /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
+ * importantly, synchronize on timer which may also be shared between
+ * multiple instances
+ */
+ @Override
+ public UUID generate()
+ {
+ final long rawTimestamp = _timer.getTimestamp();
+ // Time field components are kind of shuffled, need to slice:
+ int clockHi = (int) (rawTimestamp >>> 32);
+ int clockLo = (int) rawTimestamp;
+ // and dice
+ int midhi = (clockHi << 16) | (clockHi >>> 16);
+ // need to squeeze in type (4 MSBs in byte 6, clock hi)
+ midhi &= ~0xF000; // remove high nibble of 6th byte
+ midhi |= 0x1000; // type 1
+ long midhiL = (long) midhi;
+ midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
+ // and reconstruct
+ long l1 = (((long) clockLo) << 32) | midhiL;
+ // last detail: must force 2 MSB to be '10'
+ return new UUID(l1, _uuidL2);
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/impl/UUIDUtil.java jug-3.1.5/src/main/java/com/fasterxml/uuid/impl/UUIDUtil.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/impl/UUIDUtil.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/impl/UUIDUtil.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,308 @@
+package com.fasterxml.uuid.impl;
+
+import java.util.UUID;
+
+import com.fasterxml.uuid.UUIDType;
+
+public class UUIDUtil
+{
+ public final static int BYTE_OFFSET_CLOCK_LO = 0;
+ public final static int BYTE_OFFSET_CLOCK_MID = 4;
+ public final static int BYTE_OFFSET_CLOCK_HI = 6;
+
+ // note: clock-hi and type occupy same byte (different bits)
+ public final static int BYTE_OFFSET_TYPE = 6;
+
+ // similarly, clock sequence and variant are multiplexed
+ public final static int BYTE_OFFSET_CLOCK_SEQUENCE = 8;
+ public final static int BYTE_OFFSET_VARIATION = 8;
+
+ /*
+ /**********************************************************************
+ /* Construction (can instantiate, although usually not necessary)
+ /**********************************************************************
+ */
+
+ // note: left public just for convenience; all functionality available
+ // via static methods
+ public UUIDUtil() { }
+
+ /*
+ /**********************************************************************
+ /* Factory methods
+ /**********************************************************************
+ */
+
+ /**
+ * Factory method for creating UUIDs from the canonical string
+ * representation.
+ *
+ * @param id String that contains the canonical representation of
+ * the UUID to build; 36-char string (see UUID specs for details).
+ * Hex-chars may be in upper-case too; UUID class will always output
+ * them in lowercase.
+ */
+ public static UUID uuid(String id)
+ {
+ if (id == null) {
+ throw new NullPointerException();
+ }
+ if (id.length() != 36) {
+ throw new NumberFormatException("UUID has to be represented by the standard 36-char representation");
+ }
+
+ long lo, hi;
+ lo = hi = 0;
+
+ for (int i = 0, j = 0; i < 36; ++j) {
+
+ // Need to bypass hyphens:
+ switch (i) {
+ case 8:
+ case 13:
+ case 18:
+ case 23:
+ if (id.charAt(i) != '-') {
+ throw new NumberFormatException("UUID has to be represented by the standard 36-char representation");
+ }
+ ++i;
+ }
+ int curr;
+ char c = id.charAt(i);
+
+ if (c >= '0' && c <= '9') {
+ curr = (c - '0');
+ } else if (c >= 'a' && c <= 'f') {
+ curr = (c - 'a' + 10);
+ } else if (c >= 'A' && c <= 'F') {
+ curr = (c - 'A' + 10);
+ } else {
+ throw new NumberFormatException("Non-hex character at #"+i+": '"+c
+ +"' (value 0x"+Integer.toHexString(c)+")");
+ }
+ curr = (curr << 4);
+
+ c = id.charAt(++i);
+
+ if (c >= '0' && c <= '9') {
+ curr |= (c - '0');
+ } else if (c >= 'a' && c <= 'f') {
+ curr |= (c - 'a' + 10);
+ } else if (c >= 'A' && c <= 'F') {
+ curr |= (c - 'A' + 10);
+ } else {
+ throw new NumberFormatException("Non-hex character at #"+i+": '"+c
+ +"' (value 0x"+Integer.toHexString(c)+")");
+ }
+ if (j < 8) {
+ hi = (hi << 8) | curr;
+ } else {
+ lo = (lo << 8) | curr;
+ }
+ ++i;
+ }
+ return new UUID(hi, lo);
+ }
+
+ /**
+ * Factory method for constructing {@link java.util.UUID} instance from given
+ * 16 bytes.
+ * NOTE: since absolutely no validation is done for contents, this method should
+ * only be used if contents are known to be valid.
+ */
+ public static UUID uuid(byte[] bytes)
+ {
+ _checkUUIDByteArray(bytes, 0);
+ long l1 = gatherLong(bytes, 0);
+ long l2 = gatherLong(bytes, 8);
+ return new UUID(l1, l2);
+ }
+
+ /**
+ * Factory method for constructing {@link java.util.UUID} instance from given
+ * 16 bytes.
+ * NOTE: since absolutely no validation is done for contents, this method should
+ * only be used if contents are known to be valid.
+ *
+ * @param bytes Array that contains sequence of 16 bytes that contain a valid UUID
+ * @param offset Offset of the first of 16 bytes
+ */
+ public static UUID uuid(byte[] bytes, int offset)
+ {
+ _checkUUIDByteArray(bytes, offset);
+ return new UUID(gatherLong(bytes, offset), gatherLong(bytes, offset+8));
+ }
+
+ /**
+ * Helper method for constructing UUID instances with appropriate type
+ */
+ public static UUID constructUUID(UUIDType type, byte[] uuidBytes)
+ {
+ // first, ensure type is ok
+ int b = uuidBytes[BYTE_OFFSET_TYPE] & 0xF; // clear out high nibble
+ b |= type.raw() << 4;
+ uuidBytes[BYTE_OFFSET_TYPE] = (byte) b;
+ // second, ensure variant is properly set too
+ b = uuidBytes[UUIDUtil.BYTE_OFFSET_VARIATION] & 0x3F; // remove 2 MSB
+ b |= 0x80; // set as '10'
+ uuidBytes[BYTE_OFFSET_VARIATION] = (byte) b;
+ return uuid(uuidBytes);
+ }
+
+ public static UUID constructUUID(UUIDType type, long l1, long l2)
+ {
+ // first, ensure type is ok
+ l1 &= ~0xF000L; // remove high nibble of 6th byte
+ l1 |= (long) (type.raw() << 12);
+ // second, ensure variant is properly set too (8th byte; most-sig byte of second long)
+ l2 = ((l2 << 2) >>> 2); // remove 2 MSB
+ l2 |= (2L << 62); // set 2 MSB to '10'
+ return new UUID(l1, l2);
+ }
+
+ public static long initUUIDFirstLong(long l1, UUIDType type)
+ {
+ return initUUIDFirstLong(l1, type.raw());
+ }
+
+ public static long initUUIDFirstLong(long l1, int rawType)
+ {
+ l1 &= ~0xF000L; // remove high nibble of 6th byte
+ l1 |= (long) (rawType << 12);
+ return l1;
+ }
+
+ public static long initUUIDSecondLong(long l2)
+ {
+ l2 = ((l2 << 2) >>> 2); // remove 2 MSB
+ l2 |= (2L << 62); // set 2 MSB to '10'
+ return l2;
+ }
+
+ /*
+ /***********************************************************************
+ /* Type introspection
+ /***********************************************************************
+ */
+
+ /**
+ * Method for determining which type of UUID given UUID is.
+ * Returns null if type can not be determined.
+ *
+ * @param uuid UUID to check
+ *
+ * @return Null if UUID is null or type can not be determined (== invalid UUID);
+ * otherwise type
+ */
+ public static UUIDType typeOf(UUID uuid)
+ {
+ if (uuid == null) {
+ return null;
+ }
+ // Ok: so 4 MSB of byte at offset 6...
+ long l = uuid.getMostSignificantBits();
+ int typeNibble = (((int) l) >> 12) & 0xF;
+ switch (typeNibble) {
+ case 0:
+ // possibly null?
+ if (l == 0L && uuid.getLeastSignificantBits() == l) {
+ return UUIDType.UNKNOWN;
+ }
+ break;
+ case 1:
+ return UUIDType.TIME_BASED;
+ case 2:
+ return UUIDType.DCE;
+ case 3:
+ return UUIDType.NAME_BASED_MD5;
+ case 4:
+ return UUIDType.RANDOM_BASED;
+ case 5:
+ return UUIDType.NAME_BASED_SHA1;
+ }
+ // not recognized: return null
+ return null;
+ }
+
+ /*
+ /***********************************************************************
+ /* Conversions to other types
+ /***********************************************************************
+ */
+
+ public static byte[] asByteArray(UUID uuid)
+ {
+ long hi = uuid.getMostSignificantBits();
+ long lo = uuid.getLeastSignificantBits();
+ byte[] result = new byte[16];
+ _appendInt((int) (hi >> 32), result, 0);
+ _appendInt((int) hi, result, 4);
+ _appendInt((int) (lo >> 32), result, 8);
+ _appendInt((int) lo, result, 12);
+ return result;
+ }
+
+ public static void toByteArray(UUID uuid, byte[] buffer) {
+ toByteArray(uuid, buffer, 0);
+ }
+
+ public static void toByteArray(UUID uuid, byte[] buffer, int offset)
+ {
+ _checkUUIDByteArray(buffer, offset);
+ long hi = uuid.getMostSignificantBits();
+ long lo = uuid.getLeastSignificantBits();
+ _appendInt((int) (hi >> 32), buffer, offset);
+ _appendInt((int) hi, buffer, offset+4);
+ _appendInt((int) (lo >> 32), buffer, offset+8);
+ _appendInt((int) lo, buffer, offset+12);
+ }
+
+ /*
+ /********************************************************************************
+ /* Package helper methods
+ /********************************************************************************
+ */
+
+ //private final static long MASK_LOW_INT = 0x0FFFFFFFF;
+
+ protected final static long gatherLong(byte[] buffer, int offset)
+ {
+ long hi = ((long) _gatherInt(buffer, offset)) << 32;
+ //long lo = ((long) _gatherInt(buffer, offset+4)) & MASK_LOW_INT;
+ long lo = (((long) _gatherInt(buffer, offset+4)) << 32) >>> 32;
+ return hi | lo;
+ }
+
+ /*
+ /********************************************************************************
+ /* Internal helper methods
+ /********************************************************************************
+ */
+
+ private final static void _appendInt(int value, byte[] buffer, int offset)
+ {
+ buffer[offset++] = (byte) (value >> 24);
+ buffer[offset++] = (byte) (value >> 16);
+ buffer[offset++] = (byte) (value >> 8);
+ buffer[offset] = (byte) value;
+ }
+
+ private final static int _gatherInt(byte[] buffer, int offset)
+ {
+ return (buffer[offset] << 24) | ((buffer[offset+1] & 0xFF) << 16)
+ | ((buffer[offset+2] & 0xFF) << 8) | (buffer[offset+3] & 0xFF);
+ }
+
+ private final static void _checkUUIDByteArray(byte[] bytes, int offset)
+ {
+ if (bytes == null) {
+ throw new IllegalArgumentException("Invalid byte[] passed: can not be null");
+ }
+ if (offset < 0) {
+ throw new IllegalArgumentException("Invalid offset ("+offset+") passed: can not be negative");
+ }
+ if ((offset + 16) > bytes.length) {
+ throw new IllegalArgumentException("Invalid offset ("+offset+") passed: not enough room in byte array (need 16 bytes)");
+ }
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/Jug.java jug-3.1.5/src/main/java/com/fasterxml/uuid/Jug.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/Jug.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/Jug.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,321 @@
+/* JUG Java UUID Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid;
+
+import java.io.*;
+import java.security.*;
+import java.util.*;
+
+import com.fasterxml.uuid.impl.NameBasedGenerator;
+
+/**
+ * Simple command-line interface to UUID generation functionality.
+ */
+public class Jug
+{
+ protected final static HashMap
+ * To keep things as light-weight as possible, we won't bother defining
+ * separate interface or abstract class -- this class defines both API
+ * and the default implementation. It can thus be extended to override
+ * functionality to provide things like bridging to "real" logging systems.
+ * For simple configuration (suppress all, redirect to another stream)
+ * default implementation should be sufficient, however.
+ *
+ * Note: package
+ * Default is to low only warnings and errors
+ */
+ protected int _logLevel = LOG_ALL;
+
+ /**
+ * Output object to use, if defined; initialized to
+ *
+ * Note: exact functionality invoked depends on the logger instance:
+ * sub-classes of this class may need to do mapping to some other
+ * logging sub-system (log4j and JUL logging, for example, use their
+ * own severity levels that while generally reasonably easy to map,
+ * are nonetheless not one-to-one which the simple logger).
+ */
+ public static void setLogLevel(int level)
+ {
+ Logger l = instance;
+ if (l != null) {
+ l.doSetLogLevel(level);
+ }
+ }
+
+ /**
+ * Method that will re-direct output of the logger using the specified
+ * {@link PrintStream}. Null is allowed, and signifies that all the
+ * output should be suppressed.
+ *
+ * Note: exact functionality invoked depends on the logger instance.
+ */
+ public static void setOutput(PrintStream str)
+ {
+ Logger l = instance;
+ if (l != null) {
+ l.doSetOutput(str);
+ }
+ }
+
+ /**
+ * Method that will re-direct output of the logger using the specified
+ * {@link Writer}. Null is allowed, and signifies that all the
+ * output should be suppressed.
+ */
+ public static void setOutput(Writer w)
+ {
+ Logger l = instance;
+ if (l != null) {
+ l.doSetOutput(w);
+ }
+ }
+
+ // // // Logging methods
+
+ public static void logInfo(String msg)
+ {
+ Logger l = instance;
+ if (l != null) {
+ l.doLogInfo(msg);
+ }
+ }
+
+ public static void logWarning(String msg)
+ {
+ Logger l = instance;
+ if (l != null) {
+ l.doLogWarning(msg);
+ }
+ }
+
+ public static void logError(String msg)
+ {
+ Logger l = instance;
+ if (l != null) {
+ l.doLogError(msg);
+ }
+ }
+
+ /*
+ /**********************************************************************
+ /* Overridable implementation/instance methods
+ /**********************************************************************
+ */
+
+ // // // Config
+
+ protected void doSetLogLevel(int ll)
+ {
+ /* No need to sync for atomic value that's not used
+ * for synced or critical things
+ */
+ _logLevel = ll;
+ }
+
+ protected void doSetOutput(PrintStream str)
+ {
+ synchronized (this) {
+ _output1 = str;
+ _output2 = null;
+ }
+ }
+
+ protected void doSetOutput(Writer w)
+ {
+ synchronized (this) {
+ _output1 = null;
+ _output2 = (w instanceof PrintWriter) ?
+ (PrintWriter) w : new PrintWriter(w);
+ }
+ }
+
+ // // // Logging methods
+
+ protected void doLogInfo(String msg)
+ {
+ if (_logLevel <= LOG_INFO_AND_ABOVE && isEnabled()) {
+ synchronized (this) {
+ doWrite("INFO: "+msg);
+ }
+ }
+ }
+
+ protected void doLogWarning(String msg)
+ {
+ if (_logLevel <= LOG_WARNING_AND_ABOVE && isEnabled()) {
+ synchronized (this) {
+ doWrite("WARNING: "+msg);
+ }
+ }
+ }
+
+ protected void doLogError(String msg)
+ {
+ if (_logLevel <= LOG_ERROR_AND_ABOVE && isEnabled()) {
+ synchronized (this) {
+ doWrite("ERROR: "+msg);
+ }
+ }
+ }
+
+ /*
+ /**********************************************************************
+ /* Internal methods
+ /**********************************************************************
+ */
+
+ protected void doWrite(String msg)
+ {
+ if (_output1 != null) {
+ _output1.println(msg);
+ } else if (_output2 != null) {
+ _output2.println(msg);
+ }
+ }
+
+ /**
+ * Internal method used to quickly check if the Logger's output
+ * is suppressed or not.
+ *
+ * Note: not synchronized since it's read-only method that's return
+ * value can not be used for reliable syncing.
+ */
+ protected boolean isEnabled() {
+ return (_output1 != null) || (_output2 != null);
+ }
+}
+
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/NoArgGenerator.java jug-3.1.5/src/main/java/com/fasterxml/uuid/NoArgGenerator.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/NoArgGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/NoArgGenerator.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,14 @@
+package com.fasterxml.uuid;
+
+import java.util.UUID;
+
+/**
+ * Intermediate base class for UUID generators that do not take arguments for individual
+ * calls. This includes random and time-based variants, but not name-based ones.
+ *
+ * @since 3.0
+ */
+public abstract class NoArgGenerator extends UUIDGenerator
+{
+ public abstract UUID generate();
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/package.html jug-3.1.5/src/main/java/com/fasterxml/uuid/package.html
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/package.html 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/package.html 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,14 @@
+
+The primary point is {@link com.fasterxml.uuid.Generators}, used to construct actual
+generators, based on method to use and some optional arguments.
+
+Note: earlier JUG versions (up to 2.0) supported older JDKs (1.1); 1.4 is now needed
+since {@link java.util.UUID} is used as a core abstraction.
+
+ * The default implementation used by JUG is
+ * {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}.
+ */
+public abstract class TimestampSynchronizer
+{
+ protected TimestampSynchronizer() { }
+
+ /**
+ * Initialization method is will be called on an instance by
+ * {@link UUIDTimer} right after it's been configured with one.
+ * At this point the implementation instance should have been properly
+ * configured, and should be able to determine the first legal timestamp
+ * value (return value). Method should also initialize any locking that
+ * it does (if any), such as locking files it needs.
+ *
+ * Return value thus indicates the lowest initial time value that can
+ * be used by the caller that can not have been used by previous
+ * incarnations of the UUID generator (assuming instance was able to
+ * find properly persisted data to figure that out).
+ * However, caller also needs to make sure that it will
+ * call {@link #update} when it actually needs the time stamp for the
+ * first time,
+ * since this method can not allocate timestamps beyond this initial
+ * value at this point.
+ *
+ * @return First (and last) legal timestamp to use;
+ *Some additional assumptions about calculating the timestamp:
+ *
+ * Note about synchronization: main synchronization point (as of version
+ * 3.1.1 and above) is {@link #getTimestamp}, so caller need not
+ * synchronize access explicitly.
+ */
+public class UUIDTimer
+{
+ // // // Constants
+
+ /**
+ * Since System.longTimeMillis() returns time from january 1st 1970,
+ * and UUIDs need time from the beginning of gregorian calendar
+ * (15-oct-1582), need to apply the offset:
+ */
+ private final static long kClockOffset = 0x01b21dd213814000L;
+ /**
+ * Also, instead of getting time in units of 100nsecs, we get something
+ * with max resolution of 1 msec... and need the multiplier as well
+ */
+ private final static int kClockMultiplier = 10000;
+
+ private final static long kClockMultiplierL = 10000L;
+
+ /**
+ * Let's allow "virtual" system time to advance at most 100 milliseconds
+ * beyond actual physical system time, before adding delays.
+ */
+ private final static long kMaxClockAdvance = 100L;
+
+ // // // Configuration
+
+ /**
+ * Object used to reliably ensure that no multiple JVMs
+ * generate UUIDs, and also that the time stamp value used for
+ * generating time-based UUIDs is monotonically increasing
+ * even if system clock moves backwards over a reboot (usually
+ * due to some system level problem).
+ *
+ * See {@link TimestampSynchronizer} for details.
+ */
+ protected final TimestampSynchronizer _syncer;
+
+ /**
+ * Random number generator used to generate additional information
+ * to further reduce probability of collisions.
+ */
+ protected final Random _random;
+
+ // // // Clock state:
+
+ /**
+ * Additional state information used to protect against anomalous
+ * cases (clock time going backwards, node id getting mixed up).
+ * Third byte is actually used for seeding counter on counter
+ * overflow.
+ * Note that only lowermost 16 bits are actually used as sequence
+ */
+ private int _clockSequence;
+
+ /**
+ * Last physical timestamp value
+ * Notes: for name-based variant we will pass plain Strings, assuming this is the
+ * most common use case; even though it is possible to also pass raw byte arrays.
+ * JDK and Jug implementations have similar performance so this only changes
+ * relative speeds of name- vs time-based variants.
+ *
+ * @since 3.1
+ */
+public class MeasurePerformance
+{
+ // Let's generate quarter million UUIDs per test
+
+ private static final int ROUNDS = 250;
+ private static final int COUNT = 1000;
+
+ // also: let's just use a single name for name-based, to avoid extra overhead:
+ final String NAME = "http://www.cowtowncoder.com/blog/blog.html";
+ final byte[] NAME_BYTES;
+
+ public MeasurePerformance() throws java.io.IOException
+ {
+ NAME_BYTES = NAME.getBytes("UTF-8");
+ }
+
+ public void test() throws Exception
+ {
+ int i = 0;
+
+ final Object[] uuids = new Object[COUNT];
+
+ // can either use bogus address; or local one, no difference perf-wise
+ EthernetAddress nic = EthernetAddress.fromInterface();
+
+ // Whether to include namespace? Depends on whether we compare with JDK (which does not)
+// UUID namespaceForNamed = NAMESPACE;
+ UUID namespaceForNamed = null;
+
+ final RandomBasedGenerator secureRandomGen = Generators.randomBasedGenerator();
+ final RandomBasedGenerator utilRandomGen = Generators.randomBasedGenerator(new java.util.Random(123));
+ final TimeBasedGenerator timeGenPlain = Generators.timeBasedGenerator(nic);
+ final TimeBasedGenerator timeGenSynced = Generators.timeBasedGenerator(nic,
+ new com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer());
+ final StringArgGenerator nameGen = Generators.nameBasedGenerator(namespaceForNamed);
+
+ while (true) {
+ try { Thread.sleep(100L); } catch (InterruptedException ie) { }
+ int round = (i++ % 7);
+
+ long curr = System.currentTimeMillis();
+ String msg;
+ boolean lf = (round == 0);
+
+ switch (round) {
+
+ case 0:
+ msg = "JDK, random";
+ testJDK(uuids, ROUNDS);
+ break;
+
+ case 1:
+ msg = "JDK, name";
+ testJDKNames(uuids, ROUNDS);
+ break;
+
+ case 2:
+ msg = "Jug, time-based (non-sync)";
+ testTimeBased(uuids, ROUNDS, timeGenPlain);
+ break;
+
+ case 3:
+ msg = "Jug, time-based (SYNC)";
+ testTimeBased(uuids, ROUNDS, timeGenSynced);
+ break;
+
+ case 4:
+ msg = "Jug, SecureRandom";
+ testRandom(uuids, ROUNDS, secureRandomGen);
+ break;
+
+ case 5:
+ msg = "Jug, java.util.Random";
+ testRandom(uuids, ROUNDS, utilRandomGen);
+ break;
+
+
+ case 6:
+ msg = "Jug, name-based";
+ testNameBased(uuids, ROUNDS, nameGen);
+ break;
+
+ /*
+ case 7:
+ msg = "http://johannburkard.de/software/uuid/";
+ testUUID32(uuids, ROUNDS);
+ break;
+ */
+
+ default:
+ throw new Error("Internal error");
+ }
+
+ curr = System.currentTimeMillis() - curr;
+ if (lf) {
+ System.out.println();
+ }
+ System.out.println("Test '"+msg+"' -> "+curr+" msecs; last UUID: "+uuids[COUNT-1]);
+ }
+ }
+
+ // Test implementation from http://johannburkard.de/software/uuid/
+ /*
+ private final void testUUID32(Object[] uuids, int rounds)
+ {
+ while (--rounds >= 0) {
+ for (int i = 0, len = uuids.length; i < len; ++i) {
+ uuids[i] = new com.eaio.uuid.UUID();
+ }
+ }
+ }
+ */
+
+ private final void testJDK(Object[] uuids, int rounds)
+ {
+ while (--rounds >= 0) {
+ for (int i = 0, len = uuids.length; i < len; ++i) {
+ uuids[i] = UUID.randomUUID();
+ }
+ }
+ }
+
+ private final void testJDKNames(Object[] uuids, int rounds) throws java.io.IOException
+ {
+ while (--rounds >= 0) {
+ for (int i = 0, len = uuids.length; i < len; ++i) {
+ final byte[] nameBytes = NAME.getBytes("UTF-8");
+ uuids[i] = UUID.nameUUIDFromBytes(nameBytes);
+ }
+ }
+ }
+
+ private final void testRandom(Object[] uuids, int rounds, RandomBasedGenerator uuidGen)
+ {
+ while (--rounds >= 0) {
+ for (int i = 0, len = uuids.length; i < len; ++i) {
+ uuids[i] = uuidGen.generate();
+ }
+ }
+ }
+
+ private final void testTimeBased(Object[] uuids, int rounds, TimeBasedGenerator uuidGen)
+ {
+ while (--rounds >= 0) {
+ for (int i = 0, len = uuids.length; i < len; ++i) {
+ uuids[i] = uuidGen.generate();
+ }
+ }
+ }
+
+ private final void testNameBased(Object[] uuids, int rounds, StringArgGenerator uuidGen)
+ {
+ while (--rounds >= 0) {
+ for (int i = 0, len = uuids.length; i < len; ++i) {
+ uuids[i] = uuidGen.generate(NAME);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ new MeasurePerformance().test();
+ }
+}
diff -Nru jug-2.0.0/src/main/java/test/FileSyncTest.java jug-3.1.5/src/main/java/test/FileSyncTest.java
--- jug-2.0.0/src/main/java/test/FileSyncTest.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/test/FileSyncTest.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,46 @@
+package test;
+
+import java.util.UUID;
+
+import com.fasterxml.uuid.*;
+import com.fasterxml.uuid.ext.*;
+import com.fasterxml.uuid.impl.TimeBasedGenerator;
+
+/**
+ * Simple manual utility test class for manually checking whether file-based
+ * synchronization seems to be working or not.
+ */
+public class FileSyncTest
+{
+ public static void main(String[] args)
+ throws Exception
+ {
+ FileBasedTimestampSynchronizer sync = new FileBasedTimestampSynchronizer();
+ // Let's stress-test it...
+ sync.setUpdateInterval(2000L);
+
+ // must have a NIC for this to work, should be ok:
+ EthernetAddress eth = EthernetAddress.fromInterface();
+ TimeBasedGenerator gen = Generators.timeBasedGenerator(eth, sync);
+
+ int counter = 1;
+ while (true) {
+ UUID uuid = gen.generate();
+ // Default one is for convenient output
+ System.out.println("#"+counter+" -> "+uuid);
+
+ /* This allows lexical sorting by uuid... (not very useful,
+ * since 'real' UUID ordering is not lexical)
+ */
+ System.out.println(""+uuid+" (#"+counter+")");
+
+ // And this can be used to ensure there are no dups:
+ System.out.println(""+uuid);
+ ++counter;
+
+ try {
+ Thread.sleep(120L);
+ } catch (InterruptedException ie) { }
+ }
+ }
+}
diff -Nru jug-2.0.0/src/main/resources/META-INF/LICENSE jug-3.1.5/src/main/resources/META-INF/LICENSE
--- jug-2.0.0/src/main/resources/META-INF/LICENSE 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/resources/META-INF/LICENSE 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,7 @@
+This copy of Java UUID Generator (JUG) library is licensed under Apache (Software) License,
+version 2.0 ("the License").
+See the License for details about distribution rights, and the specific rights regarding derivate works.
+
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
diff -Nru jug-2.0.0/src/main/resources/META-INF/NOTICE jug-3.1.5/src/main/resources/META-INF/NOTICE
--- jug-2.0.0/src/main/resources/META-INF/NOTICE 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/resources/META-INF/NOTICE 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,7 @@
+Java UUID generator library has been written by Tatu Saloranta (tatu.saloranta@iki.fi)
+
+Other developers who have contributed code are:
+
+* Eric Bie contributed extensive unit test suite which has helped ensure high implementation
+ quality
+
diff -Nru jug-2.0.0/src/test/java/com/fasterxml/uuid/EthernetAddressTest.java jug-3.1.5/src/test/java/com/fasterxml/uuid/EthernetAddressTest.java
--- jug-2.0.0/src/test/java/com/fasterxml/uuid/EthernetAddressTest.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/test/java/com/fasterxml/uuid/EthernetAddressTest.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,1491 @@
+/* JUG Java Uuid Generator
+ * EthernetAddressTest.java
+ * Created on July 16, 2003, 11:17 PM
+ *
+ * Copyright (c) 2003 Eric Bie
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+import java.util.Arrays;
+import java.util.Random;
+
+import com.fasterxml.uuid.EthernetAddress;
+
+/**
+ * JUnit Test class for the com.fasterxml.uuid.EthernetAddress class.
+ *
+ * @author Eric Bie
+ * @author Tatu Saloranta (changes for version 3.0)
+ */
+public class EthernetAddressTest extends TestCase
+{
+ // constant defining the length of a valid ethernet address byte array
+ private static final int ETHERNET_ADDRESS_ARRAY_LENGTH = 6;
+
+ // some strings for failure case tests
+ private static final String IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_1 =
+ "01f23:45:67:89:ab";
+ private static final String IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_2 =
+ "01:23f45:67:89:ab";
+ private static final String IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_3 =
+ "01:23:45f67:89:ab";
+ private static final String IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_4 =
+ "01:23:45:67f89:ab";
+ private static final String IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_5 =
+ "01:23:45:67:89fab";
+ private static final String IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_6 =
+ "01f23f45f67f89fab";
+ private static final String NON_HEX_ETHERNET_ADDRESS_STRING =
+ "NON-HEX0-FORSURE0";
+ private static final String RANDOM_PROPER_LENGTH_STRING =
+ "Same LengthString";
+
+ // some valid strings for the various dropped digit cases
+ private static final String FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING =
+ "00:23:45:67:89:ab";
+ private static final String FIRST_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING =
+ "0:23:45:67:89:ab";
+ private static final String FIRST_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING =
+ ":23:45:67:89:ab";
+ private static final String SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING =
+ "01:00:45:67:89:ab";
+ private static final String SECOND_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING =
+ "01:0:45:67:89:ab";
+ private static final String SECOND_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING =
+ "01::45:67:89:ab";
+ private static final String THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:00:67:89:ab";
+ private static final String THIRD_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:0:67:89:ab";
+ private static final String THIRD_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23::67:89:ab";
+ private static final String FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45:00:89:ab";
+ private static final String FOURTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45:0:89:ab";
+ private static final String FOURTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45::89:ab";
+ private static final String FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45:67:00:ab";
+ private static final String FIFTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45:67:0:ab";
+ private static final String FIFTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45:67::ab";
+ private static final String SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45:67:89:00";
+ private static final String SIXTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45:67:89:0";
+ private static final String SIXTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING =
+ "01:23:45:67:89:";
+ private static final String MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING =
+ "01:03:00:07:00:00";
+ private static final String MIXED_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING =
+ "1:3:0:7:0:0";
+ private static final String MIXED_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING =
+ "1:3::7::";
+
+ // here are some sets of good ethernet addresses in various forms
+ private static final String NULL_ETHERNET_ADDRESS_STRING =
+ "00:00:00:00:00:00";
+ private static final long NULL_ETHERNET_ADDRESS_LONG = 0x0000000000000000L;
+ private static final byte[] NULL_ETHERNET_ADDRESS_BYTE_ARRAY =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH];
+ //private static final int[] NULL_ETHERNET_ADDRESS_INT_ARRAY = new int[ETHERNET_ADDRESS_ARRAY_LENGTH];
+ private static final EthernetAddress NULL_ETHERNET_ADDRESS =
+ new EthernetAddress(0L);
+
+ private static final String VALID_ETHERNET_ADDRESS_STRING =
+ "87:f5:93:06:d3:0c";
+ private static final String MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING =
+ "87:f5:93:06:D3:0c";
+ private static final String UPPER_CASE_VALID_ETHERNET_ADDRESS_STRING =
+ "87:F5:93:06:D3:0C";
+ private static final String LOWER_CASE_VALID_ETHERNET_ADDRESS_STRING =
+ VALID_ETHERNET_ADDRESS_STRING;
+ private static final long VALID_ETHERNET_ADDRESS_LONG =
+ 0x000087f59306d30cL;
+ private static final byte[] VALID_ETHERNET_ADDRESS_BYTE_ARRAY =
+ {
+ (byte)0x87, (byte)0xf5, (byte)0x93, (byte)0x06, (byte)0xd3, (byte)0x0c
+ };
+ private static final int[] VALID_ETHERNET_ADDRESS_INT_ARRAY =
+ {
+ 0x87, 0xf5, 0x93, 0x06, 0xd3, 0x0c
+ };
+
+ private static final byte[] ANOTHER_VALID_ETHERNET_ADDRESS_BYTE_ARRAY =
+ {
+ (byte)0x4c, (byte)0xde, (byte)0xfb, (byte)0xba, (byte)0x5a, (byte)0x1c
+ };
+ /*
+ private static final EthernetAddress VALID_ETHERNET_ADDRESS = new EthernetAddress(VALID_ETHERNET_ADDRESS_LONG);
+ private static final String ANOTHER_VALID_ETHERNET_ADDRESS_STRING = "4c:de:fb:ba:5a:1c";
+ private static final long ANOTHER_VALID_ETHERNET_ADDRESS_LONG = 0x00004cdefbba5a1cL;
+ private static final int[] ANOTHER_VALID_ETHERNET_ADDRESS_INT_ARRAY =
+ {
+ 0x4c, 0xde, 0xfb, 0xba, 0x5a, 0x1c
+ };
+ */
+ //private static final EthernetAddress ANOTHER_VALID_ETHERNET_ADDRESS = new EthernetAddress(ANOTHER_VALID_ETHERNET_ADDRESS_LONG);
+
+ // some ethernet addresses for the ordering tests
+ private static final EthernetAddress MAC0_ETHERNET_ADDRESS =
+ new EthernetAddress(0x0000015ae2e61893L);
+ private static final EthernetAddress MAC1_ETHERNET_ADDRESS =
+ new EthernetAddress(0x00001f0f1b0e8e6eL);
+ private static final EthernetAddress MAC2_ETHERNET_ADDRESS =
+ new EthernetAddress(0x000022d8afb0b888L);
+ private static final EthernetAddress MAC3_ETHERNET_ADDRESS =
+ new EthernetAddress(0x00004cfdc9a5e86aL);
+ private static final EthernetAddress MAC4_ETHERNET_ADDRESS =
+ new EthernetAddress(0x000091038ffa38eeL);
+ private static final EthernetAddress MAC5_ETHERNET_ADDRESS =
+ new EthernetAddress(0x00009857e4f202a3L);
+ private static final EthernetAddress MAC6_ETHERNET_ADDRESS =
+ new EthernetAddress(0x0000a8c0600ccc69L);
+ private static final EthernetAddress MAC7_ETHERNET_ADDRESS =
+ new EthernetAddress(0x0000a9a18860d8fcL);
+ private static final EthernetAddress MAC8_ETHERNET_ADDRESS =
+ new EthernetAddress(0x0000c8b30f0b395aL);
+ private static final EthernetAddress MAC9_ETHERNET_ADDRESS =
+ new EthernetAddress(0x0000cf74d8ef49b8L);
+
+
+ public EthernetAddressTest(java.lang.String testName)
+ {
+ super(testName);
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite(EthernetAddressTest.class);
+ return suite;
+ }
+
+ public static void main(String[] args)
+ {
+ TestRunner.run(suite());
+ }
+
+ /**************************************************************************
+ * Begin Constructor tests
+ *************************************************************************/
+ /**
+ * Test of EthernetAddress(byte[]) constructor,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testByteArrayEthernetAddressConstructor()
+ {
+ // lets test some error cases
+ // first, passing null
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ new EthernetAddress((byte[])null);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NullPointerException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an array that is too small
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ new EthernetAddress(
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH - 1]);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NumberFormatException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an array that is too big
+ try {
+ /*EthernetAddress ethernet_address =*/
+ new EthernetAddress(
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH + 1]);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ } catch (NumberFormatException ex) {
+ // this is the success case so do nothing
+ } catch (Exception ex) {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // let's test that creating a EthernetAddress from an zero'd array
+ // gives us a null EthernetAddress (definition of null EthernetAddress)
+ EthernetAddress ethernet_address =
+ new EthernetAddress(new byte[ETHERNET_ADDRESS_ARRAY_LENGTH]);
+ assertEquals(
+ "EthernetAddress(byte[]) did not create expected EthernetAddress",
+ NULL_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+
+ // let's test creating an array from a good byte array
+ ethernet_address =
+ new EthernetAddress(VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertEquals(
+ "EthernetAddress(byte[]) did not create expected EthernetAddress",
+ VALID_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+ }
+
+ /**
+ * Test of EthernetAddress(long) constructor,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testLongEthernetAddressConstructor()
+ {
+ // let's test that creating a EthernetAddress from an zero long
+ // gives us a null EthernetAddress (definition of null EthernetAddress)
+ EthernetAddress ethernet_address =
+ new EthernetAddress(0x0000000000000000L);
+ assertEquals(
+ "EthernetAddress(long) did not create expected EthernetAddress",
+ NULL_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+
+ // let's test creating an array from a good long
+ ethernet_address = new EthernetAddress(VALID_ETHERNET_ADDRESS_LONG);
+ assertEquals(
+ "EthernetAddress(long) did not create expected EthernetAddress",
+ VALID_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+ }
+
+ /**
+ * Test of EthernetAddress(String) constructor,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testStringEthernetAddressConstructor()
+ {
+ // test a null string case
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ new EthernetAddress((String)null);
+ fail("Expected exception not caught");
+ }
+ catch (NullPointerException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // test some failure cases for the string constructor
+ badStringEthernetAddressConstructorHelper(
+ IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_1);
+ badStringEthernetAddressConstructorHelper(
+ IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_2);
+ badStringEthernetAddressConstructorHelper(
+ IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_3);
+ badStringEthernetAddressConstructorHelper(
+ IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_4);
+ badStringEthernetAddressConstructorHelper(
+ IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_5);
+ badStringEthernetAddressConstructorHelper(
+ IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_6);
+ badStringEthernetAddressConstructorHelper(
+ NON_HEX_ETHERNET_ADDRESS_STRING);
+ badStringEthernetAddressConstructorHelper(
+ RANDOM_PROPER_LENGTH_STRING);
+
+ // some valid strings for the various dropped digit cases
+ goodStringEthernetAddressConstructorHelper(
+ FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ FIRST_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ FIRST_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ SECOND_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ SECOND_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ THIRD_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ THIRD_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ FOURTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ FOURTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ FIFTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ FIFTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ SIXTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ SIXTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ MIXED_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ MIXED_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+
+ // test the other good cases
+ goodStringEthernetAddressConstructorHelper(
+ NULL_ETHERNET_ADDRESS_STRING,
+ NULL_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ UPPER_CASE_VALID_ETHERNET_ADDRESS_STRING,
+ UPPER_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ LOWER_CASE_VALID_ETHERNET_ADDRESS_STRING,
+ LOWER_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ goodStringEthernetAddressConstructorHelper(
+ MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING,
+ MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ }
+
+ /**************************************************************************
+ * End Constructor tests
+ *************************************************************************/
+ /**
+ * Test of asByteArray method, of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testAsByteArray()
+ {
+ // we'll test making a couple EthernetAddresses and then check that
+ // asByteArray returns the same value in long form as used to create it
+
+ // first we'll test the null EthernetAddress
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ assertEquals("Expected length of returned array wrong",
+ ETHERNET_ADDRESS_ARRAY_LENGTH,
+ ethernet_address.asByteArray().length);
+ assertEthernetAddressArraysAreEqual(
+ NULL_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ ethernet_address.asByteArray(), 0);
+
+ // now test a non-null EthernetAddress
+ ethernet_address = new EthernetAddress(VALID_ETHERNET_ADDRESS_LONG);
+ assertEquals("Expected length of returned array wrong",
+ ETHERNET_ADDRESS_ARRAY_LENGTH,
+ ethernet_address.asByteArray().length);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ ethernet_address.asByteArray(), 0);
+
+ // let's make sure that changing the returned array doesn't mess with
+ // the wrapped EthernetAddress's internals
+ byte[] ethernet_address_byte_array = ethernet_address.asByteArray();
+ // we'll just stir it up a bit and then check that the original
+ // EthernetAddress was not changed in the process.
+ // The easiest stir is to sort it ;)
+ Arrays.sort(ethernet_address_byte_array);
+ assertEthernetAddressArraysAreNotEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ ethernet_address_byte_array, 0);
+ assertEthernetAddressArraysAreNotEqual(
+ ethernet_address.asByteArray(), 0,
+ ethernet_address_byte_array, 0);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ ethernet_address.asByteArray(), 0);
+ }
+
+ /**
+ * Test of clone method, of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testClone()
+ {
+ // as lifted from the JDK Object JavaDoc for clone:
+ // x.clone() Creates and returns a copy of x.
+ // The precise meaning of "copy" may depend on
+ // the class of the object. The general intent
+ // is that, for any object x, the expression:
+ // x.clone() != x
+ // will be true, and that the expression:
+ // x.clone().getClass() == x.getClass()
+ // will be true, but these are not absolute requirements.
+ // While it is typically the case that:
+ // x.clone().equals(x)
+ // will be true, this is not an absolute requirement.
+ // For EthernetAddress, this test will check that all the above
+ // ARE true in the case of EthernetAddress clone() because it is
+ // the desired behavior.
+ EthernetAddress x = new EthernetAddress(VALID_ETHERNET_ADDRESS_STRING);
+ assertTrue("x.clone() != x did not return true",
+ x.clone() != x);
+ assertTrue("x.clone().getClass() == x.getClass() did not return true",
+ x.clone().getClass() == x.getClass());
+ assertTrue("x.clone().equals(x) did not return true",
+ x.clone().equals(x));
+ }
+
+ /**
+ * Test of compareTo method, of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testCompareTo()
+ {
+ // first, let's make sure calling compareTo with null
+ // throws the appropriate NullPointerException
+ try
+ {
+ // the 'null EthernetAddress' will be fine
+ NULL_ETHERNET_ADDRESS.compareTo(null);
+ fail("Expected exception not thrown");
+ }
+ catch (NullPointerException ex)
+ {
+ // good, we caught the expected exception, so we passed
+ }
+ catch (Exception ex)
+ {
+ fail("Caught an unexpected exception: " + ex);
+ }
+
+ // now we'll test some simple base cases
+ // 2 null EthernetAddresses always compare to 0
+ assertEthernetAddressEqualOrderHelper(NULL_ETHERNET_ADDRESS,
+ new EthernetAddress(0L));
+
+ // 2 of the same value EthernetAddresses are always 0
+ assertEthernetAddressEqualOrderHelper(MAC0_ETHERNET_ADDRESS,
+ new EthernetAddress(MAC0_ETHERNET_ADDRESS.toLong()));
+
+ // the 'null EthernetAddress' always comes first in the ordering
+ assertEthernetAddressGreaterOrderHelper(MAC0_ETHERNET_ADDRESS,
+ NULL_ETHERNET_ADDRESS);
+
+ // EthernetAddresses will always sort
+ // with the 'numerically' greater MAC addresses coming later
+ assertEthernetAddressGreaterOrderHelper(MAC4_ETHERNET_ADDRESS,
+ MAC0_ETHERNET_ADDRESS);
+ assertEthernetAddressGreaterOrderHelper(MAC9_ETHERNET_ADDRESS,
+ MAC4_ETHERNET_ADDRESS);
+ assertEthernetAddressGreaterOrderHelper(MAC9_ETHERNET_ADDRESS,
+ MAC0_ETHERNET_ADDRESS);
+
+ // now we will test a bigger case of the compareTo functionality
+ // of the EthernetAddress class
+ // easiest way to do this is to create an array of EthernetAddresses
+ // and sort it then test that this array is in the expected order
+
+ // before sort, the array contains (in psudo-random order)
+ // 15 EthernetAddresses of this distribution:
+ // 1 - null EthernetAddress
+ // 2 - mac0
+ // 1 - mac1
+ // 1 - mac2
+ // 2 - mac3
+ // 2 - mac4
+ // 2 - mac5
+ // 1 - mac6
+ // 1 - mac7
+ // 1 - mac8
+ // 1 - mac9
+ EthernetAddress ethernet_address_array[] = new EthernetAddress[15];
+ ethernet_address_array[0] = MAC4_ETHERNET_ADDRESS;
+ ethernet_address_array[1] = MAC6_ETHERNET_ADDRESS;
+ ethernet_address_array[2] = MAC0_ETHERNET_ADDRESS;
+ ethernet_address_array[3] = MAC5_ETHERNET_ADDRESS;
+ ethernet_address_array[4] = MAC3_ETHERNET_ADDRESS;
+ ethernet_address_array[5] = MAC5_ETHERNET_ADDRESS;
+ ethernet_address_array[6] = MAC0_ETHERNET_ADDRESS;
+ ethernet_address_array[7] = NULL_ETHERNET_ADDRESS;
+ ethernet_address_array[8] = MAC8_ETHERNET_ADDRESS;
+ ethernet_address_array[9] = MAC3_ETHERNET_ADDRESS;
+ ethernet_address_array[10] = MAC4_ETHERNET_ADDRESS;
+ ethernet_address_array[11] = MAC7_ETHERNET_ADDRESS;
+ ethernet_address_array[12] = MAC1_ETHERNET_ADDRESS;
+ ethernet_address_array[13] = MAC9_ETHERNET_ADDRESS;
+ ethernet_address_array[14] = MAC2_ETHERNET_ADDRESS;
+
+ Arrays.sort(ethernet_address_array);
+ // now we should be able to see that the array is in order
+ assertEthernetAddressesMatchHelper(
+ NULL_ETHERNET_ADDRESS, ethernet_address_array[0]);
+ assertEthernetAddressesMatchHelper(
+ MAC0_ETHERNET_ADDRESS, ethernet_address_array[1]);
+ assertEthernetAddressesMatchHelper(
+ MAC0_ETHERNET_ADDRESS, ethernet_address_array[2]);
+ assertEthernetAddressesMatchHelper(
+ MAC1_ETHERNET_ADDRESS, ethernet_address_array[3]);
+ assertEthernetAddressesMatchHelper(
+ MAC2_ETHERNET_ADDRESS, ethernet_address_array[4]);
+ assertEthernetAddressesMatchHelper(
+ MAC3_ETHERNET_ADDRESS, ethernet_address_array[5]);
+ assertEthernetAddressesMatchHelper(
+ MAC3_ETHERNET_ADDRESS, ethernet_address_array[6]);
+ assertEthernetAddressesMatchHelper(
+ MAC4_ETHERNET_ADDRESS, ethernet_address_array[7]);
+ assertEthernetAddressesMatchHelper(
+ MAC4_ETHERNET_ADDRESS, ethernet_address_array[8]);
+ assertEthernetAddressesMatchHelper(
+ MAC5_ETHERNET_ADDRESS, ethernet_address_array[9]);
+ assertEthernetAddressesMatchHelper(
+ MAC5_ETHERNET_ADDRESS, ethernet_address_array[10]);
+ assertEthernetAddressesMatchHelper(
+ MAC6_ETHERNET_ADDRESS, ethernet_address_array[11]);
+ assertEthernetAddressesMatchHelper(
+ MAC7_ETHERNET_ADDRESS, ethernet_address_array[12]);
+ assertEthernetAddressesMatchHelper(
+ MAC8_ETHERNET_ADDRESS, ethernet_address_array[13]);
+ assertEthernetAddressesMatchHelper(
+ MAC9_ETHERNET_ADDRESS, ethernet_address_array[14]);
+ }
+
+ /**
+ * Test of equals method, of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testEquals()
+ {
+ // test passing null to equals returns false
+ // (as specified in the JDK docs for Object)
+ EthernetAddress x =
+ new EthernetAddress(VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertFalse("equals(null) didn't return false",
+ x.equals((Object)null));
+
+ // test passing an object which is not a EthernetAddress returns false
+ assertFalse("x.equals(non_EthernetAddress_object) didn't return false",
+ x.equals(new Object()));
+
+ // test a case where two EthernetAddresss are definitly not equal
+ EthernetAddress w =
+ new EthernetAddress(ANOTHER_VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertFalse("x == w didn't return false",
+ x == w);
+ assertFalse("x.equals(w) didn't return false",
+ x.equals(w));
+
+ // test refelexivity
+ assertTrue("x.equals(x) didn't return true",
+ x.equals(x));
+
+ // test symmetry
+ EthernetAddress y =
+ new EthernetAddress(VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertFalse("x == y didn't return false",
+ x == y);
+ assertTrue("y.equals(x) didn't return true",
+ y.equals(x));
+ assertTrue("x.equals(y) didn't return true",
+ x.equals(y));
+
+ // now we'll test transitivity
+ EthernetAddress z =
+ new EthernetAddress(VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertFalse("x == y didn't return false",
+ x == y);
+ assertFalse("x == y didn't return false",
+ y == z);
+ assertFalse("x == y didn't return false",
+ x == z);
+ assertTrue("x.equals(y) didn't return true",
+ x.equals(y));
+ assertTrue("y.equals(z) didn't return true",
+ y.equals(z));
+ assertTrue("x.equals(z) didn't return true",
+ x.equals(z));
+
+ // test consistancy (this test is just calling equals multiple times)
+ assertFalse("x == y didn't return false",
+ x == y);
+ assertTrue("x.equals(y) didn't return true",
+ x.equals(y));
+ assertTrue("x.equals(y) didn't return true",
+ x.equals(y));
+ assertTrue("x.equals(y) didn't return true",
+ x.equals(y));
+ }
+
+ /**
+ * Test of toByteArray method, of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testToByteArray()
+ {
+ // we'll test making a couple EthernetAddresses and then check that the
+ // toByteArray returns the same value in byte form as used to create it
+
+ // first we'll test the null EthernetAddress
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ assertEquals("Expected length of returned array wrong",
+ ETHERNET_ADDRESS_ARRAY_LENGTH,
+ ethernet_address.toByteArray().length);
+ assertEthernetAddressArraysAreEqual(
+ NULL_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ ethernet_address.toByteArray(), 0);
+
+ // now test a non-null EthernetAddress
+ ethernet_address = new EthernetAddress(VALID_ETHERNET_ADDRESS_LONG);
+ assertEquals("Expected length of returned array wrong",
+ ETHERNET_ADDRESS_ARRAY_LENGTH,
+ ethernet_address.toByteArray().length);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ ethernet_address.toByteArray(), 0);
+
+ // let's make sure that changing the returned array doesn't mess with
+ // the wrapped EthernetAddress's internals
+ byte[] ethernet_address_byte_array = ethernet_address.toByteArray();
+ // we'll just stir it up a bit and then check that the original
+ // EthernetAddress was not changed in the process.
+ // The easiest stir is to sort it ;)
+ Arrays.sort(ethernet_address_byte_array);
+ assertEthernetAddressArraysAreNotEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ ethernet_address_byte_array, 0);
+ assertEthernetAddressArraysAreNotEqual(
+ ethernet_address.toByteArray(), 0,
+ ethernet_address_byte_array, 0);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ ethernet_address.toByteArray(), 0);
+ }
+
+ /**
+ * Test of toByteArray(byte[]) method,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testToByteArrayDest()
+ {
+ // constant for use in this test
+ final int EXTRA_DATA_LENGTH = 9;
+
+ // lets test some error cases
+ // first, passing null
+ try
+ {
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ ethernet_address.toByteArray((byte[])null);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NullPointerException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an array that is too small
+ try {
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ byte[] ethernet_address_byte_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH - 1];
+ ethernet_address.toByteArray(ethernet_address_byte_array);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ } catch (IllegalArgumentException ex) {
+ // this is the success case so do nothing
+ } catch (Exception ex) {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // we'll test making a couple EthernetAddresses and then check that
+ // toByteArray returns the same value in byte form as used to create it
+
+ // here we'll test the null EthernetAddress
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ byte[] test_array = new byte[ETHERNET_ADDRESS_ARRAY_LENGTH];
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array);
+ assertEthernetAddressArraysAreEqual(
+ NULL_ETHERNET_ADDRESS_BYTE_ARRAY, 0, test_array, 0);
+
+ // now test a non-null EthernetAddress
+ ethernet_address = new EthernetAddress(MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0, test_array, 0);
+
+ // now test a null EthernetAddress case with extra data in the array
+ ethernet_address = new EthernetAddress(0L);
+ test_array = new byte[ETHERNET_ADDRESS_ARRAY_LENGTH + EXTRA_DATA_LENGTH];
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array);
+ assertEthernetAddressArraysAreEqual(NULL_ETHERNET_ADDRESS_BYTE_ARRAY, 0, test_array, 0);
+ for (int i = 0; i < EXTRA_DATA_LENGTH; i++)
+ {
+ assertEquals("Expected array fill value changed",
+ (byte)'x',
+ test_array[i + ETHERNET_ADDRESS_ARRAY_LENGTH]);
+ }
+
+ // now test a good EthernetAddress case with extra data in the array
+ ethernet_address =
+ new EthernetAddress(MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ test_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH + EXTRA_DATA_LENGTH];
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0, test_array, 0);
+ for (int i = 0; i < EXTRA_DATA_LENGTH; i++)
+ {
+ assertEquals("Expected array fill value changed",
+ (byte)'x',
+ test_array[i + ETHERNET_ADDRESS_ARRAY_LENGTH]);
+ }
+ }
+
+ /**
+ * Test of toByteArray(byte[], int) method,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testToByteArrayDestOffset()
+ {
+ // constant value for use in this test
+ final int EXTRA_DATA_LENGTH = 9;
+
+ // lets test some error cases
+ // first, passing null and 0
+ try
+ {
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ ethernet_address.toByteArray((byte[])null, 0);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NullPointerException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an array that is too small
+ try
+ {
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ byte[] ethernet_address_byte_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH - 1];
+ ethernet_address.toByteArray(ethernet_address_byte_array, 0);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ } catch (IllegalArgumentException ex) {
+ // this is the success case so do nothing
+ } catch (Exception ex) {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an index that is negative
+ try {
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ byte[] ethernet_address_byte_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH];
+ ethernet_address.toByteArray(ethernet_address_byte_array, -1);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ } catch (IllegalArgumentException ex) {
+ // this is the success case so do nothing
+ } catch (Exception ex) {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an index that is too big
+ try
+ {
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ byte[] ethernet_address_byte_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH];
+ ethernet_address.toByteArray(
+ ethernet_address_byte_array, ETHERNET_ADDRESS_ARRAY_LENGTH);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ } catch (IllegalArgumentException ex) {
+ // this is the success case so do nothing
+ } catch (Exception ex) {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an index that is in the array,
+ // but without enough bytes to read ETHERNET_ADDRESS_ARRAY_LENGTH
+ try {
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ byte[] ethernet_address_byte_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH];
+ ethernet_address.toByteArray(ethernet_address_byte_array, 1);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ } catch (IllegalArgumentException ex) {
+ // this is the success case so do nothing
+ } catch (Exception ex) {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // we'll test making a couple EthernetAddresss and then check
+ // that toByteArray
+ // returns the same value in byte form as used to create it
+
+ // here we'll test the null EthernetAddress at offset 0
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ byte[] test_array = new byte[ETHERNET_ADDRESS_ARRAY_LENGTH];
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array, 0);
+ assertEthernetAddressArraysAreEqual(
+ NULL_ETHERNET_ADDRESS_BYTE_ARRAY, 0, test_array, 0);
+
+ // now test a non-null EthernetAddress
+ ethernet_address =
+ new EthernetAddress(MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0, test_array, 0);
+
+ // now test a null EthernetAddress case with extra data in the array
+ ethernet_address = new EthernetAddress(0L);
+ test_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH + EXTRA_DATA_LENGTH];
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array, 0);
+ assertEthernetAddressArraysAreEqual(
+ NULL_ETHERNET_ADDRESS_BYTE_ARRAY, 0, test_array, 0);
+ for (int i = 0; i < EXTRA_DATA_LENGTH; i++) {
+ assertEquals("Expected array fill value changed",
+ (byte)'x',
+ test_array[i + ETHERNET_ADDRESS_ARRAY_LENGTH]);
+ }
+
+ // now test a null EthernetAddress case with extra data in the array
+ ethernet_address = new EthernetAddress(0L);
+ test_array = new byte[ETHERNET_ADDRESS_ARRAY_LENGTH + EXTRA_DATA_LENGTH];
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array, EXTRA_DATA_LENGTH/2);
+ assertEthernetAddressArraysAreEqual(
+ NULL_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ test_array, EXTRA_DATA_LENGTH/2);
+ for (int i = 0; i < EXTRA_DATA_LENGTH/2; i++)
+ {
+ assertEquals("Expected array fill value changed",
+ (byte)'x',
+ test_array[i]);
+ assertEquals("Expected array fill value changed",
+ (byte)'x',
+ test_array[i + ETHERNET_ADDRESS_ARRAY_LENGTH +
+ EXTRA_DATA_LENGTH/2]);
+ }
+
+ // now test a good EthernetAddress case with extra data in the array
+ ethernet_address =
+ new EthernetAddress(MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ test_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH + EXTRA_DATA_LENGTH];
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array, 0);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0, test_array, 0);
+ for (int i = 0; i < EXTRA_DATA_LENGTH; i++)
+ {
+ assertEquals("Expected array fill value changed",
+ (byte)'x',
+ test_array[i + ETHERNET_ADDRESS_ARRAY_LENGTH]);
+ }
+
+ // now test a good EthernetAddress case with extra data in the array
+ ethernet_address =
+ new EthernetAddress(MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ test_array =
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH + EXTRA_DATA_LENGTH];
+ Arrays.fill(test_array, (byte)'x');
+ ethernet_address.toByteArray(test_array, EXTRA_DATA_LENGTH/2);
+ assertEthernetAddressArraysAreEqual(
+ VALID_ETHERNET_ADDRESS_BYTE_ARRAY, 0,
+ test_array, EXTRA_DATA_LENGTH/2);
+ for (int i = 0; i < EXTRA_DATA_LENGTH/2; i++)
+ {
+ assertEquals("Expected array fill value changed",
+ (byte)'x',
+ test_array[i]);
+ assertEquals("Expected array fill value changed",
+ (byte)'x',
+ test_array[i + ETHERNET_ADDRESS_ARRAY_LENGTH +
+ EXTRA_DATA_LENGTH/2]);
+ }
+ }
+
+ /**
+ * Test of toLong method, of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testToLong()
+ {
+ // test making a couple EthernetAddresss and then check that the toLong
+ // gives back the same value in long form that was used to create it
+
+ // test the null EthernetAddress
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ assertEquals("null EthernetAddress long and toLong did not match",
+ NULL_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+
+ // test a non-null EthernetAddress
+ ethernet_address =
+ new EthernetAddress(VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertEquals("EthernetAddress long and toLong results did not match",
+ VALID_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+ }
+
+ /**
+ * Test of toString method, of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testToString()
+ {
+ // test making a few EthernetAddresss and check that the toString
+ // gives back the same value in string form that was used to create it
+
+ // test the null EthernetAddress
+ EthernetAddress ethernet_address = new EthernetAddress(0L);
+ assertEquals("null EthernetAddress string and toString did not match",
+ NULL_ETHERNET_ADDRESS_STRING.toLowerCase(),
+ ethernet_address.toString().toLowerCase());
+
+ // test a non-null EthernetAddress
+ ethernet_address =
+ new EthernetAddress(VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertEquals(
+ "EthernetAddress string and toString results did not match",
+ MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING.toLowerCase(),
+ ethernet_address.toString().toLowerCase());
+
+ // EthernetAddress implementation returns strings all lowercase.
+ // Although relying on this behavior in code is not recommended,
+ // here is a unit test which will break if this assumption
+ // becomes bad. This will act as an early warning to anyone
+ // who relies on this particular behavior.
+ ethernet_address =
+ new EthernetAddress(VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertFalse("mixed case EthernetAddress string and toString " +
+ "matched (expected toString to be all lower case)",
+ MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING.equals(
+ ethernet_address.toString()));
+ assertEquals("mixed case string toLowerCase and " +
+ "toString results did not match (expected toString to " +
+ "be all lower case)",
+ MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING.toLowerCase(),
+ ethernet_address.toString());
+ }
+
+ /**
+ * Test of valueOf(byte[]) method,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testValueOfByteArray()
+ {
+ // lets test some error cases
+ // first, passing null
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ EthernetAddress.valueOf((byte[])null);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NullPointerException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an array that is too small
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ EthernetAddress.valueOf(
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH - 1]);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NumberFormatException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an array that is too big
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ EthernetAddress.valueOf(
+ new byte[ETHERNET_ADDRESS_ARRAY_LENGTH + 1]);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NumberFormatException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // test that creating a EthernetAddress from an zero'd array
+ // gives us a null EthernetAddress (definition of null EthernetAddress)
+ EthernetAddress ethernet_address =
+ EthernetAddress.valueOf(new byte[ETHERNET_ADDRESS_ARRAY_LENGTH]);
+ assertEquals(
+ "EthernetAddress.valueOf did not create expected EthernetAddress",
+ NULL_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+
+ // let's test creating an array from a good byte array
+ ethernet_address =
+ EthernetAddress.valueOf(VALID_ETHERNET_ADDRESS_BYTE_ARRAY);
+ assertEquals(
+ "EthernetAddress.valueOf did not create expected EthernetAddress",
+ VALID_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+ }
+
+ /**
+ * Test of valueOf(int[]) method,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testValueOfIntArray()
+ {
+ // lets test some error cases
+ // first, passing null
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ EthernetAddress.valueOf((int[])null);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NullPointerException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an array that is too small
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ EthernetAddress.valueOf(
+ new int[ETHERNET_ADDRESS_ARRAY_LENGTH - 1]);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NumberFormatException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // now an array that is too big
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ EthernetAddress.valueOf(
+ new int[ETHERNET_ADDRESS_ARRAY_LENGTH + 1]);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NumberFormatException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // let's test that creating a EthernetAddress from an zero'd array
+ // gives a null EthernetAddress (definition of a null EthernetAddress)
+ EthernetAddress ethernet_address =
+ EthernetAddress.valueOf(new int[ETHERNET_ADDRESS_ARRAY_LENGTH]);
+ assertEquals(
+ "EthernetAddress.valueOf did not create expected EthernetAddress",
+ NULL_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+
+ // let's test creating an array from a good int array
+ ethernet_address =
+ EthernetAddress.valueOf(VALID_ETHERNET_ADDRESS_INT_ARRAY);
+ assertEquals(
+ "EthernetAddress.valueOf did not create expected EthernetAddress",
+ VALID_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+ }
+
+ /**
+ * Test of valueOf(long) method,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testValueOfLong()
+ {
+ // let's test that creating a EthernetAddress from an zero long
+ // gives a null EthernetAddress (definition of a null EthernetAddress)
+ EthernetAddress ethernet_address =
+ EthernetAddress.valueOf(0x0000000000000000L);
+ assertEquals(
+ "EthernetAddress.valueOf did not create expected EthernetAddress",
+ NULL_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+
+ // let's test creating an array from a good long
+ ethernet_address =
+ EthernetAddress.valueOf(VALID_ETHERNET_ADDRESS_LONG);
+ assertEquals(
+ "EthernetAddress.valueOf did not create expected EthernetAddress",
+ VALID_ETHERNET_ADDRESS_LONG,
+ ethernet_address.toLong());
+ }
+
+ /**
+ * Test of valueOf(String) method,
+ * of class com.fasterxml.uuid.EthernetAddress.
+ */
+ public void testValueOfString()
+ {
+ // test a null string case
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ EthernetAddress.valueOf((String)null);
+ fail("Expected exception not caught");
+ }
+ catch (NullPointerException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ // test some failure cases for the string constructor
+ badStringValueOfHelper(IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_1);
+ badStringValueOfHelper(IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_2);
+ badStringValueOfHelper(IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_3);
+ badStringValueOfHelper(IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_4);
+ badStringValueOfHelper(IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_5);
+ badStringValueOfHelper(IMPROPER_NUM_COLONS_ETHERNET_ADDRESS_STRING_6);
+ badStringValueOfHelper(NON_HEX_ETHERNET_ADDRESS_STRING);
+ badStringValueOfHelper(RANDOM_PROPER_LENGTH_STRING);
+
+ // some valid strings for the various dropped digit cases
+ goodStringValueOfHelper(FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(FIRST_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(FIRST_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ FIRST_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(SECOND_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(SECOND_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ SECOND_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(THIRD_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(THIRD_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ THIRD_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(FOURTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(FOURTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ FOURTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(FIFTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(FIFTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ FIFTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(SIXTH_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(SIXTH_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ SIXTH_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING,
+ MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(MIXED_GROUP_ONE_NUM_ETHERNET_ADDRESS_STRING,
+ MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(MIXED_GROUP_NO_NUM_ETHERNET_ADDRESS_STRING,
+ MIXED_GROUP_ALL_NUM_ETHERNET_ADDRESS_STRING);
+
+ // test the other good cases
+ goodStringValueOfHelper(NULL_ETHERNET_ADDRESS_STRING,
+ NULL_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(UPPER_CASE_VALID_ETHERNET_ADDRESS_STRING,
+ UPPER_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(LOWER_CASE_VALID_ETHERNET_ADDRESS_STRING,
+ LOWER_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ goodStringValueOfHelper(MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING,
+ MIXED_CASE_VALID_ETHERNET_ADDRESS_STRING);
+ }
+
+ /**
+ * Ok; this test is bit non-kosher, as it assumes existence of a valid
+ * interface
+ *
+ * @since 3.0
+ */
+ public void testFromInterface() throws Exception
+ {
+ EthernetAddress addr = EthernetAddress.fromInterface();
+ assertNotNull(addr);
+ assertNotNull(addr.toString());
+ }
+
+ public void testBogus() throws Exception
+ {
+ // First, two using pseudo-random; verify they are different
+ Random r = new Random(123);
+ EthernetAddress a1 = EthernetAddress.constructMulticastAddress(r);
+ assertNotNull(a1);
+ assertEquals(a1, a1);
+ assertTrue(a1.isMulticastAddress());
+ EthernetAddress a2 = EthernetAddress.constructMulticastAddress(r);
+ assertNotNull(a2);
+ assertTrue(a2.isMulticastAddress());
+ assertEquals(a2, a2);
+ assertFalse(a1.equals(a2));
+
+ // and then default, which uses SecureRandom
+ EthernetAddress a3 = EthernetAddress.constructMulticastAddress();
+ assertNotNull(a3);
+ assertNotNull(a3.toString());
+ }
+
+ /**************************************************************************
+ * Begin private helper functions for use in tests
+ *************************************************************************/
+ private void badStringEthernetAddressConstructorHelper(
+ String ethernetAddressString)
+ {
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ new EthernetAddress(ethernetAddressString);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NumberFormatException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+ }
+
+ private void goodStringEthernetAddressConstructorHelper(
+ String ethernetAddressString,
+ String expectedEthernetAddressString)
+ {
+ EthernetAddress ethernet_address = null;
+ try
+ {
+ ethernet_address = new EthernetAddress(ethernetAddressString);
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ assertEquals("EthernetAddresses were not equal",
+ expectedEthernetAddressString.toLowerCase(),
+ ethernet_address.toString().toLowerCase());
+ }
+
+ private void badStringValueOfHelper(String ethernetAddressString)
+ {
+ try
+ {
+ /*EthernetAddress ethernet_address =*/
+ EthernetAddress.valueOf(ethernetAddressString);
+ // if we reached here we failed because we didn't get an exception
+ fail("Expected exception not caught");
+ }
+ catch (NumberFormatException ex)
+ {
+ // this is the success case so do nothing
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+ }
+
+ private void goodStringValueOfHelper(String ethernetAddressString,
+ String expectedEthernetAddressString)
+ {
+ EthernetAddress ethernet_address = null;
+ try
+ {
+ ethernet_address = EthernetAddress.valueOf(ethernetAddressString);
+ }
+ catch (Exception ex)
+ {
+ fail("Caught unexpected exception: " + ex);
+ }
+
+ assertEquals("EthernetAddresses were not equal",
+ expectedEthernetAddressString.toLowerCase(),
+ ethernet_address.toString().toLowerCase());
+ }
+
+ private void assertEthernetAddressesMatchHelper(EthernetAddress expected,
+ EthernetAddress actual)
+ {
+ assertEquals("EthernetAddresses in long form did not match",
+ expected.toLong(),
+ actual.toLong());
+ assertEquals("EthernetAddress equals did not match",
+ expected,
+ actual);
+ }
+
+ private void assertEthernetAddressEqualOrderHelper(
+ EthernetAddress ethernetAddress1,
+ EthernetAddress ethernetAddress2)
+ {
+ assertTrue(ethernetAddress1 + " did not test as equal to " +
+ ethernetAddress2,
+ 0 == ethernetAddress1.compareTo(ethernetAddress2));
+ assertTrue(ethernetAddress2 + " did not test as equal to " +
+ ethernetAddress1,
+ 0 == ethernetAddress2.compareTo(ethernetAddress1));
+ }
+
+ private void assertEthernetAddressGreaterOrderHelper(
+ EthernetAddress ethernetAddress1,
+ EthernetAddress ethernetAddress2)
+ {
+ assertTrue(ethernetAddress1 + " did not test as larger then " +
+ ethernetAddress2,
+ 0 < ethernetAddress1.compareTo(ethernetAddress2));
+ assertTrue(ethernetAddress2 + " did not test as smaller then " +
+ ethernetAddress1,
+ 0 > ethernetAddress2.compareTo(ethernetAddress1));
+ }
+
+ private void assertEthernetAddressArraysAreEqual(byte[] array1,
+ int array1_start,
+ byte[] array2,
+ int array2_start)
+ {
+ assertTrue("Array1 start offset is invalid",
+ 0 <= array1_start);
+ assertTrue("Array2 start offset is invalid",
+ 0 <= array2_start);
+ assertTrue("Array1 is not long enough for the given start offset",
+ array1.length >= ETHERNET_ADDRESS_ARRAY_LENGTH + array1_start);
+ assertTrue("Array2 is not long enough for the given start offset",
+ array2.length >= ETHERNET_ADDRESS_ARRAY_LENGTH + array2_start);
+ for (int i = 0; i < ETHERNET_ADDRESS_ARRAY_LENGTH; i++)
+ {
+ assertEquals("Array1 and Array2 did not match (index #"+i+")",
+ array1[i + array1_start],
+ array2[i + array2_start]);
+ }
+ }
+
+ private void assertEthernetAddressArraysAreNotEqual(byte[] array1,
+ int array1_start,
+ byte[] array2,
+ int array2_start)
+ {
+ assertTrue("Array1 start offset is invalid",
+ 0 <= array1_start);
+ assertTrue("Array2 start offset is invalid",
+ 0 <= array2_start);
+ assertTrue("Array1 is not long enough for the given start offset",
+ array1.length >= ETHERNET_ADDRESS_ARRAY_LENGTH + array1_start);
+ assertTrue("Array2 is not long enough for the given start offset",
+ array2.length >= ETHERNET_ADDRESS_ARRAY_LENGTH + array2_start);
+ for (int i = 0; i < ETHERNET_ADDRESS_ARRAY_LENGTH; i++)
+ {
+ // as soon as we find a non-matching byte,
+ // we know we're not equal, so return
+ if (array1[i + array1_start] != array2[i + array2_start])
+ {
+ return;
+ }
+ }
+ fail("Array1 and Array2 matched");
+ }
+}
diff -Nru jug-2.0.0/src/test/java/com/fasterxml/uuid/SimpleGenerationTest.java jug-3.1.5/src/test/java/com/fasterxml/uuid/SimpleGenerationTest.java
--- jug-2.0.0/src/test/java/com/fasterxml/uuid/SimpleGenerationTest.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/test/java/com/fasterxml/uuid/SimpleGenerationTest.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,18 @@
+package com.fasterxml.uuid;
+
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+public class SimpleGenerationTest extends TestCase
+{
+ public void testIssue5() throws Exception
+ {
+ UUID uuid = Generators.randomBasedGenerator().generate();
+ assertNotNull(uuid);
+
+ // but second time's the charm...
+ uuid = Generators.randomBasedGenerator().generate();
+ assertNotNull(uuid);
+ }
+}
diff -Nru jug-2.0.0/src/test/java/com/fasterxml/uuid/UUIDComparatorTest.java jug-3.1.5/src/test/java/com/fasterxml/uuid/UUIDComparatorTest.java
--- jug-2.0.0/src/test/java/com/fasterxml/uuid/UUIDComparatorTest.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/test/java/com/fasterxml/uuid/UUIDComparatorTest.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,103 @@
+/* JUG Java UUID Generator
+ *
+ * Copyright (c) 2010 Tatu Saloranta
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid;
+
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+public class UUIDComparatorTest
+ extends TestCase
+{
+ public void testIntComp()
+ {
+ assertEquals(0, UUIDComparator.compareUInts(123, 123));
+ assertEquals(0, UUIDComparator.compareUInts(-9999, -9999));
+ assertEquals(0, UUIDComparator.compareUInts(0, 0));
+ assertEquals(0, UUIDComparator.compareUInts(Integer.MIN_VALUE, Integer.MIN_VALUE));
+ assertEquals(0, UUIDComparator.compareUInts(Integer.MAX_VALUE, Integer.MAX_VALUE));
+
+ assertTrue(UUIDComparator.compareUInts(0, 5) < 0);
+ assertTrue(UUIDComparator.compareUInts(5, 0) > 0);
+
+ assertTrue(UUIDComparator.compareUInts(4, 0xFFFFFFFE) < 0);
+ assertTrue(UUIDComparator.compareUInts(0xFFFFFFFE, 129) > 0);
+
+ assertTrue(UUIDComparator.compareUInts(0xFFFFFFFC, 0xFFFFFFFE) < 0);
+ assertTrue(UUIDComparator.compareUInts(0xFFFFFFFE, 0xFFFFFFFC) > 0);
+ assertTrue(UUIDComparator.compareUInts(0xFFFFFF17, 0xFFFFFF00) > 0);
+ assertTrue(UUIDComparator.compareUInts(0xFFFFFF00, 0xFFFFFF17) < 0);
+ }
+
+ public void testLongComp()
+ {
+ assertEquals(0, UUIDComparator.compareULongs(123L, 123L));
+ assertEquals(0, UUIDComparator.compareULongs(-9999L, -9999L));
+ assertEquals(0, UUIDComparator.compareULongs(0L, 0L));
+ assertEquals(0, UUIDComparator.compareULongs(Long.MIN_VALUE, Long.MIN_VALUE));
+ assertEquals(0, UUIDComparator.compareULongs(Long.MAX_VALUE, Long.MAX_VALUE));
+
+ assertTrue(UUIDComparator.compareULongs(0L, 5L) < 0);
+ assertTrue(UUIDComparator.compareULongs(5L, 0L) > 0);
+
+ // Ok, repeat int values first
+ assertTrue(UUIDComparator.compareULongs(4L, 0xFFFFFFFEL) < 0);
+ assertTrue(UUIDComparator.compareULongs(0xFFFFFFFEL, 129L) > 0);
+ assertTrue(UUIDComparator.compareULongs(0xFFFFFFFCL, 0xFFFFFFFEL) < 0);
+ assertTrue(UUIDComparator.compareULongs(0xFFFFFF17L, 0xFFFFFF00L) > 0);
+
+ assertTrue(UUIDComparator.compareULongs(1L, 0xffffffffFFFFFFFEL) < 0);
+ assertTrue(UUIDComparator.compareULongs(0xffffffffFFFFFFFEL, 13L) > 0);
+ assertTrue(UUIDComparator.compareULongs(0xffffffffFFFFFFFCL, 0xffffffffFFFFFFFEL) < 0);
+ assertTrue(UUIDComparator.compareULongs(0xffffffffFFFFFFFEL, 0xffffffffFFFFFFFCL) > 0);
+ assertTrue(UUIDComparator.compareULongs(0xffffffffFFFFFF17L, 0xffffffffFFFFFF00L) > 0);
+ assertTrue(UUIDComparator.compareULongs(0xffffffffFFFFFF00L, 0xffffffffFFFFFF17L) < 0);
+ }
+
+ /*
+ * [Issue#13]
+ */
+ public void testSorting()
+ {
+ String[] src = new String[] {
+ "7ef7c38a-bb6e-11e3-9e8f-000000000000",
+ "7f905a0b-bb6e-11e3-9e8f-000000000000",
+ "8028f08c-bb6e-11e3-9e8f-000000000000",
+ "80c1870d-bb6e-11e3-9e8f-000000000000"
+ };
+
+ /* 03-Apr-2014, tatu: NOTE: JDK's UUID.compareTo() is broken, and it can
+ * NOT be used. Which is why we have "UUIDComparator" that does work.
+ */
+ final UUIDComparator comp = new UUIDComparator();
+ for (int i = 0; i < src.length-1; ++i) {
+
+ UUID u1 = UUID.fromString(src[i]);
+ UUID u2 = UUID.fromString(src[i+1]);
+
+ assertEquals(0, comp.compare(u1, u1));
+ assertEquals(0, comp.compare(u2, u2));
+
+ int x = comp.compare(u1, u2);
+ if (x >= 0) {
+ fail("Entry #"+i+" should have value < 0, had "+x);
+ }
+ int y = comp.compare(u2, u1);
+ if (y <= 0) {
+ fail("Entry #"+i+" should have value > 0, had "+y);
+ }
+ }
+ }
+}
diff -Nru jug-2.0.0/src/test/java/com/fasterxml/uuid/UUIDGeneratorTest.java jug-3.1.5/src/test/java/com/fasterxml/uuid/UUIDGeneratorTest.java
--- jug-2.0.0/src/test/java/com/fasterxml/uuid/UUIDGeneratorTest.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/test/java/com/fasterxml/uuid/UUIDGeneratorTest.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,571 @@
+/* JUG Java Uuid Generator
+ * UUIDGeneratorTest.java
+ * Created on July 16, 2003, 11:17 PM
+ *
+ * Copyright (c) 2003 Eric Bie
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid;
+
+import java.security.MessageDigest;
+import java.util.*;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+
+import com.fasterxml.uuid.EthernetAddress;
+import com.fasterxml.uuid.Generators;
+import com.fasterxml.uuid.UUIDType;
+import com.fasterxml.uuid.impl.UUIDUtil;
+import com.fasterxml.uuid.impl.NameBasedGenerator;
+import com.fasterxml.uuid.impl.RandomBasedGenerator;
+import com.fasterxml.uuid.impl.TimeBasedGenerator;
+
+/**
+ * JUnit Test class for the com.fasterxml.uuid.UUIDGenerator class.
+ *
+ * @author Eric Bie
+ */
+public class UUIDGeneratorTest extends TestCase
+{
+ // size of the arrays to create for tests using arrays of values
+ private static final int SIZE_OF_TEST_ARRAY = 10000;
+
+ public UUIDGeneratorTest(java.lang.String testName)
+ {
+ super(testName);
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite(UUIDGeneratorTest.class);
+ return suite;
+ }
+
+ public static void main(String[] args)
+ {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Test of getDummyAddress method,
+ * of class com.fasterxml.uuid.UUIDGenerator.
+ */
+ public void testGetDummyAddress()
+ {
+ // this test will attempt to check for reasonable behavior of the
+ // getDummyAddress method
+
+ // for the random UUID generator, we will generate a bunch of
+ // dummy ethernet addresses
+ // NOTE: although creating a bunch of dummy ethernet addresses
+ // is not the normal mode of operation, we'return testing for
+ // generally good behavior, so we'll create a bunch to make sure the
+ // general patterns are observed
+ EthernetAddress ethernet_address_array[] =
+ new EthernetAddress[SIZE_OF_TEST_ARRAY];
+
+ // now create the array of uuids
+ Random rnd = new Random(123L);
+ for (int i = 0; i < ethernet_address_array.length; i++) {
+ ethernet_address_array[i] = EthernetAddress.constructMulticastAddress(rnd);
+ }
+
+ EthernetAddress null_ethernet_address = new EthernetAddress(0L);
+ for (int i = 0; i < ethernet_address_array.length; i++)
+ {
+ byte[] ethernet_address = ethernet_address_array[i].asByteArray();
+ // check that none of the EthernetAddresses are null
+ assertFalse("dummy EthernetAddress was null",
+ Arrays.equals(null_ethernet_address.asByteArray(),
+ ethernet_address));
+
+ // check that the "broadcast" bit is set in the created address
+ /* 08-Feb-2004, TSa: Fixed as per fix to actual code; apparently
+ * broadcast bit is LSB, not MSB.
+ */
+ assertEquals("dummy EthernetAddress was not broadcast",
+ 0x01,
+ (ethernet_address[0] & 0x01));
+ }
+ }
+
+ /**
+ * Test of generateRandomBasedUUID method,
+ * of class com.fasterxml.uuid.UUIDGenerator.
+ */
+ public void testGenerateRandomBasedUUID()
+ {
+ // this test will attempt to check for reasonable behavior of the
+ // generateRandomBasedUUID method
+
+ // we need a instance to use
+ RandomBasedGenerator uuid_gen = Generators.randomBasedGenerator();
+
+ // for the random UUID generator, we will generate a bunch of
+ // random UUIDs
+ UUID uuid_array[] = new UUID[SIZE_OF_TEST_ARRAY];
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++)
+ {
+ uuid_array[i] = uuid_gen.generate();
+ }
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+
+ // check that all the uuids were correct variant and version (type-4)
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.RANDOM_BASED);
+
+ // check that all uuids were unique
+ // NOTE: technically, this test 'could' fail, but statistically
+ // speaking it should be extremely unlikely unless the implementation
+ // of (Secure)Random is bad
+ checkUUIDArrayForUniqueness(uuid_array);
+ }
+
+ /**
+ * Test of generateTimeBasedUUID() method,
+ * of class com.fasterxml.uuid.UUIDGenerator.
+ */
+ public void testGenerateTimeBasedUUID()
+ {
+ // this test will attempt to check for reasonable behavior of the
+ // generateTimeBasedUUID method
+
+ // we need a instance to use
+ TimeBasedGenerator uuid_gen = Generators.timeBasedGenerator();
+
+ // first check that given a number of calls to generateTimeBasedUUID,
+ // all returned UUIDs order after the last returned UUID
+ // we'll check this by generating the UUIDs into one array and sorting
+ // then in another and checking the order of the two match
+ // change the number in the array statement if you want more or less
+ // UUIDs to be generated and tested
+ UUID uuid_array[] = new UUID[SIZE_OF_TEST_ARRAY];
+
+ // before we generate all the uuids, lets get the start time
+ long start_time = System.currentTimeMillis();
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++)
+ {
+ uuid_array[i] = uuid_gen.generate();
+ }
+
+ // now capture the end time
+ long end_time = System.currentTimeMillis();
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+
+ // check that all the uuids were correct variant and version (type-1)
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.TIME_BASED);
+
+ // check that all the uuids were generated with correct order
+ checkUUIDArrayForCorrectOrdering(uuid_array);
+
+ // check that all uuids were unique
+ checkUUIDArrayForUniqueness(uuid_array);
+
+ // check that all uuids have timestamps between the start and end time
+ checkUUIDArrayForCorrectCreationTime(uuid_array, start_time, end_time);
+ }
+
+ /**
+ * Test of generateTimeBasedUUID(EthernetAddress) method,
+ * of class com.fasterxml.uuid.UUIDGenerator.
+ */
+ public void testGenerateTimeBasedUUIDWithEthernetAddress()
+ {
+ // this test will attempt to check for reasonable behavior of the
+ // generateTimeBasedUUID(EthernetAddress) method
+ EthernetAddress ethernet_address =
+ new EthernetAddress("87:F5:93:06:D3:0C");
+
+ // we need a instance to use
+ TimeBasedGenerator uuid_gen = Generators.timeBasedGenerator(ethernet_address);
+
+ // check that given a number of calls to generateTimeBasedUUID,
+ // all returned UUIDs order after the last returned UUID
+ // we'll check this by generating the UUIDs into one array and sorting
+ // then in another and checking the order of the two match
+ // change the number in the array statement if you want more or less
+ // UUIDs to be generated and tested
+ UUID uuid_array[] = new UUID[SIZE_OF_TEST_ARRAY];
+
+ // before we generate all the uuids, lets get the start time
+ long start_time = System.currentTimeMillis();
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++) {
+ uuid_array[i] = uuid_gen.generate();
+ }
+
+ // now capture the end time
+ long end_time = System.currentTimeMillis();
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+
+ // check that all the uuids were correct variant and version (type-1)
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.TIME_BASED);
+
+ // check that all the uuids were generated with correct order
+ checkUUIDArrayForCorrectOrdering(uuid_array);
+
+ // check that all uuids were unique
+ checkUUIDArrayForUniqueness(uuid_array);
+
+ // check that all uuids have timestamps between the start and end time
+ checkUUIDArrayForCorrectCreationTime(uuid_array, start_time, end_time);
+
+ // check that all UUIDs have the correct ethernet address in the UUID
+ checkUUIDArrayForCorrectEthernetAddress(uuid_array, ethernet_address);
+ }
+
+ /**
+ * Test of generateNameBasedUUID(UUID, String)
+ * method, of class com.fasterxml.uuid.UUIDGenerator.
+ */
+ public void testGenerateNameBasedUUIDNameSpaceAndName()
+ {
+ // this test will attempt to check for reasonable behavior of the
+ // generateNameBasedUUID method
+
+ // we need a instance to use
+ NameBasedGenerator uuid_gen = Generators.nameBasedGenerator(NameBasedGenerator.NAMESPACE_URL);
+
+ UUID uuid_array[] = new UUID[SIZE_OF_TEST_ARRAY];
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++) {
+ uuid_array[i] = uuid_gen.generate("test name" + i);
+ }
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+
+ // check that all the uuids were correct variant and version
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.NAME_BASED_SHA1);
+
+ // check that all uuids were unique
+ checkUUIDArrayForUniqueness(uuid_array);
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++) {
+ uuid_array[i] = uuid_gen.generate("test name" + i);
+ }
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+
+ // check that all the uuids were correct variant and version
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.NAME_BASED_SHA1);
+
+ // check that all uuids were unique
+ checkUUIDArrayForUniqueness(uuid_array);
+
+ // now, lets make sure generating two sets of name based uuid with the
+ // same args always gives the same result
+ uuid_array = new UUID[SIZE_OF_TEST_ARRAY];
+
+ uuid_gen = Generators.nameBasedGenerator(NameBasedGenerator.NAMESPACE_URL);
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++) {
+ uuid_array[i] = uuid_gen.generate("test name" + i);
+ }
+
+ UUID uuid_array2[] = new UUID[SIZE_OF_TEST_ARRAY];
+ uuid_gen = Generators.nameBasedGenerator(NameBasedGenerator.NAMESPACE_URL);
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array2.length; i++) {
+ uuid_array2[i] = uuid_gen.generate("test name" + i);
+ }
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+ checkUUIDArrayForNonNullUUIDs(uuid_array2);
+
+ // check that all the uuids were correct variant and version
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.NAME_BASED_SHA1);
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array2, UUIDType.NAME_BASED_SHA1);
+
+ // check that all uuids were unique
+ checkUUIDArrayForUniqueness(uuid_array);
+ checkUUIDArrayForUniqueness(uuid_array2);
+
+ // check that both arrays are equal to one another
+ assertTrue("expected both arrays to be equal, they were not!",
+ Arrays.equals(uuid_array, uuid_array2));
+ }
+
+ /**
+ * Test of generateNameBasedUUID(UUID, String, MessageDigest)
+ * method, of class com.fasterxml.uuid.UUIDGenerator.
+ */
+ public void testGenerateNameBasedUUIDNameSpaceNameAndMessageDigest()
+ {
+ MessageDigest MESSAGE_DIGEST = null;
+ try
+ {
+ MESSAGE_DIGEST = MessageDigest.getInstance("MD5");
+ } catch (Exception ex) {
+ fail("exception caught getting test digest : " + ex);
+ }
+
+ // this test will attempt to check for reasonable behavior of the
+ // generateNameBasedUUID method
+
+ NameBasedGenerator uuid_gen = Generators.nameBasedGenerator(NameBasedGenerator.NAMESPACE_URL, MESSAGE_DIGEST);
+ UUID uuid_array[] = new UUID[SIZE_OF_TEST_ARRAY];
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++)
+ {
+ uuid_array[i] = uuid_gen.generate("test name"+i);
+ }
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+
+ // check that all the uuids were correct variant and version
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.NAME_BASED_MD5);
+
+ // check that all uuids were unique
+ checkUUIDArrayForUniqueness(uuid_array);
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++)
+ {
+ uuid_array[i] = uuid_gen.generate("test name" + i);
+ }
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+
+ // check that all the uuids were correct variant and version
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.NAME_BASED_MD5);
+
+ // check that all uuids were unique
+ checkUUIDArrayForUniqueness(uuid_array);
+
+ // now, lets make sure generating two sets of name based uuid with the
+ // same args always gives the same result
+ uuid_array = new UUID[SIZE_OF_TEST_ARRAY];
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array.length; i++) {
+ uuid_array[i] = uuid_gen.generate("test name" + i);
+ }
+
+ UUID uuid_array2[] = new UUID[SIZE_OF_TEST_ARRAY];
+
+ // now create the array of uuids
+ for (int i = 0; i < uuid_array2.length; i++) {
+ uuid_array2[i] = uuid_gen.generate("test name" + i);
+ }
+
+ // check that none of the UUIDs are null
+ checkUUIDArrayForNonNullUUIDs(uuid_array);
+ checkUUIDArrayForNonNullUUIDs(uuid_array2);
+
+ // check that all the uuids were correct variant and version
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array, UUIDType.NAME_BASED_MD5);
+ checkUUIDArrayForCorrectVariantAndVersion(uuid_array2, UUIDType.NAME_BASED_MD5);
+
+ // check that all uuids were unique
+ checkUUIDArrayForUniqueness(uuid_array);
+ checkUUIDArrayForUniqueness(uuid_array2);
+
+ // check that both arrays are equal to one another
+ assertTrue("expected both arrays to be equal, they were not!",
+ Arrays.equals(uuid_array, uuid_array2));
+ }
+
+ /**************************************************************************
+ * Begin Private Helper Methods for use in tests
+ *************************************************************************/
+ private class ReverseOrderUUIDComparator implements Comparatororg.safehaus.uuid.ext
does contain
- * simple wrappers to connect JUG logging to log4j and java.util.logging:
- *
- * @see org.safehaus.uuid.ext.Log4jLogger
- * @see org.safehaus.uuid.ext.JavaUtilLogger
- */
-public class Logger
-{
- /*
- //////////////////////////////////////////////////
- // Constants
- //////////////////////////////////////////////////
- */
-
- public final static int LOG_ALL = 0;
- public final static int LOG_INFO_AND_ABOVE = 1;
- public final static int LOG_WARNING_AND_ABOVE = 2;
- public final static int LOG_ERROR_AND_ABOVE = 3;
- public final static int LOG_NOTHING = 4;
-
- /*
- //////////////////////////////////////////////////
- // Static objects
- //////////////////////////////////////////////////
- */
-
- /**
- * By default we'll use this default implementation; however,
- * it can be easily changed.
- */
- private static Logger sInstance = new Logger();
-
- /*
- //////////////////////////////////////////////////
- // Default impl. configuration
- //////////////////////////////////////////////////
- */
-
- /**
- * Threshold to use for outputting varius log statements.
- *System.err
.
- */
- protected PrintStream mOutput1 = System.err;
-
- /**
- * Override output used to explicitly specify where to pass diagnostic
- * output, instead of System.err. Used if mOutput1
- * is null;
- */
- protected PrintWriter mOutput2 = null;
-
- /*
- /////////////////////////////////////////////////////////////
- // Life-cycle
- /////////////////////////////////////////////////////////////
- */
-
- protected Logger() {
- }
-
- /**
- * Method that can be used to completely re-define the logging
- * functionality JUG uses. When called, JUG will start using the
- * new instance; if instance passed is null, will basically suppress
- * all logging.
- *
- * @param inst Logger instance to use for all logging JUG does; can be
- * null, but if so, essentially disables all logging.
- */
- public synchronized static void setLogger(Logger inst)
- {
- sInstance = inst;
- }
-
- /*
- /////////////////////////////////////////////////////////////
- // Actual simple logging API
- // (static dispatchers to instance methods)
- /////////////////////////////////////////////////////////////
- */
-
- // // // Configuration
-
- /**
- * Method to set the minimum level of messages that will get logged
- * using currently specific logger instace. For example, if
- * {@link #LOG_WARNING_AND_ABOVE} is passed as the argument, warnings
- * and errors will be logged, but informational (INFO) messages will
- * not.
- *
- *
- */
-
-public class NativeInterfaces
-{
- protected final static String sDefaultLibSubdir = "jug-native";
-
- /**
- * Path to dir that contains native lib code. If not specified,
- * {@link #sDefaultLibSubdir} is used.
- */
- private static File sLibDir = null;
-
- /**
- * Whether native code is to be loaded from system-dependant standard
- * library location or not. Default is false, meaning that standard
- * location is NOT used.
- */
- private static boolean sUseStdLibDir = false;
-
- /// Whether native library has already been loaded
- private static boolean mNativeLoaded = false;
-
- /**
- * Method that allows overriding of default library directory, to
- * allow loading of native interface access code from specific
- * application dependant location.
- */
- public synchronized static void setLibDir(File f)
- {
- sLibDir = f;
- }
-
- public synchronized static void setUseStdLibDir(boolean b)
- {
- sUseStdLibDir = b;
- }
-
- protected synchronized static void checkLoad()
- {
- if (!mNativeLoaded) {
- String os = System.getProperty("os.name").trim().toLowerCase();
- String arch = System.getProperty("os.arch").trim().toLowerCase();
-
- String realOS = null, realArch = null;
-
- /* Let's try to figure canonical OS name, just in case some
- * JVMs use funny values (unlikely)
- */
- if (os.indexOf("windows") >= 0) {
- realOS = "win";
- } else if (os.indexOf("linux") >= 0) {
- realOS = "linux";
- } else if (os.indexOf("solaris") >= 0
- || os.indexOf("sunos") >= 0) {
- realOS = "solaris";
- } else if (os.indexOf("mac os x") >= 0
- || os.indexOf("macosx") >= 0) {
- realOS = "macosx";
- } else if (os.indexOf("bsd") >= 0) {
- if (os.indexOf("freebsd") >= 0) {
- realOS = "freebsd";
- } else if (os.indexOf("netbsd") >= 0) {
- realOS = "netbsd";
- } else if (os.indexOf("openbsd") >= 0) {
- realOS = "openbsd";
- } else { // default
- realOS = "bsd";
- }
- } else if (os.indexOf("aix") >= 0) {
- realOS = "aix";
- } else if (os.indexOf("hp ux") >= 0) {
- realOS = "hpux";
- } else {
- throw new Error("No native ethernet access library for OS '"+os+"'.");
- }
-
- /* And ditto for arch value... here it's more likely weird
- * values exist?
- */
- if (arch.indexOf("x86") >= 0 || arch.indexOf("sparc") >= 0
- || arch.indexOf("ppc") >= 0) {
- realArch = arch;
-
- // Apparently 'i386' means x86 architecture in JVM lingo?
- } else if (arch.indexOf("86") >= 0 || arch.indexOf("amd") >= 0) {
- realArch = "x86";
- } else {
- throw new Error("No native ethernet access library for hardware platform with value '"+arch+"'.");
- }
-
- /* Still not really guaranteed to work; not all combinations
- * of os + arch are either valid, or have matching library
- * (notably, linux+sparc and solaris+x86 are missing?)
- */
-
- String libName = realOS + "_" + realArch + "_" + "EtherAddr";
-
- if (sUseStdLibDir) {
- loadStdLib(libName);
- } else {
- loadAppLib(libName);
- }
-
- mNativeLoaded = true;
- }
- }
-
- private static void loadStdLib(String libName)
- {
- try {
- System.loadLibrary(libName);
- } catch (SecurityException sex) {
- throw new Error("Trying to load library '"+libName+"': error; "+sex.toString());
- } catch (UnsatisfiedLinkError uex) {
- throw new Error("Trying to load library '"+libName+"': error; "+uex.toString());
- }
- }
-
- private static void loadAppLib(String libName)
- {
- String realLibName = System.mapLibraryName(libName);
- String prefix = "Tried to load library '"+libName
- +"' (filename assumed to be '"+realLibName+"')";
-
- try {
- File f;
-
- if (sLibDir == null) {
- f = new File(sDefaultLibSubdir);
- f = new File(f, realLibName);
- } else {
- f = new File(sLibDir, realLibName);
- }
- // Let's first check if such a file exists...
- try {
- f = f.getCanonicalFile();
- } catch (IOException ie) {
- throw new Error(prefix+": checking existence of '"+f.getAbsolutePath()+"': "+ie.toString());
- }
- System.load(f.getAbsolutePath());
- // Uncomment for debugging:
- //System.err.println("DEBUG: "+prefix+": Ok.");
- } catch (SecurityException sex) {
- throw new Error(prefix+": error; "+sex.toString());
- } catch (UnsatisfiedLinkError unsatisfiedex) {
- throw new Error(prefix+": error; "+unsatisfiedex.toString());
- }
- }
-
- public static org.safehaus.uuid.EthernetAddress getPrimaryInterface()
- {
- checkLoad();
-
- try {
- com.ccg.net.ethernet.EthernetAddress ea =
- com.ccg.net.ethernet.EthernetAddress.getPrimaryAdapter();
- if (ea != null) {
- return new org.safehaus.uuid.EthernetAddress(ea.getBytes());
- }
- } catch (UnsatisfiedLinkError ue) {
- /* Should never happen as checkLoad() should have taken
- * care of the problems
- */
- throw new Error(ue.toString());
- }
-
- return null;
- }
-
- public static org.safehaus.uuid.EthernetAddress[] getAllInterfaces()
- {
- org.safehaus.uuid.EthernetAddress[] eas = null;
-
- checkLoad();
-
- try {
- Collection c = com.ccg.net.ethernet.EthernetAddress.getAllAdapters();
- eas = new org.safehaus.uuid.EthernetAddress[c.size()];
- Iterator it = c.iterator();
-
- for (int i = 0; it.hasNext(); ++i) {
- com.ccg.net.ethernet.EthernetAddress ea =
- (com.ccg.net.ethernet.EthernetAddress) it.next();
- eas[i] = new org.safehaus.uuid.EthernetAddress(ea.getBytes());
- }
- } catch (UnsatisfiedLinkError ue) {
- /* Should never happen as checkLoad() should have taken
- * care of the problems
- */
- throw new Error(ue.toString());
- }
-
- return eas;
- }
-
- /**
- * Test driver to test if native ethernet adapter/interface access
- * works ok. Tries to get the primary interface and output it; prints
- * out error message if access fails.
- */
- public static void main(String[] args)
- {
- if (args.length > 0 && args[0].equalsIgnoreCase("lib")) {
- System.out.println("Trying to access primary ethernet interface using system-dependant library loading (use 'app' argument for other test)");
- setUseStdLibDir(true);
- } else {
- System.out.println("Trying to access primary ethernet interface using system independent code loading (use 'lib' argument for other test)");
- setUseStdLibDir(false);
- }
-
- System.out.println("Trying to access primary ethernet interface:");
- try {
- org.safehaus.uuid.EthernetAddress pea = getPrimaryInterface();
-
- System.out.println("Ok, the interface MAC-address is: "
- +pea.toString());
- } catch (Throwable t) {
- System.out.println("Failed, error given: "+t.toString());
- }
- }
-}
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/package.html jug-3.1.5/src/java/org/safehaus/uuid/package.html
--- jug-2.0.0/src/java/org/safehaus/uuid/package.html 2005-08-17 04:31:45.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/package.html 1970-01-01 00:00:00.000000000 +0000
@@ -1,7 +0,0 @@
-
-Package that contains core (non-optional) Jug classes. These classes
-should be usable on JDK 1.1 and up, and have no external dependencies
-(with the exception of {@link org.safehaus.uuid.NativeInterfaces}
-that depends on JNI modules during runtime).
-
-
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/TagURI.java jug-3.1.5/src/java/org/safehaus/uuid/TagURI.java
--- jug-2.0.0/src/java/org/safehaus/uuid/TagURI.java 2005-07-21 05:25:49.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/TagURI.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,127 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002 Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid;
-
-import java.util.*;
-
-/**
- * A class that allows creation of tagURI instances.
- *
- * TagURIs are specified in IETF draft
- *
- * (see tagURI draft for more examples and full explanation of the
- * basic concepts)
- *
- * @param authority Authority that created tag URI; usually either a
- * fully-qualified domain name ("www.w3c.org") or an email address
- * ("tatu.saloranta@iki.fi").
- * @param identifier A locally unique identifier; often file path or
- * URL path component (like, "tst.1234567890", "/home/tatu/index.html")
- * @param date Date to add as part of the tag URI, if any; null is used
- * used to indicate that no datestamp should be added.
- *
- */
- public TagURI(String authority, String identifier, Calendar date)
- {
- StringBuffer b = new StringBuffer();
- b.append("tag:");
- b.append(authority);
- if (date != null) {
- b.append(',');
- b.append(date.get(Calendar.YEAR));
- // Month is optional if it's "january" and day is "1st":
- int month = date.get(Calendar.MONTH) - Calendar.JANUARY + 1;
- int day = date.get(Calendar.DAY_OF_MONTH);
- if (month != 1 || day != 1) {
- b.append('-');
- b.append(month);
- }
- if (day != 1) {
- b.append('-');
- b.append(day);
- }
- }
- b.append(':');
- b.append(identifier);
-
- mDesc = b.toString();
- }
-
- public String toString() { return mDesc; }
-
- public boolean equals(Object o)
- {
- if (o instanceof TagURI) {
- return mDesc.equals(((TagURI) o).toString());
- }
- return false;
- }
-
- /**
- * A simple test harness is added to make (automated) testing of the
- * class easier.
- */
- public static void main(String[] args)
- {
- System.out.println("TagURI.main()");
- System.out.println("--------------------");
- System.out.println();
-
- String[] auths = { "www.w3c.org", "www.google.com", "www.fi",
- "tatu.saloranta@iki.fi"
- };
- String[] ids = { "1234", "/home/billg/public_html/index.html",
- "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
- "foobar"
- };
-
- Calendar c = null;
- String auth = null;
- for (int i = 0; i < 4; ++i) {
- // Let's just change the date & URL a bit:
- switch (i) {
- case 2:
- c.add(Calendar.MONTH, 1);
- break;
- case 3:
- c.add(Calendar.DAY_OF_MONTH, -7);
- break;
- }
- for (int j = 0; j < 4; ++j) {
- TagURI t = new TagURI(auths[i], ids[j], c);
- System.out.println("tagURI: "+t);
- }
- if (c == null) {
- c = Calendar.getInstance();
- }
- }
- }
-}
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/TimestampSynchronizer.java jug-3.1.5/src/java/org/safehaus/uuid/TimestampSynchronizer.java
--- jug-2.0.0/src/java/org/safehaus/uuid/TimestampSynchronizer.java 2005-08-06 06:09:53.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/TimestampSynchronizer.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,82 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid;
-
-import java.io.IOException;
-
-/**
- * This is the API for utility classes optionally used by {@link UUIDTimer} to
- * ensure that timestamp values used for generating time/location-based UUIDs
- * are monotonically increasing, as well as that only one such generator
- * is ever used on a single system, even in presence of multiple JVMs.
- *0L
if it
- * can not
- * determine it and caller can use whatever value (current timestamp)
- * it has access to.
- */
- protected abstract long initialize()
- throws IOException;
-
- /**
- * Method {@link UUIDTimer} will call if this synchronizer object is
- * being replaced by another synchronizer (or removed, that is, no
- * more synchronization is to be done). It will not be called if JVM
- * terminates.
- */
- protected abstract void deactivate()
- throws IOException;
-
- /**
- * Method called by {@link UUIDTimer} to indicate that it has generated
- * a timestamp value that is beyond last legal timestamp value.
- * The method should only return once it has "locked" specified timestamp
- * value (and possible additional ones).
- *
- * @param now Timestamp value caller wants to use, and that the
- * synchronizer is asked to protect.
- *
- * @return First timestamp value that can NOT be used by the caller;
- * has to be higher than the input timestamp value
- */
- protected abstract long update(long now)
- throws IOException;
-}
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/UUIDGenerator.java jug-3.1.5/src/java/org/safehaus/uuid/UUIDGenerator.java
--- jug-2.0.0/src/java/org/safehaus/uuid/UUIDGenerator.java 2005-08-10 03:41:33.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/UUIDGenerator.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,597 +0,0 @@
-
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid;
-
-import java.io.*;
-import java.security.NoSuchAlgorithmException;
-import java.security.MessageDigest;
-import java.security.SecureRandom;
-import java.util.*;
-
-/**
- * UUIDGenerator is the class that contains factory methods for
- * generating UUIDs using one of the three specified 'standard'
- * UUID generation methods:
- * (see draft-leach-uuids-guids-01.txt for details)
- *
- *
- *
- * Some comments about performance:
- *
- *
- */
-public final class UUIDGenerator
-{
- private final static UUIDGenerator sSingleton = new UUIDGenerator();
-
- /**
- * Random-generator, used by various UUID-generation methods:
- */
- private Random mRnd = null;
-
- // Ethernet address for time-based UUIDs:
-
- private final Object mDummyAddressLock = new Object();
- private EthernetAddress mDummyAddress = null;
- private final Object mTimerLock = new Object();
- private UUIDTimer mTimer = null;
-
- /**
- * MD5 hasher for name-based digests:
- */
- private MessageDigest mHasher = null;
-
- /*
- /////////////////////////////////////////////////////
- // Life-cycle
- /////////////////////////////////////////////////////
- */
-
- /**
- * Constructor is private to enforce singleton access.
- */
- private UUIDGenerator() { }
-
- /**
- * Method used for accessing the singleton generator instance.
- */
- public static UUIDGenerator getInstance()
- {
- return sSingleton;
- }
-
- /**
- * Method that can (and should) be called once right after getting
- * the instance, to ensure that system time stamp values used are
- * valid (with respect to values used earlier by JUG instances), and
- * to use file-lock based synchronization mechanism to prevent multiple
- * JVMs from running conflicting instances of JUG (first one to be
- * started wins on contention). It can also be called to stop
- * synchronization by calling it with argument null, although such
- * usage is strongly discouraged (ie. it's a good idea to either never
- * use synchronization, or always; but not to mix modes).
- *
- * UUID uuid = gen.generateNameBasedUUID(
- * new UUID(UUID.NAMESPACE_DNS, "www.w3c.org"));
- *
- */
- public UUID generateNameBasedUUID(UUID nameSpaceUUID, String name,
- MessageDigest digest)
- {
- digest.reset();
- if (nameSpaceUUID != null) {
- digest.update(nameSpaceUUID.asByteArray());
- }
- digest.update(name.getBytes());
- return new UUID(UUID.TYPE_NAME_BASED, digest.digest());
- }
-
- /**
- * Method similar to the previous one; the difference being that a
- * shared MD5 digest instance will be used. This also means that there is
- * some synchronization overhead as MD5-instances are not thread-safe
- * per se.
- */
- public UUID generateNameBasedUUID(UUID nameSpaceUUID, String name)
- {
- MessageDigest hasher = getHashAlgorithm();
- synchronized (hasher) {
- return generateNameBasedUUID(nameSpaceUUID, name, getHashAlgorithm());
- }
- }
-
- /**
- * Method for generating UUIDs using tag URIs. A hash is calculated from
- * the given tag URI (default being MD5 hash). The resulting UUIDs
- * are reproducible, ie. given the same tag URI, same UUID will always
- * result, much like with the default name-based generation method.
- *
- * Note that this a non-standard way of generating UUIDs; it will create
- * UUIDs that appear to be name-based (and which are, but not using the
- * method specified in UUID specs).
- *
- * @param name tag URI to base UUID on.
- */
- public UUID generateTagURIBasedUUID(TagURI name)
- {
- return generateNameBasedUUID(null, name.toString());
- }
-
- /**
- * Method for generating UUIDs using tag URIs. A hash is calculated from
- * the given tag URI using the specified hashing algorith,.
- * The resulting UUIDs are reproducible, ie. given the same tag URI and
- * hash algorithm, same UUID will always result, much like with the
- * default name-based generation method.
- *
- * Note that this a non-standard way of generating UUIDs; it will create
- * UUIDs that appear to be name-based (and which are, but not using the
- * method specified in UUID specs).
- *
- * @param name tag URI to base UUID on.
- * @param hasher Hashing algorithm to use. Note that the caller has to
- * make sure that it's thread-safe to use 'hasher', either by never
- * calling this method from multiple threads, or by explicitly sync'ing
- * the calls.
- */
- public UUID generateTagURIBasedUUID(TagURI name, MessageDigest hasher)
- {
- return generateNameBasedUUID(null, name.toString(), hasher);
- }
-
- /*
- /////////////////////////////////////////////////////
- // Other methods
- /////////////////////////////////////////////////////
- */
-
- /**
- * A simple test harness is added to make (automated) testing of the
- * class easier. For real testing, JUnit based unit tests should
- * be run.
- */
- public static void main(String[] args)
- {
- UUIDGenerator g = UUIDGenerator.getInstance();
- UUID nsUUID = new UUID(UUID.NAMESPACE_URL);
-
- System.out.println("UUIDGenerator.main()");
- System.out.println();
-
- /* Let's test equality testing and ordering by using TreeSet;
- * since all UUIDs should be unique set should contain them all,
- * and in the specified order.
- */
- final int ROUNDS = 4;
- final int UUID_COUNT = ROUNDS * 3;
- Set uuids = new TreeSet();
- List timebased = new ArrayList(ROUNDS);
-
- /* First we'll create the UUIDs and do conversion tests:
- */
- for (int i = 0; i < ROUNDS; ++i) {
- System.out.print("Random UUID: ");
- UUID u = g.generateRandomBasedUUID();
- uuids.add(u);
- doTest(u, System.out, UUID.TYPE_RANDOM_BASED);
-
- System.out.print("Time-based UUID: ");
- u = g.generateTimeBasedUUID();
- uuids.add(u);
- timebased.add(u);
- doTest(u, System.out, UUID.TYPE_TIME_BASED);
-
- String name = "test-round-"+i;
- System.out.print("Named-based UUID: (namespace URL, name '"
- +name+"')");
- u = g.generateNameBasedUUID(nsUUID, name);
- uuids.add(u);
- doTest(u, System.out, UUID.TYPE_NAME_BASED);
- }
-
- /* And then we'll see if comparision & sorting work as
- * expected:
- */
- int count = uuids.size();
- System.out.print("Created "+UUID_COUNT+" uuids; ordered treeset contains "+count);
- System.out.println((count == UUID_COUNT) ? " [OK]" : " [FAIL]");
- System.out.println("Checking ordering:");
-
- // First, major ordering by type:
- Iterator it = uuids.iterator();
- int prevType = -1;
- System.out.print("Overall ordering by type: ");
- while (it.hasNext()) {
- System.out.print(".");
- UUID uuid = (UUID) it.next();
- int currType = uuid.getType();
- if (currType < prevType) {
- break;
- }
- prevType = currType;
- }
- System.out.println(it.hasNext() ? "FAIL" : "OK");
-
- // And then ordering of time-based UUIDs:
- it = uuids.iterator();
- int lastIndex = -1;
- System.out.print("Time-based UUID ordering on creation time: ");
- while (it.hasNext()) {
- UUID uuid = (UUID) it.next();
- int index = timebased.indexOf(uuid);
- if (index >= 0) {
- System.out.print("[");
- System.out.print(index);
- System.out.print("]");
- if (index <= lastIndex) {
- break;
- }
- }
- }
- System.out.println(it.hasNext() ? "FAIL" : "OK");
-
- /* Then we'll see if both shared and explicit null UUIDs are
- * recognized as null UUIDs:
- */
- doTestNull();
- }
-
- private final static void doTest(UUID uuid, PrintStream out, int type)
- {
- System.out.print(uuid.toString());
- System.out.print(" [type: "+uuid.getType());
- System.out.print(", expected "+type);
- System.out.print(type == uuid.getType() ? ": OK" : ": FAIL");
- System.out.println("]");
-
- // Conversion test, UUID <-> string
- System.out.print("... conversion UUID<->String: ");
- try {
- UUID uuid2 = UUID.valueOf(uuid.toString());
- System.out.println(uuid2.toString());
- System.out.print(" -> ");
- System.out.println(uuid.equals(uuid2) ? "OK" : "FAIL");
- } catch (NumberFormatException nex) {
- System.out.println("[FAIL: "+nex.toString()+"]");
- }
-
- // Conversion test, UUID <-> byte array
- System.out.print("... conversion UUID<->byte array: ");
- {
- UUID uuid3 = UUID.valueOf(uuid.asByteArray());
- System.out.println(uuid3.toString());
- System.out.print(" -> ");
- System.out.println(uuid.equals(uuid3) ? "OK" : "FAIL");
- }
-
- System.out.print("... considered null? ");
- boolean isNull = uuid.isNullUUID();
- System.out.print(isNull);
- System.out.print(" (shouldn't be) -> ");
- System.out.println(isNull ? "FAIL" : "OK");
- }
-
- private final static void doTestNull()
- {
- UUID sharedNull = UUID.getNullUUID();
-
- System.out.println("Testing null UUID checks:");
-
- System.out.print("Testing shared null uuid; considered null: ");
- boolean ok = sharedNull.isNullUUID();
- System.out.print(ok);
- System.out.print("; expected true -> ");
- System.out.println(ok ? "OK" : "FAIL");
-
- UUID localNull = new UUID(new byte[16]); // java runtime clears the array
-
- System.out.print("Testing explicit null uuid; considered null: ");
- ok = localNull.isNullUUID();
- System.out.print(ok);
- System.out.print("; expected true -> ");
- System.out.println(ok ? "OK" : "FAIL");
- }
-}
diff -Nru jug-2.0.0/src/java/org/safehaus/uuid/UUID.java jug-3.1.5/src/java/org/safehaus/uuid/UUID.java
--- jug-2.0.0/src/java/org/safehaus/uuid/UUID.java 2005-08-02 05:28:42.000000000 +0000
+++ jug-3.1.5/src/java/org/safehaus/uuid/UUID.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,572 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
- *
- * Licensed under the License specified in the file LICENSE which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * 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.safehaus.uuid;
-
-import java.io.Serializable;
-
-/**
- * UUID represents Universally Unique Identifiers (aka Global UID in
- * Windows world). UUIDs are usually generated via UUIDGenerator (or in
- * case of 'Null UUID', 16 zero bytes, via static method getNullUUID()),
- * or received from external systems.
- *
- * By default class caches the string presentations of UUIDs so that
- * description is only created the first time it's needed. For memory
- * stingy applications this caching can be turned off (note though
- * that if uuid.toString() is never called, desc is never calculated
- * so only loss is the space allocated for the desc pointer... which
- * can of course be commented out to save memory).
- *
- * Similarly, hash code is calculated when it's needed for the first
- * time, and from thereon that value is just returned. This means
- * that using UUIDs as keys should be reasonably efficient.
- *
- * UUIDs can be compared for equality, serialized, cloned and even sorted.
- * Equality is a simple bit-wise comparison. Ordering (for sorting) is done by
- * first ordering based on type (in the order of numeric values of
- * types), secondarily by time stamp (only for time-based time stamps),
- * and finally by straight numeric byte-by-byte comparison (from
- * most to least significant bytes).
- */
-
-public class UUID
- implements Serializable, Cloneable, Comparable
-{
- private final static String kHexChars = "0123456789abcdefABCDEF";
-
- public final static byte INDEX_CLOCK_HI = 6;
- public final static byte INDEX_CLOCK_MID = 4;
- public final static byte INDEX_CLOCK_LO = 0;
-
- public final static byte INDEX_TYPE = 6;
- // Clock seq. & variant are multiplexed...
- public final static byte INDEX_CLOCK_SEQUENCE = 8;
- public final static byte INDEX_VARIATION = 8;
-
- public final static byte TYPE_NULL = 0;
- public final static byte TYPE_TIME_BASED = 1;
- public final static byte TYPE_DCE = 2; // Not used
- public final static byte TYPE_NAME_BASED = 3;
- public final static byte TYPE_RANDOM_BASED = 4;
-
- /* 'Standard' namespaces defined (suggested) by UUID specs:
- */
- public final static String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
- public final static String NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
- public final static String NAMESPACE_OID = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
- public final static String NAMESPACE_X500 = "6ba7b814-9dad-11d1-80b4-00c04fd430c8";
-
- /* By default let's cache desc, can be turned off. For hash code
- * there's no point in turning it off (since the int is already
- * part of the instance memory allocation); if you want to save
- * those 4 bytes (or possibly bit more if alignment is bad) just
- * comment out hash caching.
- */
- private static boolean sDescCaching = true;
-
- /**
- * The shared null UUID. Would be nice to do lazy instantiation, but
- * if the instance really has to be a singleton, that would mean
- * class-level locking (synchronized getNullUUID()), which would
- * be some overhead... So let's just bite the bullet the first time
- * assuming creation of the null UUID (plus wasted space if it's
- * not needed) can be ignored.
- */
- private final static UUID sNullUUID = new UUID();
-
- private final byte[] mId = new byte[16];
- // Both string presentation and hash value may be cached...
- private transient String mDesc = null;
- private transient int mHashCode = 0;
-
- /* *** Object creation: *** */
-
- /**
- * Default constructor creates a NIL UUID, one that contains all
- * zeroes
- *
- * Note that the clearing of array is actually unnecessary as
- * JVMs are required to clear up the allocated arrays by default.
- */
- public UUID()
- {
- /*
- for (int i = 0; i < 16; ++i) {
- mId[i] = (byte)0;
- }
- */
- }
-
- /**
- * Constructor for cases where you already have the 16-byte binary
- * representation of the UUID (for example if you save UUIDs binary
- * takes less than half of space string representation takes).
- *
- * @param data array that contains the binary representation of UUID
- */
- public UUID(byte[] data)
- {
- /* Could call the other constructor... and/or use System.arraycopy.
- * However, it's likely that those would make this slower to use,
- * and initialization is really simple as is in any case.
- */
- for (int i = 0; i < 16; ++i) {
- mId[i] = data[i];
- }
- }
-
- /**
- * Constructor for cases where you already have the binary
- * representation of the UUID (for example if you save UUIDs binary
- * takes less than half of space string representation takes) in
- * a byte array
- *
- * @param data array that contains the binary representation of UUID
- * @param start byte offset where UUID starts
- */
- public UUID(byte[] data, int start)
- {
- for (int i = 0; i < 16; ++i) {
- mId[i] = data[start + i];
- }
- }
-
- /**
- * Protected constructor used by UUIDGenerator
- *
- * @param type UUID type
- * @param data 16 byte UUID contents
- */
- UUID(int type, byte[] data)
- {
- for (int i = 0; i < 16; ++i) {
- mId[i] = data[i];
- }
- // Type is multiplexed with time_hi:
- mId[INDEX_TYPE] &= (byte) 0x0F;
- mId[INDEX_TYPE] |= (byte) (type << 4);
- // Variant masks first two bits of the clock_seq_hi:
- mId[INDEX_VARIATION] &= (byte) 0x3F;
- mId[INDEX_VARIATION] |= (byte) 0x80;
- }
-
- /**
- * Constructor for creating UUIDs from the canonical string
- * representation
- *
- * Note that implementation is optimized for speed, not necessarily
- * code clarity... Also, since what we get might not be 100% canonical
- * (see below), let's not yet populate mDesc here.
- *
- * @param id String that contains the canonical representation of
- * the UUID to build; 36-char string (see UUID specs for details).
- * Hex-chars may be in upper-case too; UUID class will always output
- * them in lowercase.
- */
- public UUID(String id)
- throws NumberFormatException
- {
- if (id == null) {
- throw new NullPointerException();
- }
- if (id.length() != 36) {
- throw new NumberFormatException("UUID has to be represented by the standard 36-char representation");
- }
-
- for (int i = 0, j = 0; i < 36; ++j) {
- // Need to bypass hyphens:
- switch (i) {
- case 8:
- case 13:
- case 18:
- case 23:
- if (id.charAt(i) != '-') {
- throw new NumberFormatException("UUID has to be represented by the standard 36-char representation");
- }
- ++i;
- }
- int index;
- char c = id.charAt(i);
-
- if (c >= '0' && c <= '9') {
- mId[j] = (byte) ((c - '0') << 4);
- } else if (c >= 'a' && c <= 'f') {
- mId[j] = (byte) ((c - 'a' + 10) << 4);
- } else if (c >= 'A' && c <= 'F') {
- mId[j] = (byte) ((c - 'A' + 10) << 4);
- } else {
- throw new NumberFormatException("Non-hex character '"+c+"'");
- }
-
- c = id.charAt(++i);
-
- if (c >= '0' && c <= '9') {
- mId[j] |= (byte) (c - '0');
- } else if (c >= 'a' && c <= 'f') {
- mId[j] |= (byte) (c - 'a' + 10);
- } else if (c >= 'A' && c <= 'F') {
- mId[j] |= (byte) (c - 'A' + 10);
- } else {
- throw new NumberFormatException("Non-hex character '"+c+"'");
- }
- ++i;
- }
- }
-
- /**
- * Default cloning behaviour (bitwise copy) is just fine...
- *
- * Could clear out cached string presentation, but there's
- * probably no point in doing that.
- */
- public Object clone()
- {
- try {
- return super.clone();
- } catch (CloneNotSupportedException e) {
- // shouldn't happen
- return null;
- }
- }
-
- /* *** Configuration: *** */
- public static void setDescCaching(boolean state)
- {
- sDescCaching = state;
- }
-
- /* *** Accessors: *** */
-
- /**
- * Accessor for getting the shared null UUID
- *
- * @return the shared null UUID
- */
- public static UUID getNullUUID()
- {
- return sNullUUID;
- }
-
- public boolean isNullUUID()
- {
- // Assuming null uuid is usually used for nulls:
- if (this == sNullUUID) {
- return true;
- }
- // Could also check hash code; null uuid has -1 as hash?
- byte[] data = mId;
- int i = mId.length;
- byte zero = (byte) 0;
- while (--i >= 0) {
- if (data[i] != zero) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Returns the UUID type code
- *
- * @return UUID type
- */
- public int getType()
- {
- return (mId[INDEX_TYPE] & 0xFF) >> 4;
- }
-
- /**
- * Returns the UUID as a 16-byte byte array
- *
- * @return 16-byte byte array that contains UUID bytes in the network
- * byte order
- */
- public byte[] asByteArray()
- {
- byte[] result = new byte[16];
- toByteArray(result);
- return result;
- }
-
- /**
- * Fills in the 16 bytes (from index pos) of the specified byte array
- * with the UUID contents.
- *
- * @param dst Byte array to fill
- * @param pos Offset in the array
- */
- public void toByteArray(byte[] dst, int pos)
- {
- byte[] src = mId;
- for (int i = 0; i < 16; ++i) {
- dst[pos+i] = src[i];
- }
- }
-
- public void toByteArray(byte[] dst) { toByteArray(dst, 0); }
-
- /**
- * 'Synonym' for 'asByteArray'
- */
- public byte[] toByteArray() { return asByteArray(); }
-
- /* *** Standard methods from Object overridden: *** */
-
- /**
- * Could use just the default hash code, but we can probably create
- * a better identity hash (ie. same contents generate same hash)
- * manually, without sacrificing speed too much. Although multiplications
- * with modulos would generate better hashing, let's use just shifts,
- * and do 2 bytes at a time.
- *
- *
- *
- *
- *System.currentTimeMillis()
- * returned: used to catch (and report) cases where system clock
- * goes backwards. Is also used to limit "drifting", that is, amount
- * timestamps used can differ from the system time value. This value
- * is not guaranteed to be monotonically increasing.
- */
- private long mLastSystemTimestamp = 0L;
-
- /**
- * Timestamp value last used for generating a UUID (along with
- * {@link #mClockCounter}. Usually the same as
- * {@link #mLastSystemTimestamp}, but not always (system clock
- * moved backwards). Note that this value is guaranteed to be
- * monotonically increasing; that is, at given absolute time points
- * t1 and t2 (where t2 is after t1), t1 <= t2 will always hold true.
- */
- private long mLastUsedTimestamp = 0L;
-
- /**
- * First timestamp that can NOT be used without synchronizing
- * using synchronization object ({@link #mSync}). Only used when
- * external timestamp synchronization (and persistence) is used,
- * ie. when {@link #mSync} is not null.
- */
- private long mFirstUnsafeTimestamp = Long.MAX_VALUE;
-
- /**
- * Counter used to compensate inadequate resolution of JDK system
- * timer.
- */
- private int mClockCounter = 0;
-
- /**
- * Object used to reliably ensure that no multiple JVMs
- * generate UUIDs, and also that the time stamp value used for
- * generating time-based UUIDs is monotonically increasing
- * even if system clock moves backwards over a reboot (usually
- * due to some system level problem).
- *mFile1
is more recent; false that mFile2
+ * is.
+ */
+ boolean mFirstActive = false;
+
+ /**
+ * Constructor that uses default values for names of files to use
+ * (files will get created in the current working directory), as
+ * well as for the update frequency value (10 seconds).
+ */
+ public FileBasedTimestampSynchronizer()
+ throws IOException
+ {
+ this(new File(DEFAULT_LOCK_FILE_NAME1), new File(DEFAULT_LOCK_FILE_NAME2));
+ }
+
+ public FileBasedTimestampSynchronizer(File lockFile1, File lockFile2)
+ throws IOException
+ {
+ this(lockFile1, lockFile2, DEFAULT_UPDATE_INTERVAL);
+ }
+
+ public FileBasedTimestampSynchronizer(File lockFile1, File lockFile2, long interval)
+ throws IOException
+ {
+ mInterval = interval;
+ mLocked1 = new LockedFile(lockFile1);
+
+ boolean ok = false;
+ try {
+ mLocked2 = new LockedFile(lockFile2);
+ ok = true;
+ } finally {
+ if (!ok) {
+ mLocked1.deactivate();
+ }
+ }
+
+ // But let's leave reading up to initialization
+ }
+
+ /*
+ //////////////////////////////////////////////////////////////
+ // Configuration
+ //////////////////////////////////////////////////////////////
+ */
+
+ public void setUpdateInterval(long interval)
+ {
+ if (interval < 1L) {
+ throw new IllegalArgumentException("Illegal value ("+interval+"); has to be a positive integer value");
+ }
+ mInterval = interval;
+ }
+
+ /*
+ //////////////////////////////////////////////////////////////
+ // Implementation of the API
+ //////////////////////////////////////////////////////////////
+ */
+
+ /**
+ * This method is to be called only once by
+ * {@link com.fasterxml.uuid.UUIDTimer}. It
+ * should fetch the persisted timestamp value, which indicates
+ * first timestamp value that is guaranteed NOT to have used by
+ * a previous incarnation. If it can not determine such value, it
+ * is to return 0L as a marker.
+ *
+ * @return First timestamp value that was NOT locked by lock files;
+ * 0L to indicate that no information was read.
+ */
+ protected long initialize()
+ throws IOException
+ {
+ long ts1 = mLocked1.readStamp();
+ long ts2 = mLocked2.readStamp();
+ long result;
+
+ if (ts1 > ts2) {
+ mFirstActive = true;
+ result = ts1;
+ } else {
+ mFirstActive = false;
+ result = ts2;
+ }
+
+ /* Hmmh. If we didn't get a time stamp (-> 0), or if written time is
+ * ahead of current time, let's log something:
+ */
+ if (result <= 0L) {
+ Logger.logWarning("Could not determine safe timer starting point: assuming current system time is acceptable");
+ } else {
+ long now = System.currentTimeMillis();
+ //long diff = now - result;
+
+ /* It's more suspicious if old time was ahead... although with
+ * longer iteration values, it can be ahead without errors. So
+ * let's base check on current iteration value:
+ */
+ if ((now + mInterval) < result) {
+ Logger.logWarning("Safe timestamp read is "+(result - now)+" milliseconds in future, and is greater than the inteval ("+mInterval+")");
+ }
+
+ /* Hmmh. Is there any way a suspiciously old timestamp could be
+ * harmful? It can obviously be useless but...
+ */
+ }
+
+ return result;
+ }
+
+ public void deactivate()
+ throws IOException
+ {
+ doDeactivate(mLocked1, mLocked2);
+ }
+
+ /**
+ * @return Timestamp value that the caller can NOT use. That is, all
+ * timestamp values prior to (less than) this value can be used
+ * ok, but this value and ones after can only be used by first
+ * calling update.
+ */
+ public long update(long now)
+ throws IOException
+ {
+ long nextAllowed = now + mInterval;
+
+ /* We have to make sure to (over)write the one that is NOT
+ * actively used, to ensure that we always have fully persisted
+ * timestamp value, even if the write process gets interruped
+ * half-way through.
+ */
+
+ if (mFirstActive) {
+ mLocked2.writeStamp(nextAllowed);
+ } else {
+ mLocked1.writeStamp(nextAllowed);
+ }
+
+ mFirstActive = !mFirstActive;
+
+ return nextAllowed;
+ }
+
+ /*
+ //////////////////////////////////////////////////////////////
+ // Internal methods
+ //////////////////////////////////////////////////////////////
+ */
+
+ protected static void doDeactivate(LockedFile lf1, LockedFile lf2)
+ {
+ if (lf1 != null) {
+ lf1.deactivate();
+ }
+ if (lf2 != null) {
+ lf2.deactivate();
+ }
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/JavaUtilLogger.java jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/JavaUtilLogger.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/JavaUtilLogger.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/JavaUtilLogger.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,132 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid.ext;
+
+import java.io.*;
+
+//import com.fasterxml.uuid.Logger;
+
+/**
+ * Simple wrapper that allows easy connecting of JUG logging into JDK 1.4+
+ * logging implementation (aka "java.util.logging" aka "JUL".
+ *Logger
instance.
+ *Logger
constructed to correspond with
+ * com.fasterxml.uuid.Logger
class (this generally determines
+ * j.u.l category output etc settings).
+ *System.currentTimeMillis()
. A single timestamp
+ * is stored into a file using {@link RandomAccessFile} in fully
+ * synchronized mode. Value is written in ISO-Latin (ISO-8859-1)
+ * encoding (superset of Ascii, 1 byte per char) as 16-digit hexadecimal
+ * number, surrounded by brackets. As such, file produced should
+ * always have exact size of 18 bytes. For extra robustness, slight
+ * variations in number of digits are accepeted, as are white space
+ * chars before and after bracketed value.
+ */
+class LockedFile
+{
+ /**
+ * Expected file length comes from hex-timestamp (16 digits),
+ * preamble "[0x",(3 chars) and trailer "]\r\n" (2 chars, linefeed
+ * to help debugging -- in some environments, missing trailing linefeed
+ * causes problems: also, 2-char linefeed to be compatible with all
+ * standard linefeeds on MacOS, Unix and Windows).
+ */
+ final static int DEFAULT_LENGTH = 22;
+
+ final static long READ_ERROR = 0L;
+
+ // // // Configuration:
+
+ final File mFile;
+
+ // // // File state
+
+ RandomAccessFile mRAFile;
+
+ FileChannel mChannel;
+
+ FileLock mLock;
+
+ ByteBuffer mWriteBuffer = null;
+
+ /**
+ * Flag set if the original file (created before this instance was
+ * created) had size other than default size and needs to be
+ * truncated
+ */
+ boolean mWeirdSize;
+
+ /**
+ * Marker used to ensure that the timestamps stored are monotonously
+ * increasing. Shouldn't really be needed, since caller should take
+ * care of it, but let's be bit paranoid here.
+ */
+ long mLastTimestamp = 0L;
+
+ LockedFile(File f)
+ throws IOException
+ {
+ mFile = f;
+
+ RandomAccessFile raf = null;
+ FileChannel channel = null;
+ FileLock lock = null;
+ boolean ok = false;
+
+ try { // let's just use a single block to share cleanup code
+ raf = new RandomAccessFile(f, "rwd");
+
+ // Then lock them, if possible; if not, let's err out
+ channel = raf.getChannel();
+ if (channel == null) {
+ throw new IOException("Failed to access channel for '"+f+"'");
+ }
+ lock = channel.tryLock();
+ if (lock == null) {
+ throw new IOException("Failed to lock '"+f+"' (another JVM running UUIDGenerator?)");
+ }
+ ok = true;
+ } finally {
+ if (!ok) {
+ doDeactivate(f, raf, lock);
+ }
+ }
+
+ mRAFile = raf;
+ mChannel = channel;
+ mLock = lock;
+ }
+
+ public void deactivate()
+ {
+ RandomAccessFile raf = mRAFile;
+ mRAFile = null;
+ FileLock lock = mLock;
+ mLock = null;
+ doDeactivate(mFile, raf, lock);
+ }
+
+ public long readStamp()
+ {
+ int size;
+
+ try {
+ size = (int) mChannel.size();
+ } catch (IOException ioe) {
+ doLogError("Failed to read file size: "+ioe);
+ return READ_ERROR;
+ }
+
+ mWeirdSize = (size != DEFAULT_LENGTH);
+
+ // Let's check specifically empty files though
+ if (size == 0) {
+ doLogWarning("Missing or empty file, can not read timestamp value");
+ return READ_ERROR;
+ }
+
+ // Let's also allow some slack... but just a bit
+ if (size > 100) {
+ size = 100;
+ }
+ byte[] data = new byte[size];
+ try {
+ mRAFile.readFully(data);
+ } catch (IOException ie) {
+ doLogError("Failed to read "+size+" bytes: "+ie);
+ return READ_ERROR;
+ }
+
+ /* Ok, got data. Now, we could just directly parse the bytes (since
+ * it is single-byte encoding)... but for convenience, let's create
+ * the String (this is only called once per JVM session)
+ */
+ char[] cdata = new char[size];
+ for (int i = 0; i < size; ++i) {
+ cdata[i] = (char) (data[i] & 0xFF);
+ }
+ String dataStr = new String(cdata);
+ // And let's trim leading (and trailing, who cares)
+ dataStr = dataStr.trim();
+
+ long result = -1;
+ String err = null;
+
+ if (!dataStr.startsWith("[0")
+ || dataStr.length() < 3
+ || Character.toLowerCase(dataStr.charAt(2)) != 'x') {
+ err = "does not start with '[0x' prefix";
+ } else {
+ int ix = dataStr.indexOf(']', 3);
+ if (ix <= 0) {
+ err = "does not end with ']' marker";
+ } else {
+ String hex = dataStr.substring(3, ix);
+ if (hex.length() > 16) {
+ err = "length of the (hex) timestamp too long; expected 16, had "+hex.length()+" ('"+hex+"')";
+ } else {
+ try {
+ result = Long.parseLong(hex, 16);
+ } catch (NumberFormatException nex) {
+ err = "does not contain a valid hex timestamp; got '"
+ +hex+"' (parse error: "+nex+")";
+ }
+ }
+ }
+ }
+
+ // Unsuccesful?
+ if (result < 0L) {
+ doLogError("Malformed timestamp file contents: "+err);
+ return READ_ERROR;
+ }
+
+ mLastTimestamp = result;
+ return result;
+ }
+
+ final static String HEX_DIGITS = "0123456789abcdef";
+
+ public void writeStamp(long stamp)
+ throws IOException
+ {
+ // Let's do sanity check first:
+ if (stamp <= mLastTimestamp) {
+ /* same stamp is not dangerous, but pointless... so warning,
+ * not an error:
+ */
+ if (stamp == mLastTimestamp) {
+ doLogWarning("Trying to re-write existing timestamp ("+stamp+")");
+ return;
+ }
+ throw new IOException(""+getFileDesc()+" trying to overwrite existing value ("+mLastTimestamp+") with an earlier timestamp ("+stamp+")");
+ }
+
+//System.err.println("!!!! Syncing ["+mFile+"] with "+stamp+" !!!");
+
+ // Need to initialize the buffer?
+ if (mWriteBuffer == null) {
+ mWriteBuffer = ByteBuffer.allocate(DEFAULT_LENGTH);
+ mWriteBuffer.put(0, (byte) '[');
+ mWriteBuffer.put(1, (byte) '0');
+ mWriteBuffer.put(2, (byte) 'x');
+ mWriteBuffer.put(19, (byte) ']');
+ mWriteBuffer.put(20, (byte) '\r');
+ mWriteBuffer.put(21, (byte) '\n');
+ }
+
+ // Converting to hex is simple
+ for (int i = 18; i >= 3; --i) {
+ int val = (((int) stamp) & 0x0F);
+ mWriteBuffer.put(i, (byte) HEX_DIGITS.charAt(val));
+ stamp = (stamp >> 4);
+ }
+ // and off we go:
+ mWriteBuffer.position(0); // to make sure we always write it all
+ mChannel.write(mWriteBuffer, 0L);
+ if (mWeirdSize) {
+ mRAFile.setLength(DEFAULT_LENGTH);
+ mWeirdSize = false;
+ }
+
+ // This is probably not needed (as the random access file is supposedly synced)... but let's be safe:
+ mChannel.force(false);
+
+ // And that's it!
+ }
+
+ /*
+ //////////////////////////////////////////////////////////////
+ // Internal methods
+ //////////////////////////////////////////////////////////////
+ */
+
+ protected void doLogWarning(String msg)
+ {
+ Logger.logWarning("(file '"+getFileDesc()+"') "+msg);
+ }
+
+ protected void doLogError(String msg)
+ {
+ Logger.logError("(file '"+getFileDesc()+"') "+msg);
+ }
+
+ protected String getFileDesc() {
+ return mFile.toString();
+ }
+
+ protected static void doDeactivate(File f, RandomAccessFile raf,
+ FileLock lock)
+ {
+ if (lock != null) {
+ try {
+ lock.release();
+ } catch (Throwable t) {
+ Logger.logError("Failed to release lock (for file '"+f+"'): "+t);
+ }
+ }
+ if (raf != null) {
+ try {
+ raf.close();
+ } catch (Throwable t) {
+ Logger.logError("Failed to close file '"+f+"':"+t);
+ }
+ }
+ }
+}
+
+
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/Log4jLogger.java jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/Log4jLogger.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/ext/Log4jLogger.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/ext/Log4jLogger.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,130 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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 com.fasterxml.uuid.ext;
+
+import java.io.*;
+
+//import com.fasterxml.uuid.Logger;
+
+/**
+ * Simple wrapper that allows easy connecting of JUG logging into log4j
+ * logging subsystem.
+ *Logger
instance.
+ *Logger
constructed to correspond with
+ * com.fasterxml.uuid.Logger
class (this generally determines
+ * log4j category output etc settings).
+ *
+
+com.fasterxml.uuid.ext
does contain
+ * simple wrappers to connect JUG logging to log4j and java.util.logging:
+ *
+ * @see com.fasterxml.uuid.ext.Log4jLogger
+ * @see com.fasterxml.uuid.ext.JavaUtilLogger
+ */
+public class Logger
+{
+ /*
+ //////////////////////////////////////////////////
+ // Constants
+ //////////////////////////////////////////////////
+ */
+
+ public final static int LOG_ALL = 0;
+ public final static int LOG_INFO_AND_ABOVE = 1;
+ public final static int LOG_WARNING_AND_ABOVE = 2;
+ public final static int LOG_ERROR_AND_ABOVE = 3;
+ public final static int LOG_NOTHING = 4;
+
+ /*
+ /**********************************************************************
+ /* Static objects
+ /**********************************************************************
+ */
+
+ /**
+ * By default we'll use this default implementation; however,
+ * it can be easily changed.
+ */
+ private static Logger instance = new Logger();
+
+ /*
+ /**********************************************************************
+ /* Default impl. configuration
+ /**********************************************************************
+ */
+
+ /**
+ * Threshold to use for outputting varius log statements.
+ *System.err
.
+ */
+ protected PrintStream _output1 = System.err;
+
+ /**
+ * Override output used to explicitly specify where to pass diagnostic
+ * output, instead of System.err. Used if _output1
+ * is null;
+ */
+ protected PrintWriter _output2 = null;
+
+ /*
+ /**********************************************************************
+ /* Life-cycle
+ /**********************************************************************
+ */
+
+ protected Logger() { }
+
+ /**
+ * Method that can be used to completely re-define the logging
+ * functionality JUG uses. When called, JUG will start using the
+ * new instance; if instance passed is null, will basically suppress
+ * all logging.
+ *
+ * @param inst Logger instance to use for all logging JUG does; can be
+ * null, but if so, essentially disables all logging.
+ */
+ public synchronized static void setLogger(Logger inst)
+ {
+ instance = inst;
+ }
+
+ /*
+ /**********************************************************************
+ /* Actual simple logging API
+ /* (static dispatchers to instance methods)
+ /**********************************************************************
+ */
+
+ // // // Configuration
+
+ /**
+ * Method to set the minimum level of messages that will get logged
+ * using currently specific logger instace. For example, if
+ * {@link #LOG_WARNING_AND_ABOVE} is passed as the argument, warnings
+ * and errors will be logged, but informational (INFO) messages will
+ * not.
+ *0L
if it
+ * can not
+ * determine it and caller can use whatever value (current timestamp)
+ * it has access to.
+ */
+ protected abstract long initialize()
+ throws IOException;
+
+ /**
+ * Method {@link UUIDTimer} will call if this synchronizer object is
+ * being replaced by another synchronizer (or removed, that is, no
+ * more synchronization is to be done). It will not be called if JVM
+ * terminates.
+ */
+ protected abstract void deactivate()
+ throws IOException;
+
+ /**
+ * Method called by {@link UUIDTimer} to indicate that it has generated
+ * a timestamp value that is beyond last legal timestamp value.
+ * The method should only return once it has "locked" specified timestamp
+ * value (and possible additional ones).
+ *
+ * @param now Timestamp value caller wants to use, and that the
+ * synchronizer is asked to protect.
+ *
+ * @return First timestamp value that can NOT be used by the caller;
+ * has to be higher than the input timestamp value
+ */
+ protected abstract long update(long now)
+ throws IOException;
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/UUIDComparator.java jug-3.1.5/src/main/java/com/fasterxml/uuid/UUIDComparator.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/UUIDComparator.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/UUIDComparator.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,77 @@
+package com.fasterxml.uuid;
+
+import java.util.Comparator;
+import java.util.UUID;
+
+/**
+ * Default {@link java.util.UUID} comparator is not very useful, since
+ * it just does blind byte-by-byte comparison which does not work well
+ * for time+location - based UUIDs. Additionally it also uses signed
+ * comparisons for longs which can lead to unexpected behavior
+ * This comparator does implement proper lexical ordering: starting with
+ * type (different types are collated
+ * separately), followed by time and location (for time/location based),
+ * and simple lexical (byte-by-byte) ordering for name/hash and random
+ * variants.
+ *
+ * @author tatu
+ */
+public class UUIDComparator implements Comparator
+ *
+ *
+ *
+ *System.currentTimeMillis()
+ * returned: used to catch (and report) cases where system clock
+ * goes backwards. Is also used to limit "drifting", that is, amount
+ * timestamps used can differ from the system time value. This value
+ * is not guaranteed to be monotonically increasing.
+ */
+ private long _lastSystemTimestamp = 0L;
+
+ /**
+ * Timestamp value last used for generating a UUID (along with
+ * {@link #_clockCounter}. Usually the same as
+ * {@link #_lastSystemTimestamp}, but not always (system clock
+ * moved backwards). Note that this value is guaranteed to be
+ * monotonically increasing; that is, at given absolute time points
+ * t1 and t2 (where t2 is after t1), t1 <= t2 will always hold true.
+ */
+ private long _lastUsedTimestamp = 0L;
+
+ /**
+ * First timestamp that can NOT be used without synchronizing
+ * using synchronization object ({@link #_syncer}). Only used when
+ * external timestamp synchronization (and persistence) is used,
+ * ie. when {@link #_syncer} is not null.
+ */
+ private long _firstUnsafeTimestamp = Long.MAX_VALUE;
+
+ /**
+ * Counter used to compensate inadequate resolution of JDK system
+ * timer.
+ */
+ private int _clockCounter = 0;
+
+ public UUIDTimer(Random rnd, TimestampSynchronizer sync) throws IOException
+ {
+ _random = rnd;
+ _syncer = sync;
+ initCounters(rnd);
+ _lastSystemTimestamp = 0L;
+ // This may get overwritten by the synchronizer
+ _lastUsedTimestamp = 0L;
+
+ /* Ok, now; synchronizer can tell us what is the first timestamp
+ * value that definitely was NOT used by the previous incarnation.
+ * This can serve as the last used time stamp, assuming it is not
+ * less than value we are using now.
+ */
+ if (sync != null) {
+ long lastSaved = sync.initialize();
+ if (lastSaved > _lastUsedTimestamp) {
+ _lastUsedTimestamp = lastSaved;
+ }
+ }
+
+ /* Also, we need to make sure there are now no safe values (since
+ * synchronizer is not yet requested to allocate any):
+ */
+ _firstUnsafeTimestamp = 0L; // ie. will always trigger sync.update()
+ }
+
+ private void initCounters(Random rnd)
+ {
+ /* Let's generate the clock sequence field now; as with counter,
+ * this reduces likelihood of collisions (as explained in UUID specs)
+ */
+ _clockSequence = rnd.nextInt();
+ /* Ok, let's also initialize the counter...
+ * Counter is used to make it slightly less likely that
+ * two instances of UUIDGenerator (from separate JVMs as no more
+ * than one can be created in one JVM) would produce colliding
+ * time-based UUIDs. The practice of using multiple generators,
+ * is strongly discouraged, of course, but just in case...
+ */
+ _clockCounter = (_clockSequence >> 16) & 0xFF;
+ }
+
+ public int getClockSequence() {
+ return (_clockSequence & 0xFFFF);
+ }
+
+ /**
+ * Method that constructs unique timestamp suitable for use for
+ * constructing UUIDs. Default implementation is fully synchronized;
+ * sub-classes may choose to implemented alternate strategies
+ *
+ * @return 64-bit timestamp to use for constructing UUID
+ */
+ public synchronized long getTimestamp()
+ {
+ long systime = System.currentTimeMillis();
+ /* Let's first verify that the system time is not going backwards;
+ * independent of whether we can use it:
+ */
+ if (systime < _lastSystemTimestamp) {
+ Logger.logWarning("System time going backwards! (got value "+systime+", last "+_lastSystemTimestamp);
+ // Let's write it down, still
+ _lastSystemTimestamp = systime;
+ }
+
+ /* But even without it going backwards, it may be less than the
+ * last one used (when generating UUIDs fast with coarse clock
+ * resolution; or if clock has gone backwards over reboot etc).
+ */
+ if (systime <= _lastUsedTimestamp) {
+ /* Can we just use the last time stamp (ok if the counter
+ * hasn't hit max yet)
+ */
+ if (_clockCounter < kClockMultiplier) { // yup, still have room
+ systime = _lastUsedTimestamp;
+ } else { // nope, have to roll over to next value and maybe wait
+ long actDiff = _lastUsedTimestamp - systime;
+ long origTime = systime;
+ systime = _lastUsedTimestamp + 1L;
+
+ Logger.logWarning("Timestamp over-run: need to reinitialize random sequence");
+
+ /* Clock counter is now at exactly the multiplier; no use
+ * just anding its value. So, we better get some random
+ * numbers instead...
+ */
+ initCounters(_random);
+
+ /* But do we also need to slow down? (to try to keep virtual
+ * time close to physical time; i.e. either catch up when
+ * system clock has been moved backwards, or when coarse
+ * clock resolution has forced us to advance virtual timer
+ * too far)
+ */
+ if (actDiff >= kMaxClockAdvance) {
+ slowDown(origTime, actDiff);
+ }
+ }
+ } else {
+ /* Clock has advanced normally; just need to make sure counter is
+ * reset to a low value (need not be 0; good to leave a small
+ * residual to further decrease collisions)
+ */
+ _clockCounter &= 0xFF;
+ }
+
+ _lastUsedTimestamp = systime;
+
+ /* Ok, we have consistent clock (virtual or physical) value that
+ * we can and should use.
+ * But do we need to check external syncing now?
+ */
+ if (_syncer != null && systime >= _firstUnsafeTimestamp) {
+ try {
+ _firstUnsafeTimestamp = _syncer.update(systime);
+ } catch (IOException ioe) {
+ throw new RuntimeException("Failed to synchronize timestamp: "+ioe);
+ }
+ }
+
+ /* Now, let's translate the timestamp to one UUID needs, 100ns
+ * unit offset from the beginning of Gregorian calendar...
+ */
+ systime *= kClockMultiplierL;
+ systime += kClockOffset;
+
+ // Plus add the clock counter:
+ systime += _clockCounter;
+ // and then increase
+ ++_clockCounter;
+ return systime;
+ }
+
+ /*
+ /**********************************************************************
+ /* Test-support methods
+ /**********************************************************************
+ */
+
+ /* Method for accessing timestamp to use for creating UUIDs.
+ * Used ONLY by unit tests, hence protected.
+ */
+ protected final void getAndSetTimestamp(byte[] uuidBytes)
+ {
+ long timestamp = getTimestamp();
+
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) _clockSequence;
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) (_clockSequence >> 8);
+
+ // Time fields aren't nicely split across the UUID, so can't just
+ // linearly dump the stamp:
+ int clockHi = (int) (timestamp >>> 32);
+ int clockLo = (int) timestamp;
+
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_HI] = (byte) (clockHi >>> 24);
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_HI+1] = (byte) (clockHi >>> 16);
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_MID] = (byte) (clockHi >>> 8);
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_MID+1] = (byte) clockHi;
+
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_LO] = (byte) (clockLo >>> 24);
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_LO+1] = (byte) (clockLo >>> 16);
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_LO+2] = (byte) (clockLo >>> 8);
+ uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_LO+3] = (byte) clockLo;
+ }
+
+ /*
+ /**********************************************************************
+ /* Private methods
+ /**********************************************************************
+ */
+
+ private final static int MAX_WAIT_COUNT = 50;
+
+ /**
+ * Simple utility method to use to wait for couple of milliseconds,
+ * to let system clock hopefully advance closer to the virtual
+ * timestamps used. Delay is kept to just a millisecond or two,
+ * to prevent excessive blocking; but that should be enough to
+ * eventually synchronize physical clock with virtual clock values
+ * used for UUIDs.
+ *
+ * @param msecs Number of milliseconds to wait for from current
+ * time point
+ */
+ protected static void slowDown(long startTime, long actDiff)
+ {
+ /* First, let's determine how long we'd like to wait.
+ * This is based on how far ahead are we as of now.
+ */
+ long ratio = actDiff / kMaxClockAdvance;
+ long delay;
+
+ if (ratio < 2L) { // 200 msecs or less
+ delay = 1L;
+ } else if (ratio < 10L) { // 1 second or less
+ delay = 2L;
+ } else if (ratio < 600L) { // 1 minute or less
+ delay = 3L;
+ } else {
+ delay = 5L;
+ }
+ Logger.logWarning("Need to wait for "+delay+" milliseconds; virtual clock advanced too far in the future");
+ long waitUntil = startTime + delay;
+ int counter = 0;
+ do {
+ try {
+ Thread.sleep(delay);
+ } catch (InterruptedException ie) { }
+ delay = 1L;
+ /* This is just a sanity check: don't want an "infinite"
+ * loop if clock happened to be moved backwards by, say,
+ * an hour...
+ */
+ if (++counter > MAX_WAIT_COUNT) {
+ break;
+ }
+ } while (System.currentTimeMillis() < waitUntil);
+ }
+}
diff -Nru jug-2.0.0/src/main/java/com/fasterxml/uuid/UUIDType.java jug-3.1.5/src/main/java/com/fasterxml/uuid/UUIDType.java
--- jug-2.0.0/src/main/java/com/fasterxml/uuid/UUIDType.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/com/fasterxml/uuid/UUIDType.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,29 @@
+package com.fasterxml.uuid;
+
+/**
+ * Enumeration of different flavors of UUIDs: 5 specified by specs
+ * (RFC-4122)
+ * and one
+ * virtual entry ("UNKNOWN") to represent invalid one that consists of
+ * all zero bites
+ */
+public enum UUIDType {
+ TIME_BASED(1),
+ DCE(2),
+ NAME_BASED_MD5(3),
+ RANDOM_BASED(4),
+ NAME_BASED_SHA1(5),
+ UNKNOWN(0)
+ ;
+
+ private final int _raw;
+
+ private UUIDType(int raw) {
+ _raw = raw;
+ }
+
+ /**
+ * Returns "raw" type constants, embedded within UUID bytes.
+ */
+ public int raw() { return _raw; }
+}
diff -Nru jug-2.0.0/src/main/java/perf/MeasurePerformance.java jug-3.1.5/src/main/java/perf/MeasurePerformance.java
--- jug-2.0.0/src/main/java/perf/MeasurePerformance.java 1970-01-01 00:00:00.000000000 +0000
+++ jug-3.1.5/src/main/java/perf/MeasurePerformance.java 2018-02-21 02:29:25.000000000 +0000
@@ -0,0 +1,183 @@
+package perf;
+
+import java.util.UUID;
+
+import com.fasterxml.uuid.*;
+import com.fasterxml.uuid.impl.RandomBasedGenerator;
+import com.fasterxml.uuid.impl.TimeBasedGenerator;
+
+/**
+ * Simple micro-benchmark for evaluating performance of various UUID generation
+ * techniques, including JDK's method as well as JUG's variants.
+ *