org.openrdf.util.rmirouting
Class ChannelIfaceImpl

java.lang.Object
  extended byorg.openrdf.util.rmirouting.ChannelIfaceImpl
All Implemented Interfaces:
ChannelIface, Remote, Unreferenced

public class ChannelIfaceImpl
extends Object
implements ChannelIface, Unreferenced

The implementation of a server side ChannelIface wraper used to handle all the method invocation requests made by a client. It's instances can be accessed via the standart RMI subsystem.

To create and support the notion of session we provide a single, inheritable server context, into which the current session settings are stored and mantained.

This is necessary because, while working with Sesame remotely through some already exported object references, you share server resources with the other users, which may work simolatenously with Sesame either via the HTTP or RMI. So these context help so keep track of the user from whict the cirrrent request is originated.

An example of such different, per session, settings are current user id, its password, currently selected reposiotry, etc. So to allow a smooth multiuser access trough all the various access layers to a single running Sesame server. To identify the different conteexts we use a cookie which is unique among the different sessinos, but its value is inherited from the current one, automaticaly, when a stub is created at the server.

The usual way to export a stub, allowing remote access to an instance, is through the static createStub() method of this class.

 ...
 SesameService localSesame = Sesame.getService("system.conf");
 Remote remoteServiceStub = ChannelIfaceImpl.createStub(localSesame);
 ...
 

While transported to the client. it can wrap this Remote ref into dynamic proxy localy with the static ChannelIfaceInvocation.wrapIt() method.

 ...
 SesameService remoteSesame = (SesameService)ChannelIfaceInvocation.wrapIt(remote);
 remoteSesame.login(user, pass);
 ...
 
All this wrapping is made automaticaly becasue all the remote calls are routed trough instances of ChannelIfaceImpl and ChannelIfaceInvocation where such wrappig/stubbing is done for all method arguments and its return value on both sides of the channel.

So only the first ever instance(usualy the one retieved from the RMI Registry) should be wrapped in that manner as it is shown in the example above.

