diff --git a/maxkey-core/src/main/java/org/maxkey/uuid/NodeIDGetter.java b/maxkey-core/src/main/java/org/maxkey/uuid/NodeIDGetter.java new file mode 100644 index 000000000..b93f76715 --- /dev/null +++ b/maxkey-core/src/main/java/org/maxkey/uuid/NodeIDGetter.java @@ -0,0 +1,58 @@ +package org.maxkey.uuid; +//$Id$ + +// +//(C) Copyright 2005 VeriSign, Inc. All Rights Reserved. +// +//VeriSign, Inc. shall have no responsibility, financial or +//otherwise, for any consequences arising out of the use of +//this material. The program material is provided on an "AS IS" +//BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +//express or implied. The user is responsible for determining +//any necessary third party rights or authorizations that may +//be required for the use of the materials. Users are advised +//that they may need authorizations under certain patents from +//Microsoft and IBM, or others. Please see notice.txt file. +//VeriSign disclaims any obligation to notify the user of any +//such third party rights. +// + +public class NodeIDGetter +{ + private static Object lock = new Object(); + private static byte[] nodeID = null; + + private NodeIDGetter() { throw new Error(); } + + private static native void getNodeID(byte[] nodeID); + + public static byte[] getNodeID() + { + if(nodeID == null) { + synchronized(lock) { + if(nodeID == null) { + try { + byte[] data = new UUID("00000000-0000-0000-0000-" + + System.getProperty("org.apache.tsik.uuid.nodeid")).toByteArray(); + nodeID = new byte[6]; + System.arraycopy(data, 10, nodeID, 0, 6); + return nodeID; + } catch(Exception ex) { + // phooey. + } + + try { + System.loadLibrary("NodeIDGetter"); + nodeID = new byte[6]; + getNodeID(nodeID); + } catch(LinkageError ex) { + // phooey again. + } + + nodeID = UUIDRandomness.randomNodeID(); + } + } + } + return nodeID; + } +} diff --git a/maxkey-core/src/main/java/org/maxkey/uuid/TimestampUUIDGenerator.java b/maxkey-core/src/main/java/org/maxkey/uuid/TimestampUUIDGenerator.java new file mode 100644 index 000000000..0074c95f7 --- /dev/null +++ b/maxkey-core/src/main/java/org/maxkey/uuid/TimestampUUIDGenerator.java @@ -0,0 +1,56 @@ +package org.maxkey.uuid; +//$Id$ + +// +//(C) Copyright 2005 VeriSign, Inc. All Rights Reserved. +// +//VeriSign, Inc. shall have no responsibility, financial or +//otherwise, for any consequences arising out of the use of +//this material. The program material is provided on an "AS IS" +//BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +//express or implied. The user is responsible for determining +//any necessary third party rights or authorizations that may +//be required for the use of the materials. Users are advised +//that they may need authorizations under certain patents from +//Microsoft and IBM, or others. Please see notice.txt file. +//VeriSign disclaims any obligation to notify the user of any +//such third party rights. +// + +/** +* A more solid timestamp-based UUID generator, this one keeps its +* timestamps within a millisecond or so of the current time, and is +* thread-safe. +*/ +public class TimestampUUIDGenerator + extends UnsynchronizedTimestampUUIDGenerator + implements UUIDGenerator +{ + /** + * Creates a UUIDGenerator with the specified clock sequence number + * and node ID. + * + * @throws NullPointerException if node == null + * @throws IllegalArgumentException if clock_sequence is out of + * range or node.length != 6 + */ + public TimestampUUIDGenerator(int clock_sequence, + byte[] node) + { + super(clock_sequence, node); + } + + /** + * Generates a new UUID. + * + * @throws IllegalStateException if adjustmentOverflow() throws it + */ + public UUID nextUUID() + { + synchronized(this) { + checkSystemTime(); + return super.nextUUID(); + } + } + +} diff --git a/maxkey-core/src/main/java/org/maxkey/uuid/UUID.java b/maxkey-core/src/main/java/org/maxkey/uuid/UUID.java new file mode 100644 index 000000000..c140ab1b0 --- /dev/null +++ b/maxkey-core/src/main/java/org/maxkey/uuid/UUID.java @@ -0,0 +1,363 @@ +package org.maxkey.uuid; + +//$Id$ + +// +//(C) Copyright 2005 VeriSign, Inc. All Rights Reserved. +// +//VeriSign, Inc. shall have no responsibility, financial or +//otherwise, for any consequences arising out of the use of +//this material. The program material is provided on an "AS IS" +//BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +//express or implied. The user is responsible for determining +//any necessary third party rights or authorizations that may +//be required for the use of the materials. Users are advised +//that they may need authorizations under certain patents from +//Microsoft and IBM, or others. Please see notice.txt file. +//VeriSign disclaims any obligation to notify the user of any +//such third party rights. +// + +/** +* Immutable representation of a Universally Unique Identifier (UUID), +* also known (less presumptuously) as a Globally Unique Identifier (GUID). +* These identifiers can be generated in a distributed fashion without +* central coordination, and are reasonably small (128 bits), making them +* suitable for a wide range of purposes. +* +* @see http://www.opengroup.org/onlinepubs/9629399/apdxa.htm +* @see http://www.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01.txt +*/ + +import java.io.*; +import java.security.MessageDigest; +import java.util.Arrays; + +public final class UUID implements Serializable +{ + /** + * + */ + private static final long serialVersionUID = 687078561200656066L; +// Format variants. + public static final int VARIANT_NCS = 0x00; + public static final int VARIANT_NCS_MASK = 0x80; + public static final int VARIANT_DCE = 0x80; + public static final int VARIANT_DCE_MASK = 0xC0; + public static final int VARIANT_MICROSOFT = 0xC0; + public static final int VARIANT_MICROSOFT_MASK = 0xE0; + public static final int VARIANT_RESERVED = 0xE0; + public static final int VARIANT_RESERVED_MASK = 0xE0; + + // Version numbers for VARIANT_DCE. + public static final int VERSION_TIMESTAMP = 0x1000; + public static final int VERSION_UID = 0x2000; + public static final int VERSION_NAME = 0x3000; + public static final int VERSION_RANDOM = 0x4000; + public static final int VERSION_MASK = 0xF000; + + // Data representing the UUID. + private transient int time_low; + private transient short time_mid, time_hi_and_version; + private transient byte clock_seq_hi_and_reserved; + private transient byte clock_seq_low; + private transient byte[] node; + + // Some annotations so we don't have to compute them multiple times. + private transient int hash_code; + private transient String string_rep; + private transient byte[] binary_rep; + + private static UUIDGenerator default_generator; + + /** + * The distinguished nil UUID, one whose bits are all zeroes. + */ + public static final UUID nil = new UUID((int)0, + (short)0, + (short)0, + (byte)0, + (byte)0, + new byte[] { 0, 0, 0, 0, 0, 0 }); + + /** + * Creates a new UUID with the specified value. + * + * @throws NullPointerException if node is null + * @throws IllegalArgumentException if node.length != 6 + */ + public UUID(int time_low, + short time_mid, + short time_hi_and_version, + byte clock_seq_low, + byte clock_seq_hi_and_reserved, + byte[] node) + throws NullPointerException, IllegalArgumentException + { + if(node == null) throw new NullPointerException(); + if(node.length != 6) throw new IllegalArgumentException(); + + this.time_low = time_low; + this.time_mid = time_mid; + this.time_hi_and_version = time_hi_and_version; + this.clock_seq_low = clock_seq_low; + this.clock_seq_hi_and_reserved = clock_seq_hi_and_reserved; + this.node = new byte[6]; + System.arraycopy(node, 0, this.node, 0, 6); + } + + /** + * Creates a UUID from its string representation. + * + * @throws NullPointerException if s is null + * @throws IllegalArgumentException if s.length() != 36 or any expected hyphens are missing + * @throws NumberFormatException if an expected hex digit isn't one + */ + public UUID(String s) + throws NullPointerException, + IllegalArgumentException, + NumberFormatException + { + if(s == null) throw new NullPointerException(); + if(s.length() != 36) throw new IllegalArgumentException(); + time_low = parseHex(s.substring(0, 8)); + if(s.charAt(8) != '-') throw new IllegalArgumentException(); + time_mid = (short) parseHex(s.substring(9, 13)); + if(s.charAt(13) != '-') throw new IllegalArgumentException(); + time_hi_and_version = (short) parseHex(s.substring(14, 18)); + if(s.charAt(18) != '-') throw new IllegalArgumentException(); + clock_seq_hi_and_reserved = (byte) parseHex(s.substring(19, 21)); + clock_seq_low = (byte) parseHex(s.substring(21, 23)); + if(s.charAt(23) != '-') throw new IllegalArgumentException(); + node = new byte[6]; + for(int i = 0; i < 6; i++) + node[i] = (byte) parseHex(s.substring(2 * i + 24, 2 * i + 26)); + } + + /** + * Reads the 16 bytes of a UUID from the specified + * DataInput source. + * + * @throws NullPointerException if in == null + * @throws IOException if the read fails + */ + public UUID(DataInput in) throws IOException + { + if(in == null) throw new NullPointerException(); + readData(in); + } + + /** + * Constructs a UUID from 16 data bytes. + * + * @throws NullPointerException if data == null + * @throws IllegalArgumentException if data.length != 16 + */ + public UUID(byte[] data) + { + if(data == null) throw new NullPointerException(); + if(data.length != 16) throw new IllegalArgumentException(); + try { + readData(new DataInputStream(new ByteArrayInputStream(data))); + } catch(IOException ex) { + throw new IllegalArgumentException(); + } + } + + private void readData(DataInput in) throws IOException + { + time_low = in.readInt(); + time_mid = in.readShort(); + time_hi_and_version = in.readShort(); + clock_seq_hi_and_reserved = in.readByte(); + clock_seq_low = in.readByte(); + node = new byte[6]; + in.readFully(node); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException + { + readData(in); + } + + /** + * Writes the 16 data bytes of this UUID to the specified + * DataOutput interface. + * + * @throws IOException if the DataOutput interface does + */ + public void writeData(DataOutput out) throws IOException + { + out.writeInt(time_low); + out.writeShort(time_mid); + out.writeShort(time_hi_and_version); + out.writeByte(clock_seq_hi_and_reserved); + out.writeByte(clock_seq_low); + out.write(node); + } + + private void writeObject(ObjectOutputStream out) throws IOException + { + writeData(out); + } + + /* + * Returns true if two UUIDs are equal by value. + */ + public boolean equals(Object obj) + { + if(obj == null || !(obj instanceof UUID)) + return false; + + UUID other = (UUID) obj; + + if(this == other) return true; + + if(hash_code != 0 && + other.hash_code != 0 && + hash_code != other.hash_code) + return false; + + return + time_low == other.time_low && + time_mid == other.time_mid && + time_hi_and_version == other.time_hi_and_version && + clock_seq_low == other.clock_seq_low && + clock_seq_hi_and_reserved == other.clock_seq_hi_and_reserved && + Arrays.equals(node, other.node); + } + + /** + * Returns a hash code for this UUID. + */ + public int hashCode() + { + if(hash_code == 0) { + synchronized(this) { + if(hash_code == 0) { + hash_code = toString().hashCode(); + if(hash_code == 0) + hash_code = -1; + } + } + } + return hash_code; + } + + /** + * Utility method for toString(). + */ + private static void appendHex(StringBuffer sb, long num, int digits) + { + if(digits > 0 && digits < 16) + num = num & ((1L << (digits * 4)) - 1); + + String str = Long.toHexString(num); + int len = str.length(); + while(len < digits) { + sb.append('0'); + len++; + } + sb.append(str); + } + + /** + * Utility method for UUID(String) constructor. + */ + private static int parseHex(String s) throws NumberFormatException + { + if(s.charAt(0) == '-') + throw new NumberFormatException(); + + return Integer.parseInt(s, 16); + } + + /** + * Returns the string representation of this UUID. + */ + public String toString() + { + if(string_rep == null) { + synchronized(this) { + if(string_rep == null) { + StringBuffer sb = new StringBuffer(); + appendHex(sb, time_low, 8); + sb.append('-'); + appendHex(sb, time_mid, 4); + sb.append('-'); + appendHex(sb, time_hi_and_version, 4); + sb.append('-'); + appendHex(sb, clock_seq_hi_and_reserved, 2); + appendHex(sb, clock_seq_low, 2); + sb.append('-'); + for(int i = 0; i < 6; i++) + appendHex(sb, node[i], 2); + string_rep = sb.toString(); + } + } + } + return string_rep; + } + + /** + * Returns an array of 16 bytes containing the binary representation + * of this UUID. + */ + public byte[] toByteArray() + { + if(binary_rep == null) { + synchronized(this) { + if(binary_rep == null) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(16); + writeData(new DataOutputStream(baos)); + binary_rep = baos.toByteArray(); + } catch(IOException ex) { + throw new RuntimeException(); + } + } + } + } + return (byte[]) binary_rep.clone(); + } + + /** + * Creates a new, unique UUID. + */ + public static UUID generate() + { + if(default_generator == null) + default_generator = new TimestampUUIDGenerator(UUIDRandomness.randomClockSequence(), NodeIDGetter.getNodeID()); + + return default_generator.nextUUID(); + } + + /** + * Creates a UUID based on a hash of a namespace designator + * UUID and a name. + */ + public static UUID fromName(UUID namespace, String name) + { + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + namespace.writeData(dos); + dos.flush(); + md5.update(baos.toByteArray()); + baos.reset(); + dos.writeUTF(name); + dos.flush(); + byte[] data = baos.toByteArray(); + md5.update(data, 2, data.length - 2); + data = md5.digest(); // this should be 16 bytes + UUID uuid = new UUID(data); + uuid.clock_seq_hi_and_reserved = (byte) ((uuid.clock_seq_hi_and_reserved & ~VARIANT_DCE_MASK) | VARIANT_DCE); + uuid.time_hi_and_version = (short) ((uuid.time_hi_and_version & ~VERSION_MASK) | VERSION_NAME); + return uuid; + } catch(Exception ex) { + throw new RuntimeException(); + } + } +} diff --git a/maxkey-core/src/main/java/org/maxkey/uuid/UUIDGenerator.java b/maxkey-core/src/main/java/org/maxkey/uuid/UUIDGenerator.java new file mode 100644 index 000000000..988fc59b3 --- /dev/null +++ b/maxkey-core/src/main/java/org/maxkey/uuid/UUIDGenerator.java @@ -0,0 +1,12 @@ +package org.maxkey.uuid; + +/** + * An interface representing an object that generates UUIDs. + */ +public interface UUIDGenerator +{ + /** + * Generates a new unique UUID according to this generator's rules. + */ + UUID nextUUID(); +} \ No newline at end of file diff --git a/maxkey-core/src/main/java/org/maxkey/uuid/UUIDRandomness.java b/maxkey-core/src/main/java/org/maxkey/uuid/UUIDRandomness.java new file mode 100644 index 000000000..f94582e66 --- /dev/null +++ b/maxkey-core/src/main/java/org/maxkey/uuid/UUIDRandomness.java @@ -0,0 +1,58 @@ +// $Id$ + +// +// (C) Copyright 2005 VeriSign, Inc. All Rights Reserved. +// +// VeriSign, Inc. shall have no responsibility, financial or +// otherwise, for any consequences arising out of the use of +// this material. The program material is provided on an "AS IS" +// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +// express or implied. The user is responsible for determining +// any necessary third party rights or authorizations that may +// be required for the use of the materials. Users are advised +// that they may need authorizations under certain patents from +// Microsoft and IBM, or others. Please see notice.txt file. +// VeriSign disclaims any obligation to notify the user of any +// such third party rights. +// + +package org.maxkey.uuid; + +import java.security.*; + +public final class UUIDRandomness +{ + static SecureRandom random = new SecureRandom(); + + private UUIDRandomness() + { + throw new Error(); + } + + public static byte[] randomNodeID() + { + byte[] id = new byte[6]; + synchronized(random) { + random.nextBytes(id); + } + id[0] |= 0x01; + return id; + } + + public static int randomClockSequence() + { + synchronized(random) { + return random.nextInt(16384); + } + } + + public static int nextRandomClockSequence(int prev) + { + int next; + synchronized(random) { + next = random.nextInt(16383); + } + if(next >= prev) next++; + return next; + } +} \ No newline at end of file diff --git a/maxkey-core/src/main/java/org/maxkey/uuid/UnsynchronizedTimestampUUIDGenerator.java b/maxkey-core/src/main/java/org/maxkey/uuid/UnsynchronizedTimestampUUIDGenerator.java new file mode 100644 index 000000000..d9723efda --- /dev/null +++ b/maxkey-core/src/main/java/org/maxkey/uuid/UnsynchronizedTimestampUUIDGenerator.java @@ -0,0 +1,114 @@ +package org.maxkey.uuid; + +//$Id$ + +// +//(C) Copyright 2005 VeriSign, Inc. All Rights Reserved. +// +//VeriSign, Inc. shall have no responsibility, financial or +//otherwise, for any consequences arising out of the use of +//this material. The program material is provided on an "AS IS" +//BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +//express or implied. The user is responsible for determining +//any necessary third party rights or authorizations that may +//be required for the use of the materials. Users are advised +//that they may need authorizations under certain patents from +//Microsoft and IBM, or others. Please see notice.txt file. +//VeriSign disclaims any obligation to notify the user of any +//such third party rights. +// + +/** +* As simple and fast of a timestamp-based UUIDGenerator as is practical. +* This class is not thread-safe, and the timestamp field in its UUIDs is +* not reliably close to the actual time. +*/ +public class UnsynchronizedTimestampUUIDGenerator implements UUIDGenerator +{ + /** + * Number of milliseconds between the Gregorian calendar + * cutover and the Unix epoch. + */ + public static final long EPOCH_OFFSET = 12219292800000L; + + /** + * Number of units of UUID time resolution per unit of system + * clock resolution. + */ + public static final long CLOCK_RES = 10000L; + + protected long last_time; + protected long clock_adj; + protected int clock_sequence; + protected byte[] node; + + /** + * Creates a UUIDGenerator with the specified clock sequence number + * and node ID. + * + * @throws NullPointerException if node == null + * @throws IllegalArgumentException if clock_sequence is out of range or node.length != 6 + */ + public UnsynchronizedTimestampUUIDGenerator(int clock_sequence, + byte[] node) + { + if(clock_sequence < 0 || clock_sequence >= 16384) + throw new IllegalArgumentException(); + if(node == null) + throw new NullPointerException(); + if(node.length != 6) + throw new IllegalArgumentException(); + + this.clock_sequence = clock_sequence; + this.node = (byte[]) node.clone(); + checkSystemTime(); + } + + /** + * Reads the current system time and updates last_time, clock_sequence + * and clock_adj based on it. + */ + protected void checkSystemTime() { + long sys_time = System.currentTimeMillis(); + + /* If monotonicity is lost, bump clock_sequence. */ + if(sys_time < last_time) + clock_sequence = UUIDRandomness.nextRandomClockSequence(clock_sequence); + + /* If the clock ticked, clear the adjustment. */ + if(sys_time != last_time) { + last_time = sys_time; + clock_adj = 0; + } + } + + /** + * Called when clock_adj >= CLOCK_RES, expected to take corrective action. + * May throw an IllegalStateException if corrective action fails. + */ + protected void adjustmentOverflow() throws IllegalStateException + { + checkSystemTime(); + if(clock_adj >= CLOCK_RES) + throw new IllegalStateException(); + } + + /** + * Generates a new UUID. + * + * @throws IllegalStateException if adjustmentOverflow() throws it + */ + public UUID nextUUID() + { + long unique_time = (last_time + EPOCH_OFFSET) * CLOCK_RES + clock_adj; + if(++clock_adj > CLOCK_RES) adjustmentOverflow(); + + return new UUID((int) (unique_time & 0xFFFFFFFF), + (short) ((unique_time >> 32) & 0xFFFF), + (short) (((unique_time >> 48) & 0x0FFF) | UUID.VERSION_TIMESTAMP), + (byte) (clock_sequence & 0xFF), + (byte) (((clock_sequence >> 8) & 0x3F) | UUID.VARIANT_DCE), + node); + } +} + diff --git a/maxkey-core/src/test/java/com/connsec/util/UUIDGeneratorTest.java b/maxkey-core/src/test/java/com/connsec/util/UUIDGeneratorTest.java index d8971d04e..78bf96ad7 100644 --- a/maxkey-core/src/test/java/com/connsec/util/UUIDGeneratorTest.java +++ b/maxkey-core/src/test/java/com/connsec/util/UUIDGeneratorTest.java @@ -3,7 +3,7 @@ package com.connsec.util; import java.util.Date; //import java.util.UUID; -import org.apache.tsik.uuid.UUID; +import org.maxkey.uuid.UUID; import org.junit.Test; import org.maxkey.util.UUIDGenerator; diff --git a/maxkey-lib/other/tsik-1.0.0.jar b/maxkey-lib/other/tsik-1.0.0.jar deleted file mode 100644 index 51adee220..000000000 Binary files a/maxkey-lib/other/tsik-1.0.0.jar and /dev/null differ diff --git a/maxkey-protocols/maxkey-protocol-tokenbased/bin/main/.gitignore b/maxkey-protocols/maxkey-protocol-tokenbased/bin/main/.gitignore new file mode 100644 index 000000000..59d60644b --- /dev/null +++ b/maxkey-protocols/maxkey-protocol-tokenbased/bin/main/.gitignore @@ -0,0 +1,2 @@ +/META-INF/ +/org/