KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mule > providers > http > HttpClientMessageDispatcher


1 /*
2  * $Id: HttpClientMessageDispatcher.java 3982 2006-11-22 14:28:01Z lajos $
3  * --------------------------------------------------------------------------------------
4  * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
5  *
6  * The software in this package is published under the terms of the MuleSource MPL
7  * license, a copy of which has been included with this distribution in the
8  * LICENSE.txt file.
9  */

10
11 package org.mule.providers.http;
12
13 import java.io.IOException JavaDoc;
14 import java.io.OutputStream JavaDoc;
15 import java.net.ConnectException JavaDoc;
16 import java.net.URI JavaDoc;
17 import java.net.URISyntaxException JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.Properties JavaDoc;
21
22 import org.apache.commons.codec.binary.Base64;
23 import org.apache.commons.httpclient.Cookie;
24 import org.apache.commons.httpclient.Header;
25 import org.apache.commons.httpclient.HostConfiguration;
26 import org.apache.commons.httpclient.HttpClient;
27 import org.apache.commons.httpclient.HttpMethod;
28 import org.apache.commons.httpclient.HttpState;
29 import org.apache.commons.httpclient.HttpStatus;
30 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
31 import org.apache.commons.httpclient.UsernamePasswordCredentials;
32 import org.apache.commons.httpclient.auth.AuthScope;
33 import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
34 import org.apache.commons.httpclient.methods.GetMethod;
35 import org.apache.commons.httpclient.methods.PostMethod;
36 import org.apache.commons.httpclient.methods.RequestEntity;
37 import org.apache.commons.httpclient.protocol.Protocol;
38 import org.apache.commons.io.IOUtils;
39 import org.apache.commons.lang.StringUtils;
40 import org.mule.config.i18n.Message;
41 import org.mule.impl.MuleMessage;
42 import org.mule.impl.message.ExceptionPayload;
43 import org.mule.providers.AbstractMessageDispatcher;
44 import org.mule.providers.http.transformers.HttpClientMethodResponseToObject;
45 import org.mule.providers.http.transformers.ObjectToHttpClientMethodRequest;
46 import org.mule.providers.streaming.StreamMessageAdapter;
47 import org.mule.umo.UMOEvent;
48 import org.mule.umo.UMOException;
49 import org.mule.umo.UMOMessage;
50 import org.mule.umo.endpoint.UMOImmutableEndpoint;
51 import org.mule.umo.provider.DispatchException;
52 import org.mule.umo.provider.ReceiveException;
53 import org.mule.umo.provider.UMOConnector;
54 import org.mule.umo.provider.UMOMessageAdapter;
55 import org.mule.umo.provider.UMOStreamMessageAdapter;
56 import org.mule.umo.transformer.TransformerException;
57 import org.mule.umo.transformer.UMOTransformer;
58
59 /**
60  * <code>HttpClientMessageDispatcher</code> dispatches Mule events over HTTP.
61  */

