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:
true if the argument (args[0]) is an instance of a dynamic proxy class that implements the same ordered set of interfaces as proxy and this invocation handler is equal to the invocation handler of that argument, and returns false otherwise. proxy containing a new invocation handler with the specified new client constraints. The new invocation handler is created by invoking the {@link #setClientConstraints setClientConstraints} methodof this object with the specified client constraints (args[0]). An exception is thrown if proxy is not an instance of a dynamic proxy class containing this invocation handler. BasicInvocationHandler's client constraints. true if the argument (args[0]) is an instance of a dynamic proxy class that implements the same ordered set of interfaces as proxy and invoking the {@link #checkTrustEquivalence checkTrustEquivalence} methodof this object with the invocation handler of that argument returns true, and returns false otherwise. Otherwise, a remote call is made as follows:
The object endpoint's {@link ObjectEndpoint#newCall newCall}method is invoked to obtain an {@link 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 {@link OutboundRequestIterator#hasNext hasNext} method returnsfalse, then this method throws a {@link 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 {@link OutboundRequestIterator#next next} methodis invoked to obtain an {@link OutboundRequest OutboundRequest}for the current attempt. Ifnextreturns normally, the request's {@link OutboundRequest#getUnfulfilledConstraints getUnfulfilledConstraints} method is invoked, and if thereturned requirements or preferences include {@link Integrity#YES Integrity.YES}, object integrity is enforced for the current remote call attempt. If the returned requirements include any constraint other than an {@link Integrity}constraint, an {@link UnsupportedConstraintException} isgenerated and, as described below, wrapped and handled like any otherExceptionthrown from a remote call attempt. Otherwise, the marshalling of the remote call proceeds with the following steps in order:
- A byte of value
0x00is written to the request output stream of theOutboundRequestto indicate the version of the marshalling protocol being used.- A byte is written to specify object integrity enforcement:
0x01if object integrity is being enforced for this remote call attempt, and0x00otherwise.- A client context collection is created containing an {@link IntegrityEnforcement} element that reflects whether or notobject integrity is being enforced for this remote call attempt.
- The {@link #createMarshalOutputStream createMarshalOutputStream} method is invoked, passing
proxy,method, theOutboundRequest, and the client context, to create the marshal output stream for marshalling the remote call.- The {@link #marshalMethod marshalMethod} method of thisinvocation handler is invoked with
proxy,method, the marshal output stream, and the client context.- The {@link #marshalArguments marshalArguments} method ofthis 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 {@link ObjectEndpoint#executeCall executeCall} method is invoked with the
OutboundRequest. IfexecuteCallreturns aRemoteException, then this method throws that exception (and thus the remote call attempt iteration terminates). IfexecuteCallreturnsnull, 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 {@link ProtocolException} isgenerated and, as described below, wrapped and handled like any otherExceptionthrown from a remote call attempt.- If the byte is
0x01, indicating a normal return, the {@link #createMarshalInputStream createMarshalInputStream} method is invoked, passingproxy,method, theOutboundRequest, abooleanindicating whether or not object integrity is being enforced, and the client context, to create the marshal input stream for unmarshalling the response, and the {@link #unmarshalReturn unmarshalReturn} method of this invocation handler is invokedwithproxy,method, the marshal input stream, and the client context. This method returns the value returned byunmarshalReturn(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 thecreateMarshalInputStreammethod as described for the previous case, and the {@link #unmarshalThrow unmarshalThrow} method of this invocation handler is invokedwithproxy,method, the marshal input stream, and the client context. This method throws the exception returned byunmarshalThrow(and thus the remote call attempt iteration terminates).- If the byte is any other value, a
ProtocolExceptionis generated and, as described below, wrapped and handled like any otherExceptionthrown from a remote call attempt.If an
IOExceptionis thrown during the attempt to communicate the remote call, then it is wrapped in aRemoteExceptionas follows:
- If
marshalMethodwas not invoked for this attempt, or if an invocation of {@link OutboundRequest#getDeliveryStatus getDeliveryStatus} on theOutboundRequestreturnsfalse, or if a marshalling protocol version mismatch was detected, then
- if the
IOExceptionis a {@link java.net.UnknownHostException java.net.UnknownHostException}, it is wrapped in a {@link java.rmi.UnknownHostException java.rmi.UnknownHostException};- if it is a {@link java.net.ConnectException java.net.ConnectException}, it is wrapped in a {@link java.rmi.ConnectException java.rmi.ConnectException};
- if it is any other
IOException, it is wrapped in a {@link ConnectIOException}.- Otherwise, if
executeCallwas not invoked for this attempt, theIOExceptionis wrapped in a {@link MarshalException}, and ifexecuteCallwas invoked, it is wrapped in an {@link UnmarshalException}.If a {@link ClassNotFoundException} is thrownduring the unmarshalling, then it is wrapped in an {@link UnmarshalException}.
In all cases, either the request output stream and the response input stream will be closed or the
OutboundRequestwill 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 {@link IllegalArgumentException} ifproxy 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).
@throws Throwable {@inheritDoc}
@see java.lang.reflect.UndeclaredThrowableException
| |