1. /*
  2. * @(#)Activatable.java 1.32 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.rmi.activation;
  8. import java.lang.reflect.Constructor;
  9. import java.rmi.activation.UnknownGroupException;
  10. import java.rmi.activation.UnknownObjectException;
  11. import java.rmi.Remote;
  12. import java.rmi.RemoteException;
  13. import java.rmi.MarshalledObject;
  14. import java.rmi.NoSuchObjectException;
  15. import java.rmi.server.*;
  16. /**
  17. * The <code>Activatable</code> class provides support for remote
  18. * objects that require persistent access over time and that
  19. * can be activated by the system.
  20. *
  21. * @author Ann Wollrath
  22. * @version 1.32, 03/01/23
  23. * @since 1.2
  24. */
  25. public abstract class Activatable extends RemoteServer {
  26. /**
  27. * @serial Activation Identifier for this object.
  28. */
  29. private ActivationID id;
  30. /** indicate compatibility with the Java 2 SDK v1.2 version of class */
  31. private static final long serialVersionUID = -3120617863591563455L;
  32. /* parameter types for server ref constructor invocation used below */
  33. private static Class[] idPortParamTypes = {
  34. ActivationID.class, int.class
  35. };
  36. /* parameter types for server ref constructor invocation used below */
  37. private static Class[] idPortFactoryParamTypes = {
  38. ActivationID.class, int.class, RMIClientSocketFactory.class,
  39. RMIServerSocketFactory.class
  40. };
  41. /**
  42. * Constructor used to register and export the object on a
  43. * specified port (an anonymous port is chosen if port=0) .
  44. *
  45. * A concrete subclass of this class must call this constructor to
  46. * register and export the object during <i>initial</i> construction. As
  47. * a side-effect of activatable object construction, the remote
  48. * object is both "registered" with the activation system and
  49. * "exported" (on an anonymous port if port=0) to the RMI runtime
  50. * so that it is available to accept incoming calls from clients.
  51. *
  52. * @param location the location for classes for this object
  53. * @param data the object's initialization data
  54. * @param port the port on which the object is exported (an anonymous
  55. * port is used if port=0)
  56. * @param restart if true, the object is restarted (reactivated) when
  57. * either the activator is restarted or the object's activation group
  58. * is restarted after an unexpected crash; if false, the object is only
  59. * activated on demand. Specifying <code>restart</code> to be
  60. * <code>true</code> does not force an initial immediate activation of
  61. * a newly registered object; initial activation is lazy.
  62. * @exception ActivationException if object registration fails.
  63. * @exception RemoteException if either of the following fails:
  64. * a) registering the object with the activation system or b) exporting
  65. * the object to the RMI runtime.
  66. * @since 1.2
  67. */
  68. protected Activatable(String location,
  69. MarshalledObject data,
  70. boolean restart,
  71. int port)
  72. throws ActivationException, RemoteException
  73. {
  74. super();
  75. id = exportObject(this, location, data, restart, port);
  76. }
  77. /**
  78. * Constructor used to register and export the object on a
  79. * specified port (an anonymous port is chosen if port=0) . <p>
  80. *
  81. * A concrete subclass of this class must call this constructor to
  82. * register and export the object during <i>initial</i> construction. As
  83. * a side-effect of activatable object construction, the remote
  84. * object is both "registered" with the activation system and
  85. * "exported" (on an anonymous port if port=0) to the RMI runtime
  86. * so that it is available to accept incoming calls from clients.
  87. *
  88. * @param location the location for classes for this object
  89. * @param data the object's initialization data
  90. * @param restart if true, the object is restarted (reactivated) when
  91. * either the activator is restarted or the object's activation group
  92. * is restarted after an unexpected crash; if false, the object is only
  93. * activated on demand. Specifying <code>restart</code> to be
  94. * <code>true</code> does not force an initial immediate activation of
  95. * a newly registered object; initial activation is lazy.
  96. * @param port the port on which the object is exported (an anonymous
  97. * port is used if port=0)
  98. * @param csf the client-side socket factory for making calls to the
  99. * remote object
  100. * @param ssf the server-side socket factory for receiving remote calls
  101. * @exception ActivationException if object registration fails.
  102. * @exception RemoteException if either of the following fails:
  103. * a) registering the object with the activation system or b) exporting
  104. * the object to the RMI runtime.
  105. * @since 1.2
  106. */
  107. protected Activatable(String location,
  108. MarshalledObject data,
  109. boolean restart,
  110. int port,
  111. RMIClientSocketFactory csf,
  112. RMIServerSocketFactory ssf)
  113. throws ActivationException, RemoteException
  114. {
  115. super();
  116. id = exportObject(this, location, data, restart, port, csf, ssf);
  117. }
  118. /**
  119. * Constructor used to activate/export the object on a specified
  120. * port. An "activatable" remote object must have a constructor that
  121. * takes two arguments: <ul>
  122. * <li>the object's activation identifier (<code>ActivationID</code>), and
  123. * <li>the object's initialization data (a <code>MarshalledObject</code>).
  124. * </ul><p>
  125. *
  126. * A concrete subclass of this class must call this constructor when it is
  127. * <i>activated</i> via the two parameter constructor described above. As
  128. * a side-effect of construction, the remote object is "exported"
  129. * to the RMI runtime (on the specified <code>port</code>) and is
  130. * available to accept incoming calls from clients.
  131. *
  132. * @param id activation identifier for the object
  133. * @param port the port number on which the object is exported
  134. * @exception RemoteException if exporting the object to the RMI
  135. * runtime fails
  136. * @since 1.2
  137. */
  138. protected Activatable(ActivationID id, int port)
  139. throws RemoteException
  140. {
  141. super();
  142. this.id = id;
  143. exportObject(this, id, port);
  144. }
  145. /**
  146. * Constructor used to activate/export the object on a specified
  147. * port. An "activatable" remote object must have a constructor that
  148. * takes two arguments: <ul>
  149. * <li>the object's activation identifier (<code>ActivationID</code>), and
  150. * <li>the object's initialization data (a <code>MarshalledObject</code>).
  151. * </ul><p>
  152. *
  153. * A concrete subclass of this class must call this constructor when it is
  154. * <i>activated</i> via the two parameter constructor described above. As
  155. * a side-effect of construction, the remote object is "exported"
  156. * to the RMI runtime (on the specified <code>port</code>) and is
  157. * available to accept incoming calls from clients.
  158. *
  159. * @param id activation identifier for the object
  160. * @param port the port number on which the object is exported
  161. * @param csf the client-side socket factory for making calls to the
  162. * remote object
  163. * @param ssf the server-side socket factory for receiving remote calls
  164. * @exception RemoteException if exporting the object to the RMI
  165. * runtime fails
  166. * @since 1.2
  167. */
  168. protected Activatable(ActivationID id, int port,
  169. RMIClientSocketFactory csf,
  170. RMIServerSocketFactory ssf)
  171. throws RemoteException
  172. {
  173. super();
  174. this.id = id;
  175. exportObject(this, id, port, csf, ssf);
  176. }
  177. /**
  178. * Returns the object's activation identifier. The method is
  179. * protected so that only subclasses can obtain an object's
  180. * identifier.
  181. * @return the object's activation identifier
  182. * @since 1.2
  183. */
  184. protected ActivationID getID() {
  185. return id;
  186. }
  187. /**
  188. * Register an object descriptor for an activatable remote
  189. * object so that is can be activated on demand.
  190. *
  191. * @param desc the object's descriptor
  192. * @return the stub for the activatable remote object
  193. * @exception UnknownGroupException if group id in <code>desc</code>
  194. * is not registered with the activation system
  195. * @exception ActivationException if activation system is not running
  196. * @exception RemoteException if remote call fails
  197. * @since 1.2
  198. */
  199. public static Remote register(ActivationDesc desc)
  200. throws UnknownGroupException, ActivationException, RemoteException
  201. {
  202. // register object with activator.
  203. ActivationID id =
  204. ActivationGroup.getSystem().registerObject(desc);
  205. return sun.rmi.server.ActivatableRef.getStub(desc, id);
  206. }
  207. /**
  208. * Informs the system that the object with the corresponding activation
  209. * <code>id</code> is currently inactive. If the object is currently
  210. * active, the object is "unexported" from the RMI runtime (only if
  211. * there are no pending or in-progress calls)
  212. * so the that it can no longer receive incoming calls. This call
  213. * informs this VM's ActivationGroup that the object is inactive,
  214. * that, in turn, informs its ActivationMonitor. If this call
  215. * completes successfully, a subsequent activate request to the activator
  216. * will cause the object to reactivate. The operation may still
  217. * succeed if the object is considered active but has already
  218. * unexported itself.
  219. *
  220. * @param id the object's activation identifier
  221. * @return true if the operation succeeds (the operation will
  222. * succeed if the object in currently known to be active and is
  223. * either already unexported or is currently exported and has no
  224. * pending/executing calls); false is returned if the object has
  225. * pending/executing calls in which case it cannot be deactivated
  226. * @exception UnknownObjectException if object is not known (it may
  227. * already be inactive)
  228. * @exception ActivationException if group is not active
  229. * @exception RemoteException if call informing monitor fails
  230. * @since 1.2
  231. */
  232. public static boolean inactive(ActivationID id)
  233. throws UnknownObjectException, ActivationException, RemoteException
  234. {
  235. return ActivationGroup.currentGroup().inactiveObject(id);
  236. }
  237. /**
  238. * Revokes previous registration for the activation descriptor
  239. * associated with <code>id</code>. An object can no longer be
  240. * activated via that <code>id</code>.
  241. *
  242. * @param id the object's activation identifier
  243. * @exception UnknownObjectException if object (<code>id</code>) is unknown
  244. * @exception ActivationException if activation system is not running
  245. * @exception RemoteException if remote call to activation system fails
  246. * @since 1.2
  247. */
  248. public static void unregister(ActivationID id)
  249. throws UnknownObjectException, ActivationException, RemoteException
  250. {
  251. ActivationGroup.getSystem().unregisterObject(id);
  252. }
  253. /**
  254. * This <code>exportObject</code> method may be invoked explicitly
  255. * by an "activatable" object, that does not extend the
  256. * <code>Activatable</code> class, in order to both a) register
  257. * the object's activation descriptor, constructed from the supplied
  258. * <code>location</code>, and <code>data</code>, with
  259. * the activation system (so the object can be activated), and
  260. * b) export the remote object, <code>obj</code>, on a specific
  261. * port (if port=0, then an anonymous port is chosen). Once the
  262. * object is exported, it can receive incoming RMI calls.<p>
  263. *
  264. * This method does not need to be called if <code>obj</code>
  265. * extends <code>Activatable</code>, since the first constructor
  266. * calls this method.
  267. *
  268. * @param obj the object being exported
  269. * @param location the object's code location
  270. * @param data the object's bootstrapping data
  271. * @param restart if true, the object is restarted (reactivated) when
  272. * either the activator is restarted or the object's activation group
  273. * is restarted after an unexpected crash; if false, the object is only
  274. * activated on demand. Specifying <code>restart</code> to be
  275. * <code>true</code> does not force an initial immediate activation of
  276. * a newly registered object; initial activation is lazy.
  277. * @param port the port on which the object is exported (an anonymous
  278. * port is used if port=0)
  279. * @return the activation identifier obtained from registering the
  280. * descriptor, <code>desc</code>, with the activation system
  281. * the wrong group
  282. * @exception ActivationException if activation group is not active
  283. * @exception RemoteException if object registration or export fails
  284. * @since 1.2
  285. */
  286. public static ActivationID exportObject(Remote obj,
  287. String location,
  288. MarshalledObject data,
  289. boolean restart,
  290. int port)
  291. throws ActivationException, RemoteException
  292. {
  293. ActivationDesc desc = new ActivationDesc(obj.getClass().getName(),
  294. location, data, restart);
  295. ActivationID id = ActivationGroup.getSystem().registerObject(desc);
  296. Remote stub = exportObject(obj, id, port);
  297. ActivationGroup.currentGroup().activeObject(id, obj);
  298. return id;
  299. }
  300. /**
  301. * This <code>exportObject</code> method may be invoked explicitly
  302. * by an "activatable" object, that does not extend the
  303. * <code>Activatable</code> class, in order to both a) register
  304. * the object's activation descriptor, constructed from the supplied
  305. * <code>location</code>, and <code>data</code>, with
  306. * the activation system (so the object can be activated), and
  307. * b) export the remote object, <code>obj</code>, on a specific
  308. * port (if port=0, then an anonymous port is chosen). Once the
  309. * object is exported, it can receive incoming RMI calls.<p>
  310. *
  311. * This method does not need to be called if <code>obj</code>
  312. * extends <code>Activatable</code>, since the first constructor
  313. * calls this method.
  314. *
  315. * @param obj the object being exported
  316. * @param location the object's code location
  317. * @param data the object's bootstrapping data
  318. * @param restart if true, the object is restarted (reactivated) when
  319. * either the activator is restarted or the object's activation group
  320. * is restarted after an unexpected crash; if false, the object is only
  321. * activated on demand. Specifying <code>restart</code> to be
  322. * <code>true</code> does not force an initial immediate activation of
  323. * a newly registered object; initial activation is lazy.
  324. * @param port the port on which the object is exported (an anonymous
  325. * port is used if port=0)
  326. * @param csf the client-side socket factory for making calls to the
  327. * remote object
  328. * @param ssf the server-side socket factory for receiving remote calls
  329. * @return the activation identifier obtained from registering the
  330. * descriptor, <code>desc</code>, with the activation system
  331. * the wrong group
  332. * @exception ActivationException if activation group is not active
  333. * @exception RemoteException if object registration or export fails
  334. * @since 1.2
  335. */
  336. public static ActivationID exportObject(Remote obj,
  337. String location,
  338. MarshalledObject data,
  339. boolean restart,
  340. int port,
  341. RMIClientSocketFactory csf,
  342. RMIServerSocketFactory ssf)
  343. throws ActivationException, RemoteException
  344. {
  345. ActivationDesc desc = new ActivationDesc(obj.getClass().getName(),
  346. location, data, restart);
  347. ActivationID id = ActivationGroup.getSystem().registerObject(desc);
  348. Remote stub = exportObject(obj, id, port, csf, ssf);
  349. ActivationGroup.currentGroup().activeObject(id, obj);
  350. return id;
  351. }
  352. /**
  353. * Export the activatable remote object to the RMI runtime to make
  354. * the object available to receive incoming calls. The object is
  355. * exported on an anonymous port, if <code>port</code> is zero. <p>
  356. *
  357. * During activation, this <code>exportObject</code> method should
  358. * be invoked explicitly by an "activatable" object, that does not
  359. * extend the <code>Activatable</code> class. There is no need for objects
  360. * that do extend the <code>Activatable</code> class to invoke this
  361. * method directly; this method is called by the second constructor
  362. * above (which a subclass should invoke from its special activation
  363. * constructor).
  364. *
  365. * @return the stub for the activatable remote object
  366. * @param obj the remote object implementation
  367. * @param id the object's activation identifier
  368. * @param port the port on which the object is exported (an anonymous
  369. * port is used if port=0)
  370. * @exception RemoteException if object export fails
  371. * @since 1.2
  372. */
  373. public static Remote exportObject(Remote obj,
  374. ActivationID id,
  375. int port)
  376. throws RemoteException
  377. {
  378. Object[] args = new Object[] { id, new Integer(port) };
  379. return exportObject(obj, "ActivatableServerRef",
  380. idPortParamTypes, args);
  381. }
  382. /**
  383. * Export the activatable remote object to the RMI runtime to make
  384. * the object available to receive incoming calls. The object is
  385. * exported on an anonymous port, if <code>port</code> is zero. <p>
  386. *
  387. * During activation, this <code>exportObject</code> method should
  388. * be invoked explicitly by an "activatable" object, that does not
  389. * extend the <code>Activatable</code> class. There is no need for objects
  390. * that do extend the <code>Activatable</code> class to invoke this
  391. * method directly; this method is called by the second constructor
  392. * above (which a subclass should invoke from its special activation
  393. * constructor).
  394. *
  395. * @return the stub for the activatable remote object
  396. * @param obj the remote object implementation
  397. * @param id the object's activation identifier
  398. * @param port the port on which the object is exported (an anonymous
  399. * port is used if port=0)
  400. * @param csf the client-side socket factory for making calls to the
  401. * remote object
  402. * @param ssf the server-side socket factory for receiving remote calls
  403. * @exception RemoteException if object export fails
  404. * @since 1.2
  405. */
  406. public static Remote exportObject(Remote obj,
  407. ActivationID id,
  408. int port,
  409. RMIClientSocketFactory csf,
  410. RMIServerSocketFactory ssf)
  411. throws RemoteException
  412. {
  413. Object[] args = new Object[] { id, new Integer(port), csf, ssf };
  414. return exportObject(obj, "ActivatableServerRef",
  415. idPortFactoryParamTypes, args);
  416. }
  417. /**
  418. * Remove the remote object, obj, from the RMI runtime. If
  419. * successful, the object can no longer accept incoming RMI calls.
  420. * If the force parameter is true, the object is forcibly unexported
  421. * even if there are pending calls to the remote object or the
  422. * remote object still has calls in progress. If the force
  423. * parameter is false, the object is only unexported if there are
  424. * no pending or in progress calls to the object.
  425. *
  426. * @param obj the remote object to be unexported
  427. * @param force if true, unexports the object even if there are
  428. * pending or in-progress calls; if false, only unexports the object
  429. * if there are no pending or in-progress calls
  430. * @return true if operation is successful, false otherwise
  431. * @exception NoSuchObjectException if the remote object is not
  432. * currently exported
  433. * @since 1.2
  434. */
  435. public static boolean unexportObject(Remote obj, boolean force)
  436. throws NoSuchObjectException
  437. {
  438. return sun.rmi.transport.ObjectTable.unexportObject(obj, force);
  439. }
  440. /*
  441. * Create an instance of given server ref type with constructor chosen
  442. * by indicated paramters and supplied with given arguements, and
  443. * export remote object with it.
  444. *
  445. * All this code needs to be duplicated from UnicastRemoteObject
  446. * because java does not have "friends".
  447. */
  448. private static Remote exportObject(Remote obj, String refType,
  449. Class[] params, Object[] args)
  450. throws RemoteException
  451. {
  452. // compose name of server ref class and find it
  453. String refClassName = RemoteRef.packagePrefix + "." + refType;
  454. Class refClass;
  455. try {
  456. refClass = Class.forName(refClassName);
  457. } catch (ClassNotFoundException e) {
  458. throw new ExportException(
  459. "No class found for server ref type: " + refType);
  460. }
  461. if (!ServerRef.class.isAssignableFrom(refClass)) {
  462. throw new ExportException(
  463. "Server ref class not instance of " +
  464. ServerRef.class.getName() + ": " + refClass.getName());
  465. }
  466. // create server ref instance using given constructor and arguments
  467. ServerRef serverRef;
  468. try {
  469. java.lang.reflect.Constructor cons =
  470. refClass.getConstructor(params);
  471. serverRef = (ServerRef) cons.newInstance(args);
  472. // if impl does extend Activatable, set its ref
  473. if (obj instanceof Activatable)
  474. ((Activatable)obj).ref = serverRef;
  475. } catch (Exception e) {
  476. throw new ExportException(
  477. "Exception creating instance of server ref class: " +
  478. refClass.getName(), e);
  479. }
  480. return serverRef.exportObject(obj, null);
  481. }
  482. }