1 10 11 package org.mule.providers.http; 12 13 import java.io.IOException ; 14 import java.io.OutputStream ; 15 import java.net.ConnectException ; 16 import java.net.URI ; 17 import java.net.URISyntaxException ; 18 import java.util.Iterator ; 19 import java.util.Map ; 20 import java.util.Properties ; 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 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 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 } 97 98 } 99 100 protected void doDisconnect() throws Exception 101 { 102 client = null; 103 } 104 105 110 protected void doDispatch(UMOEvent event) throws Exception 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 ( 118 "Http call returned a status of: " + httpMethod.getStatusCode() + " " 119 + httpMethod.getStatusText())); 120 } 121 } 122 123 128 public UMOConnector getConnector() 129 { 130 return connector; 131 } 132 133 138 public Object getDelegateSession() throws UMOException 139 { 140 return null; 141 } 142 143 155 protected UMOMessage doReceive(UMOImmutableEndpoint endpoint, long timeout) throws Exception 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 StringBuffer header = new StringBuffer (128); 165 header.append("Basic "); 166 header.append(new String (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 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 201 { 202 try 204 { 205 URI uri = event.getEndpoint().getEndpointURI().getUri(); 206 207 processCookies(event); 208 int code = client.executeMethod(getHostConfig(uri), httpMethod); 210 211 return httpMethod; 212 } 213 catch (ConnectException cex) 214 { 215 throw new DispatchException(event.getMessage(), event.getEndpoint(), cex); 217 } 218 catch (Exception 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 policy = (String )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 method = msg.getStringProperty(HttpConnector.HTTP_METHOD_PROPERTY, HttpConstants.METHOD_POST); 247 URI uri = event.getEndpoint().getEndpointURI().getUri(); 248 HttpMethod httpMethod; 249 Object 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 ) 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 headers = sma.getOutputHandler().getHeaders(event); 276 for (Iterator iterator = headers.entrySet().iterator(); iterator.hasNext();) 277 { 278 Map.Entry entry = (Map.Entry )iterator.next(); 279 postMethod.addRequestHeader((String )entry.getKey(), (String )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 authScopeHost = msg.getStringProperty("http.auth.scope.host", null); 297 int authScopePort = msg.getIntProperty("http.auth.scope.port", -1); 298 String authScopeRealm = msg.getStringProperty("http.auth.scope.realm", null); 299 String 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 ( 303 event.getCredentials().getPassword()))); 304 client.getParams().setAuthenticationPreemptive(true); 305 } 306 else 307 { 308 client.getParams().setAuthenticationPreemptive(false); 310 } 311 return httpMethod; 312 } 313 314 319 protected UMOMessage doSend(UMOEvent event) throws Exception 320 { 321 HttpMethod httpMethod = getMethod(event); 322 323 httpMethod = execute(event, httpMethod, false); 324 325 try 326 { 327 Properties h = new Properties (); 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 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 ("Http call returned a status of: " + httpMethod.getStatusCode() + " " 346 + httpMethod.getStatusText()))); 347 } 348 UMOMessage m; 349 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 body = IOUtils.toByteArray(httpMethod.getResponseBodyAsStream()); 361 if (body == null) 362 { 363 body = StringUtils.EMPTY; 364 } 365 UMOMessageAdapter adapter = connector.getMessageAdapter(new Object []{body, h}); 366 m = new MuleMessage(adapter); 367 } 368 m.setExceptionPayload(ep); 369 return m; 370 } 371 catch (Exception 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 uri) throws URISyntaxException 385 { 386 Protocol protocol = Protocol.getProtocol(uri.getScheme().toLowerCase()); 387 388 String 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 config.setProxy(connector.getProxyHostname(), connector.getProxyPort()); 396 } 397 return config; 398 } 399 400 protected void doDispose() 401 { 402 } 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 outputStream) throws IOException 422 { 423 messageAdapter.getOutputHandler().write(event, outputStream); 424 } 425 426 public long getContentLength() 427 { 428 return -1L; 429 } 430 431 public String getContentType() 432 { 433 return event.getMessage().getStringProperty(HttpConstants.HEADER_CONTENT_TYPE, null); 434 } 435 } 436 437 } 438 | Popular Tags |