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      */
UID()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      */
UID(short num)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      */
UID(int unique, long time, short count)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      */
hashCode()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      */
equals(Object obj)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      */
toString()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      */
write(DataOutput out)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      */
read(DataInput in)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 }
270