KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > remoting > rmi > RmiClientInterceptorUtils


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.remoting.rmi;
18
19 import java.lang.reflect.InvocationTargetException JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21 import java.rmi.ConnectException JavaDoc;
22 import java.rmi.ConnectIOException JavaDoc;
23 import java.rmi.MarshalException JavaDoc;
24 import java.rmi.NoSuchObjectException JavaDoc;
25 import java.rmi.Remote JavaDoc;
26 import java.rmi.RemoteException JavaDoc;
27 import java.rmi.StubNotFoundException JavaDoc;
28 import java.rmi.UnknownHostException JavaDoc;
29 import java.rmi.UnmarshalException JavaDoc;
30 import java.util.Arrays JavaDoc;
31
32 import org.aopalliance.intercept.MethodInvocation;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36 import org.springframework.remoting.RemoteAccessException;
37 import org.springframework.remoting.RemoteConnectFailureException;
38 import org.springframework.remoting.RemoteProxyFailureException;
39
40 /**
41  * Factored-out methods for performing invocations within an RMI client.
42  * Can handle both RMI and non-RMI service interfaces working on an RMI stub.
43  *
44  * <p>Note: This is an SPI class, not intended to be used by applications.
45  *
46  * @author Juergen Hoeller
47  * @since 1.1
48  */

