net.jini.jeri
Class BasicInvocationHandler

java.lang.Object
  extended by net.jini.jeri.BasicInvocationHandler
All Implemented Interfaces:
Serializable, InvocationHandler, TrustEquivalence

public class BasicInvocationHandler
extends Object
implements InvocationHandler, TrustEquivalence, Serializable

A basic implementation of the InvocationHandler interface. This invocation handler implements Java(TM) Remote Method Invocation (Java RMI) call semantics when handling a remote invocation to a remote object.

BasicInvocationHandler instances contain an ObjectEndpoint, optional client constraints, and optional server constraints. The client and server constraints control the handling of remote methods, and they are represented as MethodConstraints objects that map remote methods to corresponding per-method constraints.

Invocation requests sent via the invoke method use the protocol defined in that method. This invocation handler also assumes that the return value conforms to the protocol outlined in the BasicInvocationDispatcher.dispatch method.

Since:
2.0
Author:
Sun Microsystems, Inc.
See Also:
BasicInvocationDispatcher, Serialized Form
Implementation Specifics:
This implementation's invoke method throws IllegalArgumentException if a remote invocation is to be made and the proxy argument is an instance of an interface whose binary name is javax.management.MBeanServerConnection or any of the names produced by the following procedure:
For each resource named com/sun/jini/proxy/resources/InvocationHandler.moreProhibitedProxyInterfaces that is visible to the system class loader, the contents of the resource are parsed as UTF-8 text to produce a list of interface names. The resource must contain a list of binary names of interfaces, one per line. Space and tab characters surrounding each name, as well as blank lines, are ignored. The comment character is '#'; on each line, all characters starting with the first comment character are ignored.

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

Level Description
FAILED exception thrown from final attempt to communicate a remote call
HANDLED exception caught in attempt to communicate a remote call
FINE remote method being invoked
FINE successful return of remote call
FINEST more detailed information on the above (for example, actual argument and return values)

Constructor Summary
BasicInvocationHandler(BasicInvocationHandler other, MethodConstraints clientConstraints)
          Creates a new BasicInvocationHandler with the specified client constraints and with the same ObjectEndpoint and server constraints as the given other BasicInvocationHandler.
BasicInvocationHandler(ObjectEndpoint oe, MethodConstraints serverConstraints)
          Creates a new BasicInvocationHandler with the specified ObjectEndpoint and server constraints.
 
Method Summary
 boolean checkTrustEquivalence(Object obj)
          Returns true if the specified object (which is not yet known to be trusted) is equivalent in trust, content, and function to this known trusted object, and false otherwise.
protected  ObjectInputStream createMarshalInputStream(Object proxy, Method method, OutboundRequest request, boolean integrity, Collection context)
          Returns a new ObjectInputStream instance to use to read objects from the response input stream obtained by invoking the getResponseInputStream method on the given request.
protected  ObjectOutputStream createMarshalOutputStream(Object proxy, Method method, OutboundRequest request, Collection context)
          Returns a new ObjectOutputStream instance to use to write objects to the request output stream obtained by invoking the getRequestOutputStream method on the given request.
 boolean equals(Object obj)
          Compares the specified object with this BasicInvocationHandler for equality.
 MethodConstraints getClientConstraints()
          Returns this BasicInvocationHandler's client constraints.
 ObjectEndpoint getObjectEndpoint()
          Returns this BasicInvocationHandler's ObjectEndpoint.
 MethodConstraints getServerConstraints()
          Returns this BasicInvocationHandler's server constraints.
 int hashCode()
          Returns the hash code value for this invocation handler.
 Object invoke(Object proxy, Method method, Object[] args)
          Processes a method invocation made on the encapsulating proxy instance, proxy, and returns the result.
protected  void marshalArguments(Object proxy, Method method, Object[] args, ObjectOutputStream out, Collection context)
          Marshals the arguments for the specified remote method to the outgoing request stream, out.
protected  void marshalMethod(Object proxy, Method method, ObjectOutputStream out, Collection context)
          Marshals a representation of the given method to the outgoing request stream, out.
