1 /* 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 26 package java.rmi.activation; 27 28 import java.rmi.MarshalledObject; 29 import java.rmi.NoSuchObjectException; 30 import java.rmi.Remote; 31 import java.rmi.RemoteException; 32 import java.rmi.activation.UnknownGroupException; 33 import java.rmi.activation.UnknownObjectException; 34 import java.rmi.server.RMIClientSocketFactory; 35 import java.rmi.server.RMIServerSocketFactory; 36 import java.rmi.server.RemoteServer; 37 import 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 */ 55 public 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 }