net.jini.jeri
Class BasicInvocationDispatcher

java.lang.Object
  extended by net.jini.jeri.BasicInvocationDispatcher
All Implemented Interfaces:
InvocationDispatcher
Direct Known Subclasses:
AccessILFactory.AccessDispatcher, SystemAccessILFactory.SystemDispatcher

public class BasicInvocationDispatcher
extends Object
implements InvocationDispatcher

A basic implementation of the InvocationDispatcher interface, providing preinvocation access control for remote objects exported using BasicJeriExporter.

This invocation dispatcher handles incoming remote method invocations initiated by proxies using BasicInvocationHandler, and expects that a dispatched request, encapsulated in the InboundRequest object passed to the dispatch method, was sent using the protocol implemented by BasicInvocationHandler.

A basic permission-based preinvocation access control mechanism is provided. A permission class can be specified when an invocation dispatcher is constructed; instances of that class are constructed using either a Method instance or a String representing the remote method being invoked. The class can have a constructor with a Method parameter to permit an arbitrary mapping to the actual permission target name and actions; otherwise, the class must have a constructor taking the fully qualified name of the remote method as a String. For each incoming call on a remote object, the client subject must be granted the associated permission for that remote method. (Access control for an individual remote method can effectively be disabled by granting the associated permission to all protection domains.) A simple subclass of AccessPermission is typically used as the permission class.

Other access control mechanisms can be implemented by subclassing this class and overriding the various protected methods.

This class is designed to support dispatching remote calls to the ProxyTrust.getProxyVerifier method to the local ServerProxyTrust.getProxyVerifier method of a remote object, to allow a remote object to be exported in such a way that its proxy can be directly trusted by clients as well as in such a way that its proxy can be trusted by clients using ProxyTrustVerifier.

Since:
2.0
Author:
Sun Microsystems, Inc.
See Also:
BasicInvocationHandler
Implementation Specifics:
This implementation uses the following system property:
com.sun.jini.jeri.server.suppressStackTrace
If true, removes server-side stack traces before marshalling an exception thrown as a result of a remote call. The default value is false.

This implementation uses the Logger named net.jini.jeri.BasicInvocationDispatcher to log information at the following levels:

Level Description
FAILED exception that caused a request to be aborted
FAILED exceptional result of a remote call
FINE incoming remote call
FINE successful return of remote call
FINEST more detailed information on the above (for example, actual argument and return values)

Constructor Summary
BasicInvocationDispatcher(Collection methods, ServerCapabilities serverCapabilities, MethodConstraints serverConstraints, Class permissionClass, ClassLoader loader)
          Creates an invocation dispatcher to receive incoming remote calls for the specified methods, for a server and transport with the specified capabilities, enforcing the specified constraints, performing preinvocation access control using the specified permission class (if any).
 
Method Summary
protected  void checkAccess(Remote impl, Method method, InvocationConstraints constraints, Collection context)
          Checks that the client has permission to invoke the specified method on the specified remote object.
static void checkClientPermission(Permission permission)
          Checks that the client subject for the current remote call has the specified permission.
static void checkPermissionClass(Class permissionClass)
          Checks that the specified class is a valid permission class for use in preinvocation access control.
protected  ObjectInputStream createMarshalInputStream(Object impl, InboundRequest request, boolean integrity, Collection context)
          Returns a new marshal input stream to use to read objects from the request input stream obtained by invoking the getRequestInputStream method on the given request.
protected  ObjectOutputStream createMarshalOutputStream(Object impl, Method method, InboundRequest request, Collection context)
          Returns a new marshal output stream to use to write objects to the response output stream obtained by invoking the getResponseOutputStream method on the given request.
 void dispatch(Remote impl, InboundRequest request, Collection context)
          Dispatches the specified inbound request to the specified remote object.
protected  ClassLoader getClassLoader()
          Returns the class loader specified during construction.
protected  Object invoke(Remote impl, Method method, Object[] args, Collection context)
          Invokes the specified method on the specified remote object impl, with the specified arguments.
protected  void marshalReturn(Remote impl, Method method, Object returnValue, ObjectOutputStream out, Collection context)
          Marshals the specified return value for the specified remote method to the marshal output stream, out.
protected  void marshalThrow(Remote impl, Method method, Throwable throwable, ObjectOutputStream out, Collection context)
          Marshals the throwable for the specified remote method to the marshal output stream, out.
protected  Object[] unmarshalArguments(Remote impl, Method method, ObjectInputStream in, Collection context)
          Unmarshals the arguments for the specified remote method from the specified marshal input stream, in, and returns an Object array containing the arguments read.
