1 /*
   2  * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.rmi.server;
  26 
  27 import java.io.DataInput;
  28 import java.io.DataOutput;
  29 import java.io.IOException;
  30 import java.io.Serializable;
  31 import java.security.SecureRandom;
  32 
  33 /**
  34  * A <code>UID</code> represents an identifier that is unique over time
  35  * with respect to the host it is generated on, or one of 2<sup>16</sup>
  36  * "well-known" identifiers.
  37  *
  38  * <p>The {@link #UID()} constructor can be used to generate an
  39  * identifier that is unique over time with respect to the host it is
  40  * generated on.  The {@link #UID(short)} constructor can be used to
  41  * create one of 2<sup>16</sup> well-known identifiers.
  42  *
  43  * <p>A <code>UID</code> instance contains three primitive values:
  44  * <ul>
  45  * <li><code>unique</code>, an <code>int</code> that uniquely identifies
  46  * the VM that this <code>UID</code> was generated in, with respect to its
  47  * host and at the time represented by the <code>time</code> value (an
  48  * example implementation of the <code>unique</code> value would be a
  49  * process identifier),
  50  *  or zero for a well-known <code>UID</code>
  51  * <li><code>time</code>, a <code>long</code> equal to a time (as returned
  52  * by {@link System#currentTimeMillis()}) at which the VM that this
  53  * <code>UID</code> was generated in was alive,
  54  * or zero for a well-known <code>UID</code>
  55  * <li><code>count</code>, a <code>short</code> to distinguish
  56  * <code>UID</code>s generated in the same VM with the same
  57  * <code>time</code> value
  58  * </ul>
  59  *
  60  * <p>An independently generated <code>UID</code> instance is unique
  61  * over time with respect to the host it is generated on as long as
  62  * the host requires more than one millisecond to reboot and its system
  63  * clock is never set backward.  A globally unique identifier can be
  64  * constructed by pairing a <code>UID</code> instance with a unique host
  65  * identifier, such as an IP address.
  66  *
  67  * @author      Ann Wollrath
  68  * @author      Peter Jones
  69  * @since       1.1
  70  */
  71 public final class UID implements Serializable {
  72 
  73     private static int hostUnique;
  74     private static boolean hostUniqueSet = false;
  75 
  76     private static final Object lock = new Object();
  77     private static long lastTime = System.currentTimeMillis();
  78     private static short lastCount = Short.MIN_VALUE;
  79 
  80     /** indicate compatibility with JDK 1.1.x version of class */
  81     private static final long serialVersionUID = 1086053664494604050L;
  82 
  83     /**
  84      * number that uniquely identifies the VM that this <code>UID</code>
  85      * was generated in with respect to its host and at the given time
  86      * @serial
  87      */
  88     private final int unique;
  89 
  90     /**
  91      * a time (as returned by {@link System#currentTimeMillis()}) at which
  92      * the VM that this <code>UID</code> was generated in was alive
  93      * @serial
  94      */
  95     private final long time;
  96 
  97     /**
  98      * 16-bit number to distinguish <code>UID</code> instances created
  99      * in the same VM with the same time value
 100      * @serial
 101      */
 102     private final short count;
 103 
 104     /**
 105      * Generates a <code>UID</code> that is unique over time with
 106      * respect to the host that it was generated on.
 107      */
 108     public UID() {
 109 
 110         synchronized (lock) {
 111             if (!hostUniqueSet) {
 112                 hostUnique = (new SecureRandom()).nextInt();
 113                 hostUniqueSet = true;
 114             }
 115             unique = hostUnique;
 116             if (lastCount == Short.MAX_VALUE) {
 117                 boolean interrupted = Thread.interrupted();
 118                 boolean done = false;
 119                 while (!done) {
 120                     long now = System.currentTimeMillis();
 121                     if (now == lastTime) {
 122                         // wait for time to change
 123                         try {
 124                             Thread.sleep(1);
 125                         } catch (InterruptedException e) {
 126                             interrupted = true;
 127                         }
 128                     } else {
 129                         // If system time has gone backwards increase
 130                         // original by 1ms to maintain uniqueness
 131                         lastTime = (now < lastTime) ? lastTime+1 : now;
 132                         lastCount = Short.MIN_VALUE;
 133                         done = true;
 134                     }
 135                 }
 136                 if (interrupted) {
 137                     Thread.currentThread().interrupt();
 138                 }
 139             }
 140             time = lastTime;
 141             count = lastCount++;
 142         }
 143     }
 144 
 145     /**
 146      * Creates a "well-known" <code>UID</code>.
 147      *
 148      * There are 2<sup>16</sup> possible such well-known ids.
 149      *
 150      * <p>A <code>UID</code> created via this constructor will not
 151      * clash with any <code>UID</code>s generated via the no-arg
 152      * constructor.
 153      *
 154      * @param   num number for well-known <code>UID</code>
 155      */
 156     public UID(short num) {
 157         unique = 0;
 158         time = 0;
 159         count = num;
 160     }
 161 
 162     /**
 163      * Constructs a <code>UID</code> given data read from a stream.
 164      */
 165     private UID(int unique, long time, short count) {
 166         this.unique = unique;
 167         this.time = time;
 168         this.count = count;
 169     }
 170 
 171     /**
 172      * Returns the hash code value for this <code>UID</code>.
 173      *
 174      * @return  the hash code value for this <code>UID</code>
 175      */
 176     public int hashCode() {
 177         return (int) time + (int) count;
 178     }
 179 
 180     /**
 181      * Compares the specified object with this <code>UID</code> for
 182      * equality.
 183      *
 184      * This method returns <code>true</code> if and only if the
 185      * specified object is a <code>UID</code> instance with the same
 186      * <code>unique</code>, <code>time</code>, and <code>count</code>
 187      * values as this one.
 188      *
 189      * @param   obj the object to compare this <code>UID</code> to
 190      *
 191      * @return  <code>true</code> if the given object is equivalent to
 192      * this one, and <code>false</code> otherwise
 193      */
 194     public boolean equals(Object obj) {
 195         if (obj instanceof UID) {
 196             UID uid = (UID) obj;
 197             return (unique == uid.unique &&
 198                     count == uid.count &&
 199                     time == uid.time);
 200         } else {
 201             return false;
 202         }
 203     }
 204 
 205     /**
 206      * Returns a string representation of this <code>UID</code>.
 207      *
 208      * @return  a string representation of this <code>UID</code>
 209      */
 210     public String toString() {
 211         return Integer.toString(unique,16) + ":" +
 212             Long.toString(time,16) + ":" +
 213             Integer.toString(count,16);
 214     }
 215 
 216     /**
 217      * Marshals a binary representation of this <code>UID</code> to
 218      * a <code>DataOutput</code> instance.
 219      *
 220      * <p>Specifically, this method first invokes the given stream's
 221      * {@link DataOutput#writeInt(int)} method with this <code>UID</code>'s
 222      * <code>unique</code> value, then it invokes the stream's
 223      * {@link DataOutput#writeLong(long)} method with this <code>UID</code>'s
 224      * <code>time</code> value, and then it invokes the stream's
 225      * {@link DataOutput#writeShort(int)} method with this <code>UID</code>'s
 226      * <code>count</code> value.
 227      *
 228      * @param   out the <code>DataOutput</code> instance to write
 229      * this <code>UID</code> to
 230      *
 231      * @throws  IOException if an I/O error occurs while performing
 232      * this operation
 233      */
 234     public void write(DataOutput out) throws IOException {
 235         out.writeInt(unique);
 236         out.writeLong(time);
 237         out.writeShort(count);
 238     }
 239 
 240     /**
 241      * Constructs and returns a new <code>UID</code> instance by
 242      * unmarshalling a binary representation from an
 243      * <code>DataInput</code> instance.
 244      *
 245      * <p>Specifically, this method first invokes the given stream's
 246      * {@link DataInput#readInt()} method to read a <code>unique</code> value,
 247      * then it invoke's the stream's
 248      * {@link DataInput#readLong()} method to read a <code>time</code> value,
 249      * then it invoke's the stream's
 250      * {@link DataInput#readShort()} method to read a <code>count</code> value,
 251      * and then it creates and returns a new <code>UID</code> instance
 252      * that contains the <code>unique</code>, <code>time</code>, and
 253      * <code>count</code> values that were read from the stream.
 254      *
 255      * @param   in the <code>DataInput</code> instance to read
 256      * <code>UID</code> from
 257      *
 258      * @return  unmarshalled <code>UID</code> instance
 259      *
 260      * @throws  IOException if an I/O error occurs while performing
 261      * this operation
 262      */
 263     public static UID read(DataInput in) throws IOException {
 264         int unique = in.readInt();
 265         long time = in.readLong();
 266         short count = in.readShort();
 267         return new UID(unique, time, count);
 268     }
 269 }