blob: 1fbbaf33a94defdacef04ea6b85d197268672b81 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package java.rmi.server;
26
27import java.io.DataInput;
28import java.io.DataOutput;
29import java.io.IOException;
30import java.io.Serializable;
31import 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 JDK1.1
70 */
71public 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.currentThread().sleep(1);
125 } catch (InterruptedException e) {
126 interrupted = true;
127 }
128 } else {
129 lastTime = now;
130 lastCount = Short.MIN_VALUE;
131 done = true;
132 }
133 }
134 if (interrupted) {
135 Thread.currentThread().interrupt();
136 }
137 }
138 time = lastTime;
139 count = lastCount++;
140 }
141 }
142
143 /**
144 * Creates a "well-known" <code>UID</code>.
145 *
146 * There are 2<sup>16</sup> possible such well-known ids.
147 *
148 * <p>A <code>UID</code> created via this constructor will not
149 * clash with any <code>UID</code>s generated via the no-arg
150 * constructor.
151 *
152 * @param num number for well-known <code>UID</code>
153 */
154 public UID(short num) {
155 unique = 0;
156 time = 0;
157 count = num;
158 }
159
160 /**
161 * Constructs a <code>UID</code> given data read from a stream.
162 */
163 private UID(int unique, long time, short count) {
164 this.unique = unique;
165 this.time = time;
166 this.count = count;
167 }
168
169 /**
170 * Returns the hash code value for this <code>UID</code>.
171 *
172 * @return the hash code value for this <code>UID</code>
173 */
174 public int hashCode() {
175 return (int) time + (int) count;
176 }
177
178 /**
179 * Compares the specified object with this <code>UID</code> for
180 * equality.
181 *
182 * This method returns <code>true</code> if and only if the
183 * specified object is a <code>UID</code> instance with the same
184 * <code>unique</code>, <code>time</code>, and <code>count</code>
185 * values as this one.
186 *
187 * @param obj the object to compare this <code>UID</code> to
188 *
189 * @return <code>true</code> if the given object is equivalent to
190 * this one, and <code>false</code> otherwise
191 */
192 public boolean equals(Object obj) {
193 if (obj instanceof UID) {
194 UID uid = (UID) obj;
195 return (unique == uid.unique &&
196 count == uid.count &&
197 time == uid.time);
198 } else {
199 return false;
200 }
201 }
202
203 /**
204 * Returns a string representation of this <code>UID</code>.
205 *
206 * @return a string representation of this <code>UID</code>
207 */
208 public String toString() {
209 return Integer.toString(unique,16) + ":" +
210 Long.toString(time,16) + ":" +
211 Integer.toString(count,16);
212 }
213
214 /**
215 * Marshals a binary representation of this <code>UID</code> to
216 * a <code>DataOutput</code> instance.
217 *
218 * <p>Specifically, this method first invokes the given stream's
219 * {@link DataOutput#writeInt(int)} method with this <code>UID</code>'s
220 * <code>unique</code> value, then it invokes the stream's
221 * {@link DataOutput#writeLong(long)} method with this <code>UID</code>'s
222 * <code>time</code> value, and then it invokes the stream's
223 * {@link DataOutput#writeShort(int)} method with this <code>UID</code>'s
224 * <code>count</code> value.
225 *
226 * @param out the <code>DataOutput</code> instance to write
227 * this <code>UID</code> to
228 *
229 * @throws IOException if an I/O error occurs while performing
230 * this operation
231 */
232 public void write(DataOutput out) throws IOException {
233 out.writeInt(unique);
234 out.writeLong(time);
235 out.writeShort(count);
236 }
237
238 /**
239 * Constructs and returns a new <code>UID</code> instance by
240 * unmarshalling a binary representation from an
241 * <code>DataInput</code> instance.
242 *
243 * <p>Specifically, this method first invokes the given stream's
244 * {@link DataInput#readInt()} method to read a <code>unique</code> value,
245 * then it invoke's the stream's
246 * {@link DataInput#readLong()} method to read a <code>time</code> value,
247 * then it invoke's the stream's
248 * {@link DataInput#readShort()} method to read a <code>count</code> value,
249 * and then it creates and returns a new <code>UID</code> instance
250 * that contains the <code>unique</code>, <code>time</code>, and
251 * <code>count</code> values that were read from the stream.
252 *
253 * @param in the <code>DataInput</code> instance to read
254 * <code>UID</code> from
255 *
256 * @return unmarshalled <code>UID</code> instance
257 *
258 * @throws IOException if an I/O error occurs while performing
259 * this operation
260 */
261 public static UID read(DataInput in) throws IOException {
262 int unique = in.readInt();
263 long time = in.readLong();
264 short count = in.readShort();
265 return new UID(unique, time, count);
266 }
267}