49 public abstract class RmiClientInterceptorUtils {
50
51     private static final String JavaDoc ORACLE_CONNECTION_EXCEPTION = "com.evermind.server.rmi.RMIConnectionException";
52
53     private static final Log logger = LogFactory.getLog(RmiClientInterceptorUtils.class);
54
55
56     /**
57      * Apply the given method invocation to the given RMI stub.
58      * <p>Delegate to the corresponding method if the RMI stub does not directly
59      * implemented the invoked method. This typically happens when a non-RMI service
60      * interface is used for an RMI service. The methods of such a service interface
61      * have to match the RMI stub methods, but they typically don't declare
62      * <code>java.rmi.RemoteException</code>: A RemoteException thrown by the RMI stub
63      * will be automatically converted to Spring's RemoteAccessException.
64      * @param invocation the AOP MethodInvocation
65      * @param stub the RMI stub
66      * @param serviceName the name of the service (for debugging purposes)
67      * @return the invocation result, if any
68      * @throws Throwable exception to be thrown to the caller
69      * @see java.rmi.RemoteException
70      * @see org.springframework.remoting.RemoteAccessException
71      */

72     public static Object JavaDoc invoke(MethodInvocation invocation, Remote JavaDoc stub, String JavaDoc serviceName) throws Throwable JavaDoc {
73         try {
74             return doInvoke(invocation, stub);
75         }
76         catch (InvocationTargetException JavaDoc ex) {
77             Throwable JavaDoc targetEx = ex.getTargetException();
78             if (targetEx instanceof RemoteException JavaDoc) {
79                 RemoteException JavaDoc rex = (RemoteException JavaDoc) targetEx;
80                 throw convertRmiAccessException(invocation.getMethod(), rex, serviceName);
81             }
82             else {
83                 throw targetEx;
84             }
85         }
86     }
87
88     /**
89      * Perform a raw method invocation on the given RMI stub,
90      * letting reflection exceptions through as-is.
91      * @param invocation the AOP MethodInvocation
92      * @param stub the RMI stub
93      * @return the invocation result, if any
94      * @throws InvocationTargetException if thrown by reflection
95      */

96     public static Object JavaDoc doInvoke(MethodInvocation invocation, Remote JavaDoc stub) throws InvocationTargetException JavaDoc {
97         Method JavaDoc method = invocation.getMethod();
98         try {
99             if (method.getDeclaringClass().isInstance(stub)) {
100                 // directly implemented
101
return method.invoke(stub, invocation.getArguments());
102             }
103             else {
104                 // not directly implemented
105
Method JavaDoc stubMethod = stub.getClass().getMethod(method.getName(), method.getParameterTypes());
106                 return stubMethod.invoke(stub, invocation.getArguments());
107             }
108         }
109         catch (InvocationTargetException JavaDoc ex) {
110             throw ex;
111         }
112         catch (NoSuchMethodException JavaDoc ex) {
113             throw new RemoteProxyFailureException("No matching RMI stub method found for: " + method, ex);
114         }
115         catch (Throwable JavaDoc ex) {
116             throw new RemoteProxyFailureException("Invocation of RMI stub method failed: " + method, ex);
117         }
118     }
119
120     /**
121      * Wrap the given arbitrary exception that happened during remote access
122      * in either a RemoteException or a Spring RemoteAccessException (if the
123      * method signature does not support RemoteException).
124      * <p>Only call this for remote access exceptions, not for exceptions
125      * thrown by the target service itself!
126      * @param method the invoked method
127      * @param ex the exception that happened, to be used as cause for the
128      * RemoteAccessException or RemoteException
129      * @param message the message for the RemoteAccessException respectively
130      * RemoteException
131      * @return the exception to be thrown to the caller
132      */

133     public static Exception JavaDoc convertRmiAccessException(Method JavaDoc method, Throwable JavaDoc ex, String JavaDoc message) {
134         if (logger.isDebugEnabled()) {
135             logger.debug(message, ex);
136         }
137         if (!Arrays.asList(method.getExceptionTypes()).contains(RemoteException JavaDoc.class)) {
138             return new RemoteAccessException(message, ex);
139         }
140         else {
141             return new RemoteException JavaDoc(message, ex);
142         }
143     }
144
145     /**
146      * Convert the given RemoteException that happened during remote access
147      * to Spring's RemoteAccessException if the method signature does not
148      * support RemoteException. Else, return the original RemoteException.
149      * @param method the invoked method
150      * @param ex the RemoteException that happened
151      * @param serviceName the name of the service (for debugging purposes)
152      * @return the exception to be thrown to the caller
153      */

154     public static Exception JavaDoc convertRmiAccessException(Method JavaDoc method, RemoteException JavaDoc ex, String JavaDoc serviceName) {
155         return convertRmiAccessException(method, ex, isConnectFailure(ex), serviceName);
156     }
157
158     /**
159      * Convert the given RemoteException that happened during remote access
160      * to Spring's RemoteAccessException if the method signature does not
161      * support RemoteException. Else, return the original RemoteException.
162      * @param method the invoked method
163      * @param ex the RemoteException that happened
164      * @param isConnectFailure whether the given exception should be considered
165      * a connect failure
166      * @param serviceName the name of the service (for debugging purposes)
167      * @return the exception to be thrown to the caller
168      */

169     public static Exception JavaDoc convertRmiAccessException(
170             Method JavaDoc method, RemoteException JavaDoc ex, boolean isConnectFailure, String JavaDoc serviceName) {
171
172         if (logger.isDebugEnabled()) {
173             logger.debug("Remote service [" + serviceName + "] threw exception", ex);
174         }
175         if (!Arrays.asList(method.getExceptionTypes()).contains(RemoteException JavaDoc.class)) {
176             if (isConnectFailure) {
177                 return new RemoteConnectFailureException("Cannot connect to remote service [" + serviceName + "]", ex);
178             }
179             else {
180                 return new RemoteAccessException("Cannot access remote service [" + serviceName + "]", ex);
181             }
182         }
183         else {
184             return ex;
185         }
186     }
187
188     /**
189      * Determine whether the given RMI exception indicates a connect failure.
190      * <p>Treats RMI's ConnectException, ConnectIOException, UnknownHostException,
191      * NoSuchObjectException, StubNotFoundException, MarshalException and
192      * UnmarshalException as connect failure, as well as Oracle's OC4J
193      * <code>com.evermind.server.rmi.RMIConnectionException</code>
194      * (which doesn't derive from from any well-known RMI connect exception).
195      * @param ex the RMI exception to check
196      * @return whether the exception should be treated as connect failure
197      * @see java.rmi.ConnectException
198      * @see java.rmi.ConnectIOException
199      * @see java.rmi.UnknownHostException
200      * @see java.rmi.NoSuchObjectException
201      * @see java.rmi.StubNotFoundException
202      * @see java.rmi.MarshalException
203      * @see java.rmi.UnmarshalException
204      */

205     public static boolean isConnectFailure(RemoteException JavaDoc ex) {
206         return (ex instanceof ConnectException JavaDoc || ex instanceof ConnectIOException JavaDoc ||
207                 ex instanceof UnknownHostException JavaDoc ||
208                 ex instanceof NoSuchObjectException JavaDoc || ex instanceof StubNotFoundException JavaDoc ||
209                 ex instanceof MarshalException JavaDoc || ex instanceof UnmarshalException JavaDoc ||
210                 ORACLE_CONNECTION_EXCEPTION.equals(ex.getClass().getName()));
211     }
212
213 }
214
Popular Tags