1 /*
   2  * Copyright (c) 1996, 2019, 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 package java.rmi.server;
  26 
  27 import java.io.ObjectInputFilter;
  28 import java.rmi.*;
  29 import sun.rmi.server.UnicastServerRef;
  30 import sun.rmi.server.UnicastServerRef2;
  31 import sun.rmi.transport.LiveRef;
  32 
  33 /**
  34  * Used for exporting a remote object with JRMP and obtaining a stub
  35  * that communicates to the remote object. Stubs are either generated
  36  * at runtime using dynamic proxy objects, or they are generated statically
  37  * at build time, typically using the {@code rmic} tool.
  38  *
  39  * <p><strong>Deprecated: Static Stubs.</strong> <em>Support for statically
  40  * generated stubs is deprecated. This includes the API in this class that
  41  * requires the use of static stubs, as well as the runtime support for
  42  * loading static stubs.  Generating stubs dynamically is preferred, using one
  43  * of the non-deprecated ways of exporting objects as listed below. Do
  44  * not run {@code rmic} to generate static stub classes. It is unnecessary, and
  45  * it is also deprecated.</em>
  46  *
  47  * <p>There are eight ways to export remote objects:
  48  *
  49  * <ol>
  50  *
  51  * <li>Subclassing {@code UnicastRemoteObject} and calling the
  52  * {@link #UnicastRemoteObject()} constructor.
  53  *
  54  * <li>Subclassing {@code UnicastRemoteObject} and calling the
  55  * {@link #UnicastRemoteObject(int) UnicastRemoteObject(port)} constructor.
  56  *
  57  * <li>Subclassing {@code UnicastRemoteObject} and calling the
  58  * {@link #UnicastRemoteObject(int, RMIClientSocketFactory, RMIServerSocketFactory)
  59  * UnicastRemoteObject(port, csf, ssf)} constructor.
  60  *
  61  * <li>Calling the
  62  * {@link #exportObject(Remote) exportObject(Remote)} method.
  63  * <strong>Deprecated.</strong>
  64  *
  65  * <li>Calling the
  66  * {@link #exportObject(Remote, int) exportObject(Remote, port)} method.
  67  *
  68  * <li>Calling the
  69  * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory)
  70  * exportObject(Remote, port, csf, ssf)} method.
  71  *
  72  * <li>Calling the
  73  * {@link #exportObject(Remote, int, ObjectInputFilter) exportObject(Remote, port, filter)} method.
  74  *
  75  * <li>Calling the
  76  * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory, ObjectInputFilter)
  77  * exportObject(Remote, port, csf, ssf, filter)} method.
  78  *
  79  * </ol>
  80  *
  81  * <p>The fourth technique, {@link #exportObject(Remote)},
  82  * always uses statically generated stubs and is deprecated.
  83  *
  84  * <p>The other techniques all use the following approach: if the
  85  * {@code java.rmi.server.ignoreStubClasses} property is {@code true}
  86  * (case insensitive) or if a static stub cannot be found, stubs are generated
  87  * dynamically using {@link java.lang.reflect.Proxy Proxy} objects. Otherwise,
  88  * static stubs are used.
  89  *
  90  * <p>The default value of the
  91  * {@code java.rmi.server.ignoreStubClasses} property is {@code false}.
  92  *
  93  * <p>Statically generated stubs are typically pregenerated from the
  94  * remote object's class using the {@code rmic} tool. A static stub is
  95  * loaded and an instance of that stub class is constructed as described
  96  * below.
  97  *
  98  * <ul>
  99  *
 100  * <li>A "root class" is determined as follows: if the remote object's
 101  * class directly implements an interface that extends {@link Remote}, then
 102  * the remote object's class is the root class; otherwise, the root class is
 103  * the most derived superclass of the remote object's class that directly
 104  * implements an interface that extends {@code Remote}.
 105  *
 106  * <li>The name of the stub class to load is determined by concatenating
 107  * the binary name of the root class with the suffix {@code _Stub}.
 108  *
 109  * <li>The stub class is loaded by name using the class loader of the root
 110  * class. The stub class must be public, it must extend {@link RemoteStub}, it must
 111  * reside in a package that is exported to at least the {@code java.rmi} module, and it
 112  * must have a public constructor that has one parameter of type {@link RemoteRef}.
 113  *
 114  * <li>Finally, an instance of the stub class is constructed with a
 115  * {@link RemoteRef}.
 116  *
 117  * <li>If the appropriate stub class could not be found, or if the stub class
 118  * could not be loaded, or if a problem occurs creating the stub instance, a
 119  * {@link StubNotFoundException} is thrown.
 120  *
 121  * </ul>
 122  *
 123  * <p>Stubs are dynamically generated by constructing an instance of
 124  * a {@link java.lang.reflect.Proxy Proxy} with the following characteristics:
 125  *
 126  * <ul>
 127  *
 128  * <li>The proxy's class is defined according to the specifications for the
 129  * <a href="{@docRoot}/java.base/java/lang/reflect/Proxy.html#membership">
 130  * {@code Proxy}
 131  * </a>
 132  * class, using the class loader of the remote object's class.
 133  *
 134  * <li>The proxy implements all the remote interfaces implemented by the
 135  * remote object's class.
 136  *
 137  * <li>Each remote interface must either be public and reside in a package that is
 138  * {@linkplain Module#isExported(String,Module) exported}
 139  * to at least the {@code java.rmi} module, or it must reside in a package that is
 140  * {@linkplain Module#isOpen(String,Module) open}
 141  * to at least the {@code java.rmi} module.
 142  *
 143  * <li>The proxy's invocation handler is a {@link
 144  * RemoteObjectInvocationHandler} instance constructed with a
 145  * {@link RemoteRef}.
 146  *
 147  * <li>If the proxy could not be created, a {@link StubNotFoundException}
 148  * will be thrown.
 149  *
 150  * </ul>
 151  *
 152  * <p>
 153  * Exported remote objects receive method invocations from the stubs
 154  * as described in the RMI specification. Each invocation's operation and
 155  * parameters are unmarshaled using a custom {@link java.io.ObjectInputStream}.
 156  * If an {@link ObjectInputFilter} is provided and is not {@code null} when the object
 157  * is exported, it is used to filter the parameters as they are unmarshaled from the stream.
 158  * The filter is used for all invocations and all parameters regardless of
 159  * the method being invoked or the parameter values.
 160  * If no filter is provided or is {@code null} for the exported object then the
 161  * {@code ObjectInputStream} default filter, if any, is used. The default filter is
 162  * configured with {@link ObjectInputFilter.Config#setSerialFilter(ObjectInputFilter)
 163  * ObjectInputFilter.Config.setSerialFilter}.
 164  * If the filter rejects any of the parameters, the {@code InvalidClassException}
 165  * thrown by {@code ObjectInputStream} is reported as the cause of an
 166  * {@link UnmarshalException}.
 167  *
 168  * @implNote
 169  * Depending upon which constructor or static method is used for exporting an
 170  * object, {@link RMISocketFactory} may be used for creating sockets.
 171  * By default, server sockets created by {@link RMISocketFactory}
 172  * listen on all network interfaces. See the
 173  * {@link RMISocketFactory} class and the section
 174  * <a href="{@docRoot}/../specs/rmi/server.html#rmi-socket-factories">RMI Socket Factories</a>
 175  * in the
 176  * <a href="{@docRoot}/../specs/rmi/index.html">Java RMI Specification</a>.
 177  *
 178  * @author  Ann Wollrath
 179  * @author  Peter Jones
 180  * @since   1.1
 181  **/
 182 public class UnicastRemoteObject extends RemoteServer {
 183 
 184     /**
 185      * @serial port number on which to export object
 186      */
 187     private int port = 0;
 188 
 189     /**
 190      * @serial client-side socket factory (if any)
 191      */
 192     @SuppressWarnings("serial") // Not statically typed as Serializable
 193     private RMIClientSocketFactory csf = null;
 194 
 195     /**
 196      * @serial server-side socket factory (if any) to use when
 197      * exporting object
 198      */
 199     @SuppressWarnings("serial") // Not statically typed as Serializable
 200     private RMIServerSocketFactory ssf = null;
 201 
 202     /* indicate compatibility with JDK 1.1.x version of class */
 203     private static final long serialVersionUID = 4974527148936298033L;
 204 
 205     /**
 206      * Creates and exports a new UnicastRemoteObject object using an
 207      * anonymous port.
 208      *
 209      * <p>The object is exported with a server socket
 210      * created using the {@link RMISocketFactory} class.
 211      *
 212      * @throws RemoteException if failed to export object
 213      * @since 1.1
 214      */
 215     protected UnicastRemoteObject() throws RemoteException
 216     {
 217         this(0);
 218     }
 219 
 220     /**
 221      * Creates and exports a new UnicastRemoteObject object using the
 222      * particular supplied port.
 223      *
 224      * <p>The object is exported with a server socket
 225      * created using the {@link RMISocketFactory} class.
 226      *
 227      * @param port the port number on which the remote object receives calls
 228      * (if <code>port</code> is zero, an anonymous port is chosen)
 229      * @throws RemoteException if failed to export object
 230      * @since 1.2
 231      */
 232     protected UnicastRemoteObject(int port) throws RemoteException
 233     {
 234         this.port = port;
 235         exportObject((Remote) this, port);
 236     }
 237 
 238     /**
 239      * Creates and exports a new UnicastRemoteObject object using the
 240      * particular supplied port and socket factories.
 241      *
 242      * <p>Either socket factory may be {@code null}, in which case
 243      * the corresponding client or server socket creation method of
 244      * {@link RMISocketFactory} is used instead.
 245      *
 246      * @param port the port number on which the remote object receives calls
 247      * (if <code>port</code> is zero, an anonymous port is chosen)
 248      * @param csf the client-side socket factory for making calls to the
 249      * remote object
 250      * @param ssf the server-side socket factory for receiving remote calls
 251      * @throws RemoteException if failed to export object
 252      * @since 1.2
 253      */
 254     protected UnicastRemoteObject(int port,
 255                                   RMIClientSocketFactory csf,
 256                                   RMIServerSocketFactory ssf)
 257         throws RemoteException
 258     {
 259         this.port = port;
 260         this.csf = csf;
 261         this.ssf = ssf;
 262         exportObject((Remote) this, port, csf, ssf);
 263     }
 264 
 265     /**
 266      * Re-export the remote object when it is deserialized.
 267      */
 268     private void readObject(java.io.ObjectInputStream in)
 269         throws java.io.IOException, java.lang.ClassNotFoundException
 270     {
 271         in.defaultReadObject();
 272         reexport();
 273     }
 274 
 275     /**
 276      * Returns a clone of the remote object that is distinct from
 277      * the original.
 278      *
 279      * @exception CloneNotSupportedException if clone failed due to
 280      * a RemoteException.
 281      * @return the new remote object
 282      * @since 1.1
 283      */
 284     public Object clone() throws CloneNotSupportedException
 285     {
 286         try {
 287             UnicastRemoteObject cloned = (UnicastRemoteObject) super.clone();
 288             cloned.reexport();
 289             return cloned;
 290         } catch (RemoteException e) {
 291             throw new ServerCloneException("Clone failed", e);
 292         }
 293     }
 294 
 295     /*
 296      * Exports this UnicastRemoteObject using its initialized fields because
 297      * its creation bypassed running its constructors (via deserialization
 298      * or cloning, for example).
 299      */
 300     private void reexport() throws RemoteException
 301     {
 302         if (csf == null && ssf == null) {
 303             exportObject((Remote) this, port);
 304         } else {
 305             exportObject((Remote) this, port, csf, ssf);
 306         }
 307     }
 308 
 309     /**
 310      * Exports the remote object to make it available to receive incoming
 311      * calls using an anonymous port. This method will always return a
 312      * statically generated stub.
 313      *
 314      * <p>The object is exported with a server socket
 315      * created using the {@link RMISocketFactory} class.
 316      *
 317      * @param obj the remote object to be exported
 318      * @return remote object stub
 319      * @exception RemoteException if export fails
 320      * @since 1.1
 321      * @deprecated This method is deprecated because it supports only static stubs.
 322      * Use {@link #exportObject(Remote, int) exportObject(Remote, port)} or
 323      * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory)
 324      * exportObject(Remote, port, csf, ssf)}
 325      * instead.
 326      */
 327     @Deprecated
 328     public static RemoteStub exportObject(Remote obj)
 329         throws RemoteException
 330     {
 331         /*
 332          * Use UnicastServerRef constructor passing the boolean value true
 333          * to indicate that only a generated stub class should be used.  A
 334          * generated stub class must be used instead of a dynamic proxy
 335          * because the return value of this method is RemoteStub which a
 336          * dynamic proxy class cannot extend.
 337          */
 338         return (RemoteStub) exportObject(obj, new UnicastServerRef(true));
 339     }
 340 
 341     /**
 342      * Exports the remote object to make it available to receive incoming
 343      * calls, using the particular supplied port.
 344      *
 345      * <p>The object is exported with a server socket
 346      * created using the {@link RMISocketFactory} class.
 347      *
 348      * @param obj the remote object to be exported
 349      * @param port the port to export the object on
 350      * @return remote object stub
 351      * @exception RemoteException if export fails
 352      * @since 1.2
 353      */
 354     public static Remote exportObject(Remote obj, int port)
 355         throws RemoteException
 356     {
 357         return exportObject(obj, new UnicastServerRef(port));
 358     }
 359 
 360     /**
 361      * Exports the remote object to make it available to receive incoming
 362      * calls, using a transport specified by the given socket factory.
 363      *
 364      * <p>Either socket factory may be {@code null}, in which case
 365      * the corresponding client or server socket creation method of
 366      * {@link RMISocketFactory} is used instead.
 367      *
 368      * @param obj the remote object to be exported
 369      * @param port the port to export the object on
 370      * @param csf the client-side socket factory for making calls to the
 371      * remote object
 372      * @param ssf the server-side socket factory for receiving remote calls
 373      * @return remote object stub
 374      * @exception RemoteException if export fails
 375      * @since 1.2
 376      */
 377     public static Remote exportObject(Remote obj, int port,
 378                                       RMIClientSocketFactory csf,
 379                                       RMIServerSocketFactory ssf)
 380         throws RemoteException
 381     {
 382 
 383         return exportObject(obj, new UnicastServerRef2(port, csf, ssf));
 384     }
 385 
 386     /**
 387      * Exports the remote object to make it available to receive incoming
 388      * calls, using the particular supplied port
 389      * and {@linkplain ObjectInputFilter filter}.
 390      *
 391      * <p>The object is exported with a server socket
 392      * created using the {@link RMISocketFactory} class.
 393      *
 394      * @param obj the remote object to be exported
 395      * @param port the port to export the object on
 396      * @param filter an ObjectInputFilter applied when deserializing invocation arguments;
 397      *               may be {@code null}
 398      * @return remote object stub
 399      * @exception RemoteException if export fails
 400      * @since 9
 401      */
 402     public static Remote exportObject(Remote obj, int port,
 403                                       ObjectInputFilter filter)
 404             throws RemoteException
 405     {
 406         return exportObject(obj, new UnicastServerRef(new LiveRef(port), filter));
 407     }
 408 
 409     /**
 410      * Exports the remote object to make it available to receive incoming
 411      * calls, using a transport specified by the given socket factory
 412      * and {@linkplain ObjectInputFilter filter}.
 413      *
 414      * <p>Either socket factory may be {@code null}, in which case
 415      * the corresponding client or server socket creation method of
 416      * {@link RMISocketFactory} is used instead.
 417      *
 418      * @param obj the remote object to be exported
 419      * @param port the port to export the object on
 420      * @param csf the client-side socket factory for making calls to the
 421      * remote object
 422      * @param ssf the server-side socket factory for receiving remote calls
 423      * @param filter an ObjectInputFilter applied when deserializing invocation arguments;
 424      *               may be {@code null}
 425      * @return remote object stub
 426      * @exception RemoteException if export fails
 427      * @since 9
 428      */
 429     public static Remote exportObject(Remote obj, int port,
 430                                       RMIClientSocketFactory csf,
 431                                       RMIServerSocketFactory ssf,
 432                                       ObjectInputFilter filter)
 433         throws RemoteException
 434     {
 435         return exportObject(obj, new UnicastServerRef2(port, csf, ssf, filter));
 436     }
 437 
 438     /**
 439      * Removes the remote object, obj, from the RMI runtime. If
 440      * successful, the object can no longer accept incoming RMI calls.
 441      * If the force parameter is true, the object is forcibly unexported
 442      * even if there are pending calls to the remote object or the
 443      * remote object still has calls in progress.  If the force
 444      * parameter is false, the object is only unexported if there are
 445      * no pending or in progress calls to the object.
 446      *
 447      * @param obj the remote object to be unexported
 448      * @param force if true, unexports the object even if there are
 449      * pending or in-progress calls; if false, only unexports the object
 450      * if there are no pending or in-progress calls
 451      * @return true if operation is successful, false otherwise
 452      * @exception NoSuchObjectException if the remote object is not
 453      * currently exported
 454      * @since 1.2
 455      */
 456     public static boolean unexportObject(Remote obj, boolean force)
 457         throws java.rmi.NoSuchObjectException
 458     {
 459         return sun.rmi.transport.ObjectTable.unexportObject(obj, force);
 460     }
 461 
 462     /**
 463      * Exports the specified object using the specified server ref.
 464      */
 465     private static Remote exportObject(Remote obj, UnicastServerRef sref)
 466         throws RemoteException
 467     {
 468         // if obj extends UnicastRemoteObject, set its ref.
 469         if (obj instanceof UnicastRemoteObject) {
 470             ((UnicastRemoteObject) obj).ref = sref;
 471         }
 472         return sref.exportObject(obj, null, false);
 473     }
 474 }