protected  Method unmarshalMethod(Remote impl, ObjectInputStream in, Collection context)
          Unmarshals a method representation from the marshal input stream, in, and returns the Method object corresponding to that representation.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

BasicInvocationDispatcher

public BasicInvocationDispatcher(Collection methods,
                                 ServerCapabilities serverCapabilities,
                                 MethodConstraints serverConstraints,
                                 Class permissionClass,
                                 ClassLoader loader)
                          throws ExportException
Creates an invocation dispatcher to receive incoming remote calls for the specified methods, for a server and transport with the specified capabilities, enforcing the specified constraints, performing preinvocation access control using the specified permission class (if any). The specified class loader is used by the createMarshalInputStream method.

For each combination of constraints that might need to be enforced (obtained by calling the possibleConstraints method on the specified server constraints, or using an empty constraints instance if the specified server constraints instance is null), calling the checkConstraints method of the specified capabilities object with those constraints must return constraints containing at most an Integrity constraint as a requirement, or an ExportException is thrown.

Parameters:
methods - a collection of Method instances for the remote methods
serverCapabilities - the transport capabilities of the server
serverConstraints - the server constraints, or null
permissionClass - the permission class, or null
loader - the class loader, or null
Throws:
SecurityException - if the permission class is not null and is in a named package and a security manager exists and invoking its checkPackageAccess method with the package name of the permission class throws a SecurityException
IllegalArgumentException - if the permission class is abstract, is not public, is not a subclass of Permission, or does not have a public constructor that has either one String parameter or one Method parameter and has no declared exceptions, or if any element of methods is not a Method instance
NullPointerException - if methods or serverCapabilities is null, or if methods contains a null element
ExportException - if any of the possible server constraints cannot be satisfied according to the specified server capabilities
Method Detail

getClassLoader

protected final ClassLoader getClassLoader()
Returns the class loader specified during construction.

Returns:
the class loader

checkPermissionClass

public static void checkPermissionClass(Class permissionClass)
Checks that the specified class is a valid permission class for use in preinvocation access control.

Parameters:
permissionClass - the permission class, or null
Throws:
IllegalArgumentException - if the permission class is abstract, is not a subclass of Permission, or does not have a public constructor that has either one String parameter or one Method parameter and has no declared exceptions

dispatch

public void dispatch(Remote impl,
                     InboundRequest request,
                     Collection context)
Dispatches the specified inbound request to the specified remote object. When used in conjunction with BasicJeriExporter, this method is called in a context that has the security context and context class loader specified by BasicJeriExporter.export.

BasicInvocationDispatcher implements this method to execute the following actions in order:

Specified by:
dispatch in interface InvocationDispatcher
Parameters:
impl - a remote object
request - inbound request object for reading arguments and writing the result
context - a modifiable server context collection
Throws:
NullPointerException - if any argument is null

createMarshalInputStream

protected ObjectInputStream createMarshalInputStream(Object impl,
                                                     InboundRequest request,
                                                     boolean integrity,
                                                     Collection context)
                                              throws IOException
Returns a new marshal input stream to use to read objects from the request input stream obtained by invoking the getRequestInputStream method on the given request.

BasicInvocationDispatcher implements this method as follows:

First, a class loader is selected to use as the defaultLoader and the verifierLoader for the marshal input stream instance. If the class loader specified at construction is not null, the selected loader is that loader. Otherwise, if a security manager exists, its checkPermission method is invoked with the permission RuntimePermission("getClassLoader"); this invocation may throw a SecurityException. If the above security check succeeds, the selected loader is the class loader of impl's class.

This method returns a new MarshalInputStream instance constructed with the input stream (obtained from the request as specified above) for the input stream in, the selected loader for defaultLoader and verifierLoader, the boolean integrity for verifyCodebaseIntegrity, and an unmodifiable view of context for the context collection. The useCodebaseAnnotations method is invoked on the created stream before it is returned.

A subclass can override this method to control how the marshal input stream is created or implemented.

Parameters:
impl - the remote object
request - the inbound request
integrity - true if object integrity is being enforced for the remote call, and false otherwise
context - the server context
Returns:
a new marshal input stream for unmarshalling a call request
Throws:
IOException - if an I/O exception occurs
NullPointerException - if any argument is null

createMarshalOutputStream

protected ObjectOutputStream createMarshalOutputStream(Object impl,
                                                       Method method,
                                                       InboundRequest request,
                                                       Collection context)
                                                throws IOException
Returns a new marshal output stream to use to write objects to the response output stream obtained by invoking the getResponseOutputStream method on the given request.

This method will be called with a null method argument if an IOException occurred when reading method information from the incoming call stream.

