Class Remote

All Implemented Interfaces:
Invoke, RemoteInvoke, Serializable, Remote, Unreferenced

public final class Remote extends UnicastRemoteObject implements RemoteInvoke, Unreferenced
This class takes any object, and allows it to be called from remote VMs. This class eliminates the need to maintain multiple specialised stubs for multiple, application specific objects. It effectively allows any object to be remoted, and makes all of the object's public methods, including its static ones, remotely callable. It also contains several very useful utility methods, to further support the invoke package paradigm.

It can also be run as an application, to load an object from a URL, and remote it within a JVM.

Version:
1.0, 01-Nov-99 Initial release
See Also:
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    private static final class 
     
    private static final class 
     
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private static final HashMap
     
    private static String
     
    private static int
     
    private static Remote.RCSF
     
    private static Remote.RSSF
     
    private static String
     
    private static int
     
    final Object
    This is the reference to the local (or possibly remote) object reference being made remotely invokable by this Virtual Machine.
    private static final Vector
     
    private static final Object[]
     
    private static final Class[]
     
    private static final Class[]
     
    private boolean
     

    Fields inherited from class java.rmi.server.RemoteObject

    ref
  • Constructor Summary

    Constructors
    Constructor
    Description
    Remote(Object item)
    The constructor takes any object, and allows it to be remotely invoked.
    This constructor allows for complete configuration of an object's remoting; normally this should be used for rare and highly specialised cases.
    Remote(Object item, String host, int port)
    The constructor takes any object, and allows it to be remotely invoked.
  • Method Summary

    Modifier and Type
    Method
    Description
    static Class
    This method emulates server Java5 argument autoboxing.
    This method controls the automatic-unexporting of a remote reference when it is no longer referenced by any clients.
    static void
    config(int serverPort, String clientHost, int clientPort, String proxyHost, int proxyPort, String username, String password)
    This method configures the server's TCP parameters for RMI through HTTP proxy servers.
    static void
    config(String serverHost, int serverPort, String clientHost, int clientPort)
    This method configures the server's TCP parameters for RMI.
    protected void
    If the remote wrapper is being garbage collected, and it hasn't already been explicitly unexported, let's do that now, as a courtesy.
    static Method
    findBestMethod(Object item, String method, Class[] args)
    This method attempts to resolve the argument inheritance blindness in Java reflection-based method selection.
    static String
    This is the default server network address on which left unspecified, clients connect to remoted items.
    static int
    This is the default server host port on which left unspecified, items are being remoted.
    This is the default RMIClientSocketFactory on which left unspecified, items are being remoted.
    static String
    This is the default server host address on which left unspecified, items are being remoted.
    static int
    This is the default client port on which left unspecified, items are being remoted.
    This is the default RMIServerSocketFactory on which left unspecified, items are being remoted.
    static Object
    A utility method to load either an item, or a zipped marshalled object (zedmob) of an item, from a URL, file, or from a remote rmiregistry.
    static Object
    invoke(Object item, String method, Object args)
    This function may be called reentrantly, so the item object must synchronize its critical sections as necessary.
    invoke(String method, Object args)
    The sole generic, multi-purpose interface for communication between VMs.
    static void
    main(String[] args)
    The application method loads a zipped marshalled object (zedmob) from a URL, or a file, and allows it run in this virtual machine.
    send(String url)
    This method sends its remote reference to another item, either from a URL, file, or from a remote rmiregistry.
    static void
    This method will brutally un-remote all currently remotely invocable wrappers.
    boolean
    unexport(boolean force)
    This method will attempt to make the wrapper no longer remotely invocable.
    static boolean
    unexportObject(Remote obj, boolean force)
    Deprecated.
    It is strongly recommended to use the instance method unexport, for improved code clarity.
    void
    This method is called by the RMI runtime sometime after it determines the collection of listening clients becomes empty.
    static Object
    A utility method to reconstitute a zipped marshalled object (zedmob) into a remote item reference, proxy object, or local object.
    void
    This method will write this remote item reference to an output stream as a zipped marshalled object (zedmob).
    static void
    This method will write the local item, remote item reference, or proxy, to an output stream as a zipped marshalled object (zedmob).

    Methods inherited from class java.rmi.server.UnicastRemoteObject

    clone, exportObject, exportObject, exportObject, exportObject, exportObject

    Methods inherited from class java.rmi.server.RemoteServer

    getClientHost, getLog, setLog

    Methods inherited from class java.rmi.server.RemoteObject

    equals, getRef, hashCode, toString, toStub

    Methods inherited from class java.lang.Object

    getClass, notify, notifyAll, wait, wait, wait
  • Field Details

    • defaultServerHost

      private static String defaultServerHost
    • defaultClientHost

      private static String defaultClientHost
    • defaultServerPort

      private static int defaultServerPort
    • defaultClientPort

      private static int defaultClientPort
    • defaultRCSF

      private static Remote.RCSF defaultRCSF
    • defaultRSSF

      private static Remote.RSSF defaultRSSF
    • cache

      private static final HashMap cache
    • items

      private static final Vector items
    • NULL

      private static final Class[] NULL
    • OBJECT

      private static final Class[] OBJECT
    • NOARGS

      private static final Object[] NOARGS
    • unexportOnUnreference

      private boolean unexportOnUnreference
    • item

      public final Object item
      This is the reference to the local (or possibly remote) object reference being made remotely invokable by this Virtual Machine. It is declared public to provide the convenience to refer to both the wrapper, and its wrapped object, via a single reference.
  • Constructor Details

    • Remote

      public Remote(Object item) throws RemoteException
      The constructor takes any object, and allows it to be remotely invoked. If the object implements the Invoke interface, it will route all remote invocations directly to it. Otherwise it will use Java reflection to attempt to invoke the remote calls directly on the object's public methods.
      Parameters:
      item - The object to make remotely callable. It may be an arbitrary object of any type, it can even be a reference to a remote reference from another host, being re-remoted through this JVM.
    • Remote

      public Remote(Object item, String host, int port) throws RemoteException
      The constructor takes any object, and allows it to be remotely invoked. If the object implements the Invoke interface, it will route all remote invocations directly to it. Otherwise it will use Java reflection to attempt to invoke the remote calls directly on the object's public methods.
      Parameters:
      item - The object to make remotely callable. It may be an arbitrary object of any type, it can even be a reference to a remote reference from another host, being re-remoted through this JVM.
      host - The network interface on which clients will communicate with this item. It is typically specified when clients have more than one.
      port - The TCP port over which the server and client will communicate
    • Remote

      public Remote(Object item, int port, RMIServerSocketFactory rssf, RMIClientSocketFactory rcsf) throws RemoteException
      This constructor allows for complete configuration of an object's remoting; normally this should be used for rare and highly specialised cases. Any or all of the parameters can be null (or zero in the case of the port) to use the default static values. Most often this used to add encrypted sockets to the framework. Note: the RMIClientSocketFactory must be seriallisable.
      Parameters:
      item - The object to make remotely callable. It may be an arbitrary object of any type, it can even be a reference to a remote reference from another host, being re-remoted through this JVM.
      port - The server TCP port number on which the server will be operating.
      rssf - The custom server socket factory to be used to accept connections from remote clients.
      rcsf - The custom client socket factory to be used to communicate with this item, by remote clients. (please regard carefully the note above)
  • Method Details

    • finalize

      protected void finalize() throws Throwable
      If the remote wrapper is being garbage collected, and it hasn't already been explicitly unexported, let's do that now, as a courtesy.
      Overrides:
      finalize in class Object
      Throws:
      Throwable
    • getDefaultServerSocketFactory

      public static RMIServerSocketFactory getDefaultServerSocketFactory()
      This is the default RMIServerSocketFactory on which left unspecified, items are being remoted. Its value can be changed via the static config method.
      Returns:
      The server socket factory on which the item is accepting inbound connections
    • getDefaultClientSocketFactory

      public static RMIClientSocketFactory getDefaultClientSocketFactory()
      This is the default RMIClientSocketFactory on which left unspecified, items are being remoted. Its value can be changed via the static config method.
      Returns:
      The client socket factory on which the item is accepting inbound connections
    • getDefaultServerHost

      public static String getDefaultServerHost()
      This is the default server host address on which left unspecified, items are being remoted. Its value can be changed via the static config method.
      Returns:
      The network interface on which the item is accepting inbound connections
    • getDefaultServerPort

      public static int getDefaultServerPort()
      This is the default client port on which left unspecified, items are being remoted. Its value can be changed via the static config method. It is generally the same as the default server port, unless port translation is being used
      Returns:
      The network interface TCP port on which the item is accepting inbound connections
    • getDefaultClientHost

      public static String getDefaultClientHost()
      This is the default server network address on which left unspecified, clients connect to remoted items. Its value can be changed via the static config method. It is typically different from the default server host if the remoted items are operating behind NAT.
      Returns:
      The network interface on which the the item is accepting inbound connections from clients
    • getDefaultClientPort

      public static int getDefaultClientPort()
      This is the default server host port on which left unspecified, items are being remoted. Its value can be changed via the static config method.
      Returns:
      The network interface TCP port on which the item is accepting inbound connections
    • config

      public static void config(String serverHost, int serverPort, String clientHost, int clientPort)
      This method configures the server's TCP parameters for RMI. It allows complete specification of client-side and server-side ports and hostnames. It used to override the default values, which are anonymous, meaning from an unused pool, selected by the OS. It is necessary when either the VM is operating behind a firewall, has multiple network interfaces, is multi-homed, or is using NAT. The first two parameters control how the sockets will be configured locally, the second two control how a remote object's sockets will be configured to communicate with this server.

      Note: If this class is to be specifically configured, it must be done before any items are remoted. It can be called only one time, any subsequent calls will result in an IllegalArgumentException being thrown.

      Parameters:
      serverHost - The local network interface on which the item will will be remotely invokable. Typically it is specified when the server has multiple phyisical network interfaces, or is multi-homed, i.e. having multiple logical network interfaces. The value can be null, which will make the item accessible on all network interfaces, this is identical to providing the special port address "0.0.0.0".
      serverPort - Specifies the local port on which the server is serving clients. It can be zero, to use an anonymous port. If firewalls are being used, it must be an accessible port, into this server. If this port is zero, and the ClientPort argument is non-zero, then the ClientPort value will automatically substituted.
      clientHost - The host name, or IP address the remote client will use to communicate with this server. If null, it will be the same as serverHost resolution. This would need to be explicitly specified if the server is operating behind NAT; i.e. when the server's subnet IP address is not the same as its address outside the subnet.
      clientPort - Specifies the particular port on which the client will connect to the server. Typically this is the same number as the serverPort argument, but could be different, if port translation is being used. If the clientPort field is 0, i.e. anonymous, its port value will be automatically assigned to match the server, even if the server port is also anonymous.
    • config

      public static void config(int serverPort, String clientHost, int clientPort, String proxyHost, int proxyPort, String username, String password)
      This method configures the server's TCP parameters for RMI through HTTP proxy servers. This is necessary when the client or server, or both, are behind firewalls, and the only method of access to the internet is through HTTP proxy servers. There will be a fairly significant performance hit incurred using the HTTP tunnel, but it is better than having no connectivity at all. Due to an unfortunate oversight in the design of the standard RMISocketFactory, no server network interface can be specified, instead it will listen on all network interfaces. It is probably not a problem for most, but is probably not desirable for multi-homed hosts.

      Note: If this class is to be configured, it must be done before any items are remoted.

      Parameters:
      serverPort - Specifies the local port on which the server is serving clients. It can be zero, to use an anonymous port. If firewalls are being used, it must be an accessible port, into this server. If this port is zero, and the ClientPort argument is non-zero, then the ClientPort value will automatically substituted.
      clientHost - The host name, or IP address the remote client will use to communicate with this server. If null, it will be the same as serverHost resolution. This would need to be explicitly specified if the server is operating behind NAT; i.e. when the server's subnet IP address is not the same as its address outside the subnet.
      clientPort - Specifies the particular port on which the client will connect to the server. Typically this is the same number as the serverPort argument, but could be different, if port translation is being used. If the clientPort field is 0, i.e. anonymous, its port value will be automatically assigned to match the server, even if the
      proxyHost - The name or address of the proxy server used to gain HTTP access to the internet.
      proxyPort - The port number of the proxy server used to gain HTTP access to the internet.
      username - The proxy account user name required for permission, if non-null.
      password - The proxy account password required for permission, if non-null.
    • shutdown

      public static void shutdown()
      This method will brutally un-remote all currently remotely invocable wrappers. This can be used to allow the JVM to shut down without having to call System.exit() also, to support use in managed container systems. Following this execution, objects can be newly remoted again.
    • zedmob

      public static Object zedmob(InputStream is) throws ClassNotFoundException, IOException
      A utility method to reconstitute a zipped marshalled object (zedmob) into a remote item reference, proxy object, or local object. Typically a file containing a zedmob has the file extension .zmob as an identifier.

      Note: on completion of reading the item from the stream, the stream will be automatically closed.

      Parameters:
      is - The input stream containing the zedmob of the item reference.
      Returns:
      A reconstituted reference to the item.
      Throws:
      IOException - if the zedmob format is invalid.
      ClassNotFoundException - if a proxy object was sent, and remote class loading was not enabled in this VM.
    • zedmob

      public static void zedmob(OutputStream os, Object ref) throws IOException
      This method will write the local item, remote item reference, or proxy, to an output stream as a zipped marshalled object (zedmob). A zedmob is the standard serialized format in this paradigm. This can be used to 'freeze-dry' the object to a file for later use, to send it over the network, or to an object archival service, for example.

      Note: on completion of writing the item, or reference, the stream will be closed. Typically, when saved to a file, a zedmob has the file extension .zmob to provide obvious identification.

      Parameters:
      os - The output stream on which to write the reference. It may be a file stream, a socket stream, or any other type of stream.
      ref - The item or reference to be serialized.
      Throws:
      IOException - For any stream related writing error.
    • getItem

      A utility method to load either an item, or a zipped marshalled object (zedmob) of an item, from a URL, file, or from a remote rmiregistry. If the item is in a local file, it can be either inside the server's jar file, or on its local file system.

      Loading an item from a file can be specified in one of three ways:

      • As a URL; in the format file://path/name.
      • As a class file; in the format path/name
      • As a serialized item; in the format /path/name

      File loading will first be attempted from within the server's jar file, if that fails, it will then look in the local filesystem.

      Note: any socket connections made by the incoming item cannot be known at compile time, therefore proper operation if this VM is behind a firewall could be blocked. Use behind a firewall would require knowing all the ports that would be needed in advance, and enabling them before loading the proxy.

      Parameters:
      url - The URL where to get the object: file://, http://, ftp://, /path/name, path/name, or //[host][:port]/[name]. The host, port, and name, are all optional. If missing the host is presumed local, the port 1099, and the name "main". The referenced resource can be returned as a MarshalledObject, it will be extracted automatically. If the URL is null, it will be assumed to be ///.
      Returns:
      A reference to the item contained in the URL. It may be either local, or remote to this VM.
      Throws:
      RemoteException - if the remote registry could not be reached.
      NotBoundException - if the requested name is not in the registry.
      IOException - if the zedmob format is invalid.
      ClassNotFoundException - if a proxy was sent to the VM, and proxy hosting was not enabled.
      InstantiationException - when the URL specifies a class name which cannot be instantiated at runtime.
      IllegalAccessException - when the url specifies a class name and it does not support a no-arg constructor.
      MalformedURLException - if the URL is not in the format explained
    • autobox

      public static Class autobox(Class arg)
      This method emulates server Java5 argument autoboxing. It is used by findBestMethod. This technique has been most graciously championed by project member Zac Wolfe. It allows public server methods to use primitive types for arguments, and return values.
      Parameters:
      arg - The the argument class to test for boxing. If the argument type is primitive, it will be substituted with the corresponding primitive class representation.
      Returns:
      The corresponding class matching the primitive type, or the original argument class, if it is not primitive.
    • findBestMethod

      public static Method findBestMethod(Object item, String method, Class[] args)
      This method attempts to resolve the argument inheritance blindness in Java reflection-based method selection. It has been most graciously championed by project member Fredrik Larsen, with help from project member Li Ma. If more than one matching method is found, based on argument polymorphism, it will try to select the most applicable one. It works very well if the inheritence trees for the arguments are shallow. However, it may not always pick the best method if the arguments have deep inheritance trees. Fortunately it works for both classes, and interfaces.
      Parameters:
      item - The object on which to find the most applicable public method.
      method - The name of the method, which is to be invoked.
      args - The class representations of the arguments to be provided to the method, it can be either null or length 0, if the method takes no arguments
      Returns:
      The most applicable method, which will accept all of these arguments, or null, if none match.
    • invoke

      public static Object invoke(Object item, String method, Object args) throws Exception
      This function may be called reentrantly, so the item object must synchronize its critical sections as necessary. The specified method will be invoked, with the provided arguments if any, on the internal object's public method via the framework Java reflection mechanism, and the result returned, if any. The method is declared static to centralize the implementation, and allow other derived classes to use this mechanism without having to reimplement it.
      Parameters:
      item - The object on which to invoke the method. If the item implements the Invoke interface, the call will be passed directly to it.
      method - The method name to be invoked.
      args - The arguments to provide to the method for its invocation.
      Returns:
      The resulting data, if any, from the invocation. Note: if the method invocation is remote, and the result is neither serialisable, nor a remote object reference; the object, if non-null, will be automatically returned in a TransparentItemProxy, implementing all of the interfaces of the return object instance.
      Throws:
      IllegalArgumentException - If the method argument is null.
      NoSuchMethodException - If no matching method can be found.
      Exception - If the item rejected the invocation, for application specific reasons. The cause of the exception will be automatically unpacked from an internally resulting java.lang.reflect.InvocationTargetException, to provide the calling code with the actual exception resulting from the method invocation. Special thanks to Petr Stepan for pointing out this improvement, and providing a link to the discussion.
    • unexport

      public boolean unexport(boolean force) throws NoSuchObjectException
      This method will attempt to make the wrapper no longer remotely invocable. As a list of all remoted wrappers is maintained, this method will remove the reference from the list. If a lot of objects are being remoted and unremoted during the life of the JVM, it is highly recommended to use this method, rather than the inherited static unexportObject method, as it will not remove the reference from the internal list.
      Parameters:
      force - true to un-remote the object wrapper, even if invocations are in progress or pending, if false, do not un-remote unless idle.
      Returns:
      true if the wrapper was successfully un-remoted, false if it is still remoted.
      Throws:
      NoSuchObjectException - If this wrapper has already been un-remoted
    • unexportObject

      public static boolean unexportObject(Remote obj, boolean force) throws NoSuchObjectException
      Deprecated.
      It is strongly recommended to use the instance method unexport, for improved code clarity.
      This this method overrides the implementation provided by the superclass UnicastRemoteObject. It will route the invocation to the instance unexport method of this class, to properly remove the remote reference from the internal list of exported objects. This list is needed to support the static shutdown method provided by this class.
      Throws:
      NoSuchObjectException
    • invoke

      public Object invoke(String method, Object args) throws Exception
      The sole generic, multi-purpose interface for communication between VMs. This function may be called reentrantly, so the inner object must synchronize its critical sections as necessary. Technically, it simply passes the call to this class' static invoke method. If the arriving arguments are encapsulated in a MarshalledObject, they will be extracted here automatically.
      Specified by:
      invoke in interface Invoke
      Parameters:
      method - The method to invoke on the internal object.
      args - The arguments to provide to the method for its invocation. It can be a single object, an array of objects, or even null.
      Returns:
      The sychronous data, if any, resulting from the invocation.
      Throws:
      RemoteException - For network communication related reasons.
      IllegalArgumentException - If reflection is going to be used, and the method argument is null.
      NoSuchMethodException - If no matching method can be found.
      Exception - If the internal item rejected the invocation, for application specific reasons.
    • send

      public Object send(String url) throws Exception
      This method sends its remote reference to another item, either from a URL, file, or from a remote rmiregistry. It will invoke the local getItem method to obtain a reference to the remote item. It will next invoke the received reference's invoke method with a "send" value, and a reference to itself as its sole argument.
      Parameters:
      url - The URL where to get the remote host interface: file://, http://, ftp://, /path/name, path/name, or //[host][:port]/[name]. The host, port, and name, are all optional. If missing the host is presumed local, the port 1099, and the name "main". If the URL is null, it will be assumed to be ///.
      Returns:
      Whatever the item returns in receipt of the reference, even null.
      Throws:
      Exception - Either from the getItem invocation, or if the item reference invocation fails.
    • zedmob

      public void zedmob(OutputStream os) throws IOException
      This method will write this remote item reference to an output stream as a zipped marshalled object (zedmob). A zedmob is the standard serialized format for a remote item reference, in this paradigm. This can be used to 'freeze-dry' the remote reference, to a file for later use, send it over the network, or to an object archival service, for example.
      Parameters:
      os - The output stream on which to write the reference. It may be a file stream, a socket stream, or any other type of stream.
      Throws:
      IOException - For any stream related writing error.
    • unreferenced

      public void unreferenced()
      This method is called by the RMI runtime sometime after it determines the collection of listening clients becomes empty. If the wrapped object whishes to be notified of being unreferenced, it need only implement the java.rmi.server.Unreferenced interface itself, and the invocation will be passed along. Normally it is used to close any open resources, needed to serve its clients. Highest thanks to Petr Stepan, for the suggestion for this most excellent addition.
      Specified by:
      unreferenced in interface Unreferenced
    • clientScope

      public Remote clientScope()
      This method controls the automatic-unexporting of a remote reference when it is no longer referenced by any clients. Often an application will provide a remote reference to a special short-term use object on the client side. The RMI runtime does not automatically unexport remote references, as they typically belong to server objects. Remoted object references used for temporary transactions, e.g. Futures, can quickly accumulate into a large memory leak. Once unexported, this remote object wrapper is no longer remotely invocable. The wrapped object can be provided to a new instance of Remote, to make it remotely invocable again. It effectively places the lifetime of this object under the control of the client(s), rather than the server, which is normally the case. Quite simply, it causes the unexport method to be called implicitly, when the wrapper becomes unreferenced by all clients. Very handy and important!
      Returns:
      A reference to this wrapper, purely to allow the convenient construct of:

      return new Remote(tempObj).clientScope();

    • main

      public static void main(String[] args) throws Exception
      The application method loads a zipped marshalled object (zedmob) from a URL, or a file, and allows it run in this virtual machine. It uses the getItem method to load the item. Following loading of the item, it will also create an rmiregistry, and bind a remote reference to it under the name "main". This will also allow remote clients to connect to, and interact with it.

      Note:It will require a security policy, to define what permissions the loaded item will be allowed. There are six optional configuration parameters:

      • args[0] The optional URL where to get the object: file:// http:// ftp:// ..., /path/name , path/name , or alternatively; //[host][:port]/[name]. If no arguments are provided, the URL will be assumed to be //localhost:1099/main.
      • args[1] The optional external client host name, if using NAT.
      • args[2] The optional external client port number, if using NAT.
      • args[3] The optional internal client host name, if multi home/NIC.
      • args[4] The optional internal client port number, if using NAT.
      • args[5] The optional URL where to get a proxy item: file:// http:// ftp:// ..., //host:port/name (rmiregistry), /path/name (serialized), or path/name (class). It will be passed into the loaded proxy as the sole argument to a setItem method invoked on the loaded item.
      Throws:
      Exception