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