BasicInvocationDispatcher implements this method to return a new MarshalOutputStream instance constructed with the output stream obtained from the request as specified above and an unmodifiable view of the given context collection.

A subclass can override this method to control how the marshal output stream is created or implemented.

Parameters:
impl - the remote object
method - the possibly-null Method instance corresponding to the interface method invoked on the remote object
request - the inbound request
context - the server context
Returns:
a new marshal output stream for marshalling a call response
Throws:
IOException - if an I/O exception occurs
NullPointerException - if impl, request, or context is null

checkAccess

protected void checkAccess(Remote impl,
                           Method method,
                           InvocationConstraints constraints,
                           Collection context)
Checks that the client has permission to invoke the specified method on the specified remote object.

BasicInvocationDispatcher implements this method as follows:

If a permission class was specified when this invocation dispatcher was constructed, checkClientPermission is called with a permission constructed from the permission class. If the permission class has a constructor with a Method parameter, the permission is constructed by passing the specified method to that constructor. Otherwise the permission is constructed by passing the fully qualified name of the method to the constructor with a String parameter, where the argument is formed by concatenating the name of the declaring class of the specified method and the name of the method, separated by ".".

A subclass can override this method to implement other preinvocation access control mechanisms.

Parameters:
impl - the remote object
method - the remote method
constraints - the enforced constraints for the specified method, or null
context - the server context
Throws:
SecurityException - if the current client subject does not have permission to invoke the method
IllegalStateException - if the current thread is not executing an incoming remote call for a remote object
NullPointerException - if impl, method, or context is null

checkClientPermission

public static void checkClientPermission(Permission permission)
Checks that the client subject for the current remote call has the specified permission. The client subject is obtained by calling ServerContext.getServerContextElement, passing the class ClientSubject, and then calling the getClientSubject method of the returned element (if any). If a security manager is installed, a ProtectionDomain is constructed with an empty CodeSource (null location and certificates), null permissions, null class loader, and the principals from the client subject (if any), and the implies method of that protection domain is invoked with the specified permission. If true is returned, this method returns normally, otherwise a SecurityException is thrown. If no security manager is installed, this method returns normally.

Note that the permission grant required to satisfy this check must be to the client's principals alone (or a subset thereof); it cannot be qualified by what code is being executed. At the point in a remote call where this method is intended to be used, the useful "call stack" only exists at the other end of the remote call (on the client side), and so cannot meaningfully enter into the access control decision.

Parameters:
permission - the requested permission
Throws:
SecurityException - if the current client subject has not been granted the specified permission
IllegalStateException - if the current thread is not executing an incoming remote method for a remote object
NullPointerException - if permission is null

unmarshalMethod

protected Method unmarshalMethod(Remote impl,
                                 ObjectInputStream in,
                                 Collection context)
                          throws IOException,
                                 NoSuchMethodException,
                                 ClassNotFoundException
Unmarshals a method representation from the marshal input stream, in, and returns the Method object corresponding to that representation. For each remote call, the dispatch method calls this method to unmarshal the method representation.

BasicInvocationDispatcher implements this method to call the readLong method on the marshal input stream to read the method's representation encoded as a JRMP method hash (defined in section 8.3 of the Java(TM) Remote Method Invocation (Java RMI) specification) and return its corresponding Method object chosen from the collection of methods passed to the constructor of this invocation dispatcher. If more than one method has the same hash, it is arbitrary as to which one is returned.

A subclass can override this method to control how the remote method is unmarshalled.

Parameters:
impl - the remote object
in - the marshal input stream for the remote call
context - the server context passed to the dispatch method for the remote call being processed
Returns:
a Method object corresponding to the method representation
Throws:
IOException - if an I/O exception occurs
NoSuchMethodException - if the method representation does not correspond to a valid method
ClassNotFoundException - if a class could not be found during unmarshalling
NullPointerException - if any argument is null

unmarshalArguments

protected Object[] unmarshalArguments(Remote impl,
                                      Method method,
                                      ObjectInputStream in,
                                      Collection context)
                               throws IOException,
                                      ClassNotFoundException
Unmarshals the arguments for the specified remote method from the specified marshal input stream, in, and returns an Object array containing the arguments read. For each remote call, the dispatch method calls this method to unmarshal arguments.

BasicInvocationDispatcher implements this method to unmarshal each argument as follows:

If the corresponding declared parameter type is primitive, then the primitive value is read from the stream using the corresponding read method for that primitive type (for example, if the type is int.class, then the primitive int value is read to the stream using the readInt method) and the value is wrapped in the corresponding primitive wrapper class for that type (e.g., Integer for int, etc.). Otherwise, the argument is read from the stream using the readObject method and returned as is.

