001 /*
002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package java.rmi.server;
026
027 import java.io.DataInput;
028 import java.io.DataOutput;
029 import java.io.IOException;
030 import java.io.Serializable;
031 import java.security.SecureRandom;
032
033 /**
034 * A <code>UID</code> represents an identifier that is unique over time
035 * with respect to the host it is generated on, or one of 2<sup>16</sup>
036 * "well-known" identifiers.
037 *
038 * <p>The {@link #UID()} constructor can be used to generate an
039 * identifier that is unique over time with respect to the host it is
040 * generated on. The {@link #UID(short)} constructor can be used to
041 * create one of 2<sup>16</sup> well-known identifiers.
042 *
043 * <p>A <code>UID</code> instance contains three primitive values:
044 * <ul>
045 * <li><code>unique</code>, an <code>int</code> that uniquely identifies
046 * the VM that this <code>UID</code> was generated in, with respect to its
047 * host and at the time represented by the <code>time</code> value (an
048 * example implementation of the <code>unique</code> value would be a
049 * process identifier),
050 * or zero for a well-known <code>UID</code>
051 * <li><code>time</code>, a <code>long</code> equal to a time (as returned
052 * by {@link System#currentTimeMillis()}) at which the VM that this
053 * <code>UID</code> was generated in was alive,
054 * or zero for a well-known <code>UID</code>
055 * <li><code>count</code>, a <code>short</code> to distinguish
056 * <code>UID</code>s generated in the same VM with the same
057 * <code>time</code> value
058 * </ul>
059 *
060 * <p>An independently generated <code>UID</code> instance is unique
061 * over time with respect to the host it is generated on as long as
062 * the host requires more than one millisecond to reboot and its system
063 * clock is never set backward. A globally unique identifier can be
064 * constructed by pairing a <code>UID</code> instance with a unique host
065 * identifier, such as an IP address.
066 *
067 * @author Ann Wollrath
068 * @author Peter Jones
069 * @version 1.30, 07/05/05
070 * @since JDK1.1
071 */
072 public final class UID implements Serializable {
073
074 private static int hostUnique;
075 private static boolean hostUniqueSet = false;
076
077 private static final Object lock = new Object();
078 private static long lastTime = System.currentTimeMillis();
079 private static short lastCount = Short.MIN_VALUE;
080
081 /** indicate compatibility with JDK 1.1.x version of class */
082 private static final long serialVersionUID = 1086053664494604050L;
083
084 /**
085 * number that uniquely identifies the VM that this <code>UID</code>
086 * was generated in with respect to its host and at the given time
087 * @serial
088 */
089 private final int unique;
090
091 /**
092 * a time (as returned by {@link System#currentTimeMillis()}) at which
093 * the VM that this <code>UID</code> was generated in was alive
094 * @serial
095 */
096 private final long time;
097
098 /**
099 * 16-bit number to distinguish <code>UID</code> instances created
100 * in the same VM with the same time value
101 * @serial
102 */
103 private final short count;
104
105 /**
106 * Generates a <code>UID</code> that is unique over time with
107 * respect to the host that it was generated on.
108 */
109 public UID() {
110
111 synchronized (lock) {
112 if (!hostUniqueSet) {
113 hostUnique = (new SecureRandom()).nextInt();
114 hostUniqueSet = true;
115 }
116 unique = hostUnique;
117 if (lastCount == Short.MAX_VALUE) {
118 boolean interrupted = Thread.interrupted();
119 boolean done = false;
120 while (!done) {
121 long now = System.currentTimeMillis();
122 if (now <= lastTime) {
123 // wait for time to change
124 try {
125 Thread.currentThread().sleep(1);
126 } catch (InterruptedException e) {
127 interrupted = true;
128 }
129 } else {
130 lastTime = now;
131 lastCount = Short.MIN_VALUE;
132 done = true;
133 }
134 }
135 if (interrupted) {
136 Thread.currentThread().interrupt();
137 }
138 }
139 time = lastTime;
140 count = lastCount++;
141 }
142 }
143
144 /**
145 * Creates a "well-known" <code>UID</code>.
146 *
147 * There are 2<sup>16</sup> possible such well-known ids.
148 *
149 * <p>A <code>UID</code> created via this constructor will not
150 * clash with any <code>UID</code>s generated via the no-arg
151 * constructor.
152 *
153 * @param num number for well-known <code>UID</code>
154 */
155 public UID(short num) {
156 unique = 0;
157 time = 0;
158 count = num;
159 }
160
161 /**
162 * Constructs a <code>UID</code> given data read from a stream.
163 */
164 private UID(int unique, long time, short count) {
165 this .unique = unique;
166 this .time = time;
167 this .count = count;
168 }
169
170 /**
171 * Returns the hash code value for this <code>UID</code>.
172 *
173 * @return the hash code value for this <code>UID</code>
174 */
175 public int hashCode() {
176 return (int) time + (int) count;
177 }
178
179 /**
180 * Compares the specified object with this <code>UID</code> for
181 * equality.
182 *
183 * This method returns <code>true</code> if and only if the
184 * specified object is a <code>UID</code> instance with the same
185 * <code>unique</code>, <code>time</code>, and <code>count</code>
186 * values as this one.
187 *
188 * @param obj the object to compare this <code>UID</code> to
189 *
190 * @return <code>true</code> if the given object is equivalent to
191 * this one, and <code>false</code> otherwise
192 */
193 public boolean equals(Object obj) {
194 if (obj instanceof UID) {
195 UID uid = (UID) obj;
196 return (unique == uid.unique && count == uid.count && time == uid.time);
197 } else {
198 return false;
199 }
200 }
201
202 /**
203 * Returns a string representation of this <code>UID</code>.
204 *
205 * @return a string representation of this <code>UID</code>
206 */
207 public String toString() {
208 return Integer.toString(unique, 16) + ":"
209 + Long.toString(time, 16) + ":"
210 + Integer.toString(count, 16);
211 }
212
213 /**
214 * Marshals a binary representation of this <code>UID</code> to
215 * a <code>DataOutput</code> instance.
216 *
217 * <p>Specifically, this method first invokes the given stream's
218 * {@link DataOutput#writeInt(int)} method with this <code>UID</code>'s
219 * <code>unique</code> value, then it invokes the stream's
220 * {@link DataOutput#writeLong(long)} method with this <code>UID</code>'s
221 * <code>time</code> value, and then it invokes the stream's
222 * {@link DataOutput#writeShort(int)} method with this <code>UID</code>'s
223 * <code>count</code> value.
224 *
225 * @param out the <code>DataOutput</code> instance to write
226 * this <code>UID</code> to
227 *
228 * @throws IOException if an I/O error occurs while performing
229 * this operation
230 */
231 public void write(DataOutput out) throws IOException {
232 out.writeInt(unique);
233 out.writeLong(time);
234 out.writeShort(count);
235 }
236
237 /**
238 * Constructs and returns a new <code>UID</code> instance by
239 * unmarshalling a binary representation from an
240 * <code>DataInput</code> instance.
241 *
242 * <p>Specifically, this method first invokes the given stream's
243 * {@link DataInput#readInt()} method to read a <code>unique</code> value,
244 * then it invoke's the stream's
245 * {@link DataInput#readLong()} method to read a <code>time</code> value,
246 * then it invoke's the stream's
247 * {@link DataInput#readShort()} method to read a <code>count</code> value,
248 * and then it creates and returns a new <code>UID</code> instance
249 * that contains the <code>unique</code>, <code>time</code>, and
250 * <code>count</code> values that were read from the stream.
251 *
252 * @param in the <code>DataInput</code> instance to read
253 * <code>UID</code> from
254 *
255 * @return unmarshalled <code>UID</code> instance
256 *
257 * @throws IOException if an I/O error occurs while performing
258 * this operation
259 */
260 public static UID read(DataInput in) throws IOException {
261 int unique = in.readInt();
262 long time = in.readLong();
263 short count = in.readShort();
264 return new UID(unique, time, count);
265 }
266 }
|