001/* UID.java -- The unique object Id 002 Copyright (c) 2006 Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package java.rmi.server; 040 041import java.io.DataInput; 042import java.io.DataOutput; 043import java.io.IOException; 044import java.io.Serializable; 045import java.net.InetAddress; 046 047/** 048 * Represents the unique identifier over time for the host which has generated 049 * it. It contains time (when created), counter (the number of the UID 050 * creation order) and virtual machine id components. The UID can also be 051 * constructed specifying a "well known" identifier in the for of short: 052 * this identifier defines the UID uniqueness alone. 053 * 054 * @author Audrius Meskauskas (audriusa@bioinformatics.org) 055 */ 056public final class UID 057 implements Serializable 058{ 059 /** 060 * Use the serial version uid for interoperability. 061 */ 062 private static final long serialVersionUID = 1086053664494604050L; 063 064 /** 065 * The UID counter (the ordinary number in the sequence of number of UID's, 066 * created during the recent millisecond). In the next millisecond, it 067 * starts from the minimal value again. In the unlikely case of creating 068 * more than 65536 uids per millisecond the process pauses till the next 069 * ms. 070 */ 071 private static short uidCounter = Short.MIN_VALUE; 072 073 /** 074 * The time, when the last UID has been created. 075 */ 076 private static long last; 077 078 /** 079 * This constant tries to be the unique identifier of the virtual machine. 080 */ 081 private static final int machineId = getMachineId(); 082 083 /** 084 * The UID number in the UID creation sequence. 085 */ 086 private short count; 087 088 /** 089 * Always gets the uniqueNr value. 090 */ 091 private int unique; 092 093 /** 094 * The time stamp, when the UID was created. 095 */ 096 private long time; 097 098 /** 099 * Create the new UID that would have the described features of the 100 * uniqueness. 101 */ 102 public UID() 103 { 104 synchronized (UID.class) 105 { 106 time = System.currentTimeMillis(); 107 unique = machineId; 108 if (time > last) 109 { 110 last = time; 111 count = uidCounter = Short.MIN_VALUE; 112 } 113 else 114 { 115 if (uidCounter == Short.MAX_VALUE) 116 { 117 // Make a 2 ms pause if the counter has reached the maximal 118 // value. This should seldom happen. 119 try 120 { 121 Thread.sleep(2); 122 } 123 catch (InterruptedException e) 124 { 125 } 126 uidCounter = Short.MIN_VALUE; 127 time = last = System.currentTimeMillis(); 128 } 129 count = ++uidCounter; 130 } 131 } 132 } 133 134 /** 135 * Create the new UID with the well known id (number). All UIDs, creates 136 * with the this constructor having the same parameter are equal to each 137 * other (regardless to the host and time where they were created. 138 * 139 * @param wellKnownId the well known UID. 140 */ 141 public UID(short wellKnownId) 142 { 143 unique = wellKnownId; 144 } 145 146 /** 147 * Get the hashCode of this UID. 148 */ 149 public int hashCode() 150 { 151 return (int) (unique ^ time ^ count); 152 } 153 154 /** 155 * Compare this UID with another UID for equality (not equal to other types of 156 * objects). 157 */ 158 public boolean equals(Object other) 159 { 160 if (other instanceof UID) 161 { 162 UID ui = (UID) other; 163 return unique == ui.unique && time == ui.time && count == ui.count; 164 } 165 else 166 return false; 167 } 168 169 public static UID read(DataInput in) throws IOException 170 { 171 UID uid = new UID(); 172 uid.unique = in.readInt(); 173 uid.time = in.readLong(); 174 uid.count = in.readShort(); 175 return (uid); 176 } 177 178 public void write(DataOutput out) throws IOException 179 { 180 out.writeInt(unique); 181 out.writeLong(time); 182 out.writeShort(count); 183 } 184 185 /** 186 * Do our best to get the Id of this virtual machine. 187 */ 188 static int getMachineId() 189 { 190 int hostIpHash; 191 192 try 193 { 194 // Try to get the host IP. 195 String host = InetAddress.getLocalHost().toString(); 196 // This hash is content - based, not the address based. 197 hostIpHash = host.hashCode(); 198 } 199 catch (Exception e) 200 { 201 // Failed due some reason. 202 hostIpHash = 0; 203 } 204 205 // Should be the unque address if hashcodes are addresses. 206 // Additionally, add the time when the RMI system was probably started 207 // (this class was first instantiated). 208 return new Object().hashCode() ^ (int) System.currentTimeMillis() 209 ^ hostIpHash; 210 } 211 212 /** 213 * Get the string representation of this UID. 214 * 215 * @return a string, uniquely identifying this id. 216 */ 217 public String toString() 218 { 219 int max = Character.MAX_RADIX; 220 // Translate into object count, counting from 0. 221 long lc = (count - Short.MIN_VALUE) & 0xFFFF; 222 return Long.toString(unique, max) + ":" + Long.toString(time, max) + "." 223 + Long.toString(lc, max); 224 } 225}