001 /* UID.java -- The unique object Id 002 Copyright (c) 2006 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package java.rmi.server; 040 041 import java.io.DataInput; 042 import java.io.DataOutput; 043 import java.io.IOException; 044 import java.io.Serializable; 045 import 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 */ 056 public 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 }