A subclass can override this method to unmarshal the arguments in an alternative context, perform post-processing on the arguments, unmarshal additional implicit data, or otherwise control how the arguments are unmarshalled. In general, the context used should mirror the context in which the arguments are manipulated in the implementation of the remote object.

Parameters:
impl - the remote object
method - the Method instance corresponding to the interface method invoked on the remote object
in - the incoming request stream for the remote call
context - the server context passed to the dispatch method for the remote call being processed
Returns:
an Object array containing the unmarshalled arguments. If an argument's corresponding declared parameter type is primitive, then its value is represented with an instance of the corresponding primitive wrapper class; otherwise, the value for that argument is an object of a class assignable to the declared parameter type.
Throws:
IOException - if an I/O exception occurs
ClassNotFoundException - if a class could not be found during unmarshalling
NullPointerException - if any argument is null

invoke

protected Object invoke(Remote impl,
                        Method method,
                        Object[] args,
                        Collection context)
                 throws Throwable
Invokes the specified method on the specified remote object impl, with the specified arguments. If the invocation completes normally, the return value will be returned by this method. If the invocation throws an exception, this method will throw the same exception.

BasicInvocationDispatcher implements this method as follows:

If the specified method is not set accessible or is not a public method of a public class an IllegalArgumentException is thrown.

If the specified method is ProxyTrust.getProxyVerifier and the remote object is an instance of ServerProxyTrust, the getProxyVerifier method of the remote object is called and the result is returned.

Otherwise, the specified method's invoke method is called with the specified remote object and the specified arguments, and the result is returned. If invoke throws an InvocationTargetException, that exception is caught and the target exception inside it is thrown to the caller. Any other exception thrown during any of this computation is thrown to the caller.

A subclass can override this method to invoke the method in an alternative context, perform pre- or post-processing, or otherwise control how the method is invoked.

Parameters:
impl - the remote object
method - the Method instance corresponding to the interface method invoked on the remote object
args - the method arguments
context - the server context passed to the dispatch method for the remote call being processed
Returns:
the result of the method invocation on impl
Throws:
NullPointerException - if any argument is null
Throwable - the exception thrown from the method invocation on impl

marshalReturn

protected void marshalReturn(Remote impl,
                             Method method,
                             Object returnValue,
                             ObjectOutputStream out,
                             Collection context)
                      throws IOException
Marshals the specified return value for the specified remote method to the marshal output stream, out. After invoking the method on the remote object impl, the dispatch method calls this method to marshal the value returned from the invocation on that remote object.

BasicInvocationDispatcher implements this method as follows:

If the declared return type of the method is void, then no return value is written to the stream. If the return type is a primitive type, then the primitive value is written to the stream (for example, if the type is int.class, then the primitive int value is written to the stream using the writeInt method). Otherwise, the return value is written to the stream using the writeObject method.

A subclass can override this method to marshal the return value in an alternative context, perform pre- or post-processing on the return value, marshal additional implicit data, or otherwise control how the return value is marshalled. In general, the context used should mirror the context in which the result is computed in the implementation of the remote object.

Parameters:
impl - the remote object
method - the Method instance corresponding to the interface method invoked on the remote object
returnValue - the return value to marshal to the stream
out - the marshal output stream
context - the server context passed to the dispatch method for the remote call being processed
Throws:
IOException - if an I/O exception occurs
NullPointerException - if impl, method, out, or context is null

marshalThrow

protected void marshalThrow(Remote impl,
                            Method method,
                            Throwable throwable,
                            ObjectOutputStream out,
                            Collection context)
                     throws IOException
Marshals the throwable for the specified remote method to the marshal output stream, out. For each method invocation on impl that throws an exception, this method is called to marshal the throwable. This method is also called if an exception occurs reading the method information from the incoming call stream, as a result of calling unmarshalMethod; in this case, the Method instance will be null.

BasicInvocationDispatcher implements this method to marshal the throwable to the stream using the writeObject method.

A subclass can override this method to marshal the throwable in an alternative context, perform pre- or post-processing on the throwable, marshal additional implicit data, or otherwise control how the throwable is marshalled. In general, the context used should mirror the context in which the exception is generated in the implementation of the remote object.

Parameters:
impl - the remote object
method - the possibly-null Method instance corresponding to the interface method invoked on the remote object
throwable - a throwable to marshal to the stream
out - the marshal output stream
context - the server context
Throws:
IOException - if an I/O exception occurs
NullPointerException - if impl, throwable, out, or context is null


Copyright 2007, multiple authors.
Licensed under the Apache License, Version 2.0, see the NOTICE file for attributions.