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