src/java.rmi/share/classes/java/rmi/server/RemoteObject.java
changeset 47216 71c04702a3d5
parent 37782 ad8fe7507ecc
child 51181 01b8120f867a
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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 }