KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > remoting > httpinvoker > HttpInvokerClientInterceptor


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.httpinvoker;
18
19 import java.io.IOException JavaDoc;
20 import java.net.ConnectException JavaDoc;
21
22 import org.aopalliance.intercept.MethodInterceptor;
23 import org.aopalliance.intercept.MethodInvocation;
24
25 import org.springframework.aop.support.AopUtils;
26 import org.springframework.beans.factory.BeanClassLoaderAware;
27 import org.springframework.remoting.RemoteAccessException;
28 import org.springframework.remoting.RemoteConnectFailureException;
29 import org.springframework.remoting.support.RemoteInvocation;
30 import org.springframework.remoting.support.RemoteInvocationBasedAccessor;
31 import org.springframework.remoting.support.RemoteInvocationResult;
32 import org.springframework.util.ClassUtils;
33
34 /**
35  * Interceptor for accessing an HTTP invoker service.
36  * The service URL must be an HTTP URL exposing an HTTP invoker service.
37  *
38  * <p>Serializes remote invocation objects and deserializes remote invocation
39  * result objects. Uses Java serialization just like RMI, but provides the
40  * same ease of setup as Caucho's HTTP-based Hessian and Burlap protocols.
41  *
42  * <P>HTTP invoker is a very extensible and customizable protocol.
43  * It supports the RemoteInvocationFactory mechanism, like RMI invoker,
44  * allowing to include additional invocation attributes (for example,
45  * a security context). Furthermore, it allows to customize request
46  * execution via the {@link HttpInvokerRequestExecutor} strategy.
47  *
48  * <p>Can use the JDK's {@link java.rmi.server.RMIClassLoader} to load
49  * classes from a given {@link #setCodebaseUrl codebase}, performing
50  * on-demand dynamic code download from a remote location. The codebase
51  * can consist of multiple URLs, separated by spaces. Note that
52  * RMIClassLoader requires a SecurityManager to be set, analogous to
53  * when using dynamic class download with standard RMI!
54  * (See the RMI documentation for details.)
55  *
56  * @author Juergen Hoeller
57  * @since 1.1
58  * @see #setServiceUrl
59  * @see #setCodebaseUrl
60  * @see #setRemoteInvocationFactory
61  * @see #setHttpInvokerRequestExecutor
62  * @see HttpInvokerServiceExporter
63  * @see HttpInvokerProxyFactoryBean
64  * @see java.rmi.server.RMIClassLoader
65  */