62 public class HttpClientMessageDispatcher extends AbstractMessageDispatcher
63 {
64     private final HttpConnector connector;
65     private volatile HttpClient client = null;
66     private final UMOTransformer receiveTransformer;
67
68     public HttpClientMessageDispatcher(UMOImmutableEndpoint endpoint)
69     {
70         super(endpoint);
71         this.connector = (HttpConnector)endpoint.getConnector();
72         receiveTransformer = new HttpClientMethodResponseToObject();
73     }
74
75     protected void doConnect(UMOImmutableEndpoint endpoint) throws Exception JavaDoc
76     {
77         if (client == null)
78         {
79             client = new HttpClient();
80
81             HttpState state = new HttpState();
82             if (connector.getProxyUsername() != null)
83             {
84                 state.setProxyCredentials(new AuthScope(null, -1, null, null),
85                     new UsernamePasswordCredentials(connector.getProxyUsername(),
86                         connector.getProxyPassword()));
87             }
88             client.setState(state);
89             client.setHttpConnectionManager(new MultiThreadedHttpConnectionManager());
90
91             // test the connection
92
// HeadMethod method = new
93
// HeadMethod(endpoint.getEndpointURI().getAddress());
94
// client.executeMethod(getHostConfig(endpoint.getEndpointURI().getUri()),
95
// method);
96
}
97
98     }
99
100     protected void doDisconnect() throws Exception JavaDoc
101     {
102         client = null;
103     }
104
105     /*
106      * (non-Javadoc)
107      *
108      * @see org.mule.providers.AbstractConnectorSession#doDispatch(org.mule.umo.UMOEvent)
109      */

110     protected void doDispatch(UMOEvent event) throws Exception JavaDoc
111     {
112         HttpMethod httpMethod = getMethod(event);
113         execute(event, httpMethod, true);
114         if (httpMethod.getStatusCode() >= 400)
115         {
116             logger.error(httpMethod.getResponseBodyAsString());
117             throw new DispatchException(event.getMessage(), event.getEndpoint(), new Exception JavaDoc(
118                 "Http call returned a status of: " + httpMethod.getStatusCode() + " "
119                                 + httpMethod.getStatusText()));
120         }
121     }
122
123     /*
124      * (non-Javadoc)
125      *
126      * @see org.mule.umo.provider.UMOConnectorSession#getConnector()
127      */

128     public UMOConnector getConnector()
129     {
130         return connector;
131     }
132
133     /*
134      * (non-Javadoc)
135      *
136      * @see org.mule.umo.provider.UMOConnectorSession#getDelegateSession()
137      */

138     public Object JavaDoc getDelegateSession() throws UMOException
139     {
140         return null;
141     }
142
143     /**
144      * Make a specific request to the underlying transport
145      *
146      * @param endpoint the endpoint to use when connecting to the resource
147      * @param timeout the maximum time the operation should block before returning.
148      * The call should return immediately if there is data available. If
149      * no data becomes available before the timeout elapses, null will be
150      * returned
151      * @return the result of the request wrapped in a UMOMessage object. Null will be
152      * returned if no data was avaialable
153      * @throws Exception if the call to the underlying protocal cuases an exception
154      */

155     protected UMOMessage doReceive(UMOImmutableEndpoint endpoint, long timeout) throws Exception JavaDoc
156     {
157
158         HttpMethod httpMethod = new GetMethod(endpoint.getEndpointURI().getAddress());
159         httpMethod.setDoAuthentication(true);
160         if (endpoint.getEndpointURI().getUserInfo() != null
161             && endpoint.getProperty(HttpConstants.HEADER_AUTHORIZATION) == null)
162         {
163             // Add User Creds
164
StringBuffer JavaDoc header = new StringBuffer JavaDoc(128);
165             header.append("Basic ");
166             header.append(new String JavaDoc(Base64.encodeBase64(endpoint.getEndpointURI().getUserInfo().getBytes(
167                 endpoint.getEncoding()))));
168             httpMethod.addRequestHeader(HttpConstants.HEADER_AUTHORIZATION, header.toString());
169         }
170         try
171         {
172             HttpClient client = new HttpClient();
173             client.executeMethod(httpMethod);
174
175             if (httpMethod.getStatusCode() == HttpStatus.SC_OK)
176             {
177                 return (UMOMessage)receiveTransformer.transform(httpMethod);
178             }
179             else
180             {
181                 throw new ReceiveException(new Message("http", 3, httpMethod.getStatusLine().toString()),
182                     endpoint, timeout);
183             }
184         }
185         catch (ReceiveException e)
186         {
187             throw e;
188         }
189         catch (Exception JavaDoc e)
190         {
191             throw new ReceiveException(endpoint, timeout, e);
192         }
193         finally
194         {
195             httpMethod.releaseConnection();
196         }
197     }
198
199     protected HttpMethod execute(UMOEvent event, HttpMethod httpMethod, boolean closeConnection)
200         throws Exception JavaDoc
201     {
202         // TODO set connection timeout buffer etc
203
try
204         {
205             URI JavaDoc uri = event.getEndpoint().getEndpointURI().getUri();
206
207             processCookies(event);
208             // TODO can we use this code for better reporting?
209
int code = client.executeMethod(getHostConfig(uri), httpMethod);
210
211             return httpMethod;
212         }
213         catch (ConnectException JavaDoc cex)
214         {
215             // TODO employ dispatcher reconnection strategy at this point
216
throw new DispatchException(event.getMessage(), event.getEndpoint(), cex);
217         }
218         catch (Exception JavaDoc e)
219         {
220             throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
221         }
222         finally
223         {
224             if (httpMethod != null && closeConnection)
225             {
226                 httpMethod.releaseConnection();
227             }
228         }
229     }
230
231     protected void processCookies(UMOEvent event)
232     {
233         UMOMessage msg = event.getMessage();
234         Cookie[] cookies = (Cookie[])msg.removeProperty(HttpConnector.HTTP_COOKIES_PROPERTY);
235         if (cookies != null && cookies.length > 0)
236         {
237             String JavaDoc policy = (String JavaDoc)msg.removeProperty(HttpConnector.HTTP_COOKIE_SPEC_PROPERTY);
238             client.getParams().setCookiePolicy(CookieHelper.getCookiePolicy(policy));
239             client.getState().addCookies(cookies);
240         }
241     }
242
243     protected HttpMethod getMethod(UMOEvent event) throws TransformerException
244     {
245         UMOMessage msg = event.getMessage();
246         String JavaDoc method = msg.getStringProperty(HttpConnector.HTTP_METHOD_PROPERTY, HttpConstants.METHOD_POST);
247         URI JavaDoc uri = event.getEndpoint().getEndpointURI().getUri();
248         HttpMethod httpMethod;
249         Object JavaDoc body = event.getTransformedMessage();
250
251         if (body instanceof HttpMethod)
252         {
253             httpMethod = (HttpMethod)body;
254         }
255         else if (HttpConstants.METHOD_GET.equalsIgnoreCase(method))
256         {
257             httpMethod = new GetMethod(uri.toString());
258         }
259         else
260         {
261             PostMethod postMethod = new PostMethod(uri.toString());
262
263             if (body instanceof String JavaDoc)
264             {
265                 ObjectToHttpClientMethodRequest trans = new ObjectToHttpClientMethodRequest();
266                 httpMethod = (HttpMethod)trans.transform(body.toString());
267             }
268             else if (body instanceof HttpMethod)
269             {
270                 httpMethod = (HttpMethod)body;
271             }
272             else if (body instanceof UMOStreamMessageAdapter)
273             {
274                 UMOStreamMessageAdapter sma = (UMOStreamMessageAdapter)body;
275                 Map JavaDoc headers = sma.getOutputHandler().getHeaders(event);
276                 for (Iterator JavaDoc iterator = headers.entrySet().iterator(); iterator.hasNext();)
277                 {
278                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc)iterator.next();
279                     postMethod.addRequestHeader((String JavaDoc)entry.getKey(), (String JavaDoc)entry.getValue());
280                 }
281                 postMethod.setRequestEntity(new StreamPayloadRequestEntity((StreamMessageAdapter)body, event));
282                 postMethod.setContentChunked(true);
283                 httpMethod = postMethod;
284             }
285             else
286             {
287                 byte[] buffer = event.getTransformedMessageAsBytes();
288                 postMethod.setRequestEntity(new ByteArrayRequestEntity(buffer, event.getEncoding()));
289                 httpMethod = postMethod;
290             }
291
292         }
293         httpMethod.setDoAuthentication(true);
294         if (event.getCredentials() != null)
295         {
296             String JavaDoc authScopeHost = msg.getStringProperty("http.auth.scope.host", null);
297             int authScopePort = msg.getIntProperty("http.auth.scope.port", -1);
298             String JavaDoc authScopeRealm = msg.getStringProperty("http.auth.scope.realm", null);
299             String JavaDoc authScopeScheme = msg.getStringProperty("http.auth.scope.scheme", null);
300             client.getState().setCredentials(
301                 new AuthScope(authScopeHost, authScopePort, authScopeRealm, authScopeScheme),
302                 new UsernamePasswordCredentials(event.getCredentials().getUsername(), new String JavaDoc(
303                     event.getCredentials().getPassword())));
304             client.getParams().setAuthenticationPreemptive(true);
305         }
306         else
307         {
308             // don't use preemptive if there are no credentials to send
309
client.getParams().setAuthenticationPreemptive(false);
310         }
311         return httpMethod;
312     }
313
314     /*
315      * (non-Javadoc)
316      *
317      * @see org.mule.umo.provider.UMOConnector#send(org.mule.umo.UMOEvent)
318      */

