KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > rmi > server > UID


1 /*
2  * @(#)UID.java 1.22 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package java.rmi.server;
8
9 import java.io.DataInput JavaDoc;
10 import java.io.DataOutput JavaDoc;
11 import java.io.EOFException JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.InputStream JavaDoc;
14 import java.io.OutputStream JavaDoc;
15 import java.security.SecureRandom JavaDoc;
16
17 /**
18  * A <code>UID</code> represents an identifier that is unique over time
19  * with respect to the host it is generated on, or one of 2<sup>16</sup>
20  * "well-known" identifiers.
21  *
22  * <p>The {@link #UID()} constructor can be used to generate an
23  * identifier that is unique over time with respect to the host it is
24  * generated on. The {@link #UID(short)} constructor can be used to
25  * create one of 2<sup>16</sup> well-known identifiers.
26  *
27  * <p>A <code>UID</code> instance contains three primitive values:
28  * <ul>
29  * <li><code>unique</code>, an <code>int</code> that uniquely identifies
30  * the VM that this <code>UID</code> was generated in, with respect to its
31  * host and at the time represented by the <code>time</code> value (an
32  * example implementation of the <code>unique</code> value would be a
33  * process identifier),
34  * or zero for a well-known <code>UID</code>
35  * <li><code>time</code>, a <code>long</code> equal to a time (as returned
36  * by {@link System#currentTimeMillis()}) at which the VM that this
37  * <code>UID</code> was generated in was alive,
38  * or zero for a well-known <code>UID</code>
39  * <li><code>count</code>, a <code>short</code> to distinguish
40  * <code>UID</code>s generated in the same VM with the same
41  * <code>time</code> value
42  * </ul>
43  *
44  * <p>An independently generated <code>UID</code> instance is unique
45  * over time with respect to the host it is generated on as long as
46  * the host requires more than one millisecond to reboot and its system
47  * clock is never set backward. A globally unique identifier can be
48  * constructed by pairing a <code>UID</code> instance with a unique host
49  * identifier, such as an IP address.
50  *
51  * @author Ann Wollrath
52  * @author Peter Jones
53  * @version 1.22, 03/12/19
54  * @since JDK1.1
55  */

