1 /*
2 * Copyright 1996-2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 package java.rmi.server;
26
27 import java.rmi;
28 import sun.rmi.server.UnicastServerRef;
29 import sun.rmi.server.UnicastServerRef2;
30
31 /**
32 * Used for exporting a remote object with JRMP and obtaining a stub
33 * that communicates to the remote object.
34 *
35 * <p>For the constructors and static <code>exportObject</code> methods
36 * below, the stub for a remote object being exported is obtained as
37 * follows:
38 *
39 * <p><ul>
40 *
41 * <li>If the remote object is exported using the {@link
42 * #exportObject(Remote) UnicastRemoteObject.exportObject(Remote)} method,
43 * a stub class (typically pregenerated from the remote object's class
44 * using the <code>rmic</code> tool) is loaded and an instance of that stub
45 * class is constructed as follows.
46 * <ul>
47 *
48 * <li>A "root class" is determined as follows: if the remote object's
49 * class directly implements an interface that extends {@link Remote}, then
50 * the remote object's class is the root class; otherwise, the root class is
51 * the most derived superclass of the remote object's class that directly
52 * implements an interface that extends <code>Remote</code>.
53 *
54 * <li>The name of the stub class to load is determined by concatenating
55 * the binary name of the root class with the suffix <code>"_Stub"</code>.
56 *
57 * <li>The stub class is loaded by name using the class loader of the root
58 * class. The stub class must extend {@link RemoteStub} and must have a
59 * public constructor that has one parameter, of type {@link RemoteRef}.
60 *
61 * <li>Finally, an instance of the stub class is constructed with a
62 * {@link RemoteRef}.
63 * </ul>
64 *
65 * <li>If the appropriate stub class could not be found, or the stub class
66 * could not be loaded, or a problem occurs creating the stub instance, a
67 * {@link StubNotFoundException} is thrown.
68 *
69 * <p>
70 * <li>For all other means of exporting:
71 * <p><ul>
72 *
73 * <li>If the remote object's stub class (as defined above) could not be
74 * loaded or the system property
75 * <code>java.rmi.server.ignoreStubClasses</code> is set to
76 * <code>"true"</code> (case insensitive), a {@link
77 * java.lang.reflect.Proxy} instance is constructed with the following
78 * properties:
79 *
80 * <ul>
81 *
82 * <li>The proxy's class is defined by the class loader of the remote
83 * object's class.
84 *
85 * <li>The proxy implements all the remote interfaces implemented by the
86 * remote object's class.
87 *
88 * <li>The proxy's invocation handler is a {@link
89 * RemoteObjectInvocationHandler} instance constructed with a
90 * {@link RemoteRef}.
91 *
92 * <li>If the proxy could not be created, a {@link StubNotFoundException}
93 * will be thrown.
94 * </ul>
95 *
96 * <p>
97 * <li>Otherwise, an instance of the remote object's stub class (as
98 * described above) is used as the stub.
99 *
100 * </ul>
101 * </ul>
102 *
103 * @author Ann Wollrath
104 * @author Peter Jones
105 * @since JDK1.1
106 **/
107 public class UnicastRemoteObject extends RemoteServer {
108
109 /**
110 * @serial port number on which to export object
111 */
112 private int port = 0;
113
114 /**
115 * @serial client-side socket factory (if any)
116 */
117 private RMIClientSocketFactory csf = null;
118
119 /**
120 * @serial server-side socket factory (if any) to use when
121 * exporting object
122 */
123 private RMIServerSocketFactory ssf = null;
124
125 /* indicate compatibility with JDK 1.1.x version of class */
126 private static final long serialVersionUID = 4974527148936298033L;
127
128 /**
129 * Creates and exports a new UnicastRemoteObject object using an
130 * anonymous port.
131 * @throws RemoteException if failed to export object
132 * @since JDK1.1
133 */
134 protected UnicastRemoteObject() throws RemoteException
135 {
136 this(0);
137 }
138
139 /**
140 * Creates and exports a new UnicastRemoteObject object using the
141 * particular supplied port.
142 * @param port the port number on which the remote object receives calls
143 * (if <code>port</code> is zero, an anonymous port is chosen)
144 * @throws RemoteException if failed to export object
145 * @since 1.2
146 */
147 protected UnicastRemoteObject(int port) throws RemoteException
148 {
149 this.port = port;
150 exportObject((Remote) this, port);
151 }
152
153 /**
154 * Creates and exports a new UnicastRemoteObject object using the
155 * particular supplied port and socket factories.
156 * @param port the port number on which the remote object receives calls
157 * (if <code>port</code> is zero, an anonymous port is chosen)
158 * @param csf the client-side socket factory for making calls to the
159 * remote object
160 * @param ssf the server-side socket factory for receiving remote calls
161 * @throws RemoteException if failed to export object
162 * @since 1.2
163 */
164 protected UnicastRemoteObject(int port,
165 RMIClientSocketFactory csf,
166 RMIServerSocketFactory ssf)
167 throws RemoteException
168 {
169 this.port = port;
170 this.csf = csf;
171 this.ssf = ssf;
172 exportObject((Remote) this, port, csf, ssf);
173 }
174
175 /**
176 * Re-export the remote object when it is deserialized.
177 */
178 private void readObject(java.io.ObjectInputStream in)
179 throws java.io.IOException, java.lang.ClassNotFoundException
180 {
181 in.defaultReadObject();
182 reexport();
183 }
184
185 /**
186 * Returns a clone of the remote object that is distinct from
187 * the original.
188 *
189 * @exception CloneNotSupportedException if clone failed due to
190 * a RemoteException.
191 * @return the new remote object
192 * @since JDK1.1
193 */
194 public Object clone() throws CloneNotSupportedException
195 {
196 try {
197 UnicastRemoteObject cloned = (UnicastRemoteObject) super.clone();
198 cloned.reexport();
199 return cloned;
200 } catch (RemoteException e) {
201 throw new ServerCloneException("Clone failed", e);
202 }
203 }
204
205 /*
206 * Exports this UnicastRemoteObject using its initialized fields because
207 * its creation bypassed running its constructors (via deserialization
208 * or cloning, for example).
209 */
210 private void reexport() throws RemoteException
211 {
212 if (csf == null && ssf == null) {
213 exportObject((Remote) this, port);
214 } else {
215 exportObject((Remote) this, port, csf, ssf);
216 }
217 }
218
219 /**
220 * Exports the remote object to make it available to receive incoming
221 * calls using an anonymous port.
222 * @param obj the remote object to be exported
223 * @return remote object stub
224 * @exception RemoteException if export fails
225 * @since JDK1.1
226 */
227 public static RemoteStub exportObject(Remote obj)
228 throws RemoteException
229 {
230 /*
231 * Use UnicastServerRef constructor passing the boolean value true
232 * to indicate that only a generated stub class should be used. A
233 * generated stub class must be used instead of a dynamic proxy
234 * because the return value of this method is RemoteStub which a
235 * dynamic proxy class cannot extend.
236 */
237 return (RemoteStub) exportObject(obj, new UnicastServerRef(true));
238 }
239
240 /**
241 * Exports the remote object to make it available to receive incoming
242 * calls, using the particular supplied port.
243 * @param obj the remote object to be exported
244 * @param port the port to export the object on
245 * @return remote object stub
246 * @exception RemoteException if export fails
247 * @since 1.2
248 */
249 public static Remote exportObject(Remote obj, int port)
250 throws RemoteException
251 {
252 return exportObject(obj, new UnicastServerRef(port));
253 }
254
255 /**
256 * Exports the remote object to make it available to receive incoming
257 * calls, using a transport specified by the given socket factory.
258 * @param obj the remote object to be exported
259 * @param port the port to export the object on
260 * @param csf the client-side socket factory for making calls to the
261 * remote object
262 * @param ssf the server-side socket factory for receiving remote calls
263 * @return remote object stub
264 * @exception RemoteException if export fails
265 * @since 1.2
266 */
267 public static Remote exportObject(Remote obj, int port,
268 RMIClientSocketFactory csf,
269 RMIServerSocketFactory ssf)
270 throws RemoteException
271 {
272
273 return exportObject(obj, new UnicastServerRef2(port, csf, ssf));
274 }
275
276 /**
277 * Removes the remote object, obj, from the RMI runtime. If
278 * successful, the object can no longer accept incoming RMI calls.
279 * If the force parameter is true, the object is forcibly unexported
280 * even if there are pending calls to the remote object or the
281 * remote object still has calls in progress. If the force
282 * parameter is false, the object is only unexported if there are
283 * no pending or in progress calls to the object.
284 *
285 * @param obj the remote object to be unexported
286 * @param force if true, unexports the object even if there are
287 * pending or in-progress calls; if false, only unexports the object
288 * if there are no pending or in-progress calls
289 * @return true if operation is successful, false otherwise
290 * @exception NoSuchObjectException if the remote object is not
291 * currently exported
292 * @since 1.2
293 */
294 public static boolean unexportObject(Remote obj, boolean force)
295 throws java.rmi.NoSuchObjectException
296 {
297 return sun.rmi.transport.ObjectTable.unexportObject(obj, force);
298 }
299
300 /**
301 * Exports the specified object using the specified server ref.
302 */
303 private static Remote exportObject(Remote obj, UnicastServerRef sref)
304 throws RemoteException
305 {
306 // if obj extends UnicastRemoteObject, set its ref.
307 if (obj instanceof UnicastRemoteObject) {
308 ((UnicastRemoteObject) obj).ref = sref;
309 }
310 return sref.exportObject(obj, null, false);
311 }
312 }