Example on how to bind a factory to the local registry:

  ...
     try {
       SesameStartup.initialize(system_conf_path);
       String sFound[] = null;
       try {
         sFound = java.rmi.Naming.list("rmi://localhost:"+RMICenter.sRMIPort+"/FactoryInterface");
       } catch (java.rmi.ConnectException e) {
       }
       if (sFound == null || sFound.length == 0) {
           SesameServer.getSystemConfig().setRMIFactory("org.openrdf.sesame.server.rmi.FactoryInterfaceImpl", Integer.parseInt(RMICenter.sRMIPort));
           SesameServer.getSystemConfig().setRMIEnabled(true);
           FactoryInterfaceImpl.bind(new Integer(RMICenter.sRMIPort));
           ThreadLog.log("RMI binded to "+RMICenter.sRMIPort);
         } else {
           ThreadLog.log("Probably RMI binded to "+sFound[0]);
      }
  ...
 

and a short example showing how you could use Sesame locally or remote:

  ...
        FactoryInterface fi = null;
        SesameRepository rep = null;
        if (bRemoteOrLocal) {
 //remote
          try {
            fi = (FactoryInterface)ChannelIfaceInvocation.
                 wrapIt(java.rmi.Naming.lookup("//localhost:"+sRMIPort+"/FactoryInterface"));
          } catch (Throwable t) {
            t.printStackTrace();
            return;
          }

          SesameService si = fi.getService();
          si.login("testuser", "testpass");
          rep = si.getRepository(sRepository);
        } else {
 //local
          SesameStartup.initialize(sSystemConfFile);
          rep = SesameServer.getLocalService().getRepository(RMICenter.sRepository);
        }
 // eval a simple SeRQL query, no matter where is Sesame
        String query = "select X from "+
          "{X} <rdf:type> {<rdfs:Class>} "+
          "using namespace "+
          "rdf = <!http://www.w3.org/1999/02/22-rdf-syntax-ns#> , "+
          "rdfs = <!http://www.w3.org/2000/01/rdf-schema#> ";

          LocalQueryListener sysOutQL = new LocalQueryListener(-1);
          rep.performTableQuery(QueryLanguage.SERQL, query, sysOutQL);
  ...
 

Version:
1.0
Author:
Damyan Ognyanoff

Method Summary
 void batch(Object[] jobs)
          here we got the tricky part.
static Remote createStub(Object instance)
          Creates an instance of the ChannelIfaceImpl which wraps the passed object and register it into the RMI object table, so its methods can be invoked remotely by its RemoteRef.
 String[] getInterfaces()
          getInterfaces is used by the client to obtain a list of the implemented, by the wrapped instance, interfaces .
static ChannelIfaceImpl getRef(Remote stub)
          a way to retrieve an associated instance by its wraping stub
 void gotFinalized()
          gotFinalized() used by the client to notify this stub thet it was being 'garbage collected' at client side so we ca be quite sure that the association between this stub and the wraped instance can be safely removed from the storage map
 Object invoke(Object methodDescription, Object[] args)
          invoke - invokes a method of an 'instance' via reflection
static void setCurrentCookie(Object cookie)
          use it to set the thread cookie
static void setEpilogAction(RoutingAction newAction)
          a way to set an action which can cleanup the proper context at the server.
static void setPrologAction(RoutingAction newAction)
          a way to set an aicton which can be able to setup the proper context at the server.
 void unreferenced()
          unreferenced would be invoked by the DGC when the last remote reference to thist stub is being 'garbage collected'.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

setCurrentCookie

public static void setCurrentCookie(Object cookie)
use it to set the thread cookie

Parameters:
cookie - to set

getRef

public static ChannelIfaceImpl getRef(Remote stub)
a way to retrieve an associated instance by its wraping stub

Parameters:
stub - for which the associated instance to be retrieved
Returns:
the associated with the stub instance or null if not found in the map

setPrologAction

public static void setPrologAction(RoutingAction newAction)
a way to set an aicton which can be able to setup the proper context at the server. It should use the current thread cookie

Parameters:
newAction - to be set

setEpilogAction

public static void setEpilogAction(RoutingAction newAction)
a way to set an action which can cleanup the proper context at the server. It should use the current thread cookie

Parameters:
newAction - to be set

createStub

public static Remote createStub(Object instance)
Creates an instance of the ChannelIfaceImpl which wraps the passed object and register it into the RMI object table, so its methods can be invoked remotely by its RemoteRef. An association between the stub and wraped instance is stored into a map member and can be queried later with getRef.

Parameters:
instance - to be wraped and for which an Remote stub to be created
Returns:
the remote stub to the wraped instance. Note: the wraped instance should implement at least one java interface. The methods of the all the implemented interfaces by the instance and its ancestors, down to the Object class, will be exposed to the client and be visible and availible for invocation.

unreferenced

public void unreferenced()
unreferenced would be invoked by the DGC when the last remote reference to thist stub is being 'garbage collected'. At this point we safely can remove the association between the stub and the wraped instance form the map. It is derived from the java.rmi.server.Unreferenced interface.

Specified by:
unreferenced in interface Unreferenced

getInterfaces

public String[] getInterfaces()
                       throws RemoteException
getInterfaces is used by the client to obtain a list of the implemented, by the wrapped instance, interfaces . This list is used to create a dynamic proxy ont the client side, which is used to invoke any of the methods declared within these interfaces.

Specified by:
getInterfaces in interface ChannelIface
Returns:
an array of Strings with the class names of the implemented interfaces
Throws:
RemoteException

invoke

public Object invoke(Object methodDescription,
                     Object[] args)
              throws RemoteException
invoke - invokes a method of an 'instance' via reflection

Specified by:
invoke in interface ChannelIface
Parameters:
methodDescription - a description of the method being invoked
args - - parameters opassed to the method during the call
Returns:
the result of the invocation or null if the method returns 'void'
Throws:
RemoteException

gotFinalized

public void gotFinalized()
                  throws RemoteException
gotFinalized() used by the client to notify this stub thet it was being 'garbage collected' at client side so we ca be quite sure that the association between this stub and the wraped instance can be safely removed from the storage map

Specified by:
gotFinalized in interface ChannelIface
Throws:
RemoteException

batch

public void batch(Object[] jobs)
           throws RemoteException
here we got the tricky part. The method batch is used to pass a bunch of methods that needs to be invoked by this stub with just one RMI call. In such a way we can reduce the network traffic and long delays because of the time needed by the RMI to complete a single method call. Not all invoked methods can be a subject of such batching. We decide to batch only methods that return 'void' and their arguments are either Serializable or just a native ones (e.g. char, byte, long, etc.) the client proxy can decide while it shoud commit the 'batchJob' queue. This usually can happen if a 'non-void' method or a method with non-Seralizable' or native arguments is being invoked. In such a case first the queue is flushed and the that method is passed to the stub here. In order to enable this functionality the wrapped instance should implement Batchable interface.

Specified by:
batch in interface ChannelIface
Parameters:
jobs - an array of Job objects that we need to process at once each Job object has the method description and array arguments use so wen can invoke it directly
Throws:
RemoteException - that can wrap any of the exception conditions found during the execution


Copyright © 2002-2006 Aduna BV, GNU LGPL License applies.