protected  InvocationHandler setClientConstraints(MethodConstraints constraints)
          Returns a copy of this invocation handler with the specified constraints as its new client constraints.
 String toString()
          Returns a string representation of this BasicInvocationHandler.
protected  Object unmarshalReturn(Object proxy, Method method, ObjectInputStream in, Collection context)
          Unmarshals the return value for the specified remote method from the incoming response stream, in.
protected  Throwable unmarshalThrow(Object proxy, Method method, ObjectInputStream in, Collection context)
          Unmarshals the throwable for the specified remote method from the incoming response stream, in, and returns the result.
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Constructor Detail

BasicInvocationHandler

public BasicInvocationHandler(ObjectEndpoint oe,
                              MethodConstraints serverConstraints)
Creates a new BasicInvocationHandler with the specified ObjectEndpoint and server constraints.

The client constraints of the created BasicInvocationHandler will be null.

Parameters:
oe - the ObjectEndpoint for this invocation handler
serverConstraints - the server constraints, or null
Throws:
NullPointerException - if oe is null

BasicInvocationHandler

public BasicInvocationHandler(BasicInvocationHandler other,
                              MethodConstraints clientConstraints)
Creates a new BasicInvocationHandler with the specified client constraints and with the same ObjectEndpoint and server constraints as the given other BasicInvocationHandler.

This constructor is intended for use by the BasicInvocationHandler implementation of the setClientConstraints(net.jini.core.constraint.MethodConstraints) method. To create a copy of a given BasicInvocationHandler with new client constraints, use the RemoteMethodControl.setConstraints method on the containing proxy.

Parameters:
other - the BasicInvocationHandler to obtain the ObjectEndpoint and server constraints from
clientConstraints - the client constraints, or null
Throws:
NullPointerException - if other is null
Method Detail

invoke

public Object invoke(Object proxy,
                     Method method,
                     Object[] args)
              throws Throwable
Processes a method invocation made on the encapsulating proxy instance, proxy, and returns the result. This method is invoked when a method is invoked on a proxy instance that this handler is associated with.

BasicInvocationHandler implements this method as follows:

If method is one of the following methods, it is processed as described below:

Otherwise, a remote call is made as follows:

The object endpoint's newCall method is invoked to obtain an OutboundRequestIterator, passing constraints obtained by combining the client and server constraints for the specified remote method and making them absolute. If the returned iterator's hasNext method returns false, then this method throws a ConnectIOException. Otherwise, the iterator is used to make one or more attempts to communicate the remote call. Each attempt proceeds as follows:

The iterator's next method is invoked to obtain an OutboundRequest for the current attempt. If next returns normally, the request's getUnfulfilledConstraints method is invoked, and if the returned requirements or preferences include Integrity.YES, object integrity is enforced for the current remote call attempt. If the returned requirements include any constraint other than an Integrity constraint, an UnsupportedConstraintException is generated and, as described below, wrapped and handled like any other Exception thrown from a remote call attempt. Otherwise, the marshalling of the remote call proceeds with the following steps in order:
  • A byte of value 0x00 is written to the request output stream of the OutboundRequest to indicate the version of the marshalling protocol being used.
  • A byte is written to specify object integrity enforcement: 0x01 if object integrity is being enforced for this remote call attempt, and 0x00 otherwise.
  • A client context collection is created containing an IntegrityEnforcement element that reflects whether or not object integrity is being enforced for this remote call attempt.
  • The createMarshalOutputStream method is invoked, passing proxy, method, the OutboundRequest, and the client context, to create the marshal output stream for marshalling the remote call.
  • The marshalMethod method of this invocation handler is invoked with proxy, method, the marshal output stream, and the client context.
  • The marshalArguments method of this invocation handler is invoked with proxy, method, args, the marshal output stream, and the client context.
  • The marshal output stream is closed.

Then the object endpoint's executeCall method is invoked with the OutboundRequest. If executeCall returns a RemoteException, then this method throws that exception (and thus the remote call attempt iteration terminates). If executeCall returns null, then the unmarshalling of the call response proceeds as follows:

