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