diff options
Diffstat (limited to 'libjava/classpath/gnu/java/rmi/activation')
4 files changed, 846 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/rmi/activation/ActivationSystemTransient.java b/libjava/classpath/gnu/java/rmi/activation/ActivationSystemTransient.java new file mode 100644 index 00000000000..1557220e102 --- /dev/null +++ b/libjava/classpath/gnu/java/rmi/activation/ActivationSystemTransient.java @@ -0,0 +1,406 @@ +/* ActivationSystemTransient.java -- The transient RMI object activation system. + Copyright (C) 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 gnu.java.rmi.activation; + +import java.rmi.MarshalledObject; +import java.rmi.RemoteException; +import java.rmi.activation.ActivationDesc; +import java.rmi.activation.ActivationException; +import java.rmi.activation.ActivationGroup; +import java.rmi.activation.ActivationGroupDesc; +import java.rmi.activation.ActivationGroupID; +import java.rmi.activation.ActivationID; +import java.rmi.activation.ActivationInstantiator; +import java.rmi.activation.ActivationMonitor; +import java.rmi.activation.ActivationSystem; +import java.rmi.activation.Activator; +import java.rmi.activation.UnknownGroupException; +import java.rmi.activation.UnknownObjectException; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + +/** + * Provides the default transient activation system. + * + * @author Audrius Meskauskas (audriusa@bioinformatics.org) + */ +public class ActivationSystemTransient + extends DefaultActivationSystem + implements ActivationSystem, ActivationMonitor, Activator +{ + /** + * Maps group identifiers into group descriptions. + */ + protected final BidiTable groupDescs; + + /** + * Maps object identifiers into object activation descriptions + */ + protected final BidiTable descriptions; + + /** + * Maps group identifiers into already activated groups. + */ + protected transient final Map groupInstantiators = new Hashtable(); + + /** + * The cache of the activated objects, maps activation ids to remote + * object stubs. + */ + protected transient final Map activatedObjects = new HashMap(); + + /** + * The object incarnation counter. + */ + static long groupIncarnations = 0; + + /** + * The singleton of this activation system + */ + static ActivationSystem singleton; + + /** + * Set to true to print the event messages to console. + */ + public static boolean debug = false; + + + /** + * Creates the group which uses the given maps to store the data. + */ + protected ActivationSystemTransient(BidiTable objectDescriptions, + BidiTable groupDescriptiopns) + { + descriptions = objectDescriptions; + groupDescs = groupDescriptiopns; + } + + /** + * Creates the group with transient maps. + */ + protected ActivationSystemTransient() + { + this (new BidiTable(), new BidiTable()); + } + + public static ActivationSystem getInstance() + { + if (singleton == null) + singleton = new ActivationSystemTransient(); + return singleton; + } + + /** + * Activate the given object (try cache first if force = false) + */ + public MarshalledObject activate(ActivationID id, boolean force) + throws ActivationException, UnknownObjectException, RemoteException + { + if (! force) + { + synchronized (activatedObjects) + { + MarshalledObject object = (MarshalledObject) activatedObjects.get(id); + if (object != null) + return object; + } + } + + ActivationDesc desc = (ActivationDesc) descriptions.get(id); + if (desc == null) + throw new UnknownObjectException("Activating unknown object "+ + id == null ? "null" : id.toString()); + + ActivationInstantiator group = + (ActivationInstantiator) groupInstantiators.get(desc.getGroupID()); + + if (group == null) + { + // The group is not active - must be activated. + ActivationGroupID gid = desc.getGroupID(); + ActivationGroupDesc adesc = (ActivationGroupDesc) groupDescs.get(gid); + + if (adesc == null) + throw new UnknownGroupException("Activating unknown group " + + gid + " for "+ id+" this "+this); + + synchronized (ActivationSystemTransient.class) + { + groupIncarnations++; + } + + group = ActivationGroup.createGroup(gid, adesc, groupIncarnations); + activeGroup(gid, group, groupIncarnations); + } + + MarshalledObject object = group.newInstance(id, desc); + + synchronized (activatedObjects) + { + activatedObjects.put(id, object); + } + return object; + } + + /** + * Returns the activation monitor (THIS) and remebers the instantiator, used + * by that group. + */ + public ActivationMonitor activeGroup(ActivationGroupID id, + ActivationInstantiator group, + long incarnation) + throws UnknownGroupException, ActivationException, RemoteException + { + groupInstantiators.put(id, group); + return this; + } + + /** + * Get the activation descriptor for the given activation id. + * + * @return the activation descriptor, never null. + * @throws UnknownObjectException if such object is unknown. + */ + public ActivationDesc getActivationDesc(ActivationID id) + throws ActivationException, UnknownObjectException, RemoteException + { + ActivationDesc desc = (ActivationDesc) descriptions.get(id); + if (desc == null) + throw new UnknownObjectException("No desc for "+ + id == null ? "null" : id.toString()); + return desc; + } + + /** + * Get the descriptor of the given activation group. + * + * @return the activation group descriptor, never null. + * @throws UnknownGroupException if such group is unknown + */ + public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID groupId) + throws ActivationException, UnknownGroupException, RemoteException + { + ActivationGroupDesc desc = (ActivationGroupDesc) groupDescs.get(groupId); + if (desc == null) + throw new UnknownGroupException(groupId == null ? "null" + : groupId.toString()); + return desc; + } + + /** + * Create the activation group id and put this id-descriptor combination into + * the group map. The new ID will only be created if this description has not + * already been registered, otherwise the id of the registered description + * will be returned. + */ + public ActivationGroupID registerGroup(ActivationGroupDesc groupDesc) + throws ActivationException, RemoteException + { + ActivationGroupID id = (ActivationGroupID) groupDescs.getKey(groupDesc); + if (id == null) + { + id = new ActivationGroupID(this); + groupDescs.put(id, groupDesc); + } + if (debug) + System.out.println("Register group " + id +":"+groupDesc+" this "+this); + + return id; + } + + /** + * Create the object activation id and put this id-descriptor combination into + * the group map. The new ID will only be created if this description has not + * already been registered, otherwise the id of the registered description + * will be returned. + */ + public ActivationID registerObject(ActivationDesc desc) + throws ActivationException, UnknownGroupException, RemoteException + { + ActivationID id = (ActivationID) descriptions.getKey(desc); + if (id == null) + { + id = new ActivationID(this); + descriptions.put(id, desc); + } + + if (debug) + System.out.println("Register object " + id +":"+desc+" this "+this); + + return id; + } + + /** + * Replace the activation descriptor, return the previous descriptor. + */ + public ActivationDesc setActivationDesc(ActivationID id, ActivationDesc desc) + throws ActivationException, UnknownObjectException, + UnknownGroupException, RemoteException + { + ActivationDesc prev = getActivationDesc(id); + descriptions.put(id, desc); + return prev; + } + + /** + * Replace the activation group descriptor, return the previous descriptor. + */ + public ActivationGroupDesc setActivationGroupDesc( + ActivationGroupID groupId, + ActivationGroupDesc groupDesc) + throws ActivationException, UnknownGroupException, RemoteException + { + ActivationGroupDesc prev = getActivationGroupDesc(groupId); + groupDescs.put(groupId, groupDesc); + return prev; + } + + /** + * Calls .shutdown on all bidirectional tables (has no effect if these + * table are not persistent). + */ + public void shutdown() throws RemoteException + { + descriptions.shutdown(); + groupDescs.shutdown(); + } + + /** + * Remove the group from the group map + */ + public void unregisterGroup(ActivationGroupID groupId) throws ActivationException, + UnknownGroupException, RemoteException + { + if (! groupDescs.containsKey(groupId)) + throw new UnknownGroupException("Unknown group "+groupId); + + groupDescs.removeKey(groupId); + groupInstantiators.remove(groupId); + } + + /** + * Remove the object id from the active object and description maps. + */ + public void unregisterObject(ActivationID id) throws ActivationException, + UnknownObjectException, RemoteException + { + if (! descriptions.containsKey(id)) + throw new UnknownObjectException("Unregistering unknown object"); + descriptions.removeKey(id); + + synchronized (activatedObjects) + { + activatedObjects.remove(id); + } + } + + /** + * Put the object into active object map. + */ + public void activeObject(ActivationID id, MarshalledObject obj) + throws UnknownObjectException, RemoteException + { + if (! descriptions.containsKey(id)) + throw new UnknownObjectException("Activating unknown object "+ + id+" this "+this); + try + { + synchronized (activatedObjects) + { + activatedObjects.put(id, obj.get()); + } + } + catch (RemoteException e) + { + throw e; + } + catch (Exception e) + { + UnknownObjectException un = new UnknownObjectException( + "Cannot get Remote for MarshalledObject of "+id); + un.detail = e; + throw un; + } + } + + /** + * Check if the group is known. Remove all active objects, belonging to + * that group, from the active object cache. + */ + public void inactiveGroup(ActivationGroupID groupId, long incarnation) + throws UnknownGroupException, RemoteException + { + if (! groupInstantiators.containsKey(groupId)) + throw new UnknownGroupException("Inactivating unkwnon group"); + + groupInstantiators.remove(groupId); + + // Remove all members of this group from the cache. + synchronized (activatedObjects) + { + Iterator iter = activatedObjects.keySet().iterator(); + ActivationID id; + ActivationDesc desc; + while (iter.hasNext()) + { + id = (ActivationID) iter.next(); + desc = (ActivationDesc) descriptions.get(id); + if (desc.getGroupID().equals(groupId)) + activatedObjects.remove(id); + } + } + } + + /** + * Removes this id from the active object cache. + */ + public void inactiveObject(ActivationID id) throws UnknownObjectException, + RemoteException + { + if (! descriptions.containsKey(id)) + throw new UnknownObjectException("Inactivating unknown object"); + + synchronized (activatedObjects) + { + activatedObjects.remove(id); + } + } +} diff --git a/libjava/classpath/gnu/java/rmi/activation/BidiTable.java b/libjava/classpath/gnu/java/rmi/activation/BidiTable.java new file mode 100644 index 00000000000..5e421fe8d42 --- /dev/null +++ b/libjava/classpath/gnu/java/rmi/activation/BidiTable.java @@ -0,0 +1,163 @@ +/* BidiHasthable.java -- Bidirectional hash table. + Copyright (C) 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 gnu.java.rmi.activation; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * The bidirectional hash table, maps both a to b and b to a. + * + * @author Audrius Meskauskas (audriusa@bioinformatics.org) + */ +public class BidiTable +{ + /** + * Use serialVerionUID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * Maps keys to values + */ + protected Map k2v; + + /** + * Maps values to keys (in reverse) + */ + protected Map v2k; + + /** + * Create a new table that is ready to use. + */ + public BidiTable() + { + k2v = new HashMap(); + v2k = new HashMap(); + } + + /** + * Create a new instance where the hashtable fields are not initialised + * (called from derivatives that intialise hashtables in they own way. + * + * @param flags currently used to mark the different constructor only. + */ + protected BidiTable(int flags) + { + } + + /** + * Get key by value + */ + public synchronized Object getKey(Object value) + { + return v2k.get(value); + } + + /** + * Put key-value pair. + */ + public synchronized void put(Object key, Object value) + { + k2v.put(key, value); + v2k.put(value, key); + } + + /** + * Get value from key + */ + public synchronized Object get(Object key) + { + return k2v.get(key); + } + + /** + * Remove the key-value pair by key + */ + public synchronized void removeKey(Object key) + { + Object value = k2v.get(key); + if (value!=null) + { + k2v.remove(key); + v2k.remove(value); + } + } + + /** + * Check if the table contains this key. + */ + public synchronized boolean containsKey(Object key) + { + return k2v.containsKey(key); + } + + /** + * This method is called before exit and may be used to write the database + * to the disk. The default method does nothing. + */ + public synchronized void shutdown() + { + } + + /** + * Get the size. + */ + public synchronized int size() + { + return k2v.size(); + } + + /** + * Get the key collection. + */ + public synchronized Object[] keys() + { + Collection keys = k2v.keySet(); + Object[] k = new Object[keys.size()]; + + Iterator iter = keys.iterator(); + for (int i = 0; i < k.length; i++) + k[i] = iter.next(); + + return k; + } +} diff --git a/libjava/classpath/gnu/java/rmi/activation/DefaultActivationGroup.java b/libjava/classpath/gnu/java/rmi/activation/DefaultActivationGroup.java new file mode 100644 index 00000000000..3a654f2461b --- /dev/null +++ b/libjava/classpath/gnu/java/rmi/activation/DefaultActivationGroup.java @@ -0,0 +1,159 @@ +/* DefaultActivationGroup.java -- Default activation group. + Copyright (C) 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 gnu.java.rmi.activation; + +import gnu.java.rmi.server.ActivatableServerRef; +import gnu.java.rmi.server.UnicastServer; + +import java.lang.reflect.Constructor; +import java.rmi.MarshalledObject; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.activation.ActivationDesc; +import java.rmi.activation.ActivationException; +import java.rmi.activation.ActivationGroup; +import java.rmi.activation.ActivationGroupID; +import java.rmi.activation.ActivationID; +import java.rmi.activation.UnknownObjectException; + +/** + * The default activation group class. This activation group assumes that + * all classes are accessible via current thread context class loader. + * The remote class loading is not supported for security reasons. The + * activation always occurs in the current jre. + * + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) + */ +public class DefaultActivationGroup + extends ActivationGroup +{ + /** + * Use the serialVersionUID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * Used during the group creation (required constructor). + */ + static final Class[] cConstructorTypes = new Class[] + { + ActivationID.class, + MarshalledObject.class + }; + + + /** + * Create the new default activation group. + * + * @param id the group activation id. + * @param data may contain the group initialization data (unused and can be + * null) + * @throws RemoteException if the super constructor does + */ + public DefaultActivationGroup(ActivationGroupID id, MarshalledObject data) + throws RemoteException + { + super(id); + } + + + /** + * May be overridden and used as a hook. This method is called each time + * the new object is instantiated. + */ + public void activeObject(ActivationID id, Remote obj) + throws ActivationException, UnknownObjectException, RemoteException + { + // Nothing to do (the monitor is already notified in newInstance) + } + + /** + * Create the new instance of the object, using the class name and location + * information, stored in the passed descriptor. The method expects the object + * class to have the two parameter constructor, the first parameter being the + * {@link ActivationID} and the second the {@link MarshalledObject}. + * + * @param id the object activation id + * @param desc the activation descriptor, providing the information, necessary + * to create and activate the object + * @return the marshalled object, containing the exported stub of the created + * object + * @throws ActivationException if the activation fails due any reason + */ + public MarshalledObject newInstance(ActivationID id, ActivationDesc desc) + throws ActivationException, RemoteException + { + try + { + if (ActivationSystemTransient.debug) + System.out.println("Instantiating "+desc.getClassName()); + + Remote object; + Class objectClass; + + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + objectClass = loader.loadClass(desc.getClassName()); + Constructor constructor = objectClass.getConstructor(cConstructorTypes); + object = (Remote) constructor.newInstance( + new Object[] { id, desc.getData() }); + + // Make the object accessible and create the stub. + ActivatableServerRef ref = UnicastServer.getActivatableRef(id); + Remote stub = ref.exportObject(object); + + MarshalledObject marsh = new MarshalledObject(stub); + + // Notify the activation monitor. + activeObject(id, marsh); + + // Make call to the hook that may be overridden. + activeObject(id, stub); + + return marsh; + } + catch (Exception e) + { + ActivationException acex = new ActivationException( + "Unable to activate "+ desc.getClassName() + + " from "+ desc.getLocation(), e); + throw acex; + } + } + +} diff --git a/libjava/classpath/gnu/java/rmi/activation/DefaultActivationSystem.java b/libjava/classpath/gnu/java/rmi/activation/DefaultActivationSystem.java new file mode 100644 index 00000000000..754b5dcb932 --- /dev/null +++ b/libjava/classpath/gnu/java/rmi/activation/DefaultActivationSystem.java @@ -0,0 +1,118 @@ +/* DefaultActivationSystem.java -- Default RMI activation system + Copyright (C) 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 gnu.java.rmi.activation; + +import java.rmi.activation.ActivationSystem; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; + +/** + * Finds and returns the default activation system for this jre. + * + * @author Audrius Meskauskas (audriusa@bioinformatics.org) + */ +public abstract class DefaultActivationSystem +{ + /** + * The activation system (assigned if once found). + */ + static ActivationSystem system; + + /** + * The default activation registry port. + */ + static int ACTIVATION_REGISTRY_PORT; + + /** + * The name of the activation system registry port property. + */ + static String AS_PORT_PROPERTY = "java.rmi.activation.port"; + + /** + * The defalut name of the activation system in the activation registry. + */ + static String ACTIVATION_SYSTEM_NAME = "java.rmi.activation.ActivationSystem"; + + /** + * Get the activation system, default for this jre. If no external activation + * system exists, the internal activation system will be activated. This + * internal system is limited in capabilities and should be used exclusively + * for automated testing, to avoid necessity of starting rmi daemon during + * testing process. + */ + public static ActivationSystem get() + { + if (system == null) + try + { + // Obtain the port: + String asr = System.getProperty("java.rmi.activation.port"); + + if (asr != null) + { + try + { + ACTIVATION_REGISTRY_PORT = Integer.parseInt(asr); + if (ACTIVATION_REGISTRY_PORT <= 0) + throw new InternalError("Invalid " + asr + " value, " + + ACTIVATION_REGISTRY_PORT); + } + catch (NumberFormatException e) + { + throw new InternalError("Unable to parse " + asr + + " to integer"); + } + } + else + ACTIVATION_REGISTRY_PORT = ActivationSystem.SYSTEM_PORT; + + // Expect the naming service running first. + // The local host may want to use the shared registry + Registry r = LocateRegistry.getRegistry(ACTIVATION_REGISTRY_PORT); + ActivationSystem system = (ActivationSystem) r.lookup(ACTIVATION_SYSTEM_NAME); + return system; + } + catch (Exception ex) + { + system = ActivationSystemTransient.getInstance(); + } + + return system; + } +} |