KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > rmi > server > RemoteObject


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
8 package java.rmi.server;
9
10 import java.rmi.Remote JavaDoc;
11 import java.rmi.NoSuchObjectException JavaDoc;
12 import java.lang.reflect.Proxy JavaDoc;
13 import sun.rmi.server.Util;
14
15 /**
16  * The <code>RemoteObject</code> class implements the
17  * <code>java.lang.Object</code> behavior for remote objects.
18  * <code>RemoteObject</code> provides the remote semantics of Object by
19  * implementing methods for hashCode, equals, and toString.
20  *
21  * @author Ann Wollrath
22  * @author Laird Dornin
23  * @author Peter Jones
24  * @version 1.33, 03/12/19
25  * @since JDK1.1
26  */

27 public abstract class RemoteObject implements Remote JavaDoc, java.io.Serializable JavaDoc {
28
29     /** The object's remote reference. */
30     transient protected RemoteRef JavaDoc ref;
31     
32     /** indicate compatibility with JDK 1.1.x version of class */
33     private static final long serialVersionUID = -3215090123894869218L;
34
35     /**
36      * Creates a remote object.
37      */

38     protected RemoteObject() {
39     ref = null;
40     }
41     
42     /**
43      * Creates a remote object, initialized with the specified remote
44      * reference.
45      * @param newref remote reference
46      */

47     protected RemoteObject(RemoteRef JavaDoc newref) {
48     ref = newref;
49     }
50
51     /**
52      * Returns the remote reference for the remote object.
53      *
54      * <p>Note: The object returned from this method may be an instance of
55      * an implementation-specific class. The <code>RemoteObject</code>
56      * class ensures serialization portability of its instances' remote
57      * references through the behavior of its custom
58      * <code>writeObject</code> and <code>readObject</code> methods. An
59      * instance of <code>RemoteRef</code> should not be serialized outside
60      * of its <code>RemoteObject</code> wrapper instance or the result may
61      * be unportable.
62      *
63      * @return remote reference for the remote object
64      * @since 1.2
65      */

66     public RemoteRef JavaDoc getRef() {
67     return ref;
68     }
69     
70     /**
71      * Returns the stub for the remote object <code>obj</code> passed
72      * as a parameter. This operation is only valid <i>after</i>
73      * the object has been exported.
74      * @param obj the remote object whose stub is needed
75      * @return the stub for the remote object, <code>obj</code>.
76      * @exception NoSuchObjectException if the stub for the
77      * remote object could not be found.
78      * @since 1.2
79      */

80     public static Remote JavaDoc toStub(Remote JavaDoc obj) throws NoSuchObjectException JavaDoc {
81     if (obj instanceof RemoteStub JavaDoc ||
82         (obj != null &&
83          Proxy.isProxyClass(obj.getClass()) &&
84          Proxy.getInvocationHandler(obj) instanceof
85          RemoteObjectInvocationHandler JavaDoc))
86     {
87         return obj;
88     } else {
89         return sun.rmi.transport.ObjectTable.getStub(obj);
90     }
91     }
92
93     /**
94      * Returns a hashcode for a remote object. Two remote object stubs
95      * that refer to the same remote object will have the same hash code
96      * (in order to support remote objects as keys in hash tables).
97      *
98      * @see java.util.Hashtable
99      */

100     public int hashCode() {
101     return (ref == null) ? super.hashCode() : ref.remoteHashCode();
102     }
103
104     /**
105      * Compares two remote objects for equality.
106      * Returns a boolean that indicates whether this remote object is
107      * equivalent to the specified Object. This method is used when a
108      * remote object is stored in a hashtable.
109      * If the specified Object is not itself an instance of RemoteObject,
110      * then this method delegates by returning the result of invoking the
111      * <code>equals</code> method of its parameter with this remote object
112      * as the argument.
113      * @param obj the Object to compare with
114      * @return true if these Objects are equal; false otherwise.
115      * @see java.util.Hashtable
116      */

117     public boolean equals(Object JavaDoc obj) {
118     if (obj instanceof RemoteObject JavaDoc) {
119         if (ref == null) {
120         return obj == this;
121         } else {
122         return ref.remoteEquals(((RemoteObject JavaDoc)obj).ref);
123         }
124     } else if (obj != null) {
125         /*
126          * Fix for 4099660: if object is not an instance of RemoteObject,
127          * use the result of its equals method, to support symmetry is a
128          * remote object implementation class that does not extend
129          * RemoteObject wishes to support equality with its stub objects.
130          */

131         return obj.equals(this);
132     } else {
133         return false;
134     }
135     }
136
137     /**
138      * Returns a String that represents the value of this remote object.
139      */

140     public String JavaDoc toString() {
141     String JavaDoc classname = Util.getUnqualifiedName(getClass());
142     return (ref == null) ? classname :
143         classname + "[" + ref.remoteToString() + "]";
144     }
145
146     /**
147      * <code>writeObject</code> for custom serialization.
148      *
149      * <p>This method writes this object's serialized form for this class
150      * as follows:
151      *
152      * <p>The {@link RemoteRef#getRefClass(java.io.ObjectOutput) getRefClass}
153      * method is invoked on this object's <code>ref</code> field
154      * to obtain its external ref type name.
155      * If the value returned by <code>getRefClass</code> was
156      * a non-<code>null</code> string of length greater than zero,
157      * the <code>writeUTF</code> method is invoked on <code>out</code>
158      * with the value returned by <code>getRefClass</code>, and then
159      * the <code>writeExternal</code> method is invoked on
160      * this object's <code>ref</code> field passing <code>out</code>
161      * as the argument; otherwise,
162      * the <code>writeUTF</code> method is invoked on <code>out</code>
163      * with a zero-length string (<code>""</code>), and then
164      * the <code>writeObject</code> method is invoked on <code>out</code>
165      * passing this object's <code>ref</code> field as the argument.
166      *
167      * @serialData
168      *
169      * The serialized data for this class comprises a string (written with
170      * <code>ObjectOutput.writeUTF</code>) that is either the external
171      * ref type name of the contained <code>RemoteRef</code> instance
172      * (the <code>ref</code> field) or a zero-length string, followed by
173      * either the external form of the <code>ref</code> field as written by
174      * its <code>writeExternal</code> method if the string was of non-zero
175      * length, or the serialized form of the <code>ref</code> field as
176      * written by passing it to the serialization stream's
177      * <code>writeObject</code> if the string was of zero length.
178      *
179      * <p>If this object is an instance of
180      * {@link RemoteStub} or {@link RemoteObjectInvocationHandler}
181      * that was returned from any of
182      * the <code>UnicastRemoteObject.exportObject</code> methods
183      * and custom socket factories are not used,
184      * the external ref type name is <code>"UnicastRef"</code>.
185      *
186      * If this object is an instance of
187      * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
188      * that was returned from any of
189      * the <code>UnicastRemoteObject.exportObject</code> methods
190      * and custom socket factories are used,
191      * the external ref type name is <code>"UnicastRef2"</code>.
192      *
193      * If this object is an instance of
194      * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
195      * that was returned from any of
196      * the <code>java.rmi.activation.Activatable.exportObject</code> methods,
197      * the external ref type name is <code>"ActivatableRef"</code>.
198      *
199      * If this object is an instance of
200      * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
201      * that was returned from
202      * the <code>RemoteObject.toStub</code> method (and the argument passed
203      * to <code>toStub</code> was not itself a <code>RemoteStub</code>),
204      * the external ref type name is a function of how the remote object
205      * passed to <code>toStub</code> was exported, as described above.
206      *
207      * If this object is an instance of
208      * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
209      * that was originally created via deserialization,
210      * the external ref type name is the same as that which was read
211      * when this object was deserialized.
212      *
213      * <p>If this object is an instance of
214      * <code>java.rmi.server.UnicastRemoteObject</code> that does not
215      * use custom socket factories,
216      * the external ref type name is <code>"UnicastServerRef"</code>.
217      *
218      * If this object is an instance of
219      * <code>UnicastRemoteObject</code> that does
220      * use custom socket factories,
221      * the external ref type name is <code>"UnicastServerRef2"</code>.
222      *
223      * <p>Following is the data that must be written by the
224      * <code>writeExternal</code> method and read by the
225      * <code>readExternal</code> method of <code>RemoteRef</code>
226      * implementation classes that correspond to the each of the
227      * defined external ref type names:
228      *
229      * <p>For <code>"UnicastRef"</code>:
230      *
231      * <ul>
232      *
233      * <li>the hostname of the referenced remote object,
234      * written by {@link java.io.ObjectOutput#writeUTF(String)}
235      *
236      * <li>the port of the referenced remote object,
237      * written by {@link java.io.ObjectOutput#writeInt(int)}
238      *
239      * <li>the data written as a result of calling
240      * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
241      * on the <code>ObjID</code> instance contained in the reference
242      *
243      * <li>the boolean value <code>false</code>,
244      * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
245      *
246      * </ul>
247      *
248      * <p>For <code>"UnicastRef2"</code> with a
249      * <code>null</code> client socket factory:
250      *
251      * <ul>
252      *
253      * <li>the byte value <code>0x00</code>
254      * (indicating <code>null</code> client socket factory),
255      * written by {@link java.io.ObjectOutput#writeByte(int)}
256      *
257      * <li>the hostname of the referenced remote object,
258      * written by {@link java.io.ObjectOutput#writeUTF(String)}
259      *
260      * <li>the port of the referenced remote object,
261      * written by {@link java.io.ObjectOutput#writeInt(int)}
262      *
263      * <li>the data written as a result of calling
264      * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
265      * on the <code>ObjID</code> instance contained in the reference
266      *
267      * <li>the boolean value <code>false</code>,
268      * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
269      *
270      * </ul>
271      *
272      * <p>For <code>"UnicastRef2"</code> with a
273      * non-<code>null</code> client socket factory:
274      *
275      * <ul>
276      *
277      * <li>the byte value <code>0x01</code>
278      * (indicating non-<code>null</code> client socket factory),
279      * written by {@link java.io.ObjectOutput#writeByte(int)}
280      *
281      * <li>the hostname of the referenced remote object,
282      * written by {@link java.io.ObjectOutput#writeUTF(String)}
283      *
284      * <li>the port of the referenced remote object,
285      * written by {@link java.io.ObjectOutput#writeInt(int)}
286      *
287      * <li>a client socket factory (object of type
288      * <code>java.rmi.server.RMIClientSocketFactory</code>),
289      * written by passing it to an invocation of
290      * <code>writeObject</code> on the stream instance
291      *
292      * <li>the data written as a result of calling
293      * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
294      * on the <code>ObjID</code> instance contained in the reference
295      *
296      * <li>the boolean value <code>false</code>,
297      * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
298      *
299      * </ul>
300      *
301      * <p>For <code>"ActivatableRef"</code> with a
302      * <code>null</code> nested remote reference:
303      *
304      * <ul>
305      *
306      * <li>an instance of
307      * <code>java.rmi.activation.ActivationID</code>,
308      * written by passing it to an invocation of
309      * <code>writeObject</code> on the stream instance
310      *
311      * <li>a zero-length string (<code>""</code>),
312      * written by {@link java.io.ObjectOutput#writeUTF(String)}
313      *
314      * </ul>
315      *
316      * <p>For <code>"ActivatableRef"</code> with a
317      * non-<code>null</code> nested remote reference:
318      *
319      * <ul>
320      *
321      * <li>an instance of
322      * <code>java.rmi.activation.ActivationID</code>,
323      * written by passing it to an invocation of
324      * <code>writeObject</code> on the stream instance
325      *
326      * <li>the external ref type name of the nested remote reference,
327      * which must be <code>"UnicastRef2"</code>,
328      * written by {@link java.io.ObjectOutput#writeUTF(String)}
329      *
330      * <li>the external form of the nested remote reference,
331      * written by invoking its <code>writeExternal</code> method
332      * with the stream instance
333      * (see the description of the external form for
334      * <code>"UnicastRef2"</code> above)
335      *
336      * </ul>
337      *
338      * <p>For <code>"UnicastServerRef"</code> and
339      * <code>"UnicastServerRef2"</code>, no data is written by the
340      * <code>writeExternal</code> method or read by the
341      * <code>readExternal</code> method.
342      */

343     private void writeObject(java.io.ObjectOutputStream JavaDoc out)
344     throws java.io.IOException JavaDoc, java.lang.ClassNotFoundException JavaDoc
345     {
346     if (ref == null) {
347         throw new java.rmi.MarshalException JavaDoc("Invalid remote object");
348     } else {
349         String JavaDoc refClassName = ref.getRefClass(out);
350         if (refClassName == null || refClassName.length() == 0) {
351         /*
352          * No reference class name specified, so serialize
353          * remote reference.
354          */

355         out.writeUTF("");
356         out.writeObject(ref);
357         } else {
358         /*
359          * Built-in reference class specified, so delegate
360          * to reference to write out its external form.
361          */

362         out.writeUTF(refClassName);
363         ref.writeExternal(out);
364         }
365     }
366     }
367
368     /**
369      * <code>readObject</code> for custom serialization.
370      *
371      * <p>This method reads this object's serialized form for this class
372      * as follows:
373      *
374      * <p>The <code>readUTF</code> method is invoked on <code>in</code>
375      * to read the external ref type name for the <code>RemoteRef</code>
376      * instance to be filled in to this object's <code>ref</code> field.
377      * If the string returned by <code>readUTF</code> has length zero,
378      * the <code>readObject</code> method is invoked on <code>in</code>,
379      * and than the value returned by <code>readObject</code> is cast to
380      * <code>RemoteRef</code> and this object's <code>ref</code> field is
381      * set to that value.
382      * Otherwise, this object's <code>ref</code> field is set to a
383      * <code>RemoteRef</code> instance that is created of an
384      * implementation-specific class corresponding to the external ref
385      * type name returned by <code>readUTF</code>, and then
386      * the <code>readExternal</code> method is invoked on
387      * this object's <code>ref</code> field.
388      *
389      * <p>If the external ref type name is
390      * <code>"UnicastRef"</code>, <code>"UnicastServerRef"</code>,
391      * <code>"UnicastRef2"</code>, <code>"UnicastServerRef2"</code>,
392      * or <code>"ActivatableRef"</code>, a corresponding
393      * implementation-specific class must be found, and its
394      * <code>readExternal</code> method must read the serial data
395      * for that external ref type name as specified to be written
396      * in the <b>serialData</b> documentation for this class.
397      * If the external ref type name is any other string (of non-zero
398      * length), a <code>ClassNotFoundException</code> will be thrown,
399      * unless the implementation provides an implementation-specific
400      * class corresponding to that external ref type name, in which
401      * case this object's <code>ref</code> field will be set to an
402      * instance of that implementation-specific class.
403      */

404     private void readObject(java.io.ObjectInputStream JavaDoc in)
405     throws java.io.IOException JavaDoc, java.lang.ClassNotFoundException JavaDoc
406     {
407     String JavaDoc refClassName = in.readUTF();
408     if (refClassName == null || refClassName.length() == 0) {
409         /*
410          * No reference class name specified, so construct
411          * remote reference from its serialized form.
412          */

413         ref = (RemoteRef JavaDoc) in.readObject();
414     } else {
415         /*
416          * Built-in reference class specified, so delegate to
417          * internal reference class to initialize its fields from
418          * its external form.
419          */

420         String JavaDoc internalRefClassName =
421         RemoteRef.packagePrefix + "." + refClassName;
422         Class JavaDoc refClass = Class.forName(internalRefClassName);
423         try {
424         ref = (RemoteRef JavaDoc) refClass.newInstance();
425
426         /*
427          * If this step fails, assume we found an internal
428          * class that is not meant to be a serializable ref
429          * type.
430          */

431         } catch (InstantiationException JavaDoc e) {
432         throw new ClassNotFoundException JavaDoc(internalRefClassName, e);
433         } catch (IllegalAccessException JavaDoc e) {
434         throw new ClassNotFoundException JavaDoc(internalRefClassName, e);
435         } catch (ClassCastException JavaDoc e) {
436         throw new ClassNotFoundException JavaDoc(internalRefClassName, e);
437         }
438         ref.readExternal(in);
439     }
440     }
441 }
442
Popular Tags