diff options
author | Mark Wielaard <mark@gcc.gnu.org> | 2006-05-18 17:29:21 +0000 |
---|---|---|
committer | Mark Wielaard <mark@gcc.gnu.org> | 2006-05-18 17:29:21 +0000 |
commit | 4f9533c7722fa07511a94d005227961f4a4dec23 (patch) | |
tree | 9f9c470de62ee62fba1331a396450d728d2b1fad /libjava/classpath/java/rmi | |
parent | eaec4980e139903ae9b274d1abcf3a13946603a8 (diff) | |
download | gcc-4f9533c7722fa07511a94d005227961f4a4dec23.zip gcc-4f9533c7722fa07511a94d005227961f4a4dec23.tar.gz gcc-4f9533c7722fa07511a94d005227961f4a4dec23.tar.bz2 |
Imported GNU Classpath 0.90
Imported GNU Classpath 0.90
* scripts/makemake.tcl: LocaleData.java moved to gnu/java/locale.
* sources.am: Regenerated.
* gcj/javaprims.h: Regenerated.
* Makefile.in: Regenerated.
* gcj/Makefile.in: Regenerated.
* include/Makefile.in: Regenerated.
* testsuite/Makefile.in: Regenerated.
* gnu/java/lang/VMInstrumentationImpl.java: New override.
* gnu/java/net/local/LocalSocketImpl.java: Likewise.
* gnu/classpath/jdwp/VMMethod.java: Likewise.
* gnu/classpath/jdwp/VMVirtualMachine.java: Update to latest
interface.
* java/lang/Thread.java: Add UncaughtExceptionHandler.
* java/lang/reflect/Method.java: Implements GenericDeclaration and
isSynthetic(),
* java/lang/reflect/Field.java: Likewise.
* java/lang/reflect/Constructor.java
* java/lang/Class.java: Implements Type, GenericDeclaration,
getSimpleName() and getEnclosing*() methods.
* java/lang/Class.h: Add new public methods.
* java/lang/Math.java: Add signum(), ulp() and log10().
* java/lang/natMath.cc (log10): New function.
* java/security/VMSecureRandom.java: New override.
* java/util/logging/Logger.java: Updated to latest classpath
version.
* java/util/logging/LogManager.java: New override.
From-SVN: r113887
Diffstat (limited to 'libjava/classpath/java/rmi')
20 files changed, 2441 insertions, 564 deletions
diff --git a/libjava/classpath/java/rmi/activation/Activatable.java b/libjava/classpath/java/rmi/activation/Activatable.java index b4c38bf..472c65c 100644 --- a/libjava/classpath/java/rmi/activation/Activatable.java +++ b/libjava/classpath/java/rmi/activation/Activatable.java @@ -1,5 +1,6 @@ -/* Activatable.java -- - Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. +/* 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. @@ -38,68 +39,493 @@ 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; -public abstract class Activatable extends RemoteServer +/** + * 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 { -static final long serialVersionUID = -3120617863591563455L; -protected Activatable(String location, MarshalledObject data, boolean restart, int port) throws ActivationException, RemoteException { - throw new Error("Not implemented"); -} + /** + * 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); + } -protected Activatable(String location, MarshalledObject data, boolean restart, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws ActivationException, RemoteException { - throw new Error("Not implemented"); -} + /** + * 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); + } -protected Activatable(ActivationID id, int port) throws RemoteException { - throw new Error("Not implemented"); -} + /** + * 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 incomming 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; + } + } -protected Activatable(ActivationID id, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { - throw new Error("Not implemented"); -} + /** + * 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 incomming 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; -protected ActivationID getID() { - throw new Error("Not implemented"); -} + 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; + } -public static Remote register(ActivationDesc desc) throws UnknownGroupException, ActivationException, RemoteException { - throw new Error("Not implemented"); -} + /** + * 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; -public static boolean inactive(ActivationID id) throws UnknownObjectException, ActivationException, RemoteException { - throw new Error("Not implemented"); -} + } -public static void unregister(ActivationID id) throws UnknownObjectException, ActivationException, RemoteException { - throw new Error("Not implemented"); -} + /** + * 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; + } -public static ActivationID exportObject(Remote obj, String location, MarshalledObject data, boolean restart, int port) throws ActivationException, RemoteException { - throw new Error("Not implemented"); -} + /** + * 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; -public static ActivationID exportObject(Remote obj, String location, MarshalledObject data, boolean restart, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws ActivationException, RemoteException { - throw new Error("Not implemented"); -} + } -public static Remote exportObject(Remote obj, ActivationID id, int port) throws RemoteException { - throw new Error("Not implemented"); -} + /** + * Make the remote object unavailable for incoming calls. This method also + * unregisters the object, so it cannot be activated again by incomming 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(); -public static Remote exportObject(Remote obj, ActivationID id, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { - throw new Error("Not implemented"); -} - -public static boolean unexportObject(Remote obj, boolean force) throws NoSuchObjectException { - throw new Error("Not implemented"); -} + 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 + */ + public 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 + */ + public 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; + } + } } diff --git a/libjava/classpath/java/rmi/activation/ActivationDesc.java b/libjava/classpath/java/rmi/activation/ActivationDesc.java index 65894f8..b861656 100644 --- a/libjava/classpath/java/rmi/activation/ActivationDesc.java +++ b/libjava/classpath/java/rmi/activation/ActivationDesc.java @@ -1,6 +1,6 @@ -/* ActivationDecc.java -- +/* ActivationDesc.java -- record with info to activate an object Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. - + This file is part of GNU Classpath. GNU Classpath is free software; you can redistribute it and/or modify @@ -40,74 +40,215 @@ package java.rmi.activation; import java.io.Serializable; import java.rmi.MarshalledObject; -public final class ActivationDesc implements Serializable +/** + * Contains the information, necessary to activate the object. This information + * includes: + * <ul> + * <li>the object class name</li> + * <li>the object group identifier</li> + * <li>the code location (codebase URL) that can be used to load the class + * remotely</li> + * <li>the object restart mode</li> + * <li>the object specific intialization information</li> + * </ul> + * + * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub) + */ +public final class ActivationDesc + implements Serializable { + /** + * Use SVUID for interoperability. + */ static final long serialVersionUID = 7455834104417690957L; -private ActivationGroupID groupid; -private String classname; -private String location; -private MarshalledObject data; -private boolean restart; - -public ActivationDesc(String className, String location, MarshalledObject data) throws ActivationException { - this(ActivationGroup.currentGroupID(), className, location, data, false); -} - -public ActivationDesc(String className, String location, MarshalledObject data, boolean restart) throws ActivationException { - this(ActivationGroup.currentGroupID(), className, location, data, restart); -} - -public ActivationDesc(ActivationGroupID groupID, String className, String location, MarshalledObject data) { - this(groupID, className, location, data, false); -} - -public ActivationDesc(ActivationGroupID groupID, String className, String location, MarshalledObject data, boolean restart) { - this.groupid = groupID; - this.classname = className; - this.location = location; - this.data = data; - this.restart = restart; -} - -public ActivationGroupID getGroupID() { - return (groupid); -} - -public String getClassName() { - return (classname); -} - -public String getLocation() { - return (location); -} - -public MarshalledObject getData() { - return (data); -} - -public boolean getRestartMode() { - return (restart); -} - -public boolean equals(Object obj) { - if (!(obj instanceof ActivationDesc)) { - return (false); - } - ActivationDesc that = (ActivationDesc)obj; - - if (this.groupid.equals(that.groupid) && - this.classname.equals(that.classname) && - this.location.equals(that.location) && - this.data.equals(that.data) && - this.restart == that.restart) { - return (true); - } - return (false); -} - -public int hashCode() { - return (groupid.hashCode() ^ classname.hashCode() ^ location.hashCode() ^ data.hashCode()); -} - + /** + * The group id. + */ + private ActivationGroupID groupid; + + /** + * The class name. + */ + private String classname; + + /** + * The code location URL. + */ + private String location; + + /** + * The object specific intitalization data. + */ + private MarshalledObject data; + + /** + * The start mode. + */ + private boolean restart; + + /** + * Create the new activation description, assuming the object group is the + * {@link ActivationGroup#currentGroupID()}. + * + * @param className the object fully qualified class name + * @param location the code base URL + * @param data the object initialization data, contained in a marshalled form + */ + public ActivationDesc(String className, String location, MarshalledObject data) + throws ActivationException + { + this(ActivationGroup.currentGroupID(), className, location, data, false); + } + + /** + * Create the new activation description, assuming the object group is the + * {@link ActivationGroup#currentGroupID()}. + * + * @param className the object fully qualified class name + * @param location the code base URL + * @param data the object initialization data, contained in a marshalled form + * @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). + */ + public ActivationDesc(String className, String location, + MarshalledObject data, boolean restart) + throws ActivationException + { + this(ActivationGroup.currentGroupID(), className, location, data, restart); + } + + /** + * Create the new activation description. Under crash, the object will only + * be reactivated on demand. + * + * @param groupID the object group id. + * @param className the object fully qualified class name + * @param location the code base URL + * @param data the object initialization data, contained in a marshalled form + */ + public ActivationDesc(ActivationGroupID groupID, String className, + String location, MarshalledObject data) + { + this(groupID, className, location, data, false); + } + + /** + * Create the new activation description, providing full information. + * + * @param groupID the object group id. + * @param className the object fully qualified class name + * @param location the code base URL + * @param data the object initialization data, contained in a marshalled form + * @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). + */ + public ActivationDesc(ActivationGroupID groupID, String className, + String location, MarshalledObject data, boolean restart) + { + this.groupid = groupID; + this.classname = className; + this.location = location; + this.data = data; + this.restart = restart; + } + + public ActivationGroupID getGroupID() + { + return groupid; + } + + /** + * Get the class name of the object being activated + * + * @return the fully qualified class name of the object being activated + */ + public String getClassName() + { + return classname; + } + + /** + * Get the code location URL ("codebase") of the object being activated. + * + * @return the codebase of the object being activated. + */ + public String getLocation() + { + return location; + } + + public MarshalledObject getData() + { + return data; + } + + /** + * Get the object reactivation strategy after crash. + * + * @return true ir the object is activated when activator is restarted or the + * activation group is restarted. False if the object is only + * activated on demand. This flag does has no effect during the normal + * operation (the object is normally activated on demand). + */ + public boolean getRestartMode() + { + return restart; + } + + /** + * Compare this object with another activation description for equality. + * + * @return true if all fields have the equal values, false otherwise. + */ + public boolean equals(Object obj) + { + if (obj instanceof ActivationDesc) + { + ActivationDesc that = (ActivationDesc) obj; + return eq(groupid, that.groupid) && + eq(classname, that.classname) && + eq(location, that.location) && + eq(data, that.data) + && restart == that.restart; + } + else + return false; + } + + /** + * Get the hash code of this object (overridden to make the returned value + * consistent with .equals(..). + */ + public int hashCode() + { + return hash(groupid) ^ hash(classname) ^ + hash(location) ^ hash(data); + } + + /** + * Get the hashcode of x or 0 if x == null. + */ + static final int hash(Object x) + { + return x == null ? 0 : x.hashCode(); + } + + /** + * Compare by .equals if both a and b are not null, compare directly if at + * least one of them is null. + */ + static final boolean eq(Object a, Object b) + { + if (a == null || b == null) + return a == b; + else + return a.equals(b); + } } diff --git a/libjava/classpath/java/rmi/activation/ActivationGroup.java b/libjava/classpath/java/rmi/activation/ActivationGroup.java index e5774a1..5e7bbd2 100644 --- a/libjava/classpath/java/rmi/activation/ActivationGroup.java +++ b/libjava/classpath/java/rmi/activation/ActivationGroup.java @@ -1,5 +1,5 @@ -/* ActivationGroup.java -- - Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. +/* ActivationGroup.java -- the RMI activation group. + Copyright (c) 1996, 1997, 1998, 1999, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,48 +38,302 @@ exception statement from your version. */ package java.rmi.activation; +import gnu.java.rmi.activation.DefaultActivationGroup; +import gnu.java.rmi.activation.DefaultActivationSystem; + +import java.lang.reflect.Constructor; import java.rmi.MarshalledObject; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; -public abstract class ActivationGroup extends UnicastRemoteObject - implements ActivationInstantiator +/** + * The entity that receives the request to activate object and activates it. + * Frequently there is one activation group per virtual machine. + * + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) (from stub) + */ +public abstract class ActivationGroup + extends UnicastRemoteObject + implements ActivationInstantiator { -static final long serialVersionUID = -7696947875314805420L; -protected ActivationGroup(ActivationGroupID groupID) throws RemoteException { - throw new Error("Not implemented"); -} + /** + * Use the SVUID for interoperability. + */ + static final long serialVersionUID = - 7696947875314805420L; + + /** + * The Id of the current group on this VM (null if none). + */ + static ActivationGroupID currentGroupId = null; + + /** + * The groups identifier. + */ + final ActivationGroupID groupId; -public boolean inactiveObject(ActivationID id) throws ActivationException, UnknownObjectException, RemoteException { - throw new Error("Not implemented"); -} + /** + * The groups activation monitor. + */ + ActivationMonitor monitor; + + /** + * The groups incarnation number. + */ + long incarnation; + + /** + * The groups activation system. + */ + static ActivationSystem system; + + /** + * Used during the group creation (required constructor). + */ + static final Class[] cConstructorTypes = new Class[] + { + ActivationGroupID.class, + MarshalledObject.class + }; -public abstract void activeObject(ActivationID id, Remote obj) throws ActivationException, UnknownObjectException, RemoteException; + /** + * Create the new activation group with the given group id. + * + * @param aGroupId the group Id. + * + * @throws RemoteException if the group export fails. + */ + protected ActivationGroup(ActivationGroupID aGroupId) throws RemoteException + { + groupId = aGroupId; + } + + /** + * The method is called when the object is exported. The group must notify + * the activation monitor, if this was not already done before. + * + * @param id the object activation id + * @param obj the remote object implementation + * + * @throws ActivationException if the group is inactive + * @throws UnknownObjectException if such object is not known + * @throws RemoteException if the call to monitor fails + */ + public abstract void activeObject(ActivationID id, Remote obj) + throws ActivationException, UnknownObjectException, RemoteException; + + /** + * Notifies the monitor about the object being inactivated. + * + * @param id the object being inactivated. + * @return true always (must be overridden to return other values). + * @throws ActivationException never + * @throws UnknownObjectException if the object is not known + * @throws RemoteException if the remote call to monitor fails + */ + public boolean inactiveObject(ActivationID id) throws ActivationException, + UnknownObjectException, RemoteException + { + if (monitor != null) + monitor.inactiveObject(id); + return true; + } -public static ActivationGroup createGroup(ActivationGroupID id, ActivationGroupDesc desc, long incarnation) throws ActivationException { - throw new Error("Not implemented"); -} + /** + * Create the new instance of the activation group, using the class name and + * location information, stored in the passed descriptor. The method expects + * the group class to have the two parameter constructor, the first parameter + * being the {@link ActivationGroupID} and the second the + * {@link MarshalledObject}. The group must be first be registered with the + * ActivationSystem. Once a group is created, the currentGroupID method + * returns the identifier for this group until the group becomes inactive. + * + * @param id the activation group id + * @param desc the group descriptor, providing the information, necessary to + * create the group + * @param incarnation the incarnation number + * @return the created group instance + * @throws ActivationException if the activation fails due any reason + */ + public static ActivationGroup createGroup(ActivationGroupID id, + ActivationGroupDesc desc, + long incarnation) + throws ActivationException + { + // If the activation system is not yet set, set it to the system. + // passed in the group id. + if (system == null) + system = id.system; + + ActivationGroup group = null; -public static ActivationGroupID currentGroupID() { - throw new Error("Not implemented"); -} + // TODO at the moment all groups are created on the current jre and the + // group class must be reachable via thread context class loader. + Class groupClass; -public static void setSystem(ActivationSystem system) throws ActivationException { - throw new Error("Not implemented"); -} + if (desc.className != null) + { + try + { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + groupClass = loader.loadClass(desc.className); + } + catch (ClassNotFoundException e) + { + ActivationException acex = new ActivationException( + "Cannot load " + desc.className); + acex.detail = e; + throw acex; + } + } + else + groupClass = DefaultActivationGroup.class; -public static ActivationSystem getSystem() throws ActivationException { - throw new Error("Not implemented"); -} + try + { + Constructor constructor = groupClass.getConstructor(cConstructorTypes); + group = (ActivationGroup) constructor.newInstance( + new Object[] { id, desc.data }); + } + catch (Exception e) + { + ActivationException acex = new ActivationException( + "Cannot instantiate " + desc.className); + acex.detail = e; + throw acex; + } -protected void activeObject(ActivationID id, MarshalledObject mobj) throws ActivationException, UnknownObjectException, RemoteException { - throw new Error("Not implemented"); -} + currentGroupId = id; + try + { + group.monitor = getSystem().activeGroup(id, group, incarnation); + return group; + } + catch (RemoteException e) + { + ActivationException acex = new ActivationException("createGroup"); + acex.detail = e; + throw acex; + } + } -protected void inactiveGroup() throws UnknownGroupException, RemoteException { - throw new Error("Not implemented"); -} + /** + * Get the id of current activation group. + * + * @return the id of the current activation group or null if none exists. + */ + public static ActivationGroupID currentGroupID() + { + try + { + if (currentGroupId==null) + { + // This will also assing the currentGroupId to the current + // (default) group of the default system. + setSystem(DefaultActivationSystem.get()); + } + } + catch (ActivationException e) + { + InternalError ierr = new InternalError("Unable to activate AS"); + ierr.initCause(e); + throw ierr; + } + + return currentGroupId; + } + + /** + * Set the activation system for this virtual machine. The system can only + * be set if no group is active. + * + * @param aSystem the system to set + * + * @throws ActivationException if some group is active now. + */ + public static void setSystem(ActivationSystem aSystem) + throws ActivationException + { + if (currentGroupId!=null) + throw new ActivationException("Group active"); + else + { + try + { + // Register the default transient activation system and group. + system = aSystem; + ActivationGroupDesc def = new ActivationGroupDesc( + DefaultActivationGroup.class.getName(), + "", + null, + null, + null); + currentGroupId = system.registerGroup(def); + } + catch (Exception ex) + { + InternalError ierr = new InternalError("Unable to start default AG"); + ierr.initCause(ex); + throw ierr; + } + } + } + + /** + * Get the current activation system. If the system is not set via + * {@link #setSystem} method, the default system for this virtual machine is + * returned. The default system is first searched by name + * "java.rmi.activation.ActivationSystem" on the activation registry port. The + * default value of the activation registry port is + * {@link ActivationSystem#SYSTEM_PORT}, but it can be changed by putting the + * system property java.rmi.activation.port. Both activation system and + * activation registry are provided by the RMI daemon tool, RMID, if it is + * running on the local host. If the RMID is not running, the internal + * transient activation system will be created and returned. This internal + * system is highly limited in in capabilities and is not intended to be used + * anywhere apart automated testing. + * + * @return the activation system for this virtual machine + * @throws ActivationException + */ + public static ActivationSystem getSystem() throws ActivationException + { + if (system == null) + system = DefaultActivationSystem.get(); + return system; + } + + /** + * Makes the call back to the groups {@link ActivationMonitor}. + * + * @param id the id obj the object being activated + * @param mObject the marshalled object, contains the activated remote object + * stub. + * @throws ActivationException on activation error + * @throws UnknownObjectException if such object is not registered + * @throws RemoteException on remote call (to monitor) error + */ + protected void activeObject(ActivationID id, MarshalledObject mObject) + throws ActivationException, UnknownObjectException, RemoteException + { + if (monitor!=null) + monitor.activeObject(id, mObject); + + id.group = this; + } + + /** + * Makes the call back to the groups {@link ActivationMonitor} and sets + * the current group to null. + */ + protected void inactiveGroup() throws UnknownGroupException, RemoteException + { + if (monitor!=null) + monitor.inactiveGroup(groupId, incarnation); + + if (currentGroupId!=null && currentGroupId.equals(groupId)) + currentGroupId = null; + } } diff --git a/libjava/classpath/java/rmi/activation/ActivationGroupDesc.java b/libjava/classpath/java/rmi/activation/ActivationGroupDesc.java index 35b546e..76ac63b 100644 --- a/libjava/classpath/java/rmi/activation/ActivationGroupDesc.java +++ b/libjava/classpath/java/rmi/activation/ActivationGroupDesc.java @@ -1,5 +1,6 @@ -/* ActivationGroupDesc.java -- - Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. +/* ActivationGroupDesc.java -- the RMI activation group descriptor + Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,97 +39,395 @@ exception statement from your version. */ package java.rmi.activation; +import gnu.java.rmi.activation.DefaultActivationGroup; + import java.io.Serializable; import java.rmi.MarshalledObject; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.Iterator; import java.util.Properties; +import java.util.TreeSet; +import java.util.zip.Adler32; -public final class ActivationGroupDesc implements Serializable +/** + * Contains information, necessary to create of recreate the activation objects. + * The group descriptor contains: + * <ul> + * <li>The name of the group's class. This class is derived from the + * {@link ActivationGroup}.</li> + * <li>The group class code location.</li> + * <li>The marshalled object that contains the group specific initialization + * information</li> + * </ul> + * The groups are created by the {@link ActivationGroup#createGroup} method that + * expectes the group class to have the two parameter constructor, the first + * parameter being the {@link ActivationGroupID} and the second the + * {@link MarshalledObject}. + * + * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub) + */ +public final class ActivationGroupDesc + implements Serializable { - static final long serialVersionUID = -4936225423168276595L; + /** + * Contains the startup options for the {@link ActivationGroup} + * implementations. Allows to override system properties and specify other + * options for the implementation groups. + * + * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub) + */ + public static class CommandEnvironment + implements Serializable + { -public static class CommandEnvironment - implements Serializable { + /** + * Use the SVUID for interoperability. + */ + static final long serialVersionUID = 6165754737887770191L; + + /** + * The zero size string array used as argv value when null is passed. + */ + private static final String[] NO_ARGS = new String[0]; -static final long serialVersionUID = 6165754737887770191L; - -private String cmdpath; -private String[] argv; + /** + * The path to the java executable (or null for using default jre). + */ + final String command; + + /** + * The extra parameters (may be empty array but never null). + */ + final String[] options; + + /** + * Create the new command environment. + * + * @param commandPatch the full path (and name) to the java executable of + * null for using the default executable. + * @param args extra options that will be used when creating the activation + * group. Null has the same effect as the empty list. + */ + public CommandEnvironment(String commandPatch, String[] args) + { + command = commandPatch; + if (args != null) + options = args; + else + options = NO_ARGS; + } + + /** + * Get the path to the java executable. + * + * @return the path to the java executable or null for using the default + * jre. + */ + public String getCommandPath() + { + return command; + } + + /** + * Get the additional command options. + * + * @return the command options array, may be empty string + */ + public String[] getCommandOptions() + { + return options; + } + + /** + * Compare for content equality. + */ + public boolean equals(Object obj) + { + if (obj instanceof CommandEnvironment) + { + CommandEnvironment that = (CommandEnvironment) obj; -public CommandEnvironment(String cmdpath, String[] argv) { - this.cmdpath = cmdpath; - this.argv = argv; -} - -public String getCommandPath() { - return (cmdpath); -} - -public String[] getCommandOptions() { - return (argv); -} - -public boolean equals(Object obj) { - if (!(obj instanceof CommandEnvironment)) { - return (false); - } - CommandEnvironment that = (CommandEnvironment)obj; - - if (!this.cmdpath.equals(that.cmdpath)) { - return (false); - } - - int len = this.argv.length; - if (len != that.argv.length) { - return (false); - } - for (int i = 0; i < len; i++) { - if (!this.argv[i].equals(that.argv[i])) { - return (false); - } - } - return (true); -} + if (command == null || that.command == null) + { + // Use direct comparison if null is involved. + if (command != that.command) + return false; + } + else + { + // Use .equals if null is not involved. + if (! this.command.equals(that.command)) + return false; + } -public int hashCode() { - return (cmdpath.hashCode()); // Not a very good hash code. -} + return Arrays.equals(options, that.options); + } + else + return false; + } -} + /** + * Get the hash code. + */ + public int hashCode() + { + int h = command == null ? 0 : command.hashCode(); + for (int i = 0; i < options.length; i++) + h ^= options[i].hashCode(); -public ActivationGroupDesc(Properties overrides, ActivationGroupDesc.CommandEnvironment cmd) { - throw new Error("Not implemented"); -} + return h; + } + } + + /** + * Use the SVUID for interoperability. + */ + static final long serialVersionUID = - 4936225423168276595L; + + /** + * The group class name or null for the default group class implementation. + */ + final String className; + + /** + * The group class download location URL (codebase), ignored by the + * default implementation. + */ + final String location; + + /** + * The group initialization data. + */ + final MarshalledObject data; + + /** + * The path to the group jre and the parameters of this jre, may be + * null for the default jre. + */ + final ActivationGroupDesc.CommandEnvironment env; + + /** + * The properties that override the system properties. + */ + final Properties props; + + /** + * The cached hash code. + */ + transient long hash; + + /** + * Create the new activation group descriptor that will use the default + * activation group implementation with the given properties and + * environment. + * + * @param aProperties the properties that override the system properties + * @param environment the command line (and parameters), indicating, where to + * find the jre executable and with that parameters to call it. May + * be null if the default executable should be used. In this case, + * the activation group with the null name (the system default group) + * will be created. + */ + public ActivationGroupDesc(Properties aProperties, + ActivationGroupDesc.CommandEnvironment environment) + { + this(DefaultActivationGroup.class.getName(), null, null, aProperties, + environment); + } + + /** + * Create the new activation group descriptor. + * + * @param aClassName the name of the group implementation class. The null + * value indicates the default implementation. + * @param aLocation the location, from where the group implementation class + * should be loaded (ignored for the system default implementation). + * @param aData the group intialization data + * @param aProperties the properties that will override the system properties + * of the new group. These properties will be translated into -D + * options. + * @param environment the record, containing path to the jre executable and + * start options for the jre or null for using the default jre and + * options. + */ + public ActivationGroupDesc(String aClassName, String aLocation, + MarshalledObject aData, Properties aProperties, + ActivationGroupDesc.CommandEnvironment environment) + { + className = aClassName; + location = aLocation; + data = aData; + props = aProperties; + env = environment; + } + + /** + * Get the activation group class name. + * + * @return the activation group class name (null for default implementation) + */ + public String getClassName() + { + return className; + } + + /** + * Get the location, from where the group class will be loaded + * + * @return the location, from where the implementation should be loaded (null + * for the default implementation) + */ + public String getLocation() + { + return location; + } + + /** + * Get the group intialization data. + * + * @return the group intialization data in the marshalled form. + */ + public MarshalledObject getData() + { + return data; + } -public ActivationGroupDesc(String className, String location, MarshalledObject data, Properties overrides, ActivationGroupDesc.CommandEnvironment cmd) { - throw new Error("Not implemented"); -} + /** + * Get the overridded system properties. + * + * @return the overridden group system properties. + */ + public Properties getPropertyOverrides() + { + return props; + } + + /** + * Get the group command environment, containing path to the jre executable + * and startup options. + * + * @return the command environment or null if the default environment should + * be used. + */ + public ActivationGroupDesc.CommandEnvironment getCommandEnvironment() + { + return env; + } + + /** + * Compare for the content equality. + */ + public boolean equals(Object obj) + { + if (obj instanceof ActivationGroupDesc) + { + ActivationGroupDesc that = (ActivationGroupDesc) obj; -public String getClassName() { - throw new Error("Not implemented"); -} + // Ensure the hashcodes are computed. + if (hash == 0) + hashCode(); + if (that.hash == 0) + that.hashCode(); -public String getLocation() { - throw new Error("Not implemented"); -} + // We compare the hash fields as they are type long rather than int. + if (hash != that.hash) + return false; -public MarshalledObject getData() { - throw new Error("Not implemented"); -} + if (! eq(className, that.className)) + return false; + if (! eq(data, that.data)) + return false; + if (! eq(env, that.env)) + return false; + if (! eq(location, that.location)) + return false; -public Properties getPropertyOverrides() { - throw new Error("Not implemented"); -} + // Compare the properties. + if (eq(props, that.props)) + return true; -public ActivationGroupDesc.CommandEnvironment getCommandEnvironment() { - throw new Error("Not implemented"); -} + if (props.size() != that.props.size()) + return false; -public boolean equals(Object obj) { - throw new Error("Not implemented"); -} + Enumeration en = props.propertyNames(); + Object key, value; -public int hashCode() { - throw new Error("Not implemented"); -} + while (en.hasMoreElements()) + { + key = en.nextElement(); + if (! that.props.containsKey(key)) + return false; + if (! eq(props.get(key), that.props.get(key))) + return false; + } + return true; + } + else + return false; + } + + /** + * Compare for direct equality if one or both parameters are null, otherwise + * call .equals. + */ + static boolean eq(Object a, Object b) + { + if (a == null || b == null) + return a == b; + else + return a.equals(b); + } + + /** + * Return the hashcode. + */ + public int hashCode() + { + if (hash==0) + { + // Using Adler32 - the hashcode is cached, will be computed only + // once and due need to scan properties is the expensive operation + // anyway. Reliability is more important. + Adler32 adler = new Adler32(); + if (className!=null) + adler.update(className.getBytes()); + if (data!=null) + adler.update(data.hashCode()); + if (env!=null) + adler.update(env.hashCode()); + if (location!=null) + adler.update(location.getBytes()); + if (props!=null) + { + Enumeration en = props.propertyNames(); + + // Using the intermediate sorted set to ensure that the + // properties are sorted. + TreeSet pr = new TreeSet(); + + Object key; + Object value; + while (en.hasMoreElements()) + { + key = en.nextElement(); + if (key!=null) + pr.add(key); + } + + Iterator it = pr.iterator(); + while (it.hasNext()) + { + key = it.next(); + value = props.get(key); + adler.update(key.hashCode()); + if (value!=null) + adler.update(value.hashCode()); + } + } + hash = adler.getValue(); + } + return (int) hash; + } } diff --git a/libjava/classpath/java/rmi/activation/ActivationGroupID.java b/libjava/classpath/java/rmi/activation/ActivationGroupID.java index 5e0b964..e54b2a0 100644 --- a/libjava/classpath/java/rmi/activation/ActivationGroupID.java +++ b/libjava/classpath/java/rmi/activation/ActivationGroupID.java @@ -1,5 +1,5 @@ /* ActivationGroupID.java -- - Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Copyright (c) 1996, 1997, 1998, 1999, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,36 +35,88 @@ 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 java.io.Serializable; +import java.rmi.server.UID; -public class ActivationGroupID implements Serializable +/** + * This identifier identifies the activation group inside the scope of its + * activation system. It also contains (and can provide) the reference to the + * groups activation system. + * + * @see ActivationSystem#registerGroup(ActivationGroupDesc) + */ +public class ActivationGroupID + implements Serializable { - static final long serialVersionUID = -1648432278909740833L; + /** + * Use SVUID for interoperability. + */ + static final long serialVersionUID = - 1648432278909740833L; -private ActivationSystem system; + /** + * The associated activation system. + */ + final ActivationSystem system; + + /** + * The object identifier, making the ID unique. + */ + final UID uid; -public ActivationGroupID(ActivationSystem system) { - this.system = system; -} + /** + * Create the new activation group id in the scope of the given activation + * system + * + * @param aSystem the activation system + */ + public ActivationGroupID(ActivationSystem aSystem) + { + system = aSystem; + uid = new UID(); + } -public ActivationSystem getSystem() { - return (system); -} + /** + * Get the associated activation system + * + * @return the associated activation system + */ + public ActivationSystem getSystem() + { + return system; + } -public int hashCode() { - return (system.hashCode()); -} + /** + * Get the hash code of the associated activation system. + */ + public int hashCode() + { + return uid.hashCode(); + } -public boolean equals(Object obj) { - if (obj instanceof ActivationGroupID) { - ActivationGroupID that = (ActivationGroupID)obj; - if (this.system.equals(that.system)) { - return (true); - } - } - return (false); -} + /** + * Copmare for equality, returns true if the passed object is also the + * activation group id and its activation system is the same. + */ + public boolean equals(Object obj) + { + if (obj instanceof ActivationGroupID) + { + ActivationGroupID that = (ActivationGroupID) obj; + return uid.equals(that.uid); + } + else + return false; + } + + /** + * Get the string representation + */ + public String toString() + { + return uid.toString(); + } } diff --git a/libjava/classpath/java/rmi/activation/ActivationGroup_Stub.java b/libjava/classpath/java/rmi/activation/ActivationGroup_Stub.java index 249137b..fb55e5f 100644 --- a/libjava/classpath/java/rmi/activation/ActivationGroup_Stub.java +++ b/libjava/classpath/java/rmi/activation/ActivationGroup_Stub.java @@ -51,7 +51,7 @@ import java.rmi.server.RemoteStub; * * @author Roman Kennke (kennke@aicas.com) */ -public class ActivationGroup_Stub extends RemoteStub +public final class ActivationGroup_Stub extends RemoteStub implements ActivationInstantiator, Remote { private static final long serialVersionUID = 2L; diff --git a/libjava/classpath/java/rmi/activation/ActivationID.java b/libjava/classpath/java/rmi/activation/ActivationID.java index 23ed853..c4bbcd2 100644 --- a/libjava/classpath/java/rmi/activation/ActivationID.java +++ b/libjava/classpath/java/rmi/activation/ActivationID.java @@ -1,5 +1,5 @@ -/* ActivationID.java -- - Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. +/* ActivationID.java -- the object activation identifier + Copyright (c) 1996, 1997, 1998, 1999, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,38 +35,165 @@ 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 java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.rmi.Remote; import java.rmi.RemoteException; +import java.rmi.server.UID; -public class ActivationID implements Serializable +/** + * Denotes the object that can be activated over time. The instance of the + * ActivationID for the given object can be obtained in the following ways: + * <ul> + * <li>via {@link Activatable#register(ActivationDesc)}</li> + * <li>via Activatable constructor</li> + * <li>via Activatable.exportObject + * <li> + * </ul> + * An instance of the ActivationID has the {@link UID} as its component and + * hence is globally unique. + * + * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub) + */ +public class ActivationID + implements Serializable { - static final long serialVersionUID = -4608673054848209235L; - -private Activator activator; - -public ActivationID(Activator activator) { - this.activator = activator; -} + /** + * Use SVUID for interoperability. + */ + static final long serialVersionUID = - 4608673054848209235L; -public Remote activate(boolean force) throws ActivationException, UnknownObjectException, RemoteException { - throw new Error("Not implemented"); -} - -public int hashCode() { - return (activator.hashCode()); -} + /** + * The activator. + */ + transient Activator activator; + + /** + * The UID, making this instance unique. + */ + transient UID uid; + + /** + * The activation group that has activated the object with this + * activation id. The field is filled in inside the group and is used + * to notify the group about the request to inactivated the object. + */ + transient ActivationGroup group; -public boolean equals(Object obj) { - if (obj instanceof ActivationID) { - ActivationID that = (ActivationID)obj; - if (this.activator.equals(that.activator)) { - return (true); - } - } - return (false); -} + /** + * Create a new instance with the given activator. + * + * @param an_activator tha activator that should activate the object. + */ + public ActivationID(Activator an_activator) + { + activator = an_activator; + uid = new UID(); + } + + /** + * Activate the object. + * + * @param force if true, always contact the group. Otherwise, the cached value + * may be returned. + * @return the activated object + * @throws UnknownObjectException if the object is unknown + * @throws ActivationException if the activation has failed + * @throws RemoteException if the remote call has failed + */ + public Remote activate(boolean force) throws ActivationException, + UnknownObjectException, RemoteException + { + try + { + return (Remote) activator.activate(this, force).get(); + } + catch (IOException e) + { + ActivationException acex = new ActivationException("id "+uid, e); + throw acex; + } + catch (ClassNotFoundException e) + { + ActivationException acex = new ActivationException("id "+uid, e); + throw acex; + } + } + + /** + * Returns the hash code of the activator. + */ + public int hashCode() + { + return uid == null ? 0 : uid.hashCode(); + } + + /** + * Compares the activators for equality. + */ + public boolean equals(Object obj) + { + if (obj instanceof ActivationID) + { + ActivationID that = (ActivationID) obj; + return eq(uid, that.uid); + } + else + return false; + } + + /** + * Read the object from the input stream. + * + * @param in the stream to read from + * + * @throws IOException if thrown by the stream + * @throws ClassNotFoundException + */ + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException + { + uid = (UID) in.readObject(); + activator = (Activator) in.readObject(); + } + + /** + * Write the object to the output stream. + * + * @param out the stream to write int + * @throws IOException if thrown by the stream + * @throws ClassNotFoundException + */ + private void writeObject(ObjectOutputStream out) throws IOException, + ClassNotFoundException + { + out.writeObject(uid); + out.writeObject(activator); + }; + + /** + * Compare by .equals if both a and b are not null, compare directly if at + * least one of them is null. + */ + static final boolean eq(Object a, Object b) + { + if (a == null || b == null) + return a == b; + else + return a.equals(b); + } + /** + * Return the content based string representation. + */ + public String toString() + { + return uid.toString(); + } + } diff --git a/libjava/classpath/java/rmi/activation/ActivationInstantiator.java b/libjava/classpath/java/rmi/activation/ActivationInstantiator.java index 0aceb7a..a0f04ed 100644 --- a/libjava/classpath/java/rmi/activation/ActivationInstantiator.java +++ b/libjava/classpath/java/rmi/activation/ActivationInstantiator.java @@ -42,9 +42,32 @@ import java.rmi.MarshalledObject; import java.rmi.Remote; import java.rmi.RemoteException; +/** + * The implementation of this interface creates (instantiates) the new remote + * objects in response to the activation request. The instantiator is returned + * by the {@link ActivationGroup} that calls + * {@link ActivationSystem#activeGroup(ActivationGroupID, ActivationInstantiator, long)}. + */ public interface ActivationInstantiator extends Remote { + /** + * Creates and instantiate a new remote object. This method performs the + * following tasks: + * <ul> + * <li>Finds and loads (if not already loaded) the class of the object being + * instantiated</li> + * <li>Creates an instance of the object using its special two parameter + * activation constructor, the first parameter being the {@link ActivationID} + * and the second the {@link MarshalledObject}.</li> + * + * @param id the id of the object being instantiated + * @param desc the activation descriptor being instantiated + * @return the MarshalledObject, containing the stub to the newly created + * object. + * @throws ActivationException if the activation fails + * @throws RemoteException if the remote call fails + */ MarshalledObject newInstance (ActivationID id, ActivationDesc desc) throws ActivationException, RemoteException; } diff --git a/libjava/classpath/java/rmi/activation/ActivationMonitor.java b/libjava/classpath/java/rmi/activation/ActivationMonitor.java index 1e64257..e9f43ae 100644 --- a/libjava/classpath/java/rmi/activation/ActivationMonitor.java +++ b/libjava/classpath/java/rmi/activation/ActivationMonitor.java @@ -1,5 +1,6 @@ -/* ActivationMonitor.java -- - Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. +/* ActivationMonitor.java -- the RMI activation/inactivation event listener + Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,14 +43,45 @@ import java.rmi.MarshalledObject; import java.rmi.Remote; import java.rmi.RemoteException; +/** + * The activation and inactivation event listener. The group obtains this + * listener via {@link ActivationSystem#activeGroup} and must notify it + * when the group objects are activated or inactivated and also when the + * whole group becomes inactive. + * @author root. + */ public interface ActivationMonitor extends Remote { - void inactiveObject (ActivationID id) + /** + * Informs that the object is now active. + * + * @param id the activation id of the object that is now active + * @throws UnknownObjectException is such object is not known in this group + * @throws RemoteException if remote call fails + */ + void activeObject (ActivationID id, MarshalledObject obj) throws UnknownObjectException, RemoteException; - void activeObject (ActivationID id, MarshalledObject obj) + /** + * Informs that the object is not inactive. + * + * @param id the activation id of the object that is now inactive + * @throws UnknownObjectException is such object is not known in this group + * @throws RemoteException if remote call fails + */ + void inactiveObject (ActivationID id) throws UnknownObjectException, RemoteException; - void inactiveGroup (ActivationGroupID id, long incarnation) + /** + * Informs that the whole group is now inactive because all group objects are + * inactive. The group will be recreated upon the later request to activate + * any object, belonging to the group. + * + * @param groupId the group id + * @param incarnation the group incarnation number + * @throws UnknownGroupException if the group id is not known + * @throws RemoteException if the remote call fails + */ + void inactiveGroup (ActivationGroupID groupId, long incarnation) throws UnknownGroupException, RemoteException; } diff --git a/libjava/classpath/java/rmi/activation/ActivationSystem.java b/libjava/classpath/java/rmi/activation/ActivationSystem.java index 4b92d40..7196764 100644 --- a/libjava/classpath/java/rmi/activation/ActivationSystem.java +++ b/libjava/classpath/java/rmi/activation/ActivationSystem.java @@ -1,5 +1,6 @@ -/* ActivationSystem.java -- - Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. +/* ActivationSystem.java -- registers groups and objects to be activated. + Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,38 +42,165 @@ package java.rmi.activation; import java.rmi.Remote; import java.rmi.RemoteException; -public interface ActivationSystem extends Remote +/** + * <p> + * The ActivationSystem registers groups and activatable objects to be activated + * within those groups. The ActivationSystem cooperates with both the Activator, + * which activates objects registered via the ActivationSystem, and the + * ActivationMonitor, which obtains information about active and inactive + * objects and inactive groups. + * </p> + * <p> + * The activation system if frequently a remote object. As a security mean, all + * methods in this interface throw {@link java.rmi.AccessException} if called + * from the client that is not reside on the same host as the activation system. + * </p> + * @see ActivationGroup#getSystem() + */ +public interface ActivationSystem + extends Remote { + /** + * The port, used by the activation system. The value is equal to 1098 by + * default, but it can be changed by putting the system property + * . + */ int SYSTEM_PORT = 1098; - - ActivationID registerObject (ActivationDesc desc) - throws ActivationException, UnknownGroupException, RemoteException; - - void unregisterObject (ActivationID id) - throws ActivationException, UnknownObjectException, RemoteException; - - ActivationGroupID registerGroup (ActivationGroupDesc desc) - throws ActivationException, RemoteException; - - ActivationMonitor activeGroup (ActivationGroupID id, - ActivationInstantiator group, long incarnation) - throws UnknownGroupException, ActivationException, RemoteException; - - void unregisterGroup (ActivationGroupID id) - throws ActivationException, UnknownGroupException, RemoteException; - - void shutdown() - throws RemoteException; - - ActivationDesc setActivationDesc (ActivationID id, ActivationDesc desc) - throws ActivationException, UnknownObjectException, UnknownGroupException, - RemoteException; - - ActivationGroupDesc setActivationGroupDesc (ActivationGroupID id, - ActivationGroupDesc desc) - throws ActivationException, UnknownGroupException, RemoteException; - - ActivationDesc getActivationDesc (ActivationID id) throws ActivationException, UnknownObjectException, RemoteException; - - ActivationGroupDesc getActivationGroupDesc (ActivationGroupID id) throws ActivationException, UnknownGroupException, RemoteException; + + /** + * Registers the activation descriptor and creates (and returns) its + * activation identifier. The map entry (identifier to descriptor) is stored + * in the stable map and used when the {@link Activator} receives the request + * to activate the object. + * + * @param desc the activation descriptor to register. + * @return the created activation identifier that is mapped to the passed + * descriptor. + * @throws ActivationException if the registration fails (database update + * problems, etc). + * @throws UnknownGroupException the if group, specified in decriptor, is + * unknown. + * @throws RemoteException if the remote call fails. + */ + ActivationID registerObject(ActivationDesc desc) throws ActivationException, + UnknownGroupException, RemoteException; + + /** + * Removes the stored identifier-description map entry. The object will no + * longer be activable using the passed activation id + * + * @param id the activation id to remove + * @throws ActivationException if the entry removing operation failed + * (database update problems, etc) + * @throws UnknownObjectException if the passed id is not known to the system + * @throws RemoteException if the remote call fails + */ + void unregisterObject(ActivationID id) throws ActivationException, + UnknownObjectException, RemoteException; + + /** + * Register the new activation group. For instance, it can be one activation + * group per virtual machine. + * + * @param groupDesc the activation group descriptor. + * @return the created activation group ID for the activation group + * @throws ActivationException if the group registration fails + * @throws RemoteException if the remote call fails + */ + ActivationGroupID registerGroup(ActivationGroupDesc groupDesc) + throws ActivationException, RemoteException; + + /** + * This method is called from the {@link ActivationGroup} to inform the + * ActivatinSystem that the group is now active and there is the + * {@link ActivationInstantiator} for that group. This call is made internally + * from the {@link ActivationGroup#createGroup}. + * + * @param id the group id + * @param group the group activation instantiator + * @param incarnation the groups incarnatin number. + * @return the activation monitor that should be informed about the group + * state changes + * @throws UnknownGroupException if this group has not been registered + * @throws ActivationException if this group is already active + * @throws RemoteException if the remote call fails + */ + ActivationMonitor activeGroup(ActivationGroupID id, + ActivationInstantiator group, long incarnation) + throws UnknownGroupException, ActivationException, RemoteException; + + /** + * Removes the activation group with the given identifier. The group calls + * back, informing the activator about the shutdown. + * + * @param id the group activation id. + * @throws ActivationException if the database update fails + * @throws UnknownGroupException if such group is not registered + * @throws RemoteException if the remote call fails + */ + void unregisterGroup(ActivationGroupID id) throws ActivationException, + UnknownGroupException, RemoteException; + + /** + * Shutdown the activation system and all associated activation groups + * + * @throws RemoteException if the remote call fails + */ + void shutdown() throws RemoteException; + + /** + * Replace the activation descriptor for the object with the given activation + * id. + * + * @param id the activation id + * @param desc the new activation descriptor + * @return the previous activation descriptor for that object. + * @throws ActivationException if the database update fails + * @throws UnknownObjectException if the object with such id is not known + * @throws UnknownGroupException if the activation group (in desc) is not + * known. + * @throws RemoteException if the remote call fails + */ + ActivationDesc setActivationDesc(ActivationID id, ActivationDesc desc) + throws ActivationException, UnknownObjectException, + UnknownGroupException, RemoteException; + + /** + * Replaces the group descriptor for the group with the given group activation + * id. + * + * @param groupId the group id + * @param groupDesc the new group descriptor + * @return the previous group descriptor + * @throws ActivationException if the database update fails + * @throws UnknownGroupException if such group is not known + * @throws RemoteException if the remote call fails + */ + ActivationGroupDesc setActivationGroupDesc(ActivationGroupID groupId, + ActivationGroupDesc groupDesc) + throws ActivationException, UnknownGroupException, RemoteException; + + /** + * Get the activation descriptor for the object with the given activation id. + * + * @param id the object activation id + * @return the activation descriptor for that object + * @throws ActivationException if the database access fails + * @throws UnknownObjectException if this object is not known + * @throws RemoteException if the remote call fails + */ + ActivationDesc getActivationDesc(ActivationID id) throws ActivationException, + UnknownObjectException, RemoteException; + + /** + * Get the group descriptor for the group with the given id. + * + * @param groupId the group id + * @return the group descriptor + * @throws ActivationException if the database access fails + * @throws UnknownGroupException if the group with such id is not known + * @throws RemoteException if the remote call fails + */ + ActivationGroupDesc getActivationGroupDesc(ActivationGroupID groupId) + throws ActivationException, UnknownGroupException, RemoteException; } diff --git a/libjava/classpath/java/rmi/activation/Activator.java b/libjava/classpath/java/rmi/activation/Activator.java index 2fb5a58..57a4d16 100644 --- a/libjava/classpath/java/rmi/activation/Activator.java +++ b/libjava/classpath/java/rmi/activation/Activator.java @@ -42,9 +42,31 @@ import java.rmi.MarshalledObject; import java.rmi.Remote; import java.rmi.RemoteException; +/** + * Activates remote object, providing the live reference to the activable remote + * object. Usually there is only one activator per host. + * + * @see ActivationSystem + * @see ActivationMonitor + */ public interface Activator extends Remote { + /** + * Activate the object, associated with the given activation identifier. The + * activator looks for the {@link ActivationDesc}riptor for the passed + * identifier, determines the object activation group and initiates object + * recreation either via {@link ActivationInstantiator} or via + * {@link Class#newInstance()}. + * + * @param id the identifier of the object to activate. + * @param force if true, the activator always contacts the group to obtain the + * reference. If false, it may return the cached value. + * @return the activated remote object (its stub). + * @throws UnknownObjectException if the object with this id is unknown + * @throws ActivationException if the activation has failed due other reason + * @throws RemoteException if the remote call has failed. + */ MarshalledObject activate (ActivationID id, boolean force) throws ActivationException, UnknownObjectException, RemoteException; } diff --git a/libjava/classpath/java/rmi/activation/package.html b/libjava/classpath/java/rmi/activation/package.html index 444782d..9df518f 100644 --- a/libjava/classpath/java/rmi/activation/package.html +++ b/libjava/classpath/java/rmi/activation/package.html @@ -1,6 +1,6 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <!-- package.html - describes classes in java.rmi.activation package. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,7 +40,34 @@ exception statement from your version. --> <head><title>GNU Classpath - java.rmi.activation</title></head> <body> -<p></p> - +In the previous Classpath releases, an instance of a UnicastRemoteObject +could be accessed from a server that: +<ul> +<li>has created an instance of that object<li> +<li>has been running <i>all<i> the time</li> +</ul> +<p>The the activation system allows to activate and execute the object +implementation on demand rather than running all time. If the activation +system is persistent, the server can be terminated and then restarted. +The clients, still holding remote references to the server side +activatable objects, will activate those objects again. The server side +objects will be reinstantiated (activated) during the first call of any +remote method of such object. +</p><p> +The RMI client code for activatable objects is no different than the code for +accessing non-activatable remote objects. Activation is a server-side feature. +</p><p> +In order for an object to be activated, the "activatable" object class +(independently if it extends the {@link Activatable} class or not) defines a +special public constructor that takes two arguments, its activation identifier +({@link ActivationID}) and its activation data ({@link java.rmi.MarshalledObject}), +supplied in the activation descriptor used during registration. When an +activation group activates a remote object, it constructs the object via +this special constructor. The remote object implementation may use the +activation data to initialize itself in a needed manner. The remote object may +also retain its activation identifier, so that it can inform the activation +group when it becomes inactive (via a call to the Activatable.inactive method). +</p> +@author Audrius Meskauskas (audriusa@bioinformatics.org) (from empty) </body> </html> diff --git a/libjava/classpath/java/rmi/dgc/VMID.java b/libjava/classpath/java/rmi/dgc/VMID.java index f960d9c..dc989c2 100644 --- a/libjava/classpath/java/rmi/dgc/VMID.java +++ b/libjava/classpath/java/rmi/dgc/VMID.java @@ -1,5 +1,5 @@ -/* VMID.java - Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. +/* VMID.java -- The object ID, unique between all virtual machines. + Copyright (c) 1996, 1997, 1998, 1999, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,37 +41,72 @@ import java.io.Serializable; import java.net.InetAddress; import java.net.UnknownHostException; import java.rmi.server.UID; - +import java.util.Arrays; + +/** + * An identifier that is unique accross the all virtual machines. This class is + * used by distributed garbage collector to identify the virtual machine of + * the client, but may also be used in various other cases, when such identifier + * is required. This class separately stores and transfers the host IP + * address, but will try to do its best also for the case if it failed to + * determine it. The alternative algorithms are used in {@link UID} that is + * part of this class. The VMID's, created on the same host, but in the two + * separately (parallely) running virtual machines are different. + */ public final class VMID implements Serializable { + /** + * Use SVUID for interoperability. + */ static final long serialVersionUID = -538642295484486218L; - static final boolean areWeUnique; + /** + * If true, the IP of this host can ve reliably determined. + */ + static boolean areWeUnique; + /** + * The IP address of the local host. + */ static byte[] localAddr; + /** + * The IP address of the local host. + */ private byte[] addr; + /** + * The cached hash code. + */ + transient int hash; + + /** + * The UID of this VMID. + */ private UID uid; static - { - byte[] addr; - boolean awu = true; - try { - addr = InetAddress.getLocalHost().getAddress(); - if (addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) { - awu = false; - } - } - catch (UnknownHostException _) { - addr = new byte[]{ 127, 0, 0, 1 }; - awu = false; + { + // This "local host" value usually indicates that the local + // IP address cannot be reliably determined. + byte[] localHost = new byte[] { 127, 0, 0, 1 }; + + try + { + localAddr = InetAddress.getLocalHost().getAddress(); + areWeUnique = !Arrays.equals(localHost, localAddr); + } + catch (UnknownHostException uhex) + { + localAddr = localHost; + areWeUnique = false; + } } - localAddr = addr; - areWeUnique = awu; - } - + + /** + * Create the new VMID. All VMID's are unique accross tha all virtual + * machines. + */ public VMID() { addr = localAddr; @@ -79,42 +114,58 @@ public final class VMID implements Serializable } /** - * @deprecated + * Return true if it is possible to get the accurate address of this host. + * If false is returned, the created VMID's are less reliable, but the + * starting time and possibly the memory allocation are also taken into + * consideration in the incorporated UID. Hence the VMID's, created on the + * different virtual machines, still should be different. + * + * @deprecated VMID's are more or less always reliable. + * + * @return false if the local host ip address is 127.0.0.1 or unknown, + * true otherwise. */ public static boolean isUnique () { return areWeUnique; } - + + /** + * Get the hash code of this VMID. + */ public int hashCode () { - return super.hashCode(); - } - - public boolean equals (Object obj) - { - if (!(obj instanceof VMID)) - { - return false; - } - - VMID other = (VMID) obj; - if (addr.length != other.addr.length) + if (hash==0) { - return false; + for (int i = 0; i < localAddr.length; i++) + hash += addr[i]; + hash = hash ^ uid.hashCode(); } - - for (int i = addr.length - 1; i >= 0; i--) + return hash; + } + + /** + * Returns true if the passed parameter is also VMID and it is equal to this + * VMID. The VMID should only be equal to itself (also if the passed value is + * another instance, cloned by serialization). + */ + public boolean equals(Object obj) + { + if (obj instanceof VMID) { - if (addr[i] != other.addr[i]) - { - return false; - } + VMID other = (VMID) obj; + + // The UID's are compared faster than arrays. + return uid.equals(other.uid) && Arrays.equals(addr, other.addr); } - - return uid.equals(other.uid); - } + else + return false; + } + + /** + * Get the string representation of this VMID. + */ public String toString () { StringBuffer buf = new StringBuffer ("[VMID: "); diff --git a/libjava/classpath/java/rmi/dgc/package.html b/libjava/classpath/java/rmi/dgc/package.html index 9458d4c..7f0a208 100644 --- a/libjava/classpath/java/rmi/dgc/package.html +++ b/libjava/classpath/java/rmi/dgc/package.html @@ -1,6 +1,6 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <!-- package.html - describes classes in java.rmi.dgc package. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,7 +40,13 @@ exception statement from your version. --> <head><title>GNU Classpath - java.rmi.dgc</title></head> <body> -<p></p> - +The Distributed Garbage Collector (DGC). The DGC is reponsible for keeping all +locally created and exported remote objects as long as they are referenced +by some remote clients. The client must periodically notify the server that +it still wants to keep the remote object on the server side. The client +notifies the server by calling methods, defined in the DGC interface. +Other classes in this package define the parameters that are used in this +interface. The DGC object of some host can be found and accessed by its +object identifier (ObjID.DGC_ID), without involving the name service. </body> </html> diff --git a/libjava/classpath/java/rmi/server/ObjID.java b/libjava/classpath/java/rmi/server/ObjID.java index 07cbbde..1aaa223 100644 --- a/libjava/classpath/java/rmi/server/ObjID.java +++ b/libjava/classpath/java/rmi/server/ObjID.java @@ -1,5 +1,6 @@ -/* ObjID.java -- - Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. +/* ObjID.java -- Unique object id with respect to the given host. + Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,59 +46,152 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; -public final class ObjID implements Serializable +/** + * Represents the object identifier, unique for the host that generated it. + * The ObjID contains inside the integer object identifier that, if needed, + * may indicated that this is a reference to one of the well known objects + * on that host (registry, activator or dgc) and the {@link UID} that + * ensures uniqueness. + */ +public final class ObjID + implements Serializable { -static final long serialVersionUID = -6386392263968365220L; -private static long next = 0x8000000000000000L; -private static final Object lock = ObjID.class; - -public static final int REGISTRY_ID = 0; -public static final int ACTIVATOR_ID = 1; -public static final int DGC_ID = 2; - -private long objNum; -private UID space; - -public ObjID() { - synchronized (lock) { - objNum = next++; - } - space = new UID(); -} - -public ObjID(int num) { - objNum = (long)num; - space = new UID((short)0); -} - -public void write(ObjectOutput out) throws IOException { - DataOutput dout = (DataOutput)out; - dout.writeLong(objNum); - space.write(dout); -} - -public static ObjID read(ObjectInput in) throws IOException { - DataInput din = (DataInput)in; - ObjID id = new ObjID(); - id.objNum = din.readLong(); - id.space = UID.read(din); - return (id); -} - -public int hashCode() { - return ((int)objNum); -} - -public boolean equals(Object obj) { - if (obj instanceof ObjID && this.objNum == ((ObjID)obj).objNum) { - return (true); - } - return (false); -} - -public String toString() { - return ("[objNum: " + objNum + ", " + space + "]"); -} + /** + * Use serial version uid for interoperability. + */ + static final long serialVersionUID = - 6386392263968365220L; + + /** + * The object counter, which value is assigned when creating the ordinary + * objects without the known object id. The counter is incremented each time + * the new ObjID is constructed. + */ + private static long next = 0x8000000000000000L; + + /** + * The object to put the lock on when incrementing {@link #next} + */ + private static final Object lock = ObjID.class; + + /** + * Defines the ID of the naming service. + */ + public static final int REGISTRY_ID = 0; + + /** + * Defines the ID of the activator. + */ + public static final int ACTIVATOR_ID = 1; + + /** + * Defines the ID of the distributed garbage collector. + */ + public static final int DGC_ID = 2; + + /** + * The object Id (either well-known value or the value of the incrementing + * object counter. + */ + long objNum; + + /** + * The object unique identifier, generated individually for each object. + */ + UID space; + + /** + * Create the new object id, unique for this host. + */ + public ObjID() + { + synchronized (lock) + { + objNum = next++; + } + space = new UID(); + } + + /** + * Create the new object id defining the well known remotely accessible + * object, present in this host. The well - known objects are: + * <ul> + * <li>{@link #REGISTRY_ID} - RMI naming service.</li> + * <li>{@link #ACTIVATOR_ID} - activator</li> + * <li>{@link #DGC_ID} - distributed garbage collector (grants lease + * durations to keep the object before it is garbage collected.</li> + * </ul> + * + * @param id the well known object id, one of the above. + */ + public ObjID(int id) + { + objNum = (long) id; + space = new UID((short) 0); + } + + /** + * Write object id as long, then the object {@link UID}. + */ + public void write(ObjectOutput out) throws IOException + { + DataOutput dout = (DataOutput) out; + dout.writeLong(objNum); + space.write(dout); + } + + /** + * Read object id (as long), then the object {@link UID}. + */ + public static ObjID read(ObjectInput in) throws IOException + { + DataInput din = (DataInput) in; + ObjID id = new ObjID(); + id.objNum = din.readLong(); + id.space = UID.read(din); + return (id); + } + + /** + * Get the hashcode. + */ + public int hashCode() + { + return space == null ? (int) objNum : space.hashCode() ^ (int) objNum; + } + + /** + * Compare for equality. + */ + public boolean equals(Object obj) + { + if (obj instanceof ObjID) + { + ObjID that = (ObjID) obj; + return that.objNum == objNum && eq(that.space, space); + } + else + return false; + } + + /** + * Compare by .equals if both a and b are not null, compare directly if at + * least one of them is null. + */ + static final boolean eq(Object a, Object b) + { + if (a == null || b == null) + return a == b; + else + return a.equals(b); + } + + /** + * Get the string representation. + */ + public String toString() + { + return (objNum + ":" + space); + } } diff --git a/libjava/classpath/java/rmi/server/Operation.java b/libjava/classpath/java/rmi/server/Operation.java index 64faf66..f7b5f02 100644 --- a/libjava/classpath/java/rmi/server/Operation.java +++ b/libjava/classpath/java/rmi/server/Operation.java @@ -38,6 +38,9 @@ exception statement from your version. */ package java.rmi.server; /** + * This class was used with jdk 1.1 stubs and skeletons. It is no longer + * needed since jdk 1.2 and higher. + * * @deprecated */ public class Operation @@ -45,6 +48,7 @@ public class Operation private String operation; /** + * Create operation with the given name. * @deprecated */ public Operation (String op) @@ -53,6 +57,8 @@ public class Operation } /** + * Get the name of the operation. + * * @deprecated */ public String getOperation () @@ -61,6 +67,8 @@ public class Operation } /** + * Return the name of the operation. + * * @deprecated */ public String toString () diff --git a/libjava/classpath/java/rmi/server/RemoteObject.java b/libjava/classpath/java/rmi/server/RemoteObject.java index 60e57dc..5b926bf 100644 --- a/libjava/classpath/java/rmi/server/RemoteObject.java +++ b/libjava/classpath/java/rmi/server/RemoteObject.java @@ -39,6 +39,7 @@ package java.rmi.server; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; import java.rmi.NoSuchObjectException; @@ -101,6 +102,9 @@ public boolean equals(Object obj) { return (this == obj); } +/** + * Get the string representation of this remote object. + */ public String toString() { if (ref == null) @@ -108,55 +112,91 @@ public boolean equals(Object obj) { return (ref.toString ()); } - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException + /** + * Read the remote object from the input stream. Expects the class name + * without package first. Then the method creates and assigns the {@link #ref} + * an instance of this class and calls its .readExternal method. The standard + * packageless class names are UnicastRef, UnicastRef2, UnicastServerRef, + * UnicastServerRef2, ActivatableRef or ActivatableServerRef. + * + * @param in the stream to read from + * @throws IOException if the IO exception occurs + * @throws ClassNotFoundException if the class with the given name is not + * present in the package gnu.java.rmi.server (for the case of the + * GNU Classpath. + */ + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { String cname = in.readUTF(); - if (!cname.equals("")) + if (! cname.equals("")) { - if (cname.equals ("UnicastRef2")) - { - // hack for interoperating with JDK - cname = "UnicastRef"; - in.read (); //some unknown UnicastRef2 field - } - - // It would be nice to use RemoteRef.packagePrefix here, but for binary - // compatibility with the JDK that has to contain "sun.rmi.server"... - cname = "gnu.java.rmi.server." + cname; - try - { - Class cls = Class.forName(cname); - ref = (RemoteRef)cls.newInstance(); - } - catch (InstantiationException e1) - { - throw new UnmarshalException("failed to create ref", e1); - } - catch (IllegalAccessException e2) - { - throw new UnmarshalException("failed to create ref", e2); - } - ref.readExternal(in); + if (cname.equals("UnicastRef2")) + { + // hack for interoperating with JDK + cname = "UnicastRef"; + in.read(); // some unknown UnicastRef2 field + } + + // It would be nice to use RemoteRef.packagePrefix here, but for binary + // compatibility with the JDK that has to contain "sun.rmi.server"... + cname = "gnu.java.rmi.server." + cname; + try + { + Class cls = Class.forName(cname); + ref = (RemoteRef) cls.newInstance(); + } + catch (InstantiationException e1) + { + throw new UnmarshalException("failed to create ref", e1); + } + catch (IllegalAccessException e2) + { + throw new UnmarshalException("failed to create ref", e2); + } + ref.readExternal(in); } - else + else { - ref = (RemoteRef)in.readObject(); + ref = (RemoteRef) in.readObject(); } } -private void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException { - if (ref == null) { - throw new UnmarshalException("no ref to serialize"); - } - String cname = ref.getRefClass(out); - if (cname != null && cname.length() > 0) { - out.writeUTF(cname); - ref.writeExternal(out); - } - else { - out.writeUTF(""); - out.writeObject(ref); - } -} + /** + * Write the remote object to the output stream. This method first calls + * {@link RemoteRef#getRefClass(ObjectOutput)} on the {@link #ref} to get the + * class name without package, writes this name and then calls the + * ref.writeObject to write the data. The standard packageless class names are + * UnicastRef, UnicastRef2, UnicastServerRef, UnicastServerRef2, + * ActivatableRef or ActivatableServerRef. The empty string with the + * subsequently following serialized ref instance be written if the + * ref.getRefClass returns null. + * + * @param out the stream to write to + * @throws IOException if one occurs during writing + * @throws ClassNotFoundException never in this implementation (specified as + * part of the API standard) + * @throws UnmarshalException if the remote reference of this remote object is + * null. + */ + private void writeObject(ObjectOutputStream out) throws IOException, + ClassNotFoundException + { + if (ref == null) + { + throw new UnmarshalException("no ref to serialize"); + } + String cname = ref.getRefClass(out); + if (cname != null && cname.length() > 0) + { + out.writeUTF(cname); + ref.writeExternal(out); + } + else + { + out.writeUTF(""); + out.writeObject(ref); + } + } } diff --git a/libjava/classpath/java/rmi/server/RemoteObjectInvocationHandler.java b/libjava/classpath/java/rmi/server/RemoteObjectInvocationHandler.java index afd1d59..2c19cd5 100644 --- a/libjava/classpath/java/rmi/server/RemoteObjectInvocationHandler.java +++ b/libjava/classpath/java/rmi/server/RemoteObjectInvocationHandler.java @@ -90,6 +90,11 @@ public class RemoteObjectInvocationHandler extends RemoteObject implements static final Class[] anObjectC = new Class[] { Object.class }; /** + * The empty object array to replace null when no args are passed. + */ + static final Object[] noArgs = new Object[0]; + + /** * Construct the remote invocation handler that forwards calls to the given * remote object. * @@ -143,6 +148,9 @@ public class RemoteObjectInvocationHandler extends RemoteObject implements throw new IllegalAccessException(name + " does not implement " + Remote.class.getName()); } + + if (parameters == null) + parameters = noArgs; String name = method.getName(); switch (name.charAt(0)) @@ -172,7 +180,7 @@ public class RemoteObjectInvocationHandler extends RemoteObject implements break; case 't': if (parameters.length == 0 && name.equals("toString")) - return proxyInstance.toString(); + return "Proxy stub:"+ref.remoteToString(); break; default: break; diff --git a/libjava/classpath/java/rmi/server/RemoteServer.java b/libjava/classpath/java/rmi/server/RemoteServer.java index 9efb12a..f022b73 100644 --- a/libjava/classpath/java/rmi/server/RemoteServer.java +++ b/libjava/classpath/java/rmi/server/RemoteServer.java @@ -1,5 +1,6 @@ /* RemoteServer.java -- - Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. + Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,6 +36,7 @@ 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.server; import gnu.java.rmi.server.RMIIncomingThread; @@ -42,35 +44,72 @@ import gnu.java.rmi.server.RMIIncomingThread; import java.io.OutputStream; import java.io.PrintStream; -public abstract class RemoteServer extends RemoteObject +/** + * A common superclass for the server implementations. + */ +public abstract class RemoteServer + extends RemoteObject { -private static final long serialVersionUID = -4100238210092549637L; - -protected RemoteServer() { - super(); -} - -protected RemoteServer(RemoteRef ref) { - super(ref); -} - -public static String getClientHost() throws ServerNotActiveException { - Thread currThread = Thread.currentThread(); - if (currThread instanceof RMIIncomingThread) { - RMIIncomingThread incomingThread = (RMIIncomingThread) currThread; - return incomingThread.getClientHost(); - } else { - throw new ServerNotActiveException( - "Unknown client host - current thread not instance of 'RMIIncomingThread'"); - } -} - -public static void setLog(OutputStream out) { - throw new Error("Not implemented"); -} - -public static PrintStream getLog() { - throw new Error("Not implemented"); -} + private static final long serialVersionUID = - 4100238210092549637L; + + /** + * Does nothing, delegates to super(). + */ + protected RemoteServer() + { + super(); + } + + /** + * Does nothing, delegates to super(ref). + */ + protected RemoteServer(RemoteRef ref) + { + super(ref); + } + + /** + * Get the host of the calling client. The current thread must be an instance + * of the {@link RMIIncomingThread}. + * + * @return the client host address + * + * @throws ServerNotActiveException if the current thread is not an instance + * of the RMIIncomingThread. + */ + public static String getClientHost() throws ServerNotActiveException + { + Thread currThread = Thread.currentThread(); + if (currThread instanceof RMIIncomingThread) + { + RMIIncomingThread incomingThread = (RMIIncomingThread) currThread; + return incomingThread.getClientHost(); + } + else + { + throw new ServerNotActiveException( + "Unknown client host - current thread not instance of 'RMIIncomingThread'"); + } + } + + /** + * Set the stream for logging RMI calls. + * + * @param out the stream to set or null to turn the logging off. + */ + public static void setLog(OutputStream out) + { + throw new Error("Not implemented"); + } + + /** + * Get the stream for logging RMI calls. + * + * @return the associated stream. + */ + public static PrintStream getLog() + { + throw new Error("Not implemented"); + } } diff --git a/libjava/classpath/java/rmi/server/UID.java b/libjava/classpath/java/rmi/server/UID.java index 0f492ba..3596304 100644 --- a/libjava/classpath/java/rmi/server/UID.java +++ b/libjava/classpath/java/rmi/server/UID.java @@ -1,5 +1,5 @@ -/* UID.java -- - Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. +/* UID.java -- The unique object Id + Copyright (c) 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,86 +42,186 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.io.Serializable; - -public final class UID implements Serializable -{ -private static final long serialVersionUID = 1086053664494604050L; - -private static final Object lock = UID.class; -private static long baseTime = System.currentTimeMillis(); -private static short nextCount = Short.MIN_VALUE; -// This is sun's algorithm - don't ask me why ... -private static final int uniqueNr = (new Object()).hashCode(); - -private int unique; -private long time; -private short count; +import java.net.InetAddress; /** - * This is sun's algorithm - don't ask me why ... + * Represents the unique identifier over time for the host which has generated + * it. It contains time (when created), counter (the number of the UID + * creation order) and virtual machine id components. The UID can also be + * constructed specifying a "well known" identifier in the for of short: + * this identifier defines the UID uniqueness alone. + * + * @author Audrius Meskauskas (audriusa@bioinformatics.org) */ -public UID() { - synchronized (lock) { - if (nextCount == Short.MAX_VALUE) { - long newtime; - for (;;) { - newtime = System.currentTimeMillis(); - if (newtime - baseTime > 1000) { - break; - } - try { - Thread.sleep(1000); - } - catch (InterruptedException _) { - } - } - baseTime = newtime; - nextCount = Short.MIN_VALUE; - } - count = nextCount++; - unique = uniqueNr; - time = baseTime; - } -} - -public UID(short num) { - unique = (int)num; - time = 0; - count = 0; -} - -public int hashCode() { - return (unique); -} - -public boolean equals(Object obj) { - if (obj instanceof UID) { - UID uid = (UID)obj; - if (this.unique == uid.unique && - this.time == uid.time && - this.count == uid.count) { - return (true); - } - } - return (false); -} - -public String toString() { - return ("[UID: " + unique + "," + time + "," + count + "]"); -} - -public void write(DataOutput out) throws IOException { - out.writeInt(unique); - out.writeLong(time); - out.writeShort(count); -} - -public static UID read(DataInput in) throws IOException { - UID id = new UID(); - id.unique = in.readInt(); - id.time = in.readLong(); - id.count = in.readShort(); - return (id); -} - +public final class UID + implements Serializable +{ + /** + * Use the serial version uid for interoperability. + */ + private static final long serialVersionUID = 1086053664494604050L; + + /** + * The UID counter (the ordinary number in the sequence of number of UID's, + * created during the recent millisecond). In the next millisecond, it + * starts from the minimal value again. In the unlikely case of creating + * more than 65536 uids per millisecond the process pauses till the next + * ms. + */ + private static short uidCounter = Short.MIN_VALUE; + + /** + * The time, when the last UID has been created. + */ + private static long last; + + /** + * This constant tries to be the unique identifier of the virtual machine. + */ + private static final int machineId = getMachineId(); + + /** + * The UID number in the UID creation sequence. + */ + private short count; + + /** + * Always gets the uniqueNr value. + */ + private int unique; + + /** + * The time stamp, when the UID was created. + */ + private long time; + + /** + * Create the new UID that would have the described features of the + * uniqueness. + */ + public UID() + { + time = System.currentTimeMillis(); + unique = machineId; + if (time > last) + { + last = time; + count = uidCounter = Short.MIN_VALUE; + } + else + { + synchronized (UID.class) + { + if (uidCounter == Short.MAX_VALUE) + { + // Make a 2 ms pause if the counter has reached the maximal + // value. This should seldom happen. + try + { + Thread.sleep(2); + } + catch (InterruptedException e) + { + } + uidCounter = Short.MIN_VALUE; + time = last = System.currentTimeMillis(); + } + + count = uidCounter++; + } + } + } + + /** + * Create the new UID with the well known id (number). All UIDs, creates + * with the this constructor having the same parameter are equal to each + * other (regardless to the host and time where they were created. + * + * @param wellKnownId the well known UID. + */ + public UID(short wellKnownId) + { + unique = wellKnownId; + } + + /** + * Get the hashCode of this UID. + */ + public int hashCode() + { + return (int) (unique ^ time ^ count); + } + + /** + * Compare this UID with another UID for equality (not equal to other types of + * objects). + */ + public boolean equals(Object other) + { + if (other instanceof UID) + { + UID ui = (UID) other; + return unique == ui.unique && time == ui.time && count == ui.count; + } + else + return false; + } + + public static UID read(DataInput in) throws IOException + { + UID uid = new UID(); + uid.unique = in.readInt(); + uid.time = in.readLong(); + uid.count = in.readShort(); + return (uid); + } + + public void write(DataOutput out) throws IOException + { + out.writeInt(unique); + out.writeLong(time); + out.writeShort(count); + } + + /** + * Do our best to get the Id of this virtual machine. + */ + static int getMachineId() + { + int hostIpHash; + + try + { + // Try to get the host IP. + String host = InetAddress.getLocalHost().toString(); + // This hash is content - based, not the address based. + hostIpHash = host.hashCode(); + } + catch (Exception e) + { + // Failed due some reason. + hostIpHash = 0; + } + + // Should be the unque address if hashcodes are addresses. + // Additionally, add the time when the RMI system was probably started + // (this class was first instantiated). + return new Object().hashCode() ^ (int) System.currentTimeMillis() + ^ hostIpHash; + } + + /** + * Get the string representation of this UID. + * + * @return a string, uniquely identifying this id. + */ + public String toString() + { + int max = Character.MAX_RADIX; + // Translate into object count, counting from 0. + long lc = (count + Short.MIN_VALUE) & 0xFFFF; + return Long.toString(time, max) + ":" + + Long.toString(unique, max) + ":" + + Long.toString(lc, max); + } } |