A byte is read from the response input stream of the OutboundRequest:

  • If the byte is 0x00, indicating a marshalling protocol version mismatch, a ProtocolException is generated and, as described below, wrapped and handled like any other Exception thrown from a remote call attempt.
  • If the byte is 0x01, indicating a normal return, the createMarshalInputStream method is invoked, passing proxy, method, the OutboundRequest, a boolean indicating whether or not object integrity is being enforced, and the client context, to create the marshal input stream for unmarshalling the response, and the unmarshalReturn method of this invocation handler is invoked with proxy, method, the marshal input stream, and the client context. This method returns the value returned by unmarshalReturn (and thus the remote call attempt iteration terminates).
  • If the byte is 0x02, indicating an exceptional return, a marshal input stream is created by calling the createMarshalInputStream method as described for the previous case, and the unmarshalThrow method of this invocation handler is invoked with proxy, method, the marshal input stream, and the client context. This method throws the exception returned by unmarshalThrow (and thus the remote call attempt iteration terminates).
  • If the byte is any other value, a ProtocolException is generated and, as described below, wrapped and handled like any other Exception thrown from a remote call attempt.

If an IOException is thrown during the attempt to communicate the remote call, then it is wrapped in a RemoteException as follows:

If a ClassNotFoundException is thrown during the unmarshalling, then it is wrapped in an UnmarshalException.

In all cases, either the request output stream and the response input stream will be closed or the OutboundRequest will be aborted before this attempt completes.

If an attempt to communicate the remote call throws an Exception (other than an exception returned by executeCall or unmarshalThrow, which terminates the remote call attempt iteration), then if marshalMethod was not invoked for the attempt or if an invocation of getDeliveryStatus on the OutboundRequest returns false, then if the iterator's hasNext method returns true, then another attempt is made. Otherwise, this method throws the Exception thrown by the last attempt (possibly wrapped as described above).

Note that invoking a remote method on a remote object via this invoke method preserves "at-most-once" call semantics. At-most-once call semantics guarantees that the remote call will either a) not execute, b) partially execute, or c) execute exactly once at the remote site. With Java RMI's at-most-once call semantics, arguments may be marshalled more than once for a given remote call.

A subclass can override this method to handle the methods of any additional non-remote interfaces implemented by the proxy or to otherwise control invocation handling behavior.

The semantics of this method are unspecified if the arguments could not have been produced by an instance of some valid dynamic proxy class containing this invocation handler. This method throws IllegalArgumentException if proxy is an instance of InvocationHandler or, if a remote call is to be made, any of the superinterfaces of proxy's class have a method with the same name and parameter types as method but that does not declare RemoteException or a superclass of RemoteException in its throws clause (even if such a method is not a member of any of the direct superinterfaces of proxy's class because of overriding).

Specified by:
invoke in interface InvocationHandler
Throws:
Throwable
See Also:
UndeclaredThrowableException

setClientConstraints

protected InvocationHandler setClientConstraints(MethodConstraints constraints)
Returns a copy of this invocation handler with the specified constraints as its new client constraints.

BasicInvocationHandler implements this method as follows:

This method looks for a public constructor declared by the class of this object with two parameters, the first parameter type being the class of this object and the second parameter type being MethodConstraints. If found, the constructor is invoked with this instance and the specified constraints, and the resulting object is returned. If the constructor could not be found or was not accessible, or if the constructor invocation throws an exception, an UndeclaredThrowableException is thrown.

A subclass can override this method to control how the invocation handler is copied.

Parameters:
constraints - the new client constraints, or null
Returns:
a copy of this invocation handler with the specified constraints as its client constraints

createMarshalOutputStream

protected ObjectOutputStream createMarshalOutputStream(Object proxy,
                                                       Method method,
                                                       OutboundRequest request,
                                                       Collection context)
                                                throws IOException
Returns a new ObjectOutputStream instance to use to write objects to the request output stream obtained by invoking the getRequestOutputStream method on the given request.

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

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