319     protected UMOMessage doSend(UMOEvent event) throws Exception JavaDoc
320     {
321         HttpMethod httpMethod = getMethod(event);
322
323         httpMethod = execute(event, httpMethod, false);
324
325         try
326         {
327             Properties JavaDoc h = new Properties JavaDoc();
328             Header[] headers = httpMethod.getResponseHeaders();
329             for (int i = 0; i < headers.length; i++)
330             {
331                 h.setProperty(headers[i].getName(), headers[i].getValue());
332             }
333
334             String JavaDoc status = String.valueOf(httpMethod.getStatusCode());
335
336             h.setProperty(HttpConnector.HTTP_STATUS_PROPERTY, status);
337             if (logger.isDebugEnabled())
338             {
339                 logger.debug("Http response is: " + status);
340             }
341             ExceptionPayload ep = null;
342             if (httpMethod.getStatusCode() >= 400)
343             {
344                 ep = new ExceptionPayload(new DispatchException(event.getMessage(), event.getEndpoint(),
345                     new Exception JavaDoc("Http call returned a status of: " + httpMethod.getStatusCode() + " "
346                                   + httpMethod.getStatusText())));
347             }
348             UMOMessage m;
349             // text or binary content?
350
Header header = httpMethod.getResponseHeader(HttpConstants.HEADER_CONTENT_TYPE);
351             if ((header != null) && event.isStreaming())
352             {
353                 HttpStreamMessageAdapter sp = (HttpStreamMessageAdapter)connector.getStreamMessageAdapter(
354                     httpMethod.getResponseBodyAsStream(), null);
355                 sp.setHttpMethod(httpMethod);
356                 m = new MuleMessage(sp, h);
357             }
358             else
359             {
360                 Object JavaDoc body = IOUtils.toByteArray(httpMethod.getResponseBodyAsStream());
361                 if (body == null)
362                 {
363                     body = StringUtils.EMPTY;
364                 }
365                 UMOMessageAdapter adapter = connector.getMessageAdapter(new Object JavaDoc[]{body, h});
366                 m = new MuleMessage(adapter);
367             }
368             m.setExceptionPayload(ep);
369             return m;
370         }
371         catch (Exception JavaDoc e)
372         {
373             throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
374         }
375         finally
376         {
377             if (httpMethod != null && !event.isStreaming())
378             {
379                 httpMethod.releaseConnection();
380             }
381         }
382     }
383
384     protected HostConfiguration getHostConfig(URI JavaDoc uri) throws URISyntaxException JavaDoc
385     {
386         Protocol protocol = Protocol.getProtocol(uri.getScheme().toLowerCase());
387
388         String JavaDoc host = uri.getHost();
389         int port = uri.getPort();
390         HostConfiguration config = new HostConfiguration();
391         config.setHost(host, port, protocol);
392         if (StringUtils.isNotBlank(connector.getProxyHostname()))
393         {
394             // add proxy support
395
config.setProxy(connector.getProxyHostname(), connector.getProxyPort());
396         }
397         return config;
398     }
399
400     protected void doDispose()
401     {
402         // template method
403
}
404
405     private class StreamPayloadRequestEntity implements RequestEntity
406     {
407         private UMOStreamMessageAdapter messageAdapter;
408         private UMOEvent event;
409
410         public StreamPayloadRequestEntity(UMOStreamMessageAdapter messageAdapter, UMOEvent event)
411         {
412             this.messageAdapter = messageAdapter;
413             this.event = event;
414         }
415
416         public boolean isRepeatable()
417         {
418             return true;
419         }
420
421         public void writeRequest(OutputStream JavaDoc outputStream) throws IOException JavaDoc
422         {
423             messageAdapter.getOutputHandler().write(event, outputStream);
424         }
425
426         public long getContentLength()
427         {
428             return -1L;
429         }
430
431         public String JavaDoc getContentType()
432         {
433             return event.getMessage().getStringProperty(HttpConstants.HEADER_CONTENT_TYPE, null);
434         }
435     }
436
437 }
438
Popular Tags