public class BasicInvocationDispatcher extends Object implements InvocationDispatcher
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
.
BasicInvocationHandler
Constructor and Description |
---|
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).
|
Modifier and Type | Method and Description |
---|---|
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. |
public BasicInvocationDispatcher(Collection methods, ServerCapabilities serverCapabilities, MethodConstraints serverConstraints, Class permissionClass, ClassLoader loader) throws ExportException
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.
methods
- a collection of Method
instances for the
remote methodsserverCapabilities
- the transport capabilities of the serverserverConstraints
- the server constraints, or null
permissionClass
- the permission class, or null
loader
- the class loader, or null
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
instanceNullPointerException
- if methods
or
serverCapabilities
is null
, or if
methods
contains a null
elementExportException
- if any of the possible server constraints
cannot be satisfied according to the specified server
capabilitiesprotected final ClassLoader getClassLoader()
public static void checkPermissionClass(Class permissionClass)
permissionClass
- the permission class, or null
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 exceptionspublic void dispatch(Remote impl, InboundRequest request, Collection context)
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:
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.
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.
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.
unmarshalMethod
of this
invocation dispatcher is called with the remote object, the marshal
input stream, and the server context to obtain the remote method.
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.
unmarshalArguments
method of this invocation
dispatcher with the remote object, the remote method, the marshal
input stream, and the server context.
IOException
,
ClassNotFoundException
, or NoSuchMethodException
), the
exception is first wrapped in an UnmarshalException
and the
wrapped exception is sent back.
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.
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.
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
.
dispatch
in interface InvocationDispatcher
impl
- a remote objectrequest
- inbound request object for reading arguments and
writing the resultcontext
- a modifiable server context collectionNullPointerException
- if any argument is null
protected ObjectInputStream createMarshalInputStream(Object impl, InboundRequest request, boolean integrity, Collection context) throws IOException
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
; this invocation may
throw a RuntimePermission
("getClassLoader")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.
impl
- the remote objectrequest
- the inbound requestintegrity
- true
if object integrity is being
enforced for the remote call, and false
otherwisecontext
- the server contextIOException
- if an I/O exception occursNullPointerException
- if any argument is null
protected ObjectOutputStream createMarshalOutputStream(Object impl, Method method, InboundRequest request, Collection context) throws IOException
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.
impl
- the remote objectmethod
- the possibly-null
Method
instance corresponding to the interface method invoked on
the remote objectrequest
- the inbound requestcontext
- the server contextIOException
- if an I/O exception occursNullPointerException
- if impl
,
request
, or context
is
null
protected void checkAccess(Remote impl, Method method, InvocationConstraints constraints, Collection context)
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.
impl
- the remote objectmethod
- the remote methodconstraints
- the enforced constraints for the specified
method, or null
context
- the server contextSecurityException
- if the current client subject does not
have permission to invoke the methodIllegalStateException
- if the current thread is not executing an
incoming remote call for a remote objectNullPointerException
- if impl
,
method
, or context
is
null
public static void checkClientPermission(Permission permission)
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.
permission
- the requested permissionSecurityException
- if the current client subject has not
been granted the specified permissionIllegalStateException
- if the current thread is not executing
an incoming remote method for a remote objectNullPointerException
- if permission
is
null
protected Method unmarshalMethod(Remote impl, ObjectInputStream in, Collection context) throws IOException, NoSuchMethodException, ClassNotFoundException
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.
impl
- the remote objectin
- the marshal input stream for the remote callcontext
- the server context passed to the dispatch
method for the remote call being processedMethod
object corresponding to the method
representationIOException
- if an I/O exception occursNoSuchMethodException
- if the method representation does not
correspond to a valid methodClassNotFoundException
- if a class could not be found during
unmarshallingNullPointerException
- if any argument is null
protected Object[] unmarshalArguments(Remote impl, Method method, ObjectInputStream in, Collection context) throws IOException, ClassNotFoundException
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.
impl
- the remote objectmethod
- the Method
instance corresponding
to the interface method invoked on the remote objectin
- the incoming request stream for the remote callcontext
- the server context passed to the dispatch
method for the remote call being processedObject
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.IOException
- if an I/O exception occursClassNotFoundException
- if a class could not be found during
unmarshallingNullPointerException
- if any argument is null
protected Object invoke(Remote impl, Method method, Object[] args, Collection context) throws Throwable
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.
impl
- the remote objectmethod
- the Method
instance corresponding
to the interface method invoked on the remote objectargs
- the method argumentscontext
- the server context passed to the dispatch
method for the remote call being processedimpl
NullPointerException
- if any argument is null
Throwable
- the exception thrown from the method invocation
on impl
protected void marshalReturn(Remote impl, Method method, Object returnValue, ObjectOutputStream out, Collection context) throws IOException
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.
impl
- the remote objectmethod
- the Method
instance corresponding
to the interface method invoked on the remote objectreturnValue
- the return value to marshal to the streamout
- the marshal output streamcontext
- the server context passed to the dispatch
method for the remote call being processedIOException
- if an I/O exception occursNullPointerException
- if impl
,
method
, out
, or
context
is null
protected void marshalThrow(Remote impl, Method method, Throwable throwable, ObjectOutputStream out, Collection context) throws IOException
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.
impl
- the remote objectmethod
- the possibly-null
Method
instance corresponding to the interface method invoked on
the remote objectthrowable
- a throwable to marshal to the streamout
- the marshal output streamcontext
- the server contextIOException
- if an I/O exception occursNullPointerException
- if impl
,
throwable
, out
, or
context
is null