- /*
- * @(#)UID.java 1.20 03/01/23
- *
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package java.rmi.server;
-
- import java.io.DataInput;
- import java.io.DataOutput;
- import java.io.EOFException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
-
- /**
- * A <code>UID</code> represents an identifier that is unique over time
- * with respect to the host it is generated on, or one of 2<sup>16</sup>
- * "well-known" identifiers.
- *
- * <p>The {@link #UID()} constructor can be used to generate an
- * identifier that is unique over time with respect to the host it is
- * generated on. The {@link #UID(short)} constructor can be used to
- * create one of 2<sup>16</sup> well-known identifiers.
- *
- * <p>A <code>UID</code> instance contains three primitive values:
- * <ul>
- * <li><code>unique</code>, an <code>int</code> that uniquely identifies
- * the VM that this <code>UID</code> was generated in, with respect to its
- * host and at the time represented by the <code>time</code> value (an
- * example implementation of the <code>unique</code> value would be a
- * process identifier),
- * or zero for a well-known <code>UID</code>
- * <li><code>time</code>, a <code>long</code> equal to a time (as returned
- * by {@link System#currentTimeMillis()}) at which the VM that this
- * <code>UID</code> was generated in was alive,
- * or zero for a well-known <code>UID</code>
- * <li><code>count</code>, a <code>short</code> to distinguish
- * <code>UID</code>s generated in the same VM with the same
- * <code>time</code> value
- * </ul>
- *
- * <p>An independently generated <code>UID</code> instance is unique
- * over time with respect to the host it is generated on as long as
- * the host requires more than one millisecond to reboot and its system
- * clock is never set backward. A globally unique identifier can be
- * constructed by pairing a <code>UID</code> instance with a unique host
- * identifier, such as an IP address.
- *
- * @author Ann Wollrath
- * @author Peter Jones
- * @version 1.20, 03/01/23
- * @since JDK1.1
- */
- public final class UID implements java.io.Serializable {
-
- private static long ONE_SECOND = 1000; // in milliseconds
- private static final int hostUnique = getHostUniqueNum();
-
- private static final Object lock = new Object();
- private static long lastTime = System.currentTimeMillis();
- private static short lastCount = Short.MIN_VALUE;
-
- /** indicate compatibility with JDK 1.1.x version of class */
- private static final long serialVersionUID = 1086053664494604050L;
-
- /**
- * number that uniquely identifies the VM that this <code>UID</code>
- * was generated in with respect to its host and at the given time
- * @serial
- */
- private final int unique;
-
- /**
- * a time (as returned by {@link System#currentTimeMillis()}) at which
- * the VM that this <code>UID</code> was generated in was alive
- * @serial
- */
- private final long time;
-
- /**
- * 16-bit number to distinguish <code>UID</code> instances created
- * in the same VM with the same time value
- * @serial
- */
- private final short count;
-
- /**
- * In the absence of an actual pid, just do something somewhat
- * random.
- */
- private static int getHostUniqueNum() {
- return (new Object()).hashCode();
- }
-
- /**
- * Generates a <code>UID</code> that is unique over time with
- * respect to the host that it was generated on.
- */
- public UID() {
- unique = hostUnique;
-
- synchronized (lock) {
- if (lastCount == Short.MAX_VALUE) {
- boolean done = false;
- while (!done) {
- long now = System.currentTimeMillis();
- if (now < lastTime + ONE_SECOND) {
- // pause for a second to wait for time to change
- try {
- Thread.currentThread().sleep(ONE_SECOND);
- } catch (java.lang.InterruptedException e) {
- } // ignore exception
- continue;
- } else {
- lastTime = now;
- lastCount = Short.MIN_VALUE;
- done = true;
- }
- }
- }
- time = lastTime;
- count = lastCount++;
- }
- }
-
- /**
- * Creates a "well-known" <code>UID</code>.
- *
- * There are 2<sup>16</sup> possible such well-known ids.
- *
- * <p>A <code>UID</code> created via this constructor will not
- * clash with any <code>UID</code>s generated via the no-arg
- * constructor.
- *
- * @param num number for well-known <code>UID</code>
- */
- public UID(short num) {
- unique = 0;
- time = 0;
- count = num;
- }
-
- /**
- * Constructs a <code>UID</code> given data read from a stream.
- */
- private UID(int unique, long time, short count) {
- this.unique = unique;
- this.time = time;
- this.count = count;
- }
-
- /**
- * Returns the hash code value for this <code>UID</code>.
- *
- * @return the hash code value for this <code>UID</code>
- */
- public int hashCode() {
- return (int) time + (int) count;
- }
-
- /**
- * Compares the specified object with this <code>UID</code> for
- * equality.
- *
- * This method returns <code>true</code> if and only if the
- * specified object is a <code>UID</code> instance with the same
- * <code>unique</code>, <code>time</code>, and <code>count</code>
- * values as this one.
- *
- * @param obj the object to compare this <code>UID</code> to
- *
- * @return <code>true</code> if the given object is equivalent to
- * this one, and <code>false</code> otherwise
- */
- public boolean equals(Object obj) {
- if ((obj != null) && (obj instanceof UID)) {
- UID uid = (UID)obj;
- return (unique == uid.unique &&
- count == uid.count &&
- time == uid.time);
- } else {
- return false;
- }
- }
-
- /**
- * Returns a string representation of this <code>UID</code>.
- *
- * @return a string representation of this <code>UID</code>
- */
- public String toString() {
- return Integer.toString(unique,16) + ":" +
- Long.toString(time,16) + ":" +
- Integer.toString(count,16);
- }
-
- /**
- * Marshals a binary representation of this <code>UID</code> to
- * a <code>DataOutput</code> instance.
- *
- * <p>Specifically, this method first invokes the given stream's
- * {@link DataOutput#writeInt(int)} method with this <code>UID</code>'s
- * <code>unique</code> value, then it invokes the stream's
- * {@link DataOutput#writeLong(long)} method with this <code>UID</code>'s
- * <code>time</code> value, and then it invokes the stream's
- * {@link DataOutput#writeShort(int)} method with this <code>UID</code>'s
- * <code>count</code> value.
- *
- * @param out the <code>DataOutput</code> instance to write
- * this <code>UID</code> to
- *
- * @throws IOException if an I/O error occurs while performing
- * this operation
- */
- public void write(DataOutput out) throws IOException {
- out.writeInt(unique);
- out.writeLong(time);
- out.writeShort(count);
- }
-
- /**
- * Constructs and returns a new <code>UID</code> instance by
- * unmarshalling a binary representation from an
- * <code>DataInput</code> instance.
- *
- * <p>Specifically, this method first invokes the given stream's
- * {@link DataInput#readInt()} method to read a <code>unique</code> value,
- * then it invoke's the stream's
- * {@link DataInput#readLong()} method to read a <code>time</code> value,
- * then it invoke's the stream's
- * {@link DataInput#readShort()} method to read a <code>count</code> value,
- * and then it creates and returns a new <code>UID</code> instance
- * that contains the <code>unique</code>, <code>time</code>, and
- * <code>count</code> values that were read from the stream.
- *
- * @param in the <code>DataInput</code> instance to read
- * <code>UID</code> from
- *
- * @return unmarshalled <code>UID</code> instance
- *
- * @throws IOException if an I/O error occurs while performing
- * this operation
- */
- public static UID read(DataInput in) throws IOException {
- int unique = in.readInt();
- long time = in.readLong();
- short count = in.readShort();
- return new UID(unique, time, count);
- }
- }