Parameters:
proxy - the proxy instance
method - the remote method invoked
request - the outbound request
context - the client context
Returns:
a new ObjectOutputStream instance for marshalling a call request
Throws:
IOException - if an I/O exception occurs
NullPointerException - if any argument is null

createMarshalInputStream

protected ObjectInputStream createMarshalInputStream(Object proxy,
                                                     Method method,
                                                     OutboundRequest request,
                                                     boolean integrity,
                                                     Collection context)
                                              throws IOException
Returns a new ObjectInputStream instance to use to read objects from the response input stream obtained by invoking the getResponseInputStream method on the given request.

BasicInvocationHandler implements this method to return a new MarshalInputStream instance constructed with the input stream obtained from request as specified above for the input stream in, the class loader of proxy's class for defaultLoader and verifierLoader, this method's integrity argument 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.

An exception is thrown if proxy is not an instance of a dynamic proxy class containing this invocation handler.

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

Parameters:
proxy - the proxy instance
method - the remote method invoked
request - the outbound request
integrity - whether or not to verify codebase integrity
context - the client context
Returns:
a new ObjectInputStream instance for unmarshalling a call response
Throws:
IOException - if an I/O exception occurs
NullPointerException - if any argument is null

marshalMethod

protected void marshalMethod(Object proxy,
                             Method method,
                             ObjectOutputStream out,
                             Collection context)
                      throws IOException
Marshals a representation of the given method to the outgoing request stream, out. For each remote call, the invoke method calls this method to marshal a representation of the method.

BasicInvocationHandler implements this method to write the JRMP method hash (defined in section 8.3 of the Java RMI specification) for the given method to the output stream using the writeLong method.

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

Parameters:
proxy - the proxy instance that the method was invoked on
method - the Method instance corresponding to the interface method invoked on the proxy instance. The declaring class of the Method object will be the interface that the method was declared in, which may be a superinterface of the proxy interface that the proxy class inherits the method through.
out - outgoing request stream for the remote call
context - the client context
Throws:
IOException - if an I/O exception occurs
NullPointerException - if any argument is null

marshalArguments

protected void marshalArguments(Object proxy,
                                Method method,
                                Object[] args,
                                ObjectOutputStream out,
                                Collection context)
                         throws IOException
Marshals the arguments for the specified remote method to the outgoing request stream, out. For each remote call, the invoke method calls this method to marshal arguments.

BasicInvocationHandler implements this method marshal each argument as follows:

If the corresponding declared parameter type is primitive, then the 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 argument is written to the stream using the writeObject method.

A subclass can override this method to marshal the arguments in an alternative context, perform pre- or post-processing on the arguments, marshal additional implicit data, or otherwise control how the arguments are marshalled.

Parameters:
proxy - the proxy instance that the method was invoked on
method - the Method instance corresponding to the interface method invoked on the proxy instance. The declaring class of the Method object will be the interface that the method was declared in, which may be a superinterface of the proxy interface that the proxy class inherits the method through.
args - an array of objects containing the values of the arguments passed in the method invocation on the proxy instance. If an argument's corresponding declared parameter type is primitive, then its value is represented with an instance of the corresponding primitive wrapper class, such as java.lang.Integer or java.lang.Boolean.
out - outgoing request stream for the remote call
context - the client context
Throws:
IOException - if an I/O exception occurs
NullPointerException - if any argument is null

unmarshalReturn

protected Object unmarshalReturn(Object proxy,
                                 Method method,
                                 ObjectInputStream in,
                                 Collection context)
                          throws IOException,
                                 ClassNotFoundException
Unmarshals the return value for the specified remote method from the incoming response stream, in. In the case that a value is returned from the invocation on the remote object, this method is called to unmarshal that return value.

BasicInvocationHandler implements this method as follows:

If the return type of the method is void, then no return value is read from the stream and null is returned. If the return type is a primitive type, then the primitive value is read from the stream (for example, if the type is int.class, then the primitive int value is read from the stream using the readInt method). Otherwise, the return value is read from the stream using the readObject method.

