1 /*
   2  * Copyright (c) 1996, 2017, 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     private RMIClientSocketFactory csf = null;
 193 
 194     /**
 195      * @serial server-side socket factory (if any) to use when
 196      * exporting object
 197      */
 198     private RMIServerSocketFactory ssf = null;
 199 
 200     /* indicate compatibility with JDK 1.1.x version of class */
 201     private static final long serialVersionUID = 4974527148936298033L;
 202 
 203     /**
 204      * Creates and exports a new UnicastRemoteObject object using an
 205      * anonymous port.
 206      *
 207      * <p>The object is exported with a server socket
 208      * created using the {@link RMISocketFactory} class.
 209      *
 210      * @throws RemoteException if failed to export object
 211      * @since 1.1
 212      */
 213     protected UnicastRemoteObject() throws RemoteException
 214     {
 215         this(0);
 216     }
 217 
 218     /**
 219      * Creates and exports a new UnicastRemoteObject object using the
 220      * particular supplied port.
 221      *
 222      * <p>The object is exported with a server socket
 223      * created using the {@link RMISocketFactory} class.
 224      *
 225      * @param port the port number on which the remote object receives calls
 226      * (if <code>port</code> is zero, an anonymous port is chosen)
 227      * @throws RemoteException if failed to export object
 228      * @since 1.2
 229      */
 230     protected UnicastRemoteObject(int port) throws RemoteException
 231     {
 232         this.port = port;
 233         exportObject((Remote) this, port);
 234     }
 235 
 236     /**
 237      * Creates and exports a new UnicastRemoteObject object using the
 238      * particular supplied port and socket factories.
 239      *
 240      * <p>Either socket factory may be {@code null}, in which case
 241      * the corresponding client or server socket creation method of
 242      * {@link RMISocketFactory} is used instead.
 243      *
 244      * @param port the port number on which the remote object receives calls
 245      * (if <code>port</code> is zero, an anonymous port is chosen)
 246      * @param csf the client-side socket factory for making calls to the
 247      * remote object
 248      * @param ssf the server-side socket factory for receiving remote calls
 249      * @throws RemoteException if failed to export object
 250      * @since 1.2
 251      */
 252     protected UnicastRemoteObject(int port,
 253                                   RMIClientSocketFactory csf,
 254                                   RMIServerSocketFactory ssf)
 255         throws RemoteException
 256     {
 257         this.port = port;
 258         this.csf = csf;
 259         this.ssf = ssf;
 260         exportObject((Remote) this, port, csf, ssf);
 261     }
 262 
 263     /**
 264      * Re-export the remote object when it is deserialized.
 265      */
 266     private void readObject(java.io.ObjectInputStream in)
 267         throws java.io.IOException, java.lang.ClassNotFoundException
 268     {
 269         in.defaultReadObject();
 270         reexport();
 271     }
 272 
 273     /**
 274      * Returns a clone of the remote object that is distinct from
 275      * the original.
 276      *
 277      * @exception CloneNotSupportedException if clone failed due to
 278      * a RemoteException.
 279      * @return the new remote object
 280      * @since 1.1
 281      */
 282     public Object clone() throws CloneNotSupportedException
 283     {
 284         try {
 285             UnicastRemoteObject cloned = (UnicastRemoteObject) super.clone();
 286             cloned.reexport();
 287             return cloned;
 288         } catch (RemoteException e) {
 289             throw new ServerCloneException("Clone failed", e);
 290         }
 291     }
 292 
 293     /*
 294      * Exports this UnicastRemoteObject using its initialized fields because
 295      * its creation bypassed running its constructors (via deserialization
 296      * or cloning, for example).
 297      */
 298     private void reexport() throws RemoteException
 299     {
 300         if (csf == null && ssf == null) {
 301             exportObject((Remote) this, port);
 302         } else {
 303             exportObject((Remote) this, port, csf, ssf);
 304         }
 305     }
 306 
 307     /**
 308      * Exports the remote object to make it available to receive incoming
 309      * calls using an anonymous port. This method will always return a
 310      * statically generated stub.
 311      *
 312      * <p>The object is exported with a server socket
 313      * created using the {@link RMISocketFactory} class.
 314      *
 315      * @param obj the remote object to be exported
 316      * @return remote object stub
 317      * @exception RemoteException if export fails
 318      * @since 1.1
 319      * @deprecated This method is deprecated because it supports only static stubs.
 320      * Use {@link #exportObject(Remote, int) exportObject(Remote, port)} or
 321      * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory)
 322      * exportObject(Remote, port, csf, ssf)}
 323      * instead.
 324      */
 325     @Deprecated
 326     public static RemoteStub exportObject(Remote obj)
 327         throws RemoteException
 328     {
 329         /*
 330          * Use UnicastServerRef constructor passing the boolean value true
 331          * to indicate that only a generated stub class should be used.  A
 332          * generated stub class must be used instead of a dynamic proxy
 333          * because the return value of this method is RemoteStub which a
 334          * dynamic proxy class cannot extend.
 335          */
 336         return (RemoteStub) exportObject(obj, new UnicastServerRef(true));
 337     }
 338 
 339     /**
 340      * Exports the remote object to make it available to receive incoming
 341      * calls, using the particular supplied port.
 342      *
 343      * <p>The object is exported with a server socket
 344      * created using the {@link RMISocketFactory} class.
 345      *
 346      * @param obj the remote object to be exported
 347      * @param port the port to export the object on
 348      * @return remote object stub
 349      * @exception RemoteException if export fails
 350      * @since 1.2
 351      */
 352     public static Remote exportObject(Remote obj, int port)
 353         throws RemoteException
 354     {
 355         return exportObject(obj, new UnicastServerRef(port));
 356     }
 357 
 358     /**
 359      * Exports the remote object to make it available to receive incoming
 360      * calls, using a transport specified by the given socket factory.
 361      *
 362      * <p>Either socket factory may be {@code null}, in which case
 363      * the corresponding client or server socket creation method of
 364      * {@link RMISocketFactory} is used instead.
 365      *
 366      * @param obj the remote object to be exported
 367      * @param port the port to export the object on
 368      * @param csf the client-side socket factory for making calls to the
 369      * remote object
 370      * @param ssf the server-side socket factory for receiving remote calls
 371      * @return remote object stub
 372      * @exception RemoteException if export fails
 373      * @since 1.2
 374      */
 375     public static Remote exportObject(Remote obj, int port,
 376                                       RMIClientSocketFactory csf,
 377                                       RMIServerSocketFactory ssf)
 378         throws RemoteException
 379     {
 380 
 381         return exportObject(obj, new UnicastServerRef2(port, csf, ssf));
 382     }
 383 
 384     /**
 385      * Exports the remote object to make it available to receive incoming
 386      * calls, using the particular supplied port
 387      * and {@linkplain ObjectInputFilter filter}.
 388      *
 389      * <p>The object is exported with a server socket
 390      * created using the {@link RMISocketFactory} class.
 391      *
 392      * @param obj the remote object to be exported
 393      * @param port the port to export the object on
 394      * @param filter an ObjectInputFilter applied when deserializing invocation arguments;
 395      *               may be {@code null}
 396      * @return remote object stub
 397      * @exception RemoteException if export fails
 398      * @since 9
 399      */
 400     public static Remote exportObject(Remote obj, int port,
 401                                       ObjectInputFilter filter)
 402             throws RemoteException
 403     {
 404         return exportObject(obj, new UnicastServerRef(new LiveRef(port), filter));
 405     }
 406 
 407     /**
 408      * Exports the remote object to make it available to receive incoming
 409      * calls, using a transport specified by the given socket factory
 410      * and {@linkplain ObjectInputFilter filter}.
 411      *
 412      * <p>Either socket factory may be {@code null}, in which case
 413      * the corresponding client or server socket creation method of
 414      * {@link RMISocketFactory} is used instead.
 415      *
 416      * @param obj the remote object to be exported
 417      * @param port the port to export the object on
 418      * @param csf the client-side socket factory for making calls to the
 419      * remote object
 420      * @param ssf the server-side socket factory for receiving remote calls
 421      * @param filter an ObjectInputFilter applied when deserializing invocation arguments;
 422      *               may be {@code null}
 423      * @return remote object stub
 424      * @exception RemoteException if export fails
 425      * @since 9
 426      */
 427     public static Remote exportObject(Remote obj, int port,
 428                                       RMIClientSocketFactory csf,
 429                                       RMIServerSocketFactory ssf,
 430                                       ObjectInputFilter filter)
 431         throws RemoteException
 432     {
 433         return exportObject(obj, new UnicastServerRef2(port, csf, ssf, filter));
 434     }
 435 
 436     /**
 437      * Removes the remote object, obj, from the RMI runtime. If
 438      * successful, the object can no longer accept incoming RMI calls.
 439      * If the force parameter is true, the object is forcibly unexported
 440      * even if there are pending calls to the remote object or the
 441      * remote object still has calls in progress.  If the force
 442      * parameter is false, the object is only unexported if there are
 443      * no pending or in progress calls to the object.
 444      *
 445      * @param obj the remote object to be unexported
 446      * @param force if true, unexports the object even if there are
 447      * pending or in-progress calls; if false, only unexports the object
 448      * if there are no pending or in-progress calls
 449      * @return true if operation is successful, false otherwise
 450      * @exception NoSuchObjectException if the remote object is not
 451      * currently exported
 452      * @since 1.2
 453      */
 454     public static boolean unexportObject(Remote obj, boolean force)
 455         throws java.rmi.NoSuchObjectException
 456     {
 457         return sun.rmi.transport.ObjectTable.unexportObject(obj, force);
 458     }
 459 
 460     /**
 461      * Exports the specified object using the specified server ref.
 462      */
 463     private static Remote exportObject(Remote obj, UnicastServerRef sref)
 464         throws RemoteException
 465     {
 466         // if obj extends UnicastRemoteObject, set its ref.
 467         if (obj instanceof UnicastRemoteObject) {
 468             ((UnicastRemoteObject) obj).ref = sref;
 469         }
 470         return sref.exportObject(obj, null, false);
 471     }
 472 }