| /* |
| * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package java.rmi.activation; |
| |
| import java.rmi.MarshalledObject; |
| import java.rmi.NoSuchObjectException; |
| import java.rmi.Remote; |
| import java.rmi.RemoteException; |
| import java.rmi.activation.UnknownGroupException; |
| import java.rmi.activation.UnknownObjectException; |
| import java.rmi.server.RMIClientSocketFactory; |
| import java.rmi.server.RMIServerSocketFactory; |
| import java.rmi.server.RemoteServer; |
| import sun.rmi.server.ActivatableServerRef; |
| |
| /** |
| * The <code>Activatable</code> class provides support for remote |
| * objects that require persistent access over time and that |
| * can be activated by the system. |
| * |
| * <p>For the constructors and static <code>exportObject</code> methods, |
| * the stub for a remote object being exported is obtained as described in |
| * {@link java.rmi.server.UnicastRemoteObject}. |
| * |
| * <p>An attempt to serialize explicitly an instance of this class will |
| * fail. |
| * |
| * @author Ann Wollrath |
| * @since 1.2 |
| * @serial exclude |
| */ |
| public abstract class Activatable extends RemoteServer { |
| |
| private ActivationID id; |
| /** indicate compatibility with the Java 2 SDK v1.2 version of class */ |
| private static final long serialVersionUID = -3120617863591563455L; |
| |
| /** |
| * Constructs an activatable remote object by registering |
| * an activation descriptor (with the specified location, data, and |
| * restart mode) for this object, and exporting the object with the |
| * specified port. |
| * |
| * <p><strong>Note:</strong> Using the <code>Activatable</code> |
| * constructors that both register and export an activatable remote |
| * object is strongly discouraged because the actions of registering |
| * and exporting the remote object are <i>not</i> guaranteed to be |
| * atomic. Instead, an application should register an activation |
| * descriptor and export a remote object separately, so that exceptions |
| * can be handled properly. |
| * |
| * <p>This method invokes the {@link |
| * #exportObject(Remote,String,MarshalledObject,boolean,int) |
| * exportObject} method with this object, and the specified location, |
| * data, restart mode, and port. Subsequent calls to {@link #getID} |
| * will return the activation identifier returned from the call to |
| * <code>exportObject</code>. |
| * |
| * @param location the location for classes for this object |
| * @param data the object's initialization data |
| * @param port the port on which the object is exported (an anonymous |
| * port is used if port=0) |
| * @param restart if true, the object is restarted (reactivated) when |
| * either the activator is restarted or the object's activation group |
| * is restarted after an unexpected crash; if false, the object is only |
| * activated on demand. Specifying <code>restart</code> to be |
| * <code>true</code> does not force an initial immediate activation of |
| * a newly registered object; initial activation is lazy. |
| * @exception ActivationException if object registration fails. |
| * @exception RemoteException if either of the following fails: |
| * a) registering the object with the activation system or b) exporting |
| * the object to the RMI runtime. |
| * @since 1.2 |
| **/ |
| protected Activatable(String location, |
| MarshalledObject<?> data, |
| boolean restart, |
| int port) |
| throws ActivationException, RemoteException |
| { |
| super(); |
| id = exportObject(this, location, data, restart, port); |
| } |
| |
| /** |
| * Constructs an activatable remote object by registering |
| * an activation descriptor (with the specified location, data, and |
| * restart mode) for this object, and exporting the object with the |
| * specified port, and specified client and server socket factories. |
| * |
| * <p><strong>Note:</strong> Using the <code>Activatable</code> |
| * constructors that both register and export an activatable remote |
| * object is strongly discouraged because the actions of registering |
| * and exporting the remote object are <i>not</i> guaranteed to be |
| * atomic. Instead, an application should register an activation |
| * descriptor and export a remote object separately, so that exceptions |
| * can be handled properly. |
| * |
| * <p>This method invokes the {@link |
| * #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory) |
| * exportObject} method with this object, and the specified location, |
| * data, restart mode, port, and client and server socket factories. |
| * Subsequent calls to {@link #getID} will return the activation |
| * identifier returned from the call to <code>exportObject</code>. |
| * |
| * @param location the location for classes for this object |
| * @param data the object's initialization data |
| * @param restart if true, the object is restarted (reactivated) when |
| * either the activator is restarted or the object's activation group |
| * is restarted after an unexpected crash; if false, the object is only |
| * activated on demand. Specifying <code>restart</code> to be |
| * <code>true</code> does not force an initial immediate activation of |
| * a newly registered object; initial activation is lazy. |
| * @param port the port on which the object is exported (an anonymous |
| * port is used if port=0) |
| * @param csf the client-side socket factory for making calls to the |
| * remote object |
| * @param ssf the server-side socket factory for receiving remote calls |
| * @exception ActivationException if object registration fails. |
| * @exception RemoteException if either of the following fails: |
| * a) registering the object with the activation system or b) exporting |
| * the object to the RMI runtime. |
| * @since 1.2 |
| **/ |
| protected Activatable(String location, |
| MarshalledObject<?> data, |
| boolean restart, |
| int port, |
| RMIClientSocketFactory csf, |
| RMIServerSocketFactory ssf) |
| throws ActivationException, RemoteException |
| { |
| super(); |
| id = exportObject(this, location, data, restart, port, csf, ssf); |
| } |
| |
| /** |
| * Constructor used to activate/export the object on a specified |
| * port. An "activatable" remote object must have a constructor that |
| * takes two arguments: <ul> |
| * <li>the object's activation identifier (<code>ActivationID</code>), and |
| * <li>the object's initialization data (a <code>MarshalledObject</code>). |
| * </ul><p> |
| * |
| * A concrete subclass of this class must call this constructor when it is |
| * <i>activated</i> via the two parameter constructor described above. As |
| * a side-effect of construction, the remote object is "exported" |
| * to the RMI runtime (on the specified <code>port</code>) and is |
| * available to accept incoming calls from clients. |
| * |
| * @param id activation identifier for the object |
| * @param port the port number on which the object is exported |
| * @exception RemoteException if exporting the object to the RMI |
| * runtime fails |
| * @since 1.2 |
| */ |
| protected Activatable(ActivationID id, int port) |
| throws RemoteException |
| { |
| super(); |
| this.id = id; |
| exportObject(this, id, port); |
| } |
| |
| /** |
| * Constructor used to activate/export the object on a specified |
| * port. An "activatable" remote object must have a constructor that |
| * takes two arguments: <ul> |
| * <li>the object's activation identifier (<code>ActivationID</code>), and |
| * <li>the object's initialization data (a <code>MarshalledObject</code>). |
| * </ul><p> |
| * |
| * A concrete subclass of this class must call this constructor when it is |
| * <i>activated</i> via the two parameter constructor described above. As |
| * a side-effect of construction, the remote object is "exported" |
| * to the RMI runtime (on the specified <code>port</code>) and is |
| * available to accept incoming calls from clients. |
| * |
| * @param id activation identifier for the object |
| * @param port the port number on which the object is exported |
| * @param csf the client-side socket factory for making calls to the |
| * remote object |
| * @param ssf the server-side socket factory for receiving remote calls |
| * @exception RemoteException if exporting the object to the RMI |
| * runtime fails |
| * @since 1.2 |
| */ |
| protected Activatable(ActivationID id, int port, |
| RMIClientSocketFactory csf, |
| RMIServerSocketFactory ssf) |
| throws RemoteException |
| { |
| super(); |
| this.id = id; |
| exportObject(this, id, port, csf, ssf); |
| } |
| |
| /** |
| * Returns the object's activation identifier. The method is |
| * protected so that only subclasses can obtain an object's |
| * identifier. |
| * @return the object's activation identifier |
| * @since 1.2 |
| */ |
| protected ActivationID getID() { |
| return id; |
| } |
| |
| /** |
| * Register an object descriptor for an activatable remote |
| * object so that is can be activated on demand. |
| * |
| * @param desc the object's descriptor |
| * @return the stub for the activatable remote object |
| * @exception UnknownGroupException if group id in <code>desc</code> |
| * is not registered with the activation system |
| * @exception ActivationException if activation system is not running |
| * @exception RemoteException if remote call fails |
| * @since 1.2 |
| */ |
| public static Remote register(ActivationDesc desc) |
| throws UnknownGroupException, ActivationException, RemoteException |
| { |
| // register object with activator. |
| ActivationID id = |
| ActivationGroup.getSystem().registerObject(desc); |
| return sun.rmi.server.ActivatableRef.getStub(desc, id); |
| } |
| |
| /** |
| * Informs the system that the object with the corresponding activation |
| * <code>id</code> is currently inactive. If the object is currently |
| * active, the object is "unexported" from the RMI runtime (only if |
| * there are no pending or in-progress calls) |
| * so the that it can no longer receive incoming calls. This call |
| * informs this VM's ActivationGroup that the object is inactive, |
| * that, in turn, informs its ActivationMonitor. If this call |
| * completes successfully, a subsequent activate request to the activator |
| * will cause the object to reactivate. The operation may still |
| * succeed if the object is considered active but has already |
| * unexported itself. |
| * |
| * @param id the object's activation identifier |
| * @return true if the operation succeeds (the operation will |
| * succeed if the object in currently known to be active and is |
| * either already unexported or is currently exported and has no |
| * pending/executing calls); false is returned if the object has |
| * pending/executing calls in which case it cannot be deactivated |
| * @exception UnknownObjectException if object is not known (it may |
| * already be inactive) |
| * @exception ActivationException if group is not active |
| * @exception RemoteException if call informing monitor fails |
| * @since 1.2 |
| */ |
| public static boolean inactive(ActivationID id) |
| throws UnknownObjectException, ActivationException, RemoteException |
| { |
| return ActivationGroup.currentGroup().inactiveObject(id); |
| } |
| |
| /** |
| * Revokes previous registration for the activation descriptor |
| * associated with <code>id</code>. An object can no longer be |
| * activated via that <code>id</code>. |
| * |
| * @param id the object's activation identifier |
| * @exception UnknownObjectException if object (<code>id</code>) is unknown |
| * @exception ActivationException if activation system is not running |
| * @exception RemoteException if remote call to activation system fails |
| * @since 1.2 |
| */ |
| public static void unregister(ActivationID id) |
| throws UnknownObjectException, ActivationException, RemoteException |
| { |
| ActivationGroup.getSystem().unregisterObject(id); |
| } |
| |
| /** |
| * Registers an activation descriptor (with the specified location, |
| * data, and restart mode) for the specified object, and exports that |
| * object with the specified port. |
| * |
| * <p><strong>Note:</strong> Using this method (as well as the |
| * <code>Activatable</code> constructors that both register and export |
| * an activatable remote object) is strongly discouraged because the |
| * actions of registering and exporting the remote object are |
| * <i>not</i> guaranteed to be atomic. Instead, an application should |
| * register an activation descriptor and export a remote object |
| * separately, so that exceptions can be handled properly. |
| * |
| * <p>This method invokes the {@link |
| * #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory) |
| * exportObject} method with the specified object, location, data, |
| * restart mode, and port, and <code>null</code> for both client and |
| * server socket factories, and then returns the resulting activation |
| * identifier. |
| * |
| * @param obj the object being exported |
| * @param location the object's code location |
| * @param data the object's bootstrapping data |
| * @param restart if true, the object is restarted (reactivated) when |
| * either the activator is restarted or the object's activation group |
| * is restarted after an unexpected crash; if false, the object is only |
| * activated on demand. Specifying <code>restart</code> to be |
| * <code>true</code> does not force an initial immediate activation of |
| * a newly registered object; initial activation is lazy. |
| * @param port the port on which the object is exported (an anonymous |
| * port is used if port=0) |
| * @return the activation identifier obtained from registering the |
| * descriptor, <code>desc</code>, with the activation system |
| * the wrong group |
| * @exception ActivationException if activation group is not active |
| * @exception RemoteException if object registration or export fails |
| * @since 1.2 |
| **/ |
| public static ActivationID exportObject(Remote obj, |
| String location, |
| MarshalledObject<?> data, |
| boolean restart, |
| int port) |
| throws ActivationException, RemoteException |
| { |
| return exportObject(obj, location, data, restart, port, null, null); |
| } |
| |
| /** |
| * Registers an activation descriptor (with the specified location, |
| * data, and restart mode) for the specified object, and exports that |
| * object with the specified port, and the specified client and server |
| * socket factories. |
| * |
| * <p><strong>Note:</strong> Using this method (as well as the |
| * <code>Activatable</code> constructors that both register and export |
| * an activatable remote object) is strongly discouraged because the |
| * actions of registering and exporting the remote object are |
| * <i>not</i> guaranteed to be atomic. Instead, an application should |
| * register an activation descriptor and export a remote object |
| * separately, so that exceptions can be handled properly. |
| * |
| * <p>This method first registers an activation descriptor for the |
| * specified object as follows. It obtains the activation system by |
| * invoking the method {@link ActivationGroup#getSystem |
| * ActivationGroup.getSystem}. This method then obtains an {@link |
| * ActivationID} for the object by invoking the activation system's |
| * {@link ActivationSystem#registerObject registerObject} method with |
| * an {@link ActivationDesc} constructed with the specified object's |
| * class name, and the specified location, data, and restart mode. If |
| * an exception occurs obtaining the activation system or registering |
| * the activation descriptor, that exception is thrown to the caller. |
| * |
| * <p>Next, this method exports the object by invoking the {@link |
| * #exportObject(Remote,ActivationID,int,RMIClientSocketFactory,RMIServerSocketFactory) |
| * exportObject} method with the specified remote object, the |
| * activation identifier obtained from registration, the specified |
| * port, and the specified client and server socket factories. If an |
| * exception occurs exporting the object, this method attempts to |
| * unregister the activation identifier (obtained from registration) by |
| * invoking the activation system's {@link |
| * ActivationSystem#unregisterObject unregisterObject} method with the |
| * activation identifier. If an exception occurs unregistering the |
| * identifier, that exception is ignored, and the original exception |
| * that occurred exporting the object is thrown to the caller. |
| * |
| * <p>Finally, this method invokes the {@link |
| * ActivationGroup#activeObject activeObject} method on the activation |
| * group in this VM with the activation identifier and the specified |
| * remote object, and returns the activation identifier to the caller. |
| * |
| * @param obj the object being exported |
| * @param location the object's code location |
| * @param data the object's bootstrapping data |
| * @param restart if true, the object is restarted (reactivated) when |
| * either the activator is restarted or the object's activation group |
| * is restarted after an unexpected crash; if false, the object is only |
| * activated on demand. Specifying <code>restart</code> to be |
| * <code>true</code> does not force an initial immediate activation of |
| * a newly registered object; initial activation is lazy. |
| * @param port the port on which the object is exported (an anonymous |
| * port is used if port=0) |
| * @param csf the client-side socket factory for making calls to the |
| * remote object |
| * @param ssf the server-side socket factory for receiving remote calls |
| * @return the activation identifier obtained from registering the |
| * descriptor with the activation system |
| * @exception ActivationException if activation group is not active |
| * @exception RemoteException if object registration or export fails |
| * @since 1.2 |
| **/ |
| public static ActivationID exportObject(Remote obj, |
| String location, |
| MarshalledObject<?> data, |
| boolean restart, |
| int port, |
| RMIClientSocketFactory csf, |
| RMIServerSocketFactory ssf) |
| throws ActivationException, RemoteException |
| { |
| ActivationDesc desc = new ActivationDesc(obj.getClass().getName(), |
| location, data, restart); |
| /* |
| * Register descriptor. |
| */ |
| ActivationSystem system = ActivationGroup.getSystem(); |
| ActivationID id = system.registerObject(desc); |
| |
| /* |
| * Export object. |
| */ |
| try { |
| exportObject(obj, id, port, csf, ssf); |
| } catch (RemoteException e) { |
| /* |
| * Attempt to unregister activation descriptor because export |
| * failed and register/export should be atomic (see 4323621). |
| */ |
| try { |
| system.unregisterObject(id); |
| } catch (Exception ex) { |
| } |
| /* |
| * Report original exception. |
| */ |
| throw e; |
| } |
| |
| /* |
| * This call can't fail (it is a local call, and the only possible |
| * exception, thrown if the group is inactive, will not be thrown |
| * because the group is not inactive). |
| */ |
| ActivationGroup.currentGroup().activeObject(id, obj); |
| |
| return id; |
| } |
| |
| /** |
| * Export the activatable remote object to the RMI runtime to make |
| * the object available to receive incoming calls. The object is |
| * exported on an anonymous port, if <code>port</code> is zero. <p> |
| * |
| * During activation, this <code>exportObject</code> method should |
| * be invoked explicitly by an "activatable" object, that does not |
| * extend the <code>Activatable</code> class. There is no need for objects |
| * that do extend the <code>Activatable</code> class to invoke this |
| * method directly because the object is exported during construction. |
| * |
| * @return the stub for the activatable remote object |
| * @param obj the remote object implementation |
| * @param id the object's activation identifier |
| * @param port the port on which the object is exported (an anonymous |
| * port is used if port=0) |
| * @exception RemoteException if object export fails |
| * @since 1.2 |
| */ |
| public static Remote exportObject(Remote obj, |
| ActivationID id, |
| int port) |
| throws RemoteException |
| { |
| return exportObject(obj, new ActivatableServerRef(id, port)); |
| } |
| |
| /** |
| * Export the activatable remote object to the RMI runtime to make |
| * the object available to receive incoming calls. The object is |
| * exported on an anonymous port, if <code>port</code> is zero. <p> |
| * |
| * During activation, this <code>exportObject</code> method should |
| * be invoked explicitly by an "activatable" object, that does not |
| * extend the <code>Activatable</code> class. There is no need for objects |
| * that do extend the <code>Activatable</code> class to invoke this |
| * method directly because the object is exported during construction. |
| * |
| * @return the stub for the activatable remote object |
| * @param obj the remote object implementation |
| * @param id the object's activation identifier |
| * @param port the port on which the object is exported (an anonymous |
| * port is used if port=0) |
| * @param csf the client-side socket factory for making calls to the |
| * remote object |
| * @param ssf the server-side socket factory for receiving remote calls |
| * @exception RemoteException if object export fails |
| * @since 1.2 |
| */ |
| public static Remote exportObject(Remote obj, |
| ActivationID id, |
| int port, |
| RMIClientSocketFactory csf, |
| RMIServerSocketFactory ssf) |
| throws RemoteException |
| { |
| return exportObject(obj, new ActivatableServerRef(id, port, csf, ssf)); |
| } |
| |
| /** |
| * Remove the remote object, obj, from the RMI runtime. If |
| * successful, the object can no longer accept incoming RMI calls. |
| * If the force parameter is true, the object is forcibly unexported |
| * even if there are pending calls to the remote object or the |
| * remote object still has calls in progress. If the force |
| * parameter is false, the object is only unexported if there are |
| * no pending or in progress calls to the object. |
| * |
| * @param obj the remote object to be unexported |
| * @param force if true, unexports the object even if there are |
| * pending or in-progress calls; if false, only unexports the object |
| * if there are no pending or in-progress calls |
| * @return true if operation is successful, false otherwise |
| * @exception NoSuchObjectException if the remote object is not |
| * currently exported |
| * @since 1.2 |
| */ |
| public static boolean unexportObject(Remote obj, boolean force) |
| throws NoSuchObjectException |
| { |
| return sun.rmi.transport.ObjectTable.unexportObject(obj, force); |
| } |
| |
| /** |
| * Exports the specified object using the specified server ref. |
| */ |
| private static Remote exportObject(Remote obj, ActivatableServerRef sref) |
| throws RemoteException |
| { |
| // if obj extends Activatable, set its ref. |
| if (obj instanceof Activatable) { |
| ((Activatable) obj).ref = sref; |
| |
| } |
| return sref.exportObject(obj, null, false); |
| } |
| } |