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      */
UnicastRemoteObject()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      */
UnicastRemoteObject(int port)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      */
UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)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      */
readObject(java.io.ObjectInputStream in)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      */
clone()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      */
reexport()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
exportObject(Remote obj)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      */
exportObject(Remote obj, int port)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      */
exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)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      */
exportObject(Remote obj, int port, ObjectInputFilter filter)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      */
exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf, ObjectInputFilter filter)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      */
unexportObject(Remote obj, boolean force)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      */
exportObject(Remote obj, UnicastServerRef sref)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 }
473