Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## net.jini.jeri
Class BasicInvocationDispatcher

    java.lang.Object
      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
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:

  - A byte specifying the marshal stream protocol version is read from the request input stream of the inbound request. If any exception is thrown when reading this byte, the inbound request is aborted and this method returns. If the byte is not `0x00`, two byte values of `0x00` (indicating a marshal stream protocol version mismatch) are written to the response output stream of the inbound request, the output stream is closed, and this method returns.
  - If the version byte is `0x00`, a second byte specifying object integrity is read from the same stream. If any exception is thrown when reading this byte, the inbound request is aborted and this method returns. Object integrity will be enforced if the value read is not `0x00`, but will not be enforced if the value is `0x00`. An `IntegrityEnforcement` element is then added to the server context, reflecting whether or not object integrity is being enforced.
  - The `createMarshalInputStream` method of this invocation dispatcher is called, passing the remote object, the inbound request, a boolean indicating if object integrity is being enforced, and the server context, to create the marshal input stream for unmarshalling the request.
  - The `unmarshalMethod` of this invocation dispatcher is called with the remote object, the marshal input stream, and the server context to obtain the remote method.
  - The `checkConstraints` method of the inbound request is called with the constraints that must be enforced for that remote method, obtained by passing the remote method to the `getConstraints` method of this invocation dispatcher's server constraints, and adding `Integrity.YES` as a requirement if object integrity is being enforced. If the unfulfilled requirements returned by `checkConstraints` contains a constraint that is not an instance of `Integrity` or if integrity is not being enforced and the returned requirements contains the element `Integrity.YES`, an `UnsupportedConstraintException` is sent back to the caller as described further below. Otherwise, the `checkAccess` method of this invocation dispatcher is called with the remote object, the remote method, the enforced constraints, and the server context.
  - The method arguments are obtained by calling the `unmarshalArguments` method of this invocation dispatcher with the remote object, the remote method, the marshal input stream, and the server context.
  - If any exception is thrown during this unmarshalling, that exception is sent back to the caller as described further below; however, if the exception is a checked exception (`IOException`, `ClassNotFoundException`, or `NoSuchMethodException`), the exception is first wrapped in an `UnmarshalException` and the wrapped exception is sent back.
  - Otherwise, if unmarshalling is successful, the `invoke` method of this invocation dispatcher is then called with the remote object, the remote method, the arguments returned by `unmarshalArguments`, and the server context. If `invoke` throws an exception, that exception is sent back to the caller as described further below.
  - The input stream is closed whether or not an exception was thrown unmarshalling the arguments or invoking the method.
  - If `invoke` returns normally, a byte value of `0x01` is written to the response output stream of the inbound request. Then the `createMarshalOutputStream` method of this invocation dispatcher is called, passing the remote object, the remote method, the inbound request, and the server context, to create the marshal output stream for marshalling the response. Then the `marshalReturn` method of this invocation dispatcher is called with the remote object, the remote method, the value returned by `invoke`, the marshal output stream, and the server context. Then the marshal output stream is closed. Any exception thrown during this marshalling is ignored.
  - When an exception is sent back to the caller, a byte value of `0x02` is written to the response output stream of the inbound request. Then a marshal output stream is created by calling the `createMarshalOutputStream` method as described above (but with a `null` remote method if one was not successfully unmarshalled). Then the `marshalThrow` method of this invocation dispatcher is called with the remote object, the remote method (or `null` if one was not successfully unmarshalled), the exception, the marshal output stream, and the server context. Then the marshal output stream is closed. Any exception thrown during this marshalling is ignored. If the exception being sent back is a `RemoteException`, it is wrapped in a `ServerException` and the wrapped exception is passed to `marshalThrow`. If the exception being sent back is an `Error`, it is wrapped in a `ServerError` and the wrapped exception is passed to `marshalThrow`. If the exception being sent back occurred before or during the call to `unmarshalMethod`, then the remote method passed to `marshalThrow` is `null`.

  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 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`

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Copyright © 2004 Sun Microsystems, Inc. All rights reserved