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 */
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       1.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.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}
270