001 /*
002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package java.rmi.server;
026
027 import java.io.DataInput;
028 import java.io.DataOutput;
029 import java.io.IOException;
030 import java.io.ObjectInput;
031 import java.io.ObjectOutput;
032 import java.io.Serializable;
033 import java.security.AccessController;
034 import java.security.SecureRandom;
035 import java.util.concurrent.atomic.AtomicLong;
036 import sun.security.action.GetPropertyAction;
037
038 /**
039 * An <code>ObjID</code> is used to identify a remote object exported
040 * to an RMI runtime. When a remote object is exported, it is assigned
041 * an object identifier either implicitly or explicitly, depending on
042 * the API used to export.
043 *
044 * <p>The {@link #ObjID()} constructor can be used to generate a unique
045 * object identifier. Such an <code>ObjID</code> is unique over time
046 * with respect to the host it is generated on.
047 *
048 * The {@link #ObjID(int)} constructor can be used to create a
049 * "well-known" object identifier. The scope of a well-known
050 * <code>ObjID</code> depends on the RMI runtime it is exported to.
051 *
052 * <p>An <code>ObjID</code> instance contains an object number (of type
053 * <code>long</code>) and an address space identifier (of type
054 * {@link UID}). In a unique <code>ObjID</code>, the address space
055 * identifier is unique with respect to a given host over time. In a
056 * well-known <code>ObjID</code>, the address space identifier is
057 * equivalent to one returned by invoking the {@link UID#UID(short)}
058 * constructor with the value zero.
059 *
060 * <p>If the system property <code>java.rmi.server.randomIDs</code>
061 * is defined to equal the string <code>"true"</code> (case insensitive),
062 * then the {@link #ObjID()} constructor will use a cryptographically
063 * strong random number generator to choose the object number of the
064 * returned <code>ObjID</code>.
065 *
066 * @author Ann Wollrath
067 * @author Peter Jones
068 * @version 1.37, 07/05/05
069 * @since JDK1.1
070 */
071 public final class ObjID implements Serializable {
072
073 /** Object number for well-known <code>ObjID</code> of the registry. */
074 public static final int REGISTRY_ID = 0;
075
076 /** Object number for well-known <code>ObjID</code> of the activator. */
077 public static final int ACTIVATOR_ID = 1;
078
079 /**
080 * Object number for well-known <code>ObjID</code> of
081 * the distributed garbage collector.
082 */
083 public static final int DGC_ID = 2;
084
085 /** indicate compatibility with JDK 1.1.x version of class */
086 private static final long serialVersionUID = -6386392263968365220L;
087
088 private static final AtomicLong nextObjNum = new AtomicLong(0);
089 private static final UID mySpace = new UID();
090 private static final SecureRandom secureRandom = new SecureRandom();
091
092 /**
093 * @serial object number
094 * @see #hashCode
095 */
096 private final long objNum;
097
098 /**
099 * @serial address space identifier (unique to host over time)
100 */
101 private final UID space;
102
103 /**
104 * Generates a unique object identifier.
105 *
106 * <p>If the system property <code>java.rmi.server.randomIDs</code>
107 * is defined to equal the string <code>"true"</code> (case insensitive),
108 * then this constructor will use a cryptographically
109 * strong random number generator to choose the object number of the
110 * returned <code>ObjID</code>.
111 */
112 public ObjID() {
113 /*
114 * If generating random object numbers, create a new UID to
115 * ensure uniqueness; otherwise, use a shared UID because
116 * sequential object numbers already ensure uniqueness.
117 */
118 if (useRandomIDs()) {
119 space = new UID();
120 objNum = secureRandom.nextLong();
121 } else {
122 space = mySpace;
123 objNum = nextObjNum.getAndIncrement();
124 }
125 }
126
127 /**
128 * Creates a "well-known" object identifier.
129 *
130 * <p>An <code>ObjID</code> created via this constructor will not
131 * clash with any <code>ObjID</code>s generated via the no-arg
132 * constructor.
133 *
134 * @param objNum object number for well-known object identifier
135 */
136 public ObjID(int objNum) {
137 space = new UID((short) 0);
138 this .objNum = objNum;
139 }
140
141 /**
142 * Constructs an object identifier given data read from a stream.
143 */
144 private ObjID(long objNum, UID space) {
145 this .objNum = objNum;
146 this .space = space;
147 }
148
149 /**
150 * Marshals a binary representation of this <code>ObjID</code> to
151 * an <code>ObjectOutput</code> instance.
152 *
153 * <p>Specifically, this method first invokes the given stream's
154 * {@link ObjectOutput#writeLong(long)} method with this object
155 * identifier's object number, and then it writes its address
156 * space identifier by invoking its {@link UID#write(DataOutput)}
157 * method with the stream.
158 *
159 * @param out the <code>ObjectOutput</code> instance to write
160 * this <code>ObjID</code> to
161 *
162 * @throws IOException if an I/O error occurs while performing
163 * this operation
164 */
165 public void write(ObjectOutput out) throws IOException {
166 out.writeLong(objNum);
167 space.write(out);
168 }
169
170 /**
171 * Constructs and returns a new <code>ObjID</code> instance by
172 * unmarshalling a binary representation from an
173 * <code>ObjectInput</code> instance.
174 *
175 * <p>Specifically, this method first invokes the given stream's
176 * {@link ObjectInput#readLong()} method to read an object number,
177 * then it invokes {@link UID#read(DataInput)} with the
178 * stream to read an address space identifier, and then it
179 * creates and returns a new <code>ObjID</code> instance that
180 * contains the object number and address space identifier that
181 * were read from the stream.
182 *
183 * @param in the <code>ObjectInput</code> instance to read
184 * <code>ObjID</code> from
185 *
186 * @return unmarshalled <code>ObjID</code> instance
187 *
188 * @throws IOException if an I/O error occurs while performing
189 * this operation
190 */
191 public static ObjID read(ObjectInput in) throws IOException {
192 long num = in.readLong();
193 UID space = UID.read(in);
194 return new ObjID(num, space);
195 }
196
197 /**
198 * Returns the hash code value for this object identifier, the
199 * object number.
200 *
201 * @return the hash code value for this object identifier
202 */
203 public int hashCode() {
204 return (int) objNum;
205 }
206
207 /**
208 * Compares the specified object with this <code>ObjID</code> for
209 * equality.
210 *
211 * This method returns <code>true</code> if and only if the
212 * specified object is an <code>ObjID</code> instance with the same
213 * object number and address space identifier as this one.
214 *
215 * @param obj the object to compare this <code>ObjID</code> to
216 *
217 * @return <code>true</code> if the given object is equivalent to
218 * this one, and <code>false</code> otherwise
219 */
220 public boolean equals(Object obj) {
221 if (obj instanceof ObjID) {
222 ObjID id = (ObjID) obj;
223 return objNum == id.objNum && space.equals(id.space);
224 } else {
225 return false;
226 }
227 }
228
229 /**
230 * Returns a string representation of this object identifier.
231 *
232 * @return a string representation of this object identifier
233 */
234 /*
235 * The address space identifier is only included in the string
236 * representation if it does not denote the local address space
237 * (or if the randomIDs property was set).
238 */
239 public String toString() {
240 return "[" + (space.equals(mySpace) ? "" : space + ", ")
241 + objNum + "]";
242 }
243
244 private static boolean useRandomIDs() {
245 String value = AccessController
246 .doPrivileged(new GetPropertyAction(
247 "java.rmi.server.randomIDs"));
248 return value == null ? true : Boolean.parseBoolean(value);
249 }
250 }
|