1. /*
  2. * @(#)RemoteObject.java 1.33 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.server;
  8. import java.rmi.Remote;
  9. import java.rmi.NoSuchObjectException;
  10. import java.lang.reflect.Proxy;
  11. import sun.rmi.server.Util;
  12. /**
  13. * The <code>RemoteObject</code> class implements the
  14. * <code>java.lang.Object</code> behavior for remote objects.
  15. * <code>RemoteObject</code> provides the remote semantics of Object by
  16. * implementing methods for hashCode, equals, and toString.
  17. *
  18. * @author Ann Wollrath
  19. * @author Laird Dornin
  20. * @author Peter Jones
  21. * @version 1.33, 03/12/19
  22. * @since JDK1.1
  23. */
  24. public abstract class RemoteObject implements Remote, java.io.Serializable {
  25. /** The object's remote reference. */
  26. transient protected RemoteRef ref;
  27. /** indicate compatibility with JDK 1.1.x version of class */
  28. private static final long serialVersionUID = -3215090123894869218L;
  29. /**
  30. * Creates a remote object.
  31. */
  32. protected RemoteObject() {
  33. ref = null;
  34. }
  35. /**
  36. * Creates a remote object, initialized with the specified remote
  37. * reference.
  38. * @param newref remote reference
  39. */
  40. protected RemoteObject(RemoteRef newref) {
  41. ref = newref;
  42. }
  43. /**
  44. * Returns the remote reference for the remote object.
  45. *
  46. * <p>Note: The object returned from this method may be an instance of
  47. * an implementation-specific class. The <code>RemoteObject</code>
  48. * class ensures serialization portability of its instances' remote
  49. * references through the behavior of its custom
  50. * <code>writeObject</code> and <code>readObject</code> methods. An
  51. * instance of <code>RemoteRef</code> should not be serialized outside
  52. * of its <code>RemoteObject</code> wrapper instance or the result may
  53. * be unportable.
  54. *
  55. * @return remote reference for the remote object
  56. * @since 1.2
  57. */
  58. public RemoteRef getRef() {
  59. return ref;
  60. }
  61. /**
  62. * Returns the stub for the remote object <code>obj</code> passed
  63. * as a parameter. This operation is only valid <i>after</i>
  64. * the object has been exported.
  65. * @param obj the remote object whose stub is needed
  66. * @return the stub for the remote object, <code>obj</code>.
  67. * @exception NoSuchObjectException if the stub for the
  68. * remote object could not be found.
  69. * @since 1.2
  70. */
  71. public static Remote toStub(Remote obj) throws NoSuchObjectException {
  72. if (obj instanceof RemoteStub ||
  73. (obj != null &&
  74. Proxy.isProxyClass(obj.getClass()) &&
  75. Proxy.getInvocationHandler(obj) instanceof
  76. RemoteObjectInvocationHandler))
  77. {
  78. return obj;
  79. } else {
  80. return sun.rmi.transport.ObjectTable.getStub(obj);
  81. }
  82. }
  83. /**
  84. * Returns a hashcode for a remote object. Two remote object stubs
  85. * that refer to the same remote object will have the same hash code
  86. * (in order to support remote objects as keys in hash tables).
  87. *
  88. * @see java.util.Hashtable
  89. */
  90. public int hashCode() {
  91. return (ref == null) ? super.hashCode() : ref.remoteHashCode();
  92. }
  93. /**
  94. * Compares two remote objects for equality.
  95. * Returns a boolean that indicates whether this remote object is
  96. * equivalent to the specified Object. This method is used when a
  97. * remote object is stored in a hashtable.
  98. * If the specified Object is not itself an instance of RemoteObject,
  99. * then this method delegates by returning the result of invoking the
  100. * <code>equals</code> method of its parameter with this remote object
  101. * as the argument.
  102. * @param obj the Object to compare with
  103. * @return true if these Objects are equal; false otherwise.
  104. * @see java.util.Hashtable
  105. */
  106. public boolean equals(Object obj) {
  107. if (obj instanceof RemoteObject) {
  108. if (ref == null) {
  109. return obj == this;
  110. } else {
  111. return ref.remoteEquals(((RemoteObject)obj).ref);
  112. }
  113. } else if (obj != null) {
  114. /*
  115. * Fix for 4099660: if object is not an instance of RemoteObject,
  116. * use the result of its equals method, to support symmetry is a
  117. * remote object implementation class that does not extend
  118. * RemoteObject wishes to support equality with its stub objects.
  119. */
  120. return obj.equals(this);
  121. } else {
  122. return false;
  123. }
  124. }
  125. /**
  126. * Returns a String that represents the value of this remote object.
  127. */
  128. public String toString() {
  129. String classname = Util.getUnqualifiedName(getClass());
  130. return (ref == null) ? classname :
  131. classname + "[" + ref.remoteToString() + "]";
  132. }
  133. /**
  134. * <code>writeObject</code> for custom serialization.
  135. *
  136. * <p>This method writes this object's serialized form for this class
  137. * as follows:
  138. *
  139. * <p>The {@link RemoteRef#getRefClass(java.io.ObjectOutput) getRefClass}
  140. * method is invoked on this object's <code>ref</code> field
  141. * to obtain its external ref type name.
  142. * If the value returned by <code>getRefClass</code> was
  143. * a non-<code>null</code> string of length greater than zero,
  144. * the <code>writeUTF</code> method is invoked on <code>out</code>
  145. * with the value returned by <code>getRefClass</code>, and then
  146. * the <code>writeExternal</code> method is invoked on
  147. * this object's <code>ref</code> field passing <code>out</code>
  148. * as the argument; otherwise,
  149. * the <code>writeUTF</code> method is invoked on <code>out</code>
  150. * with a zero-length string (<code>""</code>), and then
  151. * the <code>writeObject</code> method is invoked on <code>out</code>
  152. * passing this object's <code>ref</code> field as the argument.
  153. *
  154. * @serialData
  155. *
  156. * The serialized data for this class comprises a string (written with
  157. * <code>ObjectOutput.writeUTF</code>) that is either the external
  158. * ref type name of the contained <code>RemoteRef</code> instance
  159. * (the <code>ref</code> field) or a zero-length string, followed by
  160. * either the external form of the <code>ref</code> field as written by
  161. * its <code>writeExternal</code> method if the string was of non-zero
  162. * length, or the serialized form of the <code>ref</code> field as
  163. * written by passing it to the serialization stream's
  164. * <code>writeObject</code> if the string was of zero length.
  165. *
  166. * <p>If this object is an instance of
  167. * {@link RemoteStub} or {@link RemoteObjectInvocationHandler}
  168. * that was returned from any of
  169. * the <code>UnicastRemoteObject.exportObject</code> methods
  170. * and custom socket factories are not used,
  171. * the external ref type name is <code>"UnicastRef"</code>.
  172. *
  173. * If this object is an instance of
  174. * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
  175. * that was returned from any of
  176. * the <code>UnicastRemoteObject.exportObject</code> methods
  177. * and custom socket factories are used,
  178. * the external ref type name is <code>"UnicastRef2"</code>.
  179. *
  180. * If this object is an instance of
  181. * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
  182. * that was returned from any of
  183. * the <code>java.rmi.activation.Activatable.exportObject</code> methods,
  184. * the external ref type name is <code>"ActivatableRef"</code>.
  185. *
  186. * If this object is an instance of
  187. * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
  188. * that was returned from
  189. * the <code>RemoteObject.toStub</code> method (and the argument passed
  190. * to <code>toStub</code> was not itself a <code>RemoteStub</code>),
  191. * the external ref type name is a function of how the remote object
  192. * passed to <code>toStub</code> was exported, as described above.
  193. *
  194. * If this object is an instance of
  195. * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
  196. * that was originally created via deserialization,
  197. * the external ref type name is the same as that which was read
  198. * when this object was deserialized.
  199. *
  200. * <p>If this object is an instance of
  201. * <code>java.rmi.server.UnicastRemoteObject</code> that does not
  202. * use custom socket factories,
  203. * the external ref type name is <code>"UnicastServerRef"</code>.
  204. *
  205. * If this object is an instance of
  206. * <code>UnicastRemoteObject</code> that does
  207. * use custom socket factories,
  208. * the external ref type name is <code>"UnicastServerRef2"</code>.
  209. *
  210. * <p>Following is the data that must be written by the
  211. * <code>writeExternal</code> method and read by the
  212. * <code>readExternal</code> method of <code>RemoteRef</code>
  213. * implementation classes that correspond to the each of the
  214. * defined external ref type names:
  215. *
  216. * <p>For <code>"UnicastRef"</code>:
  217. *
  218. * <ul>
  219. *
  220. * <li>the hostname of the referenced remote object,
  221. * written by {@link java.io.ObjectOutput#writeUTF(String)}
  222. *
  223. * <li>the port of the referenced remote object,
  224. * written by {@link java.io.ObjectOutput#writeInt(int)}
  225. *
  226. * <li>the data written as a result of calling
  227. * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
  228. * on the <code>ObjID</code> instance contained in the reference
  229. *
  230. * <li>the boolean value <code>false</code>,
  231. * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
  232. *
  233. * </ul>
  234. *
  235. * <p>For <code>"UnicastRef2"</code> with a
  236. * <code>null</code> client socket factory:
  237. *
  238. * <ul>
  239. *
  240. * <li>the byte value <code>0x00</code>
  241. * (indicating <code>null</code> client socket factory),
  242. * written by {@link java.io.ObjectOutput#writeByte(int)}
  243. *
  244. * <li>the hostname of the referenced remote object,
  245. * written by {@link java.io.ObjectOutput#writeUTF(String)}
  246. *
  247. * <li>the port of the referenced remote object,
  248. * written by {@link java.io.ObjectOutput#writeInt(int)}
  249. *
  250. * <li>the data written as a result of calling
  251. * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
  252. * on the <code>ObjID</code> instance contained in the reference
  253. *
  254. * <li>the boolean value <code>false</code>,
  255. * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
  256. *
  257. * </ul>
  258. *
  259. * <p>For <code>"UnicastRef2"</code> with a
  260. * non-<code>null</code> client socket factory:
  261. *
  262. * <ul>
  263. *
  264. * <li>the byte value <code>0x01</code>
  265. * (indicating non-<code>null</code> client socket factory),
  266. * written by {@link java.io.ObjectOutput#writeByte(int)}
  267. *
  268. * <li>the hostname of the referenced remote object,
  269. * written by {@link java.io.ObjectOutput#writeUTF(String)}
  270. *
  271. * <li>the port of the referenced remote object,
  272. * written by {@link java.io.ObjectOutput#writeInt(int)}
  273. *
  274. * <li>a client socket factory (object of type
  275. * <code>java.rmi.server.RMIClientSocketFactory</code>),
  276. * written by passing it to an invocation of
  277. * <code>writeObject</code> on the stream instance
  278. *
  279. * <li>the data written as a result of calling
  280. * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
  281. * on the <code>ObjID</code> instance contained in the reference
  282. *
  283. * <li>the boolean value <code>false</code>,
  284. * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
  285. *
  286. * </ul>
  287. *
  288. * <p>For <code>"ActivatableRef"</code> with a
  289. * <code>null</code> nested remote reference:
  290. *
  291. * <ul>
  292. *
  293. * <li>an instance of
  294. * <code>java.rmi.activation.ActivationID</code>,
  295. * written by passing it to an invocation of
  296. * <code>writeObject</code> on the stream instance
  297. *
  298. * <li>a zero-length string (<code>""</code>),
  299. * written by {@link java.io.ObjectOutput#writeUTF(String)}
  300. *
  301. * </ul>
  302. *
  303. * <p>For <code>"ActivatableRef"</code> with a
  304. * non-<code>null</code> nested remote reference:
  305. *
  306. * <ul>
  307. *
  308. * <li>an instance of
  309. * <code>java.rmi.activation.ActivationID</code>,
  310. * written by passing it to an invocation of
  311. * <code>writeObject</code> on the stream instance
  312. *
  313. * <li>the external ref type name of the nested remote reference,
  314. * which must be <code>"UnicastRef2"</code>,
  315. * written by {@link java.io.ObjectOutput#writeUTF(String)}
  316. *
  317. * <li>the external form of the nested remote reference,
  318. * written by invoking its <code>writeExternal</code> method
  319. * with the stream instance
  320. * (see the description of the external form for
  321. * <code>"UnicastRef2"</code> above)
  322. *
  323. * </ul>
  324. *
  325. * <p>For <code>"UnicastServerRef"</code> and
  326. * <code>"UnicastServerRef2"</code>, no data is written by the
  327. * <code>writeExternal</code> method or read by the
  328. * <code>readExternal</code> method.
  329. */
  330. private void writeObject(java.io.ObjectOutputStream out)
  331. throws java.io.IOException, java.lang.ClassNotFoundException
  332. {
  333. if (ref == null) {
  334. throw new java.rmi.MarshalException("Invalid remote object");
  335. } else {
  336. String refClassName = ref.getRefClass(out);
  337. if (refClassName == null || refClassName.length() == 0) {
  338. /*
  339. * No reference class name specified, so serialize
  340. * remote reference.
  341. */
  342. out.writeUTF("");
  343. out.writeObject(ref);
  344. } else {
  345. /*
  346. * Built-in reference class specified, so delegate
  347. * to reference to write out its external form.
  348. */
  349. out.writeUTF(refClassName);
  350. ref.writeExternal(out);
  351. }
  352. }
  353. }
  354. /**
  355. * <code>readObject</code> for custom serialization.
  356. *
  357. * <p>This method reads this object's serialized form for this class
  358. * as follows:
  359. *
  360. * <p>The <code>readUTF</code> method is invoked on <code>in</code>
  361. * to read the external ref type name for the <code>RemoteRef</code>
  362. * instance to be filled in to this object's <code>ref</code> field.
  363. * If the string returned by <code>readUTF</code> has length zero,
  364. * the <code>readObject</code> method is invoked on <code>in</code>,
  365. * and than the value returned by <code>readObject</code> is cast to
  366. * <code>RemoteRef</code> and this object's <code>ref</code> field is
  367. * set to that value.
  368. * Otherwise, this object's <code>ref</code> field is set to a
  369. * <code>RemoteRef</code> instance that is created of an
  370. * implementation-specific class corresponding to the external ref
  371. * type name returned by <code>readUTF</code>, and then
  372. * the <code>readExternal</code> method is invoked on
  373. * this object's <code>ref</code> field.
  374. *
  375. * <p>If the external ref type name is
  376. * <code>"UnicastRef"</code>, <code>"UnicastServerRef"</code>,
  377. * <code>"UnicastRef2"</code>, <code>"UnicastServerRef2"</code>,
  378. * or <code>"ActivatableRef"</code>, a corresponding
  379. * implementation-specific class must be found, and its
  380. * <code>readExternal</code> method must read the serial data
  381. * for that external ref type name as specified to be written
  382. * in the <b>serialData</b> documentation for this class.
  383. * If the external ref type name is any other string (of non-zero
  384. * length), a <code>ClassNotFoundException</code> will be thrown,
  385. * unless the implementation provides an implementation-specific
  386. * class corresponding to that external ref type name, in which
  387. * case this object's <code>ref</code> field will be set to an
  388. * instance of that implementation-specific class.
  389. */
  390. private void readObject(java.io.ObjectInputStream in)
  391. throws java.io.IOException, java.lang.ClassNotFoundException
  392. {
  393. String refClassName = in.readUTF();
  394. if (refClassName == null || refClassName.length() == 0) {
  395. /*
  396. * No reference class name specified, so construct
  397. * remote reference from its serialized form.
  398. */
  399. ref = (RemoteRef) in.readObject();
  400. } else {
  401. /*
  402. * Built-in reference class specified, so delegate to
  403. * internal reference class to initialize its fields from
  404. * its external form.
  405. */
  406. String internalRefClassName =
  407. RemoteRef.packagePrefix + "." + refClassName;
  408. Class refClass = Class.forName(internalRefClassName);
  409. try {
  410. ref = (RemoteRef) refClass.newInstance();
  411. /*
  412. * If this step fails, assume we found an internal
  413. * class that is not meant to be a serializable ref
  414. * type.
  415. */
  416. } catch (InstantiationException e) {
  417. throw new ClassNotFoundException(internalRefClassName, e);
  418. } catch (IllegalAccessException e) {
  419. throw new ClassNotFoundException(internalRefClassName, e);
  420. } catch (ClassCastException e) {
  421. throw new ClassNotFoundException(internalRefClassName, e);
  422. }
  423. ref.readExternal(in);
  424. }
  425. }
  426. }