001 /*
002 * Copyright 1996-2003 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
026 package java.rmi.server;
027
028 import java.rmi.Remote;
029 import java.rmi.NoSuchObjectException;
030 import java.lang.reflect.Proxy;
031 import sun.rmi.server.Util;
032
033 /**
034 * The <code>RemoteObject</code> class implements the
035 * <code>java.lang.Object</code> behavior for remote objects.
036 * <code>RemoteObject</code> provides the remote semantics of Object by
037 * implementing methods for hashCode, equals, and toString.
038 *
039 * @author Ann Wollrath
040 * @author Laird Dornin
041 * @author Peter Jones
042 * @version 1.40, 07/05/05
043 * @since JDK1.1
044 */
045 public abstract class RemoteObject implements Remote,
046 java.io.Serializable {
047
048 /** The object's remote reference. */
049 transient protected RemoteRef ref;
050
051 /** indicate compatibility with JDK 1.1.x version of class */
052 private static final long serialVersionUID = -3215090123894869218L;
053
054 /**
055 * Creates a remote object.
056 */
057 protected RemoteObject() {
058 ref = null;
059 }
060
061 /**
062 * Creates a remote object, initialized with the specified remote
063 * reference.
064 * @param newref remote reference
065 */
066 protected RemoteObject(RemoteRef newref) {
067 ref = newref;
068 }
069
070 /**
071 * Returns the remote reference for the remote object.
072 *
073 * <p>Note: The object returned from this method may be an instance of
074 * an implementation-specific class. The <code>RemoteObject</code>
075 * class ensures serialization portability of its instances' remote
076 * references through the behavior of its custom
077 * <code>writeObject</code> and <code>readObject</code> methods. An
078 * instance of <code>RemoteRef</code> should not be serialized outside
079 * of its <code>RemoteObject</code> wrapper instance or the result may
080 * be unportable.
081 *
082 * @return remote reference for the remote object
083 * @since 1.2
084 */
085 public RemoteRef getRef() {
086 return ref;
087 }
088
089 /**
090 * Returns the stub for the remote object <code>obj</code> passed
091 * as a parameter. This operation is only valid <i>after</i>
092 * the object has been exported.
093 * @param obj the remote object whose stub is needed
094 * @return the stub for the remote object, <code>obj</code>.
095 * @exception NoSuchObjectException if the stub for the
096 * remote object could not be found.
097 * @since 1.2
098 */
099 public static Remote toStub(Remote obj)
100 throws NoSuchObjectException {
101 if (obj instanceof RemoteStub
102 || (obj != null && Proxy.isProxyClass(obj.getClass()) && Proxy
103 .getInvocationHandler(obj) instanceof RemoteObjectInvocationHandler)) {
104 return obj;
105 } else {
106 return sun.rmi.transport.ObjectTable.getStub(obj);
107 }
108 }
109
110 /**
111 * Returns a hashcode for a remote object. Two remote object stubs
112 * that refer to the same remote object will have the same hash code
113 * (in order to support remote objects as keys in hash tables).
114 *
115 * @see java.util.Hashtable
116 */
117 public int hashCode() {
118 return (ref == null) ? super .hashCode() : ref.remoteHashCode();
119 }
120
121 /**
122 * Compares two remote objects for equality.
123 * Returns a boolean that indicates whether this remote object is
124 * equivalent to the specified Object. This method is used when a
125 * remote object is stored in a hashtable.
126 * If the specified Object is not itself an instance of RemoteObject,
127 * then this method delegates by returning the result of invoking the
128 * <code>equals</code> method of its parameter with this remote object
129 * as the argument.
130 * @param obj the Object to compare with
131 * @return true if these Objects are equal; false otherwise.
132 * @see java.util.Hashtable
133 */
134 public boolean equals(Object obj) {
135 if (obj instanceof RemoteObject) {
136 if (ref == null) {
137 return obj == this ;
138 } else {
139 return ref.remoteEquals(((RemoteObject) obj).ref);
140 }
141 } else if (obj != null) {
142 /*
143 * Fix for 4099660: if object is not an instance of RemoteObject,
144 * use the result of its equals method, to support symmetry is a
145 * remote object implementation class that does not extend
146 * RemoteObject wishes to support equality with its stub objects.
147 */
148 return obj.equals(this );
149 } else {
150 return false;
151 }
152 }
153
154 /**
155 * Returns a String that represents the value of this remote object.
156 */
157 public String toString() {
158 String classname = Util.getUnqualifiedName(getClass());
159 return (ref == null) ? classname : classname + "["
160 + ref.remoteToString() + "]";
161 }
162
163 /**
164 * <code>writeObject</code> for custom serialization.
165 *
166 * <p>This method writes this object's serialized form for this class
167 * as follows:
168 *
169 * <p>The {@link RemoteRef#getRefClass(java.io.ObjectOutput) getRefClass}
170 * method is invoked on this object's <code>ref</code> field
171 * to obtain its external ref type name.
172 * If the value returned by <code>getRefClass</code> was
173 * a non-<code>null</code> string of length greater than zero,
174 * the <code>writeUTF</code> method is invoked on <code>out</code>
175 * with the value returned by <code>getRefClass</code>, and then
176 * the <code>writeExternal</code> method is invoked on
177 * this object's <code>ref</code> field passing <code>out</code>
178 * as the argument; otherwise,
179 * the <code>writeUTF</code> method is invoked on <code>out</code>
180 * with a zero-length string (<code>""</code>), and then
181 * the <code>writeObject</code> method is invoked on <code>out</code>
182 * passing this object's <code>ref</code> field as the argument.
183 *
184 * @serialData
185 *
186 * The serialized data for this class comprises a string (written with
187 * <code>ObjectOutput.writeUTF</code>) that is either the external
188 * ref type name of the contained <code>RemoteRef</code> instance
189 * (the <code>ref</code> field) or a zero-length string, followed by
190 * either the external form of the <code>ref</code> field as written by
191 * its <code>writeExternal</code> method if the string was of non-zero
192 * length, or the serialized form of the <code>ref</code> field as
193 * written by passing it to the serialization stream's
194 * <code>writeObject</code> if the string was of zero length.
195 *
196 * <p>If this object is an instance of
197 * {@link RemoteStub} or {@link RemoteObjectInvocationHandler}
198 * that was returned from any of
199 * the <code>UnicastRemoteObject.exportObject</code> methods
200 * and custom socket factories are not used,
201 * the external ref type name is <code>"UnicastRef"</code>.
202 *
203 * If this object is an instance of
204 * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
205 * that was returned from any of
206 * the <code>UnicastRemoteObject.exportObject</code> methods
207 * and custom socket factories are used,
208 * the external ref type name is <code>"UnicastRef2"</code>.
209 *
210 * If this object is an instance of
211 * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
212 * that was returned from any of
213 * the <code>java.rmi.activation.Activatable.exportObject</code> methods,
214 * the external ref type name is <code>"ActivatableRef"</code>.
215 *
216 * If this object is an instance of
217 * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
218 * that was returned from
219 * the <code>RemoteObject.toStub</code> method (and the argument passed
220 * to <code>toStub</code> was not itself a <code>RemoteStub</code>),
221 * the external ref type name is a function of how the remote object
222 * passed to <code>toStub</code> was exported, as described above.
223 *
224 * If this object is an instance of
225 * <code>RemoteStub</code> or <code>RemoteObjectInvocationHandler</code>
226 * that was originally created via deserialization,
227 * the external ref type name is the same as that which was read
228 * when this object was deserialized.
229 *
230 * <p>If this object is an instance of
231 * <code>java.rmi.server.UnicastRemoteObject</code> that does not
232 * use custom socket factories,
233 * the external ref type name is <code>"UnicastServerRef"</code>.
234 *
235 * If this object is an instance of
236 * <code>UnicastRemoteObject</code> that does
237 * use custom socket factories,
238 * the external ref type name is <code>"UnicastServerRef2"</code>.
239 *
240 * <p>Following is the data that must be written by the
241 * <code>writeExternal</code> method and read by the
242 * <code>readExternal</code> method of <code>RemoteRef</code>
243 * implementation classes that correspond to the each of the
244 * defined external ref type names:
245 *
246 * <p>For <code>"UnicastRef"</code>:
247 *
248 * <ul>
249 *
250 * <li>the hostname of the referenced remote object,
251 * written by {@link java.io.ObjectOutput#writeUTF(String)}
252 *
253 * <li>the port of the referenced remote object,
254 * written by {@link java.io.ObjectOutput#writeInt(int)}
255 *
256 * <li>the data written as a result of calling
257 * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
258 * on the <code>ObjID</code> instance contained in the reference
259 *
260 * <li>the boolean value <code>false</code>,
261 * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
262 *
263 * </ul>
264 *
265 * <p>For <code>"UnicastRef2"</code> with a
266 * <code>null</code> client socket factory:
267 *
268 * <ul>
269 *
270 * <li>the byte value <code>0x00</code>
271 * (indicating <code>null</code> client socket factory),
272 * written by {@link java.io.ObjectOutput#writeByte(int)}
273 *
274 * <li>the hostname of the referenced remote object,
275 * written by {@link java.io.ObjectOutput#writeUTF(String)}
276 *
277 * <li>the port of the referenced remote object,
278 * written by {@link java.io.ObjectOutput#writeInt(int)}
279 *
280 * <li>the data written as a result of calling
281 * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
282 * on the <code>ObjID</code> instance contained in the reference
283 *
284 * <li>the boolean value <code>false</code>,
285 * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
286 *
287 * </ul>
288 *
289 * <p>For <code>"UnicastRef2"</code> with a
290 * non-<code>null</code> client socket factory:
291 *
292 * <ul>
293 *
294 * <li>the byte value <code>0x01</code>
295 * (indicating non-<code>null</code> client socket factory),
296 * written by {@link java.io.ObjectOutput#writeByte(int)}
297 *
298 * <li>the hostname of the referenced remote object,
299 * written by {@link java.io.ObjectOutput#writeUTF(String)}
300 *
301 * <li>the port of the referenced remote object,
302 * written by {@link java.io.ObjectOutput#writeInt(int)}
303 *
304 * <li>a client socket factory (object of type
305 * <code>java.rmi.server.RMIClientSocketFactory</code>),
306 * written by passing it to an invocation of
307 * <code>writeObject</code> on the stream instance
308 *
309 * <li>the data written as a result of calling
310 * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)}
311 * on the <code>ObjID</code> instance contained in the reference
312 *
313 * <li>the boolean value <code>false</code>,
314 * written by {@link java.io.ObjectOutput#writeBoolean(boolean)}
315 *
316 * </ul>
317 *
318 * <p>For <code>"ActivatableRef"</code> with a
319 * <code>null</code> nested remote reference:
320 *
321 * <ul>
322 *
323 * <li>an instance of
324 * <code>java.rmi.activation.ActivationID</code>,
325 * written by passing it to an invocation of
326 * <code>writeObject</code> on the stream instance
327 *
328 * <li>a zero-length string (<code>""</code>),
329 * written by {@link java.io.ObjectOutput#writeUTF(String)}
330 *
331 * </ul>
332 *
333 * <p>For <code>"ActivatableRef"</code> with a
334 * non-<code>null</code> nested remote reference:
335 *
336 * <ul>
337 *
338 * <li>an instance of
339 * <code>java.rmi.activation.ActivationID</code>,
340 * written by passing it to an invocation of
341 * <code>writeObject</code> on the stream instance
342 *
343 * <li>the external ref type name of the nested remote reference,
344 * which must be <code>"UnicastRef2"</code>,
345 * written by {@link java.io.ObjectOutput#writeUTF(String)}
346 *
347 * <li>the external form of the nested remote reference,
348 * written by invoking its <code>writeExternal</code> method
349 * with the stream instance
350 * (see the description of the external form for
351 * <code>"UnicastRef2"</code> above)
352 *
353 * </ul>
354 *
355 * <p>For <code>"UnicastServerRef"</code> and
356 * <code>"UnicastServerRef2"</code>, no data is written by the
357 * <code>writeExternal</code> method or read by the
358 * <code>readExternal</code> method.
359 */
360 private void writeObject(java.io.ObjectOutputStream out)
361 throws java.io.IOException,
362 java.lang.ClassNotFoundException {
363 if (ref == null) {
364 throw new java.rmi.MarshalException("Invalid remote object");
365 } else {
366 String refClassName = ref.getRefClass(out);
367 if (refClassName == null || refClassName.length() == 0) {
368 /*
369 * No reference class name specified, so serialize
370 * remote reference.
371 */
372 out.writeUTF("");
373 out.writeObject(ref);
374 } else {
375 /*
376 * Built-in reference class specified, so delegate
377 * to reference to write out its external form.
378 */
379 out.writeUTF(refClassName);
380 ref.writeExternal(out);
381 }
382 }
383 }
384
385 /**
386 * <code>readObject</code> for custom serialization.
387 *
388 * <p>This method reads this object's serialized form for this class
389 * as follows:
390 *
391 * <p>The <code>readUTF</code> method is invoked on <code>in</code>
392 * to read the external ref type name for the <code>RemoteRef</code>
393 * instance to be filled in to this object's <code>ref</code> field.
394 * If the string returned by <code>readUTF</code> has length zero,
395 * the <code>readObject</code> method is invoked on <code>in</code>,
396 * and than the value returned by <code>readObject</code> is cast to
397 * <code>RemoteRef</code> and this object's <code>ref</code> field is
398 * set to that value.
399 * Otherwise, this object's <code>ref</code> field is set to a
400 * <code>RemoteRef</code> instance that is created of an
401 * implementation-specific class corresponding to the external ref
402 * type name returned by <code>readUTF</code>, and then
403 * the <code>readExternal</code> method is invoked on
404 * this object's <code>ref</code> field.
405 *
406 * <p>If the external ref type name is
407 * <code>"UnicastRef"</code>, <code>"UnicastServerRef"</code>,
408 * <code>"UnicastRef2"</code>, <code>"UnicastServerRef2"</code>,
409 * or <code>"ActivatableRef"</code>, a corresponding
410 * implementation-specific class must be found, and its
411 * <code>readExternal</code> method must read the serial data
412 * for that external ref type name as specified to be written
413 * in the <b>serialData</b> documentation for this class.
414 * If the external ref type name is any other string (of non-zero
415 * length), a <code>ClassNotFoundException</code> will be thrown,
416 * unless the implementation provides an implementation-specific
417 * class corresponding to that external ref type name, in which
418 * case this object's <code>ref</code> field will be set to an
419 * instance of that implementation-specific class.
420 */
421 private void readObject(java.io.ObjectInputStream in)
422 throws java.io.IOException,
423 java.lang.ClassNotFoundException {
424 String refClassName = in.readUTF();
425 if (refClassName == null || refClassName.length() == 0) {
426 /*
427 * No reference class name specified, so construct
428 * remote reference from its serialized form.
429 */
430 ref = (RemoteRef) in.readObject();
431 } else {
432 /*
433 * Built-in reference class specified, so delegate to
434 * internal reference class to initialize its fields from
435 * its external form.
436 */
437 String internalRefClassName = RemoteRef.packagePrefix + "."
438 + refClassName;
439 Class refClass = Class.forName(internalRefClassName);
440 try {
441 ref = (RemoteRef) refClass.newInstance();
442
443 /*
444 * If this step fails, assume we found an internal
445 * class that is not meant to be a serializable ref
446 * type.
447 */
448 } catch (InstantiationException e) {
449 throw new ClassNotFoundException(internalRefClassName,
450 e);
451 } catch (IllegalAccessException e) {
452 throw new ClassNotFoundException(internalRefClassName,
453 e);
454 } catch (ClassCastException e) {
455 throw new ClassNotFoundException(internalRefClassName,
456 e);
457 }
458 ref.readExternal(in);
459 }
460 }
461 }
|