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 */ 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 }