1. /*
  2. * @(#)ObjID.java 1.28 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.rmi.server;
  8. import java.io.DataInput;
  9. import java.io.DataOutput;
  10. import java.io.EOFException;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.io.ObjectInput;
  14. import java.io.ObjectOutput;
  15. import java.io.OutputStream;
  16. import java.security.SecureRandom;
  17. import java.util.Random;
  18. /**
  19. * An <code>ObjID</code> is used to identify a remote object exported
  20. * to an RMI runtime. When a remote object is exported, it is assigned
  21. * an object identifier either implicitly or explicitly, depending on
  22. * the API used to export.
  23. *
  24. * <p>The {@link #ObjID()} constructor can be used to generate a unique
  25. * object identifier. Such an <code>ObjID</code> is unique over time
  26. * with respect to the host it is generated on.
  27. *
  28. * The {@link #ObjID(int)} constructor can be used to create a
  29. * "well-known" object identifier. The scope of a well-known
  30. * <code>ObjID</code> depends on the RMI runtime it is exported to.
  31. *
  32. * <p>An <code>ObjID</code> instance contains an object number (of type
  33. * <code>long</code>) and an address space identifier (of type
  34. * {@link UID}). In a unique <code>ObjID</code>, the address space
  35. * identifier is unique with respect to a given host over time. In a
  36. * well-known <code>ObjID</code>, the address space identifier is
  37. * equivalent to one returned by invoking the {@link UID#UID(short)}
  38. * constructor with the value zero.
  39. *
  40. * <p>If the system property <code>java.rmi.server.randomIDs</code>
  41. * is defined to equal the string <code>"true"</code> (case insensitive),
  42. * then the {@link #ObjID()} constructor will use a cryptographically
  43. * strong random number generator to choose the object number of the
  44. * returned <code>ObjID</code>.
  45. *
  46. * @author Ann Wollrath
  47. * @author Peter Jones
  48. * @version 1.28, 03/01/23
  49. * @since JDK1.1
  50. */
  51. public final class ObjID implements java.io.Serializable {
  52. /** Object number for well-known <code>ObjID</code> of the registry. */
  53. public static final int REGISTRY_ID = 0;
  54. /** Object number for well-known <code>ObjID</code> of the activator. */
  55. public static final int ACTIVATOR_ID = 1;
  56. /**
  57. * Object number for well-known <code>ObjID</code> of
  58. * the distributed garbage collector.
  59. */
  60. public static final int DGC_ID = 2;
  61. /** indicate compatibility with JDK 1.1.x version of class */
  62. private static final long serialVersionUID = -6386392263968365220L;
  63. private static final UID mySpace;
  64. private static final Random generator;
  65. /**
  66. * @serial object number
  67. * @see #hashCode
  68. */
  69. private final long objNum;
  70. /**
  71. * @serial address space identifier (unique to host over time)
  72. */
  73. private final UID space;
  74. /**
  75. * Generates a unique object identifier.
  76. *
  77. * <p>If the system property <code>java.rmi.server.randomIDs</code>
  78. * is defined to equal the string <code>"true"</code> (case insensitive),
  79. * then this constructor will use a cryptographically
  80. * strong random number generator to choose the object number of the
  81. * returned <code>ObjID</code>.
  82. */
  83. public ObjID() {
  84. /*
  85. * Create a new UID if the SecureRandom generator is used (mySpace
  86. * will be null in this case). Using a different UID for each ObjID
  87. * ensures that ObjIDs will be unique in this VM incarnation when
  88. * paired with the result of the secure random number generator.
  89. */
  90. space = (mySpace != null) ? mySpace : new UID();
  91. objNum = generator.nextLong();
  92. }
  93. /**
  94. * Creates a "well-known" object identifier.
  95. *
  96. * <p>An <code>ObjID</code> created via this constructor will not
  97. * clash with any <code>ObjID</code>s generated via the no-arg
  98. * constructor.
  99. *
  100. * @param objNum object number for well-known object identifier
  101. */
  102. public ObjID(int objNum) {
  103. space = new UID((short) 0);
  104. this.objNum = objNum;
  105. }
  106. /**
  107. * Constructs an object identifier given data read from a stream.
  108. */
  109. private ObjID(long objNum, UID space) {
  110. this.objNum = objNum;
  111. this.space = space;
  112. }
  113. /**
  114. * Marshals a binary representation of this <code>ObjID</code> to
  115. * an <code>ObjectOutput</code> instance.
  116. *
  117. * <p>Specifically, this method first invokes the given stream's
  118. * {@link ObjectOutput#writeLong(long)} method with this object
  119. * identifier's object number, and then it writes its address
  120. * space identifier by invoking its {@link UID#write(DataOutput)}
  121. * method with the stream.
  122. *
  123. * @param out the <code>ObjectOutput</code> instance to write
  124. * this <code>ObjID</code> to
  125. *
  126. * @throws IOException if an I/O error occurs while performing
  127. * this operation
  128. */
  129. public void write(ObjectOutput out) throws IOException {
  130. out.writeLong(objNum);
  131. space.write(out);
  132. }
  133. /**
  134. * Constructs and returns a new <code>ObjID</code> instance by
  135. * unmarshalling a binary representation from an
  136. * <code>ObjectInput</code> instance.
  137. *
  138. * <p>Specifically, this method first invokes the given stream's
  139. * {@link ObjectInput#readLong()} method to read an object number,
  140. * then it invokes {@link UID#read(DataInput)} with the
  141. * stream to read an address space identifier, and then it
  142. * creates and returns a new <code>ObjID</code> instance that
  143. * contains the object number and address space identifier that
  144. * were read from the stream.
  145. *
  146. * @param in the <code>ObjectInput</code> instance to read
  147. * <code>ObjID</code> from
  148. *
  149. * @return unmarshalled <code>ObjID</code> instance
  150. *
  151. * @throws IOException if an I/O error occurs while performing
  152. * this operation
  153. */
  154. public static ObjID read(ObjectInput in) throws IOException {
  155. long num = in.readLong();
  156. UID space = UID.read(in);
  157. return new ObjID(num, space);
  158. }
  159. /**
  160. * Returns the hash code value for this object identifier, the
  161. * object number.
  162. *
  163. * @return the hash code value for this object identifier
  164. */
  165. public int hashCode() {
  166. return (int) objNum;
  167. }
  168. /**
  169. * Compares the specified object with this <code>ObjID</code> for
  170. * equality.
  171. *
  172. * This method returns <code>true</code> if and only if the
  173. * specified object is an <code>ObjID</code> instance with the same
  174. * object number and address space identifier as this one.
  175. *
  176. * @param obj the object to compare this <code>ObjID</code> to
  177. *
  178. * @return <code>true</code> if the given object is equivalent to
  179. * this one, and <code>false</code> otherwise
  180. */
  181. public boolean equals(Object obj) {
  182. if (obj instanceof ObjID) {
  183. ObjID id = (ObjID)obj;
  184. return objNum == id.objNum && space.equals(id.space);
  185. } else {
  186. return false;
  187. }
  188. }
  189. /**
  190. * Returns a string representation of this object identifier.
  191. *
  192. * @return a string representation of this object identifier
  193. */
  194. /*
  195. * The address space identifier is only included in the string
  196. * representation if it does not denote the local address space
  197. * (or if the randomIDs property was set).
  198. */
  199. public String toString() {
  200. return "[" + (space.equals(mySpace) ? "" : space + ", ") +
  201. objNum + "]";
  202. }
  203. private static final class InsecureRandom extends Random {
  204. /** unnecessary serialVersionUID to keep watchdog tools happy */
  205. private static final long serialVersionUID = -698228687531590145L;
  206. private long nextNum;
  207. public synchronized long nextLong() {
  208. return nextNum++;
  209. }
  210. }
  211. static {
  212. boolean randomIDs =
  213. ((Boolean) java.security.AccessController.doPrivileged(
  214. new sun.security.action.GetBooleanAction(
  215. "java.rmi.server.randomIDs"))).booleanValue();
  216. if (randomIDs) {
  217. generator = new SecureRandom();
  218. mySpace = null;
  219. } else {
  220. generator = new InsecureRandom();
  221. /*
  222. * The InsecureRandom implementation guarantees that object
  223. * numbers will not repeat, so the same UID value can be used
  224. * for all instances of ObjID.
  225. */
  226. mySpace = new UID();
  227. }
  228. }
  229. }