56 public final class UID implements java.io.Serializable JavaDoc {
57
58     private static final long ONE_SECOND = 1000; // in milliseconds
59
private static int hostUnique;
60     private static boolean hostUniqueSet = false;
61
62     private static final Object JavaDoc lock = new Object JavaDoc();
63     private static long lastTime = System.currentTimeMillis();
64     private static short lastCount = Short.MIN_VALUE;
65
66     /** indicate compatibility with JDK 1.1.x version of class */
67     private static final long serialVersionUID = 1086053664494604050L;
68
69     /**
70      * number that uniquely identifies the VM that this <code>UID</code>
71      * was generated in with respect to its host and at the given time
72      * @serial
73      */

74     private final int unique;
75
76     /**
77      * a time (as returned by {@link System#currentTimeMillis()}) at which
78      * the VM that this <code>UID</code> was generated in was alive
79      * @serial
80      */

81     private final long time;
82
83     /**
84      * 16-bit number to distinguish <code>UID</code> instances created
85      * in the same VM with the same time value
86      * @serial
87      */

88     private final short count;
89
90     /**
91      * Generates a <code>UID</code> that is unique over time with
92      * respect to the host that it was generated on.
93      */

94     public UID() {
95     
96     synchronized (lock) {
97         if (!hostUniqueSet) {
98         hostUnique = (new SecureRandom JavaDoc()).nextInt();
99         hostUniqueSet = true;
100         }
101         unique = hostUnique;
102         if (lastCount == Short.MAX_VALUE) {
103         boolean done = false;
104         while (!done) {
105             long now = System.currentTimeMillis();
106             if (now < lastTime + ONE_SECOND) {
107             // pause for a second to wait for time to change
108
try {
109                 Thread.currentThread().sleep(ONE_SECOND);
110             } catch (java.lang.InterruptedException JavaDoc e) {
111             } // ignore exception
112
continue;
113             } else {
114             lastTime = now;
115             lastCount = Short.MIN_VALUE;
116             done = true;
117             }
118         }
119         }
120         time = lastTime;
121         count = lastCount++;
122     }
123     }
124
125     /**
126      * Creates a "well-known" <code>UID</code>.
127      *
128      * There are 2<sup>16</sup> possible such well-known ids.
129      *
130      * <p>A <code>UID</code> created via this constructor will not
131      * clash with any <code>UID</code>s generated via the no-arg
132      * constructor.
133      *
134      * @param num number for well-known <code>UID</code>
135      */

136     public UID(short num) {
137     unique = 0;
138     time = 0;
139     count = num;
140     }
141
142     /**
143      * Constructs a <code>UID</code> given data read from a stream.
144      */

145     private UID(int unique, long time, short count) {
146     this.unique = unique;
147     this.time = time;
148     this.count = count;
149     }
150
151     /**
152      * Returns the hash code value for this <code>UID</code>.
153      *
154      * @return the hash code value for this <code>UID</code>
155      */

156     public int hashCode() {
157     return (int) time + (int) count;
158     }
159
160     /**
161      * Compares the specified object with this <code>UID</code> for
162      * equality.
163      *
164      * This method returns <code>true</code> if and only if the
165      * specified object is a <code>UID</code> instance with the same
166      * <code>unique</code>, <code>time</code>, and <code>count</code>
167      * values as this one.
168      *
169      * @param obj the object to compare this <code>UID</code> to
170      *
171      * @return <code>true</code> if the given object is equivalent to
172      * this one, and <code>false</code> otherwise
173      */

174     public boolean equals(Object JavaDoc obj) {
175     if (obj instanceof UID JavaDoc) {
176         UID JavaDoc uid = (UID JavaDoc)obj;
177         return (unique == uid.unique &&
178             count == uid.count &&
179             time == uid.time);
180     } else {
181         return false;
182     }
183     }
184
185     /**
186      * Returns a string representation of this <code>UID</code>.
187      *
188      * @return a string representation of this <code>UID</code>
189      */

190     public String JavaDoc toString() {
191     return Integer.toString(unique,16) + ":" +
192         Long.toString(time,16) + ":" +
193         Integer.toString(count,16);
194     }
195
196     /**
197      * Marshals a binary representation of this <code>UID</code> to
198      * a <code>DataOutput</code> instance.
199      *
200      * <p>Specifically, this method first invokes the given stream's
201      * {@link DataOutput#writeInt(int)} method with this <code>UID</code>'s
202      * <code>unique</code> value, then it invokes the stream's
203      * {@link DataOutput#writeLong(long)} method with this <code>UID</code>'s
204      * <code>time</code> value, and then it invokes the stream's
205      * {@link DataOutput#writeShort(int)} method with this <code>UID</code>'s
206      * <code>count</code> value.
207      *
208      * @param out the <code>DataOutput</code> instance to write
209      * this <code>UID</code> to
210      *
211      * @throws IOException if an I/O error occurs while performing
212      * this operation
213      */

214     public void write(DataOutput JavaDoc out) throws IOException JavaDoc {
215     out.writeInt(unique);
216     out.writeLong(time);
217     out.writeShort(count);
218     }
219
220     /**
221      * Constructs and returns a new <code>UID</code> instance by
222      * unmarshalling a binary representation from an
223      * <code>DataInput</code> instance.
224      *
225      * <p>Specifically, this method first invokes the given stream's
226      * {@link DataInput#readInt()} method to read a <code>unique</code> value,
227      * then it invoke's the stream's
228      * {@link DataInput#readLong()} method to read a <code>time</code> value,
229      * then it invoke's the stream's
230      * {@link DataInput#readShort()} method to read a <code>count</code> value,
231      * and then it creates and returns a new <code>UID</code> instance
232      * that contains the <code>unique</code>, <code>time</code>, and
233      * <code>count</code> values that were read from the stream.
234      *
235      * @param in the <code>DataInput</code> instance to read
236      * <code>UID</code> from
237      *
238      * @return unmarshalled <code>UID</code> instance
239      *
240      * @throws IOException if an I/O error occurs while performing
241      * this operation
242      */

243     public static UID JavaDoc read(DataInput JavaDoc in) throws IOException JavaDoc {
244     int unique = in.readInt();
245     long time = in.readLong();
246     short count = in.readShort();
247     return new UID JavaDoc(unique, time, count);
248     }
249 }
250
Popular Tags