1 /* 2 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.rmi.server; 27 28 import java.rmi.Remote; 29 import java.rmi.NoSuchObjectException; 30 import java.lang.reflect.Proxy; 31 import sun.rmi.server.Util; 32 33 /** 34 * The <code>RemoteObject</code> class implements the 35 * <code>java.lang.Object</code> behavior for remote objects. 36 * <code>RemoteObject</code> provides the remote semantics of Object by 37 * implementing methods for hashCode, equals, and toString. 38 * 39 * @author Ann Wollrath 40 * @author Laird Dornin 41 * @author Peter Jones 42 * @since 1.1 43 */ 44 public abstract class RemoteObject implements Remote, java.io.Serializable { 45 46 /** The object's remote reference. */ 47 transient protected RemoteRef ref; 48 49 /** indicate compatibility with JDK 1.1.x version of class */ 50 private static final long serialVersionUID = -3215090123894869218L; 51 52 /** 53 * Creates a remote object. 54 */ 55 protected RemoteObject() { 56 ref = null; 57 } 58 59 /** 60 * Creates a remote object, initialized with the specified remote 61 * reference. 62 * @param newref remote reference 63 */ 64 protected RemoteObject(RemoteRef newref) { 65 ref = newref; 66 } 67 68 /** 69 * Returns the remote reference for the remote object. 70 * 71 * <p>Note: The object returned from this method may be an instance of 72 * an implementation-specific class. The <code>RemoteObject</code> 73 * class ensures serialization portability of its instances' remote 74 * references through the behavior of its custom 75 * <code>writeObject</code> and <code>readObject</code> methods. An 76 * instance of <code>RemoteRef</code> should not be serialized outside 77 * of its <code>RemoteObject</code> wrapper instance or the result may 78 * be unportable. 79 * 80 * @return remote reference for the remote object 81 * @since 1.2 82 */ 83 public RemoteRef getRef() { 84 return ref; 85 } 86 87 /** 88 * Returns the stub for the remote object <code>obj</code> passed 89 * as a parameter. This operation is only valid <i>after</i> 90 * the object has been exported. 91 * @param obj the remote object whose stub is needed 92 * @return the stub for the remote object, <code>obj</code>. 93 * @exception NoSuchObjectException if the stub for the 94 * remote object could not be found. 95 * @since 1.2 96 */ 97 public static Remote toStub(Remote obj) throws NoSuchObjectException { 98 if (obj instanceof RemoteStub || 99 (obj != null && 100 Proxy.isProxyClass(obj.getClass()) && 101 Proxy.getInvocationHandler(obj) instanceof 102 RemoteObjectInvocationHandler)) 103 { 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 : 160 classname + "[" + 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, java.lang.ClassNotFoundException 362 { 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, java.lang.ClassNotFoundException 423 { 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 = 438 RemoteRef.packagePrefix + "." + 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, e); 450 } catch (IllegalAccessException e) { 451 throw new ClassNotFoundException(internalRefClassName, e); 452 } catch (ClassCastException e) { 453 throw new ClassNotFoundException(internalRefClassName, e); 454 } 455 ref.readExternal(in); 456 } 457 } 458 }