66 public class HttpInvokerClientInterceptor extends RemoteInvocationBasedAccessor
67         implements MethodInterceptor, HttpInvokerClientConfiguration, BeanClassLoaderAware {
68
69     private String JavaDoc codebaseUrl;
70
71     private HttpInvokerRequestExecutor httpInvokerRequestExecutor;
72
73     private ClassLoader JavaDoc beanClassLoader = ClassUtils.getDefaultClassLoader();
74
75
76     /**
77      * Set the codebase URL to download classes from if not found locally.
78      * Can consists of multiple URLs, separated by spaces.
79      * <p>Follows RMI's codebase conventions for dynamic class download.
80      * In contrast to RMI, where the server determines the URL for class download
81      * (via the "java.rmi.server.codebase" system property), it's the client
82      * that determines the codebase URL here. The server will usually be the
83      * same as for the service URL, just pointing to a different path there.
84      * @see #setServiceUrl
85      * @see org.springframework.remoting.rmi.CodebaseAwareObjectInputStream
86      * @see java.rmi.server.RMIClassLoader
87      */

88     public void setCodebaseUrl(String JavaDoc codebaseUrl) {
89         this.codebaseUrl = codebaseUrl;
90     }
91
92     /**
93      * Return the codebase URL to download classes from if not found locally.
94      */

95     public String JavaDoc getCodebaseUrl() {
96         return this.codebaseUrl;
97     }
98
99     /**
100      * Set the HttpInvokerRequestExecutor implementation to use for executing
101      * remote invocations.
102      * <p>Default is {@link SimpleHttpInvokerRequestExecutor}. Alternatively,
103      * consider using {@link CommonsHttpInvokerRequestExecutor} for more
104      * sophisticated needs.
105      * @see SimpleHttpInvokerRequestExecutor
106      * @see CommonsHttpInvokerRequestExecutor
107      */

108     public void setHttpInvokerRequestExecutor(HttpInvokerRequestExecutor httpInvokerRequestExecutor) {
109         this.httpInvokerRequestExecutor = httpInvokerRequestExecutor;
110     }
111
112     /**
113      * Return the HttpInvokerRequestExecutor used by this remote accessor.
114      * <p>Creates a default SimpleHttpInvokerRequestExecutor if no executor
115      * has been initialized already.
116      */

117     public HttpInvokerRequestExecutor getHttpInvokerRequestExecutor() {
118         if (this.httpInvokerRequestExecutor == null) {
119             SimpleHttpInvokerRequestExecutor executor = new SimpleHttpInvokerRequestExecutor();
120             executor.setBeanClassLoader(this.beanClassLoader);
121             this.httpInvokerRequestExecutor = executor;
122         }
123         return this.httpInvokerRequestExecutor;
124     }
125
126     public void setBeanClassLoader(ClassLoader JavaDoc classLoader) {
127         this.beanClassLoader = classLoader;
128     }
129
130     /**
131      * Return the ClassLoader that this accessor operates in,
132      * to be used for deserializing and for generating proxies.
133      */

134     protected final ClassLoader JavaDoc getBeanClassLoader() {
135         return this.beanClassLoader;
136     }
137
138     public void afterPropertiesSet() {
139         super.afterPropertiesSet();
140
141         // Eagerly initialize the default HttpInvokerRequestExecutor, if needed.
142
getHttpInvokerRequestExecutor();
143     }
144
145
146     public Object JavaDoc invoke(MethodInvocation methodInvocation) throws Throwable JavaDoc {
147         if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {
148             return "HTTP invoker proxy for service URL [" + getServiceUrl() + "]";
149         }
150
151         RemoteInvocation invocation = createRemoteInvocation(methodInvocation);
152         RemoteInvocationResult result = null;
153         try {
154             result = executeRequest(invocation);
155         }
156         catch (Throwable JavaDoc ex) {
157             throw convertHttpInvokerAccessException(ex);
158         }
159         return recreateRemoteInvocationResult(result);
160     }
161
162     /**
163      * Execute the given remote invocation via the HttpInvokerRequestExecutor.
164      * <p>Can be overridden in subclasses to pass a different configuration object
165      * to the executor. Alternatively, add further configuration properties in a
166      * subclass of this accessor: By default, the accessor passed itself as
167      * configuration object to the executor.
168      * @param invocation the RemoteInvocation to execute
169      * @return the RemoteInvocationResult object
170      * @throws IOException if thrown by I/O operations
171      * @throws ClassNotFoundException if thrown during deserialization
172      * @throws Exception in case of general errors
173      * @see #getHttpInvokerRequestExecutor
174      * @see HttpInvokerClientConfiguration
175      */

176     protected RemoteInvocationResult executeRequest(RemoteInvocation invocation) throws Exception JavaDoc {
177         return getHttpInvokerRequestExecutor().executeRequest(this, invocation);
178     }
179
180     /**
181      * Convert the given HTTP invoker access exception to an appropriate
182      * Spring RemoteAccessException.
183      * @param ex the exception to convert
184      * @return the RemoteAccessException to throw
185      */

186     protected RemoteAccessException convertHttpInvokerAccessException(Throwable JavaDoc ex) {
187         if (ex instanceof ConnectException JavaDoc) {
188             throw new RemoteConnectFailureException(
189                     "Cannot connect to HTTP invoker remote service at [" + getServiceUrl() + "]", ex);
190         }
191         else if (ex instanceof ClassNotFoundException JavaDoc) {
192             throw new RemoteAccessException(
193                     "Cannot deserialize result from HTTP invoker remote service [" + getServiceUrl() + "]", ex);
194         }
195         else {
196             throw new RemoteAccessException(
197                 "Cannot access HTTP invoker remote service at [" + getServiceUrl() + "]", ex);
198         }
199     }
200
201 }
202
Popular Tags