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 }