mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			532 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			532 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* Activatable.java -- A common ancestor for the activatable objects.
 | |
|    Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006
 | |
|    Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath 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 for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| 
 | |
| package java.rmi.activation;
 | |
| 
 | |
| import gnu.java.rmi.server.ActivatableServerRef;
 | |
| import gnu.java.rmi.server.UnicastServer;
 | |
| import gnu.java.rmi.server.UnicastServerRef;
 | |
| 
 | |
| import java.lang.reflect.Field;
 | |
| import java.rmi.MarshalledObject;
 | |
| import java.rmi.NoSuchObjectException;
 | |
| import java.rmi.Remote;
 | |
| import java.rmi.RemoteException;
 | |
| import java.rmi.server.ObjID;
 | |
| import java.rmi.server.RMIClientSocketFactory;
 | |
| import java.rmi.server.RMIServerSocketFactory;
 | |
| import java.rmi.server.RemoteObject;
 | |
| import java.rmi.server.RemoteServer;
 | |
| import java.rmi.server.UnicastRemoteObject;
 | |
| 
 | |
| /**
 | |
|  * A common ancestor for the implementations of the activatable objects. Such
 | |
|  * objects require persistent access over time and can be activated by the
 | |
|  * system. The derived classes also implements the needed interface of some
 | |
|  * remote object and usually have the two parameter constructor, the first
 | |
|  * parameter being the {@link ActivationID} and the second the
 | |
|  * {@link MarshalledObject}. Activatable is the main class that developers need
 | |
|  * to use to implement and manage activatable objects. It also contains methods
 | |
|  * for making activatable remote objects that are not derived from the
 | |
|  * Activatable class.
 | |
|  *
 | |
|  * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub)
 | |
|  */
 | |
| public abstract class Activatable
 | |
|     extends RemoteServer
 | |
| {
 | |
| 
 | |
|   /**
 | |
|    * Use SVUID for interoperability.
 | |
|    */
 | |
|   static final long serialVersionUID = - 3120617863591563455L;
 | |
| 
 | |
|   /**
 | |
|    * The object activation id.
 | |
|    */
 | |
|   final ActivationID id;
 | |
| 
 | |
|   /**
 | |
|    * This constructor is used to register export the object on the given port. A
 | |
|    * subclass of the Activatable class calls this constructor to register and
 | |
|    * export the object during initial construction. As a side-effect of
 | |
|    * activatable object construction, the remote object is both "registered"
 | |
|    * with the activation system and "exported" (on an anonymous port, if port is
 | |
|    * zero) to the RMI runtime so that it is available to accept incoming calls
 | |
|    * from clients.
 | |
|    *
 | |
|    * @param codebase the object code base url
 | |
|    * @param data the data, needed to activate the object.
 | |
|    * @param restart specifies reactivation mode after crash. If true, the object
 | |
|    *          is activated when activator is restarted or the activation group
 | |
|    *          is restarted. If false, the object is only activated on demand.
 | |
|    *          This flag does has no effect during the normal operation (the
 | |
|    *          object is normally activated on demand).
 | |
|    * @param port the port, on which the object will become available. The value
 | |
|    *          0 means anonymous port.
 | |
|    * @throws ActivationException if the activation failed
 | |
|    * @throws RemoteException if the remote call failed.
 | |
|    */
 | |
|   protected Activatable(String codebase, MarshalledObject<?> data,
 | |
|                         boolean restart, int port) throws ActivationException,
 | |
|       RemoteException
 | |
|   {
 | |
|     ActivationDesc descriptor = new ActivationDesc(getClass().getName(),
 | |
|                                                    codebase, data, restart);
 | |
|     id = obtainId(descriptor);
 | |
|     exportObject(this, id, port);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This constructor is used to register export the object on the given port,
 | |
|    * additionally specifying the socket factories. A subclass of the Activatable
 | |
|    * class calls this constructor to register and export the object during
 | |
|    * initial construction.
 | |
|    *
 | |
|    * @param codebase the object code base url
 | |
|    * @param data the data, needed to activate the object.
 | |
|    * @param restart specifies reactivation mode after crash. If true, the object
 | |
|    *          is activated when activator is restarted or the activation group
 | |
|    *          is restarted. If false, the object is only activated on demand.
 | |
|    *          This flag does has no effect during the normal operation (the
 | |
|    *          object is normally activated on demand).
 | |
|    * @param port the port, on which the object will become available. The value
 | |
|    *          0 means anonymous port.
 | |
|    * @param csf the client socket factory
 | |
|    * @param ssf the server socket factory
 | |
|    * @throws ActivationException if the activation failed
 | |
|    * @throws RemoteException if the remote call failed.
 | |
|    */
 | |
|   protected Activatable(String codebase, MarshalledObject<?> data,
 | |
|                         boolean restart, int port, RMIClientSocketFactory csf,
 | |
|                         RMIServerSocketFactory ssf) throws ActivationException,
 | |
|       RemoteException
 | |
|   {
 | |
|     ActivationDesc descriptor = new ActivationDesc(getClass().getName(),
 | |
|                                                    codebase, data, restart);
 | |
|     id = obtainId(descriptor);
 | |
|     exportObject(this, id, port);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates the new instance of activatable with the given activation id and is
 | |
|    * listening at the given port. A subclass of the Activatable class calls this
 | |
|    * constructor when the object itself is activated via its special
 | |
|    * "activation" constructor with the two parameters ({@link ActivationID},
 | |
|    * {@link MarshalledObject}). As a side effect, the object is exported and is
 | |
|    * available to accept incoming calls.
 | |
|    *
 | |
|    * @param anId the activation id
 | |
|    * @param port the port, on which the activatable will be listening
 | |
|    * @throws RemoteException if the activation failed.
 | |
|    */
 | |
|   protected Activatable(ActivationID anId, int port) throws RemoteException
 | |
|   {
 | |
|     id = anId;
 | |
|     try
 | |
|       {
 | |
|         exportObject(this, anId, port);
 | |
|       }
 | |
|     catch (Exception e)
 | |
|       {
 | |
|         e.printStackTrace();
 | |
|         RemoteException acex =
 | |
|           new RemoteException("cannot export Activatable", e);
 | |
|         throw acex;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates the new instance of activatable with the given activation id and is
 | |
|    * listening at the given port, using the specified client and server sockets
 | |
|    * factories. A subclass of the Activatable class calls this
 | |
|    * constructor when the object itself is activated via its special
 | |
|    * "activation" constructor with the two parameters ({@link ActivationID},
 | |
|    * {@link MarshalledObject}). As a side effect, the object is exported and is
 | |
|    * available to accept incoming calls.
 | |
|    *
 | |
|    * @param anId the activation id
 | |
|    * @param port the port, on which the activatable will be listening
 | |
|    * @param csf the client socket factory
 | |
|    * @param ssf the server socket factory
 | |
|    *
 | |
|    * @throws RemoteException if the remote call failed
 | |
|    */
 | |
|   protected Activatable(ActivationID anId, int port, RMIClientSocketFactory csf,
 | |
|                         RMIServerSocketFactory ssf) throws RemoteException
 | |
|   {
 | |
|     id = anId;
 | |
|     try
 | |
|       {
 | |
|         exportObject(this, anId, port, csf, ssf);
 | |
|       }
 | |
|     catch (Exception e)
 | |
|       {
 | |
|         RemoteException acex = new RemoteException();
 | |
|         acex.initCause(e);
 | |
|         throw acex;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get the objects activation identifier.
 | |
|    *
 | |
|    * @return the object activation identifier
 | |
|    */
 | |
|   protected ActivationID getID()
 | |
|   {
 | |
|     return id;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Obtain the activation Id from the activation descriptor by registering
 | |
|    * within the current group.
 | |
|    */
 | |
|   static ActivationID obtainId(ActivationDesc descriptor)
 | |
|       throws RemoteException, UnknownGroupException, ActivationException
 | |
|   {
 | |
|     ActivationGroupID id = descriptor.getGroupID();
 | |
|     ActivationSystem system;
 | |
| 
 | |
|     if (id != null)
 | |
|       system = id.getSystem();
 | |
|     else
 | |
|       system = ActivationGroup.currentGroupID().getSystem();
 | |
|     return system.registerObject(descriptor);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This method registers an activatable object. The object is expected to be
 | |
|    * on the anonymous port (null client and server socket factories).
 | |
|    *
 | |
|    * @param desc the object description.
 | |
|    * @return the remote stub for the activatable object (the first call on this
 | |
|    *         stub will activate the object).
 | |
|    * @throws UnknownGroupException if the object group identifier is unknown
 | |
|    * @throws ActivationException if the activation system is not running
 | |
|    * @throws RemoteException if the remote call fails
 | |
|    */
 | |
|   public static Remote register(ActivationDesc desc)
 | |
|       throws UnknownGroupException, ActivationException, RemoteException
 | |
|   {
 | |
|     ActivationID id = obtainId(desc);
 | |
|     try
 | |
|       {
 | |
|         return toStub(
 | |
|                       id,
 | |
|                       Thread.currentThread().getContextClassLoader().loadClass(
 | |
|                         desc.getClassName()));
 | |
|       }
 | |
|     catch (ClassNotFoundException e)
 | |
|       {
 | |
|         throw new ActivationException("Class not found: "+desc.getClassName());
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Inactivates and unexports the object. The subsequent calls will activate
 | |
|    * the object again. The object is not inactivated if it is currently
 | |
|    * executing calls.
 | |
|    *
 | |
|    * @param id the id of the object being inactivated
 | |
|    * @return true if the object has been inactivated, false if it has not been
 | |
|    *         inactivated because of the running or pending calls.
 | |
|    * @throws UnknownObjectException if the object is unknown.
 | |
|    * @throws ActivationException if the object group is not active
 | |
|    * @throws RemoteException if the remote call fails
 | |
|    */
 | |
|   public static boolean inactive(ActivationID id)
 | |
|       throws UnknownObjectException, ActivationException, RemoteException
 | |
|   {
 | |
|     if (id.group!=null)
 | |
|       id.group.inactiveObject(id);
 | |
|     return UnicastRemoteObject.unexportObject(id.activate(false), false);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Unregister the object (the object will no longer be activable with that id)
 | |
|    *
 | |
|    * @param id the object id
 | |
|    * @throws UnknownObjectException if the id is unknown
 | |
|    * @throws ActivationException if the activation system is not running
 | |
|    * @throws RemoteException if the remote call fails.
 | |
|    */
 | |
|   public static void unregister(ActivationID id) throws UnknownObjectException,
 | |
|       ActivationException, RemoteException
 | |
|   {
 | |
|     ActivationGroup.currentGroupId.getSystem().unregisterObject(id);
 | |
|     UnicastServer.unregisterActivatable(id);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Register and export the object that activatable object that is not derived
 | |
|    * from the Activatable super class. It creates and registers the object
 | |
|    * activation descriptor. There is no need to call this method if the object
 | |
|    * extends Activable, as its work is done in the constructor
 | |
|    * {@link #Activatable(String, MarshalledObject, boolean, int)}.
 | |
|    *
 | |
|    * @param obj the object, that is exported, becoming available at the given
 | |
|    *          port.
 | |
|    * @param location the object code location (codebase).
 | |
|    * @param data the data, needed to activate the object
 | |
|    * @param restart the restart mode
 | |
|    * @param port the port, where the object will be available
 | |
|    *
 | |
|    * @return the created object activation ID.
 | |
|    *
 | |
|    * @throws ActivationException if the activation group is not active
 | |
|    * @throws RemoteException if the registration or export fails
 | |
|    */
 | |
|   public static ActivationID exportObject(Remote obj, String location,
 | |
|                                           MarshalledObject<?> data,
 | |
|                                           boolean restart, int port)
 | |
|       throws ActivationException, RemoteException
 | |
|   {
 | |
|     ActivationDesc descriptor = new ActivationDesc(obj.getClass().getName(),
 | |
|                                                    location, data, restart);
 | |
|     ActivationID id = obtainId(descriptor);
 | |
|     Remote stub = exportObject(obj, id, port);
 | |
|     return id;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Register and export the object that activatable object that is not derived
 | |
|    * from the Activatable super class. It creates and registers the object
 | |
|    * activation descriptor. There is no need to call this method if the object
 | |
|    * extends Activable, as its work is done in the constructor
 | |
|    * {@link #Activatable(String, MarshalledObject, boolean, int, RMIClientSocketFactory, RMIServerSocketFactory)}
 | |
|    *
 | |
|    * @param obj the object, that is exported, becoming available at the given
 | |
|    *          port.
 | |
|    * @param location the object code location (codebase).
 | |
|    * @param data the data, needed to activate the object
 | |
|    * @param restart the restart mode
 | |
|    * @param port the port, where the object will be available
 | |
|    * @param csf the client socket factory
 | |
|    * @param ssf the server socket factory
 | |
|    *
 | |
|    * @return the created object activation ID.
 | |
|    *
 | |
|    * @throws ActivationException if the activation group is not active
 | |
|    * @throws RemoteException if the registration or export fails
 | |
|    */
 | |
|   public static ActivationID exportObject(Remote obj, String location,
 | |
|                                           MarshalledObject data,
 | |
|                                           boolean restart, int port,
 | |
|                                           RMIClientSocketFactory csf,
 | |
|                                           RMIServerSocketFactory ssf)
 | |
|       throws ActivationException, RemoteException
 | |
|   {
 | |
|     ActivationDesc descriptor = new ActivationDesc(obj.getClass().getName(),
 | |
|                                                    location, data, restart);
 | |
|     ActivationID id = obtainId(descriptor);
 | |
|     Remote stub = exportObject(obj, id, port, csf, ssf);
 | |
|     return id;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * During activation, this exportObject method should be invoked explicitly by
 | |
|    * the activatable object, that does is not derived from the Activatable
 | |
|    * class. There is no need to call this method if the object extends
 | |
|    * Activable, as its work is done in the constructor
 | |
|    * {@link #Activatable(ActivationID, int)}
 | |
|    *
 | |
|    * @param obj the object
 | |
|    * @param id the known activation id
 | |
|    * @param port the object port
 | |
|    *
 | |
|    * @return the remote stub of the activatable object
 | |
|    *
 | |
|    * @throws RemoteException if the object export fails
 | |
|    */
 | |
|   public static Remote exportObject(Remote obj, ActivationID id, int port)
 | |
|       throws RemoteException
 | |
|   {
 | |
|     Remote stub = export(id, obj, port, null);
 | |
|     return stub;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * During activation, this exportObject method should be invoked explicitly by
 | |
|    * the activatable object, that does is not derived from the Activatable
 | |
|    * class. There is no need to call this method if the object extends
 | |
|    * Activable, as its work is done in the constructor
 | |
|    * {@link #Activatable(ActivationID, int)}
 | |
|    *
 | |
|    * @param obj the object
 | |
|    * @param id the known activation id
 | |
|    * @param port the object port
 | |
|    * @param csf the client socket factory
 | |
|    * @param ssf the server socket factory
 | |
|    *
 | |
|    * @return the remote stub of the activatable object
 | |
|    *
 | |
|    * @throws RemoteException if the object export fails
 | |
|    */
 | |
|   public static Remote exportObject(Remote obj, ActivationID id, int port,
 | |
|                                     RMIClientSocketFactory csf,
 | |
|                                     RMIServerSocketFactory ssf)
 | |
|       throws RemoteException
 | |
|   {
 | |
|     Remote stub = export(id, obj, port, ssf);
 | |
|     return stub;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Make the remote object unavailable for incoming calls. This method also
 | |
|    * unregisters the object, so it cannot be activated again by incoming call
 | |
|    * (unless registered).
 | |
|    *
 | |
|    * @param obj the object to unexport
 | |
|    * @param force if true, cancel all pending or running calls to that object
 | |
|    *          (if false, the object with such calls is not unexported and false
 | |
|    *          is returned by this method).
 | |
|    * @return if the object was successfully unexported, false otherwise
 | |
|    * @throws NoSuchObjectException if such object is not known
 | |
|    */
 | |
|   public static boolean unexportObject(Remote obj, boolean force)
 | |
|       throws NoSuchObjectException
 | |
|   {
 | |
|     Object aref = UnicastServer.getExportedRef(obj);
 | |
| 
 | |
|     // Unregister it also (otherwise will be activated during the subsequent
 | |
|     // call.
 | |
|     if (aref instanceof ActivatableServerRef)
 | |
|       {
 | |
|         ActivatableServerRef aar = (ActivatableServerRef) aref;
 | |
|         UnicastServer.unregisterActivatable(aar.actId);
 | |
|       }
 | |
|     return UnicastRemoteObject.unexportObject(obj, force);
 | |
|   }
 | |
| 
 | |
|   static Remote exportObject(Remote obj, int port,
 | |
|                              RMIServerSocketFactory serverSocketFactory)
 | |
|     throws RemoteException
 | |
|   {
 | |
|     UnicastServerRef sref = null;
 | |
|     if (obj instanceof RemoteObject)
 | |
|       sref = (UnicastServerRef) ((RemoteObject) obj).getRef();
 | |
| 
 | |
|     if (sref == null)
 | |
|       sref = new UnicastServerRef(new ObjID(), port, serverSocketFactory);
 | |
| 
 | |
|     Remote stub = sref.exportObject(obj);
 | |
|     // addStub(obj, stub);
 | |
|     // TODO Need to change the place of the stub repository
 | |
|     return stub;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Create and export the new remote object, making it available at the given
 | |
|    * port, using sockets, produced by the specified factories.
 | |
|    *
 | |
|    * @param port the port, on that the object should become available. Zero
 | |
|    *          means anonymous port.
 | |
|    * @param serverSocketFactory the server socket factory
 | |
|    */
 | |
|   private static Remote export(ActivationID id, Remote obj, int port,
 | |
|                                RMIServerSocketFactory serverSocketFactory)
 | |
|       throws RemoteException
 | |
|   {
 | |
|     ActivatableServerRef sref = null;
 | |
|     sref = new ActivatableServerRef(makeId(id), id, port, serverSocketFactory);
 | |
|     return sref.exportObject(obj);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Make the object ID from the activation ID. The same activation ID always
 | |
|    * produces the identical object id.
 | |
|    *
 | |
|    * @param aid the activation id
 | |
|    *
 | |
|    * @return the object id
 | |
|    */
 | |
|   private static ObjID makeId(ActivationID aid)
 | |
|   {
 | |
|     ObjID id = new ObjID(0);
 | |
| 
 | |
|     // The fields of both ObjID and ActivationID must be package private,
 | |
|     // so we need to use the reflection to access them anyway.
 | |
|     // Probably other implementations use some very different approach.
 | |
| 
 | |
|     try
 | |
|       {
 | |
|         Field idUid =  ObjID.class.getDeclaredField("space");
 | |
|         Field aidUid = ActivationID.class.getDeclaredField("uid");
 | |
| 
 | |
|         aidUid.setAccessible(true);
 | |
|         idUid.setAccessible(true);
 | |
| 
 | |
|         idUid.set(id, aidUid.get(aid));
 | |
|       }
 | |
|     catch (Exception e)
 | |
|       {
 | |
|         InternalError ierr = new InternalError("Unable to set UID field");
 | |
|         ierr.initCause(e);
 | |
|         throw ierr;
 | |
|       }
 | |
| 
 | |
|     return id;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Connect the object to the UnicastServer (export), but not activate it.
 | |
|    * The object will be activated on the first call.
 | |
|    */
 | |
|   static Remote toStub(ActivationID anId, Class stubFor)
 | |
|   {
 | |
|     try
 | |
|       {
 | |
|         ActivatableServerRef asr =
 | |
|           new ActivatableServerRef(makeId(anId), anId, 0, null);
 | |
|         UnicastServer.exportActivatableObject(asr);
 | |
|         return asr.exportClass(stubFor);
 | |
|       }
 | |
|     catch (RemoteException e)
 | |
|       {
 | |
|         InternalError ierr = new InternalError(
 | |
|           "Failed to obtain activatable stub");
 | |
|         ierr.initCause(e);
 | |
|         throw ierr;
 | |
|       }
 | |
|   }
 | |
| }
 |