blob: 07879812774dd75abcdf82d22a5ed2432260b2a7 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2005 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
26package java.rmi.activation;
27
28import java.rmi.MarshalledObject;
29import java.rmi.NoSuchObjectException;
30import java.rmi.Remote;
31import java.rmi.RemoteException;
32import java.rmi.activation.UnknownGroupException;
33import java.rmi.activation.UnknownObjectException;
34import java.rmi.server.RMIClientSocketFactory;
35import java.rmi.server.RMIServerSocketFactory;
36import java.rmi.server.RemoteServer;
37import sun.rmi.server.ActivatableServerRef;
38
39/**
40 * The <code>Activatable</code> class provides support for remote
41 * objects that require persistent access over time and that
42 * can be activated by the system.
43 *
44 * <p>For the constructors and static <code>exportObject</code> methods,
45 * the stub for a remote object being exported is obtained as described in
46 * {@link java.rmi.server.UnicastRemoteObject}.
47 *
48 * <p>An attempt to serialize explicitly an instance of this class will
49 * fail.
50 *
51 * @author Ann Wollrath
52 * @since 1.2
53 * @serial exclude
54 */
55public abstract class Activatable extends RemoteServer {
56
57 private ActivationID id;
58 /** indicate compatibility with the Java 2 SDK v1.2 version of class */
59 private static final long serialVersionUID = -3120617863591563455L;
60
61 /**
62 * Constructs an activatable remote object by registering
63 * an activation descriptor (with the specified location, data, and
64 * restart mode) for this object, and exporting the object with the
65 * specified port.
66 *
67 * <p><strong>Note:</strong> Using the <code>Activatable</code>
68 * constructors that both register and export an activatable remote
69 * object is strongly discouraged because the actions of registering
70 * and exporting the remote object are <i>not</i> guaranteed to be
71 * atomic. Instead, an application should register an activation
72 * descriptor and export a remote object separately, so that exceptions
73 * can be handled properly.
74 *
75 * <p>This method invokes the {@link
76 * exportObject(Remote,String,MarshalledObject,boolean,port)
77 * exportObject} method with this object, and the specified location,
78 * data, restart mode, and port. Subsequent calls to {@link #getID}
79 * will return the activation identifier returned from the call to
80 * <code>exportObject</code>.
81 *
82 * @param location the location for classes for this object
83 * @param data the object's initialization data
84 * @param port the port on which the object is exported (an anonymous
85 * port is used if port=0)
86 * @param restart if true, the object is restarted (reactivated) when
87 * either the activator is restarted or the object's activation group
88 * is restarted after an unexpected crash; if false, the object is only
89 * activated on demand. Specifying <code>restart</code> to be
90 * <code>true</code> does not force an initial immediate activation of
91 * a newly registered object; initial activation is lazy.
92 * @exception ActivationException if object registration fails.
93 * @exception RemoteException if either of the following fails:
94 * a) registering the object with the activation system or b) exporting
95 * the object to the RMI runtime.
96 * @since 1.2
97 **/
98 protected Activatable(String location,
99 MarshalledObject<?> data,
100 boolean restart,
101 int port)
102 throws ActivationException, RemoteException
103 {
104 super();
105 id = exportObject(this, location, data, restart, port);
106 }
107
108 /**
109 * Constructs an activatable remote object by registering
110 * an activation descriptor (with the specified location, data, and
111 * restart mode) for this object, and exporting the object with the
112 * specified port, and specified client and server socket factories.
113 *
114 * <p><strong>Note:</strong> Using the <code>Activatable</code>
115 * constructors that both register and export an activatable remote
116 * object is strongly discouraged because the actions of registering
117 * and exporting the remote object are <i>not</i> guaranteed to be
118 * atomic. Instead, an application should register an activation
119 * descriptor and export a remote object separately, so that exceptions
120 * can be handled properly.
121 *
122 * <p>This method invokes the {@link
123 * exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory)
124 * exportObject} method with this object, and the specified location,
125 * data, restart mode, port, and client and server socket factories.
126 * Subsequent calls to {@link #getID} will return the activation
127 * identifier returned from the call to <code>exportObject</code>.
128 *
129 * @param location the location for classes for this object
130 * @param data the object's initialization data
131 * @param restart if true, the object is restarted (reactivated) when
132 * either the activator is restarted or the object's activation group
133 * is restarted after an unexpected crash; if false, the object is only
134 * activated on demand. Specifying <code>restart</code> to be
135 * <code>true</code> does not force an initial immediate activation of
136 * a newly registered object; initial activation is lazy.
137 * @param port the port on which the object is exported (an anonymous
138 * port is used if port=0)
139 * @param csf the client-side socket factory for making calls to the
140 * remote object
141 * @param ssf the server-side socket factory for receiving remote calls
142 * @exception ActivationException if object registration fails.
143 * @exception RemoteException if either of the following fails:
144 * a) registering the object with the activation system or b) exporting
145 * the object to the RMI runtime.
146 * @since 1.2
147 **/
148 protected Activatable(String location,
149 MarshalledObject<?> data,
150 boolean restart,
151 int port,
152 RMIClientSocketFactory csf,
153 RMIServerSocketFactory ssf)
154 throws ActivationException, RemoteException
155 {
156 super();
157 id = exportObject(this, location, data, restart, port, csf, ssf);
158 }
159
160 /**
161 * Constructor used to activate/export the object on a specified
162 * port. An "activatable" remote object must have a constructor that
163 * takes two arguments: <ul>
164 * <li>the object's activation identifier (<code>ActivationID</code>), and
165 * <li>the object's initialization data (a <code>MarshalledObject</code>).
166 * </ul><p>
167 *
168 * A concrete subclass of this class must call this constructor when it is
169 * <i>activated</i> via the two parameter constructor described above. As
170 * a side-effect of construction, the remote object is "exported"
171 * to the RMI runtime (on the specified <code>port</code>) and is
172 * available to accept incoming calls from clients.
173 *
174 * @param id activation identifier for the object
175 * @param port the port number on which the object is exported
176 * @exception RemoteException if exporting the object to the RMI
177 * runtime fails
178 * @since 1.2
179 */
180 protected Activatable(ActivationID id, int port)
181 throws RemoteException
182 {
183 super();
184 this.id = id;
185 exportObject(this, id, port);
186 }
187
188 /**
189 * Constructor used to activate/export the object on a specified
190 * port. An "activatable" remote object must have a constructor that
191 * takes two arguments: <ul>
192 * <li>the object's activation identifier (<code>ActivationID</code>), and
193 * <li>the object's initialization data (a <code>MarshalledObject</code>).
194 * </ul><p>
195 *
196 * A concrete subclass of this class must call this constructor when it is
197 * <i>activated</i> via the two parameter constructor described above. As
198 * a side-effect of construction, the remote object is "exported"
199 * to the RMI runtime (on the specified <code>port</code>) and is
200 * available to accept incoming calls from clients.
201 *
202 * @param id activation identifier for the object
203 * @param port the port number on which the object is exported
204 * @param csf the client-side socket factory for making calls to the
205 * remote object
206 * @param ssf the server-side socket factory for receiving remote calls
207 * @exception RemoteException if exporting the object to the RMI
208 * runtime fails
209 * @since 1.2
210 */
211 protected Activatable(ActivationID id, int port,
212 RMIClientSocketFactory csf,
213 RMIServerSocketFactory ssf)
214 throws RemoteException
215 {
216 super();
217 this.id = id;
218 exportObject(this, id, port, csf, ssf);
219 }
220
221 /**
222 * Returns the object's activation identifier. The method is
223 * protected so that only subclasses can obtain an object's
224 * identifier.
225 * @return the object's activation identifier
226 * @since 1.2
227 */
228 protected ActivationID getID() {
229 return id;
230 }
231
232 /**
233 * Register an object descriptor for an activatable remote
234 * object so that is can be activated on demand.
235 *
236 * @param desc the object's descriptor
237 * @return the stub for the activatable remote object
238 * @exception UnknownGroupException if group id in <code>desc</code>
239 * is not registered with the activation system
240 * @exception ActivationException if activation system is not running
241 * @exception RemoteException if remote call fails
242 * @since 1.2
243 */
244 public static Remote register(ActivationDesc desc)
245 throws UnknownGroupException, ActivationException, RemoteException
246 {
247 // register object with activator.
248 ActivationID id =
249 ActivationGroup.getSystem().registerObject(desc);
250 return sun.rmi.server.ActivatableRef.getStub(desc, id);
251 }
252
253 /**
254 * Informs the system that the object with the corresponding activation
255 * <code>id</code> is currently inactive. If the object is currently
256 * active, the object is "unexported" from the RMI runtime (only if
257 * there are no pending or in-progress calls)
258 * so the that it can no longer receive incoming calls. This call
259 * informs this VM's ActivationGroup that the object is inactive,
260 * that, in turn, informs its ActivationMonitor. If this call
261 * completes successfully, a subsequent activate request to the activator
262 * will cause the object to reactivate. The operation may still
263 * succeed if the object is considered active but has already
264 * unexported itself.
265 *
266 * @param id the object's activation identifier
267 * @return true if the operation succeeds (the operation will
268 * succeed if the object in currently known to be active and is
269 * either already unexported or is currently exported and has no
270 * pending/executing calls); false is returned if the object has
271 * pending/executing calls in which case it cannot be deactivated
272 * @exception UnknownObjectException if object is not known (it may
273 * already be inactive)
274 * @exception ActivationException if group is not active
275 * @exception RemoteException if call informing monitor fails
276 * @since 1.2
277 */
278 public static boolean inactive(ActivationID id)
279 throws UnknownObjectException, ActivationException, RemoteException
280 {
281 return ActivationGroup.currentGroup().inactiveObject(id);
282 }
283
284 /**
285 * Revokes previous registration for the activation descriptor
286 * associated with <code>id</code>. An object can no longer be
287 * activated via that <code>id</code>.
288 *
289 * @param id the object's activation identifier
290 * @exception UnknownObjectException if object (<code>id</code>) is unknown
291 * @exception ActivationException if activation system is not running
292 * @exception RemoteException if remote call to activation system fails
293 * @since 1.2
294 */
295 public static void unregister(ActivationID id)
296 throws UnknownObjectException, ActivationException, RemoteException
297 {
298 ActivationGroup.getSystem().unregisterObject(id);
299 }
300
301 /**
302 * Registers an activation descriptor (with the specified location,
303 * data, and restart mode) for the specified object, and exports that
304 * object with the specified port.
305 *
306 * <p><strong>Note:</strong> Using this method (as well as the
307 * <code>Activatable</code> constructors that both register and export
308 * an activatable remote object) is strongly discouraged because the
309 * actions of registering and exporting the remote object are
310 * <i>not</i> guaranteed to be atomic. Instead, an application should
311 * register an activation descriptor and export a remote object
312 * separately, so that exceptions can be handled properly.
313 *
314 * <p>This method invokes the {@link
315 * exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory)
316 * exportObject} method with the specified object, location, data,
317 * restart mode, and port, and <code>null</code> for both client and
318 * server socket factories, and then returns the resulting activation
319 * identifier.
320 *
321 * @param obj the object being exported
322 * @param location the object's code location
323 * @param data the object's bootstrapping data
324 * @param restart if true, the object is restarted (reactivated) when
325 * either the activator is restarted or the object's activation group
326 * is restarted after an unexpected crash; if false, the object is only
327 * activated on demand. Specifying <code>restart</code> to be
328 * <code>true</code> does not force an initial immediate activation of
329 * a newly registered object; initial activation is lazy.
330 * @param port the port on which the object is exported (an anonymous
331 * port is used if port=0)
332 * @return the activation identifier obtained from registering the
333 * descriptor, <code>desc</code>, with the activation system
334 * the wrong group
335 * @exception ActivationException if activation group is not active
336 * @exception RemoteException if object registration or export fails
337 * @since 1.2
338 **/
339 public static ActivationID exportObject(Remote obj,
340 String location,
341 MarshalledObject<?> data,
342 boolean restart,
343 int port)
344 throws ActivationException, RemoteException
345 {
346 return exportObject(obj, location, data, restart, port, null, null);
347 }
348
349 /**
350 * Registers an activation descriptor (with the specified location,
351 * data, and restart mode) for the specified object, and exports that
352 * object with the specified port, and the specified client and server
353 * socket factories.
354 *
355 * <p><strong>Note:</strong> Using this method (as well as the
356 * <code>Activatable</code> constructors that both register and export
357 * an activatable remote object) is strongly discouraged because the
358 * actions of registering and exporting the remote object are
359 * <i>not</i> guaranteed to be atomic. Instead, an application should
360 * register an activation descriptor and export a remote object
361 * separately, so that exceptions can be handled properly.
362 *
363 * <p>This method first registers an activation descriptor for the
364 * specified object as follows. It obtains the activation system by
365 * invoking the method {@link ActivationGroup#getSystem
366 * ActivationGroup.getSystem}. This method then obtains an {@link
367 * ActivationID} for the object by invoking the activation system's
368 * {@link ActivationSystem#registerObject registerObject} method with
369 * an {@link ActivationDesc} constructed with the specified object's
370 * class name, and the specified location, data, and restart mode. If
371 * an exception occurs obtaining the activation system or registering
372 * the activation descriptor, that exception is thrown to the caller.
373 *
374 * <p>Next, this method exports the object by invoking the {@link
375 * #exportObject(Remote,ActivationID,int,RMIClientSocketFactory,RMIServerSocketFactory)
376 * exportObject} method with the specified remote object, the
377 * activation identifier obtained from registration, the specified
378 * port, and the specified client and server socket factories. If an
379 * exception occurs exporting the object, this method attempts to
380 * unregister the activation identifier (obtained from registration) by
381 * invoking the activation system's {@link
382 * ActivationSystem#unregisterObject unregisterObject} method with the
383 * activation identifier. If an exception occurs unregistering the
384 * identifier, that exception is ignored, and the original exception
385 * that occurred exporting the object is thrown to the caller.
386 *
387 * <p>Finally, this method invokes the {@link
388 * ActivationGroup#activeObject activeObject} method on the activation
389 * group in this VM with the activation identifier and the specified
390 * remote object, and returns the activation identifier to the caller.
391 *
392 * @param obj the object being exported
393 * @param location the object's code location
394 * @param data the object's bootstrapping data
395 * @param restart if true, the object is restarted (reactivated) when
396 * either the activator is restarted or the object's activation group
397 * is restarted after an unexpected crash; if false, the object is only
398 * activated on demand. Specifying <code>restart</code> to be
399 * <code>true</code> does not force an initial immediate activation of
400 * a newly registered object; initial activation is lazy.
401 * @param port the port on which the object is exported (an anonymous
402 * port is used if port=0)
403 * @param csf the client-side socket factory for making calls to the
404 * remote object
405 * @param ssf the server-side socket factory for receiving remote calls
406 * @return the activation identifier obtained from registering the
407 * descriptor with the activation system
408 * @exception ActivationException if activation group is not active
409 * @exception RemoteException if object registration or export fails
410 * @since 1.2
411 **/
412 public static ActivationID exportObject(Remote obj,
413 String location,
414 MarshalledObject<?> data,
415 boolean restart,
416 int port,
417 RMIClientSocketFactory csf,
418 RMIServerSocketFactory ssf)
419 throws ActivationException, RemoteException
420 {
421 ActivationDesc desc = new ActivationDesc(obj.getClass().getName(),
422 location, data, restart);
423 /*
424 * Register descriptor.
425 */
426 ActivationSystem system = ActivationGroup.getSystem();
427 ActivationID id = system.registerObject(desc);
428
429 /*
430 * Export object.
431 */
432 try {
433 exportObject(obj, id, port, csf, ssf);
434 } catch (RemoteException e) {
435 /*
436 * Attempt to unregister activation descriptor because export
437 * failed and register/export should be atomic (see 4323621).
438 */
439 try {
440 system.unregisterObject(id);
441 } catch (Exception ex) {
442 }
443 /*
444 * Report original exception.
445 */
446 throw e;
447 }
448
449 /*
450 * This call can't fail (it is a local call, and the only possible
451 * exception, thrown if the group is inactive, will not be thrown
452 * because the group is not inactive).
453 */
454 ActivationGroup.currentGroup().activeObject(id, obj);
455
456 return id;
457 }
458
459 /**
460 * Export the activatable remote object to the RMI runtime to make
461 * the object available to receive incoming calls. The object is
462 * exported on an anonymous port, if <code>port</code> is zero. <p>
463 *
464 * During activation, this <code>exportObject</code> method should
465 * be invoked explicitly by an "activatable" object, that does not
466 * extend the <code>Activatable</code> class. There is no need for objects
467 * that do extend the <code>Activatable</code> class to invoke this
468 * method directly because the object is exported during construction.
469 *
470 * @return the stub for the activatable remote object
471 * @param obj the remote object implementation
472 * @param id the object's activation identifier
473 * @param port the port on which the object is exported (an anonymous
474 * port is used if port=0)
475 * @exception RemoteException if object export fails
476 * @since 1.2
477 */
478 public static Remote exportObject(Remote obj,
479 ActivationID id,
480 int port)
481 throws RemoteException
482 {
483 return exportObject(obj, new ActivatableServerRef(id, port));
484 }
485
486 /**
487 * Export the activatable remote object to the RMI runtime to make
488 * the object available to receive incoming calls. The object is
489 * exported on an anonymous port, if <code>port</code> is zero. <p>
490 *
491 * During activation, this <code>exportObject</code> method should
492 * be invoked explicitly by an "activatable" object, that does not
493 * extend the <code>Activatable</code> class. There is no need for objects
494 * that do extend the <code>Activatable</code> class to invoke this
495 * method directly because the object is exported during construction.
496 *
497 * @return the stub for the activatable remote object
498 * @param obj the remote object implementation
499 * @param id the object's activation identifier
500 * @param port the port on which the object is exported (an anonymous
501 * port is used if port=0)
502 * @param csf the client-side socket factory for making calls to the
503 * remote object
504 * @param ssf the server-side socket factory for receiving remote calls
505 * @exception RemoteException if object export fails
506 * @since 1.2
507 */
508 public static Remote exportObject(Remote obj,
509 ActivationID id,
510 int port,
511 RMIClientSocketFactory csf,
512 RMIServerSocketFactory ssf)
513 throws RemoteException
514 {
515 return exportObject(obj, new ActivatableServerRef(id, port, csf, ssf));
516 }
517
518 /**
519 * Remove the remote object, obj, from the RMI runtime. If
520 * successful, the object can no longer accept incoming RMI calls.
521 * If the force parameter is true, the object is forcibly unexported
522 * even if there are pending calls to the remote object or the
523 * remote object still has calls in progress. If the force
524 * parameter is false, the object is only unexported if there are
525 * no pending or in progress calls to the object.
526 *
527 * @param obj the remote object to be unexported
528 * @param force if true, unexports the object even if there are
529 * pending or in-progress calls; if false, only unexports the object
530 * if there are no pending or in-progress calls
531 * @return true if operation is successful, false otherwise
532 * @exception NoSuchObjectException if the remote object is not
533 * currently exported
534 * @since 1.2
535 */
536 public static boolean unexportObject(Remote obj, boolean force)
537 throws NoSuchObjectException
538 {
539 return sun.rmi.transport.ObjectTable.unexportObject(obj, force);
540 }
541
542 /**
543 * Exports the specified object using the specified server ref.
544 */
545 private static Remote exportObject(Remote obj, ActivatableServerRef sref)
546 throws RemoteException
547 {
548 // if obj extends Activatable, set its ref.
549 if (obj instanceof Activatable) {
550 ((Activatable) obj).ref = sref;
551
552 }
553 return sref.exportObject(obj, null, false);
554 }
555}