1. /*
  2. * @(#)ActivationID.java 1.28 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.rmi.activation;
  8. import java.io.IOException;
  9. import java.io.InvalidObjectException;
  10. import java.lang.reflect.InvocationHandler;
  11. import java.lang.reflect.Proxy;
  12. import java.rmi.MarshalledObject;
  13. import java.rmi.Remote;
  14. import java.rmi.RemoteException;
  15. import java.rmi.UnmarshalException;
  16. import java.rmi.server.RemoteObject;
  17. import java.rmi.server.RemoteObjectInvocationHandler;
  18. import java.rmi.server.RemoteRef;
  19. import java.rmi.server.RemoteStub;
  20. import java.rmi.server.UID;
  21. /**
  22. * Activation makes use of special identifiers to denote remote
  23. * objects that can be activated over time. An activation identifier
  24. * (an instance of the class <code>ActivationID</code>) contains several
  25. * pieces of information needed for activating an object:
  26. * <ul>
  27. * <li> a remote reference to the object's activator (a {@link
  28. * java.rmi.server.RemoteRef RemoteRef}
  29. * instance), and
  30. * <li> a unique identifier (a {@link java.rmi.server.UID UID}
  31. * instance) for the object. </ul> <p>
  32. *
  33. * An activation identifier for an object can be obtained by registering
  34. * an object with the activation system. Registration is accomplished
  35. * in a few ways: <ul>
  36. * <li>via the <code>Activatable.register</code> method
  37. * <li>via the first <code>Activatable</code> constructor (that takes
  38. * three arguments and both registers and exports the object, and
  39. * <li>via the first <code>Activatable.exportObject</code> method
  40. * that takes the activation descriptor, object and port as arguments;
  41. * this method both registers and exports the object. </ul>
  42. *
  43. * @author Ann Wollrath
  44. * @version 1.28, 03/12/19
  45. * @see Activatable
  46. * @since 1.2
  47. */
  48. public class ActivationID implements java.io.Serializable {
  49. /**
  50. * the object's activator
  51. */
  52. private transient Activator activator;
  53. /**
  54. * the object's unique id
  55. */
  56. private transient UID uid = new UID();
  57. /** indicate compatibility with the Java 2 SDK v1.2 version of class */
  58. private static final long serialVersionUID = -4608673054848209235L;
  59. /**
  60. * The constructor for <code>ActivationID</code> takes a single
  61. * argument, activator, that specifies a remote reference to the
  62. * activator responsible for activating the object associated with
  63. * this identifier. An instance of <code>ActivationID</code> is globally
  64. * unique.
  65. *
  66. * @param activator reference to the activator responsible for
  67. * activating the object
  68. * @since 1.2
  69. */
  70. public ActivationID(Activator activator) {
  71. this.activator = activator;
  72. }
  73. /**
  74. * Activate the object for this id.
  75. *
  76. * @param force if true, forces the activator to contact the group
  77. * when activating the object (instead of returning a cached reference);
  78. * if false, returning a cached value is acceptable.
  79. * @return the reference to the active remote object
  80. * @exception ActivationException if activation fails
  81. * @exception UnknownObjectException if the object is unknown
  82. * @exception RemoteException if remote call fails
  83. * @since 1.2
  84. */
  85. public Remote activate(boolean force)
  86. throws ActivationException, UnknownObjectException, RemoteException
  87. {
  88. try {
  89. MarshalledObject mobj =
  90. (MarshalledObject) activator.activate(this, force);
  91. return (Remote) mobj.get();
  92. } catch (RemoteException e) {
  93. throw e;
  94. } catch (IOException e) {
  95. throw new UnmarshalException("activation failed", e);
  96. } catch (ClassNotFoundException e) {
  97. throw new UnmarshalException("activation failed", e);
  98. }
  99. }
  100. /**
  101. * Returns a hashcode for the activation id. Two identifiers that
  102. * refer to the same remote object will have the same hash code.
  103. *
  104. * @see java.util.Hashtable
  105. * @since 1.2
  106. */
  107. public int hashCode() {
  108. return uid.hashCode();
  109. }
  110. /**
  111. * Compares two activation ids for content equality.
  112. * Returns true if both of the following conditions are true:
  113. * 1) the unique identifiers equivalent (by content), and
  114. * 2) the activator specified in each identifier
  115. * refers to the same remote object.
  116. *
  117. * @param obj the Object to compare with
  118. * @return true if these Objects are equal; false otherwise.
  119. * @see java.util.Hashtable
  120. * @since 1.2
  121. */
  122. public boolean equals(Object obj) {
  123. if (obj instanceof ActivationID) {
  124. ActivationID id = (ActivationID) obj;
  125. return (uid.equals(id.uid) && activator.equals(id.activator));
  126. } else {
  127. return false;
  128. }
  129. }
  130. /**
  131. * <code>writeObject</code> for custom serialization.
  132. *
  133. * <p>This method writes this object's serialized form for
  134. * this class as follows:
  135. *
  136. * <p>The <code>writeObject</code> method is invoked on
  137. * <code>out</code> passing this object's unique identifier
  138. * (a {@link java.rmi.server.UID UID} instance) as the argument.
  139. *
  140. * <p>Next, the {@link
  141. * java.rmi.server.RemoteRef#getRefClass(java.io.ObjectOutput)
  142. * getRefClass} method is invoked on the activator's
  143. * <code>RemoteRef</code> instance to obtain its external ref
  144. * type name. Next, the <code>writeUTF</code> method is
  145. * invoked on <code>out</code> with the value returned by
  146. * <code>getRefClass</code>, and then the
  147. * <code>writeExternal</code> method is invoked on the
  148. * <code>RemoteRef</code> instance passing <code>out</code>
  149. * as the argument.
  150. *
  151. * @serialData The serialized data for this class comprises a
  152. * <code>java.rmi.server.UID</code> (written with
  153. * <code>ObjectOutput.writeObject</code>) followed by the
  154. * external ref type name of the activator's
  155. * <code>RemoteRef</code> instance (a string written with
  156. * <code>ObjectOutput.writeUTF</code>), followed by the
  157. * external form of the <code>RemoteRef</code> instance as
  158. * written by its <code>writeExternal</code> method.
  159. *
  160. * <p>The external ref type name of the
  161. * <code>RemoteRef</Code> instance is
  162. * determined using the definitions of external ref type
  163. * names specified in the {@link java.rmi.server.RemoteObject
  164. * RemoteObject} <code>writeObject</code> method
  165. * <b>serialData</b> specification. Similarly, the data
  166. * written by the <code>writeExternal</code> method and read
  167. * by the <code>readExternal</code> method of
  168. * <code>RemoteRef</code> implementation classes
  169. * corresponding to each of the defined external ref type
  170. * names is specified in the {@link
  171. * java.rmi.server.RemoteObject RemoteObject}
  172. * <code>writeObject</code> method <b>serialData</b>
  173. * specification.
  174. **/
  175. private void writeObject(java.io.ObjectOutputStream out)
  176. throws IOException, ClassNotFoundException
  177. {
  178. out.writeObject(uid);
  179. RemoteRef ref;
  180. if (activator instanceof RemoteObject) {
  181. ref = ((RemoteObject) activator).getRef();
  182. } else if (Proxy.isProxyClass(activator.getClass())) {
  183. InvocationHandler handler = Proxy.getInvocationHandler(activator);
  184. if (!(handler instanceof RemoteObjectInvocationHandler)) {
  185. throw new InvalidObjectException(
  186. "unexpected invocation handler");
  187. }
  188. ref = ((RemoteObjectInvocationHandler) handler).getRef();
  189. } else {
  190. throw new InvalidObjectException("unexpected activator type");
  191. }
  192. out.writeUTF(ref.getRefClass(out));
  193. ref.writeExternal(out);
  194. }
  195. /**
  196. * <code>readObject</code> for custom serialization.
  197. *
  198. * <p>This method reads this object's serialized form for this
  199. * class as follows:
  200. *
  201. * <p>The <code>readObject</code> method is invoked on
  202. * <code>in</code> to read this object's unique identifier
  203. * (a {@link java.rmi.server.UID UID} instance).
  204. *
  205. * <p>Next, the <code>readUTF</code> method is invoked on
  206. * <code>in</code> to read the external ref type name of the
  207. * <code>RemoteRef</code> instance for this object's
  208. * activator. Next, the <code>RemoteRef</code>
  209. * instance is created of an implementation-specific class
  210. * corresponding to the external ref type name (returned by
  211. * <code>readUTF</code>), and the <code>readExternal</code>
  212. * method is invoked on that <code>RemoteRef</code> instance
  213. * to read the external form corresponding to the external
  214. * ref type name.
  215. *
  216. * <p>Note: If the external ref type name is
  217. * <code>"UnicastRef"</code>, <code>"UnicastServerRef"</code>,
  218. * <code>"UnicastRef2"</code>, <code>"UnicastServerRef2"</code>,
  219. * or <code>"ActivatableRef"</code>, a corresponding
  220. * implementation-specific class must be found, and its
  221. * <code>readExternal</code> method must read the serial data
  222. * for that external ref type name as specified to be written
  223. * in the <b>serialData</b> documentation for this class.
  224. * If the external ref type name is any other string (of non-zero
  225. * length), a <code>ClassNotFoundException</code> will be thrown,
  226. * unless the implementation provides an implementation-specific
  227. * class corresponding to that external ref type name, in which
  228. * case the <code>RemoteRef</code> will be an instance of
  229. * that implementation-specific class.
  230. */
  231. private void readObject(java.io.ObjectInputStream in)
  232. throws IOException, ClassNotFoundException
  233. {
  234. uid = (UID)in.readObject();
  235. try {
  236. Class refClass = Class.forName(RemoteRef.packagePrefix + "." +
  237. in.readUTF());
  238. RemoteRef ref = (RemoteRef) refClass.newInstance();
  239. ref.readExternal(in);
  240. activator = (Activator)
  241. Proxy.newProxyInstance(null,
  242. new Class[]{ Activator.class },
  243. new RemoteObjectInvocationHandler(ref));
  244. } catch (InstantiationException e) {
  245. throw (IOException)
  246. new InvalidObjectException(
  247. "Unable to create remote reference").initCause(e);
  248. } catch (IllegalAccessException e) {
  249. throw (IOException)
  250. new InvalidObjectException(
  251. "Unable to create remote reference").initCause(e);
  252. }
  253. }
  254. }