A subclass can override this method to unmarshal the return value in an alternative context, perform post-processing on the return value, unmarshal additional implicit data, or otherwise control how the return value is unmarshalled.

Parameters:
proxy - the proxy instance that the method was invoked on
method - the Method instance corresponding to the interface method invoked on the proxy instance. The declaring class of the Method object will be the interface that the method was declared in, which may be a superinterface of the proxy interface that the proxy class inherits the method through.
in - the incoming result stream for the remote call
context - the client context
Returns:
the unmarshalled return value of the method invocation on the proxy instance. If the declared return value of the interface method is a primitive type, then the value returned by invoke will be an instance of the corresponding primitive wrapper class; otherwise, it will be a type assignable to the declared return 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

unmarshalThrow

protected Throwable unmarshalThrow(Object proxy,
                                   Method method,
                                   ObjectInputStream in,
                                   Collection context)
                            throws IOException,
                                   ClassNotFoundException
Unmarshals the throwable for the specified remote method from the incoming response stream, in, and returns the result. In the case that an exception was thrown as a result of the invocation on the remote object, this method is called to unmarshal that throwable.

BasicInvocationHandler implements this method to return the throwable unmarshalled from the stream using the readObject method. If the unmarshalled throwable is a checked exception that is not assignable to any exception in the throws clause of the method implemented by the proxy's class, then: if there is no public member method of proxy's class with the same name and parameter types as method an IllegalArgumentException is thrown, otherwise that exception is wrapped in an UnexpectedException and the wrapped exception is returned.

A subclass can override this method to unmarshal the return value in an alternative context, perform post-processing on the return value, unmarshal additional implicit data, or otherwise control how the return value is unmarshalled.

Parameters:
proxy - the proxy instance that the method was invoked on
method - the Method instance corresponding to the interface method invoked on the proxy instance. The declaring class of the Method object will be the interface that the method was declared in, which may be a superinterface of the proxy interface that the proxy class inherits the method through.
context - the client context
in - the incoming result stream for the remote call
Returns:
the unmarshalled exception to throw from the method invocation on the proxy instance. The exception's type must be assignable either to any of the exception types declared in the throws clause of the interface method or to the unchecked exception types java.lang.RuntimeException or java.lang.Error.
Throws:
IOException - if an I/O exception occurs
ClassNotFoundException - if a class could not be found during unmarshalling
NullPointerException - if any argument is null

getObjectEndpoint

public final ObjectEndpoint getObjectEndpoint()
Returns this BasicInvocationHandler's ObjectEndpoint.

Returns:
the ObjectEndpoint

getClientConstraints

public final MethodConstraints getClientConstraints()
Returns this BasicInvocationHandler's client constraints.

Returns:
the client constraints

getServerConstraints

public final MethodConstraints getServerConstraints()
Returns this BasicInvocationHandler's server constraints.

Returns:
the server constraints

hashCode

public int hashCode()
Returns the hash code value for this invocation handler.

Overrides:
hashCode in class Object
Returns:
the hash code value for this invocation handler

equals

public boolean equals(Object obj)
Compares the specified object with this BasicInvocationHandler for equality.

BasicInvocationHandler implements this method to return true if and only if

A subclass should override this method if adds instance state that affects equality.

Overrides:
equals in class Object
Parameters:
obj - the object to compare with
Returns:
true if obj is equivalent to this object; false otherwise

checkTrustEquivalence

public boolean checkTrustEquivalence(Object obj)
Returns true if the specified object (which is not yet known to be trusted) is equivalent in trust, content, and function to this known trusted object, and false otherwise.

BasicInvocationHandler implements this method to return true if and only if

A subclass should override this method to perform any additional checks that are necessary.

Specified by:
checkTrustEquivalence in interface TrustEquivalence
Parameters:
obj - object to check that is not yet known to be trusted
Returns:
true if the specified object (that is not yet known to be trusted) is equivalent in trust, content, and function to this known trusted object, and returns false otherwise

toString

public String toString()
Returns a string representation of this BasicInvocationHandler.

Overrides:
toString in class Object
Returns:
a string representation of this BasicInvocationHandler


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