1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.http;
12
13 import org.mule.api.MuleContext;
14 import org.mule.api.MuleEvent;
15 import org.mule.api.MuleMessage;
16 import org.mule.api.construct.FlowConstruct;
17 import org.mule.api.endpoint.ImmutableEndpoint;
18 import org.mule.api.endpoint.InboundEndpoint;
19 import org.mule.api.lifecycle.InitialisationException;
20 import org.mule.api.processor.MessageProcessor;
21 import org.mule.config.i18n.CoreMessages;
22 import org.mule.transport.http.ntlm.NTLMScheme;
23 import org.mule.transport.tcp.TcpConnector;
24
25 import java.io.UnsupportedEncodingException;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.Set;
31
32 import org.apache.commons.codec.binary.Base64;
33 import org.apache.commons.httpclient.Credentials;
34 import org.apache.commons.httpclient.HttpClient;
35 import org.apache.commons.httpclient.HttpConnectionManager;
36 import org.apache.commons.httpclient.HttpMethod;
37 import org.apache.commons.httpclient.HttpState;
38 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
39 import org.apache.commons.httpclient.NTCredentials;
40 import org.apache.commons.httpclient.UsernamePasswordCredentials;
41 import org.apache.commons.httpclient.auth.AuthPolicy;
42 import org.apache.commons.httpclient.auth.AuthScope;
43 import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public class HttpConnector extends TcpConnector
64 {
65
66 public static final String HTTP = "http";
67 public static final String HTTP_PREFIX = "http.";
68
69
70
71
72 public static final String HTTP_STATUS_PROPERTY = HTTP_PREFIX + "status";
73 public static final String HTTP_VERSION_PROPERTY = HTTP_PREFIX + "version";
74
75
76
77
78 @Deprecated
79 public static final String HTTP_CUSTOM_HEADERS_MAP_PROPERTY = HTTP_PREFIX + "custom.headers";
80
81 public static final String HTTP_METHOD_PROPERTY = HTTP_PREFIX + "method";
82
83
84
85
86 public static final String HTTP_REQUEST_PROPERTY = HTTP_PREFIX + "request";
87
88
89
90
91 public static final String HTTP_REQUEST_PATH_PROPERTY = HTTP_PREFIX + "request.path";
92
93
94
95
96
97 public static final String HTTP_CONTEXT_PATH_PROPERTY = HTTP_PREFIX + "context.path";
98
99 public static final String HTTP_SERVLET_REQUEST_PROPERTY = HTTP_PREFIX + "servlet.request";
100 public static final String HTTP_SERVLET_RESPONSE_PROPERTY = HTTP_PREFIX + "servlet.response";
101
102
103
104
105
106 public static final String HTTP_PARAMS_PROPERTY = HTTP_PREFIX + "params";
107 public static final String HTTP_GET_BODY_PARAM_PROPERTY = HTTP_PREFIX + "get.body.param";
108 public static final String DEFAULT_HTTP_GET_BODY_PARAM_PROPERTY = "body";
109 public static final String HTTP_POST_BODY_PARAM_PROPERTY = HTTP_PREFIX + "post.body.param";
110
111 public static final String HTTP_DISABLE_STATUS_CODE_EXCEPTION_CHECK = HTTP_PREFIX + "disable.status.code.exception.check";
112 public static final String HTTP_ENCODE_PARAMVALUE = HTTP_PREFIX + "encode.paramvalue";
113
114 public static final Set<String> HTTP_INBOUND_PROPERTIES;
115
116 static
117 {
118 Set<String> props = new HashSet<String>();
119 props.add(HTTP_CONTEXT_PATH_PROPERTY);
120 props.add(HTTP_GET_BODY_PARAM_PROPERTY);
121 props.add(HTTP_METHOD_PROPERTY);
122 props.add(HTTP_PARAMS_PROPERTY);
123 props.add(HTTP_POST_BODY_PARAM_PROPERTY);
124 props.add(HTTP_REQUEST_PROPERTY);
125 props.add(HTTP_REQUEST_PATH_PROPERTY);
126 props.add(HTTP_STATUS_PROPERTY);
127 props.add(HTTP_VERSION_PROPERTY);
128 props.add(HTTP_ENCODE_PARAMVALUE);
129 HTTP_INBOUND_PROPERTIES = props;
130
131 AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, NTLMScheme.class);
132 }
133
134 public static final String HTTP_COOKIE_SPEC_PROPERTY = "cookieSpec";
135 public static final String HTTP_COOKIES_PROPERTY = "cookies";
136 public static final String HTTP_ENABLE_COOKIES_PROPERTY = "enableCookies";
137
138 public static final String COOKIE_SPEC_NETSCAPE = "netscape";
139 public static final String COOKIE_SPEC_RFC2109 = "rfc2109";
140
141 private String proxyHostname = null;
142
143 private int proxyPort = HttpConstants.DEFAULT_HTTP_PORT;
144
145 private String proxyUsername = null;
146
147 private String proxyPassword = null;
148
149 private boolean proxyNtlmAuthentication;
150
151 private String cookieSpec;
152
153 private boolean enableCookies = false;
154
155 protected HttpConnectionManager clientConnectionManager;
156
157 public HttpConnector(MuleContext context)
158 {
159 super(context);
160 }
161
162 @Override
163 protected void doInitialise() throws InitialisationException
164 {
165 super.doInitialise();
166 if (clientConnectionManager == null)
167 {
168 clientConnectionManager = new MultiThreadedHttpConnectionManager();
169 HttpConnectionManagerParams params = new HttpConnectionManagerParams();
170 if (getSendBufferSize() != INT_VALUE_NOT_SET)
171 {
172 params.setSendBufferSize(getSendBufferSize());
173 }
174 if (getReceiveBufferSize() != INT_VALUE_NOT_SET)
175 {
176 params.setReceiveBufferSize(getReceiveBufferSize());
177 }
178 if (getClientSoTimeout() != INT_VALUE_NOT_SET)
179 {
180 params.setSoTimeout(getClientSoTimeout());
181 }
182 if (getSocketSoLinger() != INT_VALUE_NOT_SET)
183 {
184 params.setLinger(getSocketSoLinger());
185 }
186
187 params.setTcpNoDelay(isSendTcpNoDelay());
188 params.setMaxTotalConnections(dispatchers.getMaxTotal());
189 params.setDefaultMaxConnectionsPerHost(dispatchers.getMaxTotal());
190 clientConnectionManager.setParams(params);
191 }
192 }
193
194 @Override
195 public void registerListener(InboundEndpoint endpoint, MessageProcessor listener, FlowConstruct flowConstruct) throws Exception
196 {
197 if (endpoint != null)
198 {
199 Map endpointProperties = endpoint.getProperties();
200 if (endpointProperties != null)
201 {
202
203 Map newProperties = new HashMap(endpointProperties.size());
204 for (Iterator entries = endpointProperties.entrySet().iterator(); entries.hasNext();)
205 {
206 Map.Entry entry = (Map.Entry) entries.next();
207 Object key = entry.getKey();
208 Object normalizedKey = HttpConstants.ALL_HEADER_NAMES.get(key);
209 if (normalizedKey != null)
210 {
211
212 key = normalizedKey;
213 }
214 newProperties.put(key, entry.getValue());
215 }
216
217 endpoint.getProperties().clear();
218 endpoint.getProperties().putAll(newProperties);
219 }
220 }
221
222 super.registerListener(endpoint, listener, flowConstruct);
223 }
224
225
226
227
228
229
230
231 @Override
232 protected Object getReceiverKey(FlowConstruct flowConstruct, InboundEndpoint endpoint)
233 {
234 String key = endpoint.getEndpointURI().toString();
235 int i = key.indexOf('?');
236 if (i > -1)
237 {
238 key = key.substring(0, i);
239 }
240 return key;
241 }
242
243
244
245
246 @Override
247 public String getProtocol()
248 {
249 return HTTP;
250 }
251
252 public String getProxyHostname()
253 {
254 return proxyHostname;
255 }
256
257 public String getProxyPassword()
258 {
259 return proxyPassword;
260 }
261
262 public int getProxyPort()
263 {
264 return proxyPort;
265 }
266
267 public String getProxyUsername()
268 {
269 return proxyUsername;
270 }
271
272 public void setProxyHostname(String host)
273 {
274 proxyHostname = host;
275 }
276
277 public void setProxyPassword(String string)
278 {
279 proxyPassword = string;
280 }
281
282 public void setProxyPort(int port)
283 {
284 proxyPort = port;
285 }
286
287 public void setProxyUsername(String string)
288 {
289 proxyUsername = string;
290 }
291
292 @Override
293 public Map getReceivers()
294 {
295 return this.receivers;
296 }
297
298 public String getCookieSpec()
299 {
300 return cookieSpec;
301 }
302
303 public void setCookieSpec(String cookieSpec)
304 {
305 if (!(COOKIE_SPEC_NETSCAPE.equalsIgnoreCase(cookieSpec) || COOKIE_SPEC_RFC2109.equalsIgnoreCase(cookieSpec)))
306 {
307 throw new IllegalArgumentException(
308 CoreMessages.propertyHasInvalidValue("cookieSpec", cookieSpec).toString());
309 }
310 this.cookieSpec = cookieSpec;
311 }
312
313 public boolean isEnableCookies()
314 {
315 return enableCookies;
316 }
317
318 public void setEnableCookies(boolean enableCookies)
319 {
320 this.enableCookies = enableCookies;
321 }
322
323
324 public HttpConnectionManager getClientConnectionManager()
325 {
326 return clientConnectionManager;
327 }
328
329 public void setClientConnectionManager(HttpConnectionManager clientConnectionManager)
330 {
331 this.clientConnectionManager = clientConnectionManager;
332 }
333
334 protected HttpClient doClientConnect() throws Exception
335 {
336 HttpState state = new HttpState();
337
338 if (getProxyUsername() != null)
339 {
340 Credentials credentials;
341 if (isProxyNtlmAuthentication())
342 {
343 credentials = new NTCredentials(getProxyUsername(), getProxyPassword(), getProxyHostname(), "");
344 }
345 else
346 {
347 credentials = new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword());
348 }
349
350 AuthScope authscope = new AuthScope(getProxyHostname(), getProxyPort());
351
352 state.setProxyCredentials(authscope, credentials);
353 }
354
355 HttpClient client = new HttpClient();
356 client.setState(state);
357 client.setHttpConnectionManager(getClientConnectionManager());
358
359 return client;
360 }
361
362 protected void setupClientAuthorization(MuleEvent event, HttpMethod httpMethod,
363 HttpClient client, ImmutableEndpoint endpoint)
364 throws UnsupportedEncodingException
365 {
366 httpMethod.setDoAuthentication(true);
367 client.getParams().setAuthenticationPreemptive(true);
368
369 if (event != null && event.getCredentials() != null)
370 {
371 MuleMessage msg = event.getMessage();
372 String authScopeHost = msg.getOutboundProperty(HTTP_PREFIX + "auth.scope.host", event.getMessageSourceURI().getHost());
373 int authScopePort = msg.getOutboundProperty(HTTP_PREFIX + "auth.scope.port", event.getMessageSourceURI().getPort());
374 String authScopeRealm = msg.getOutboundProperty(HTTP_PREFIX + "auth.scope.realm", AuthScope.ANY_REALM);
375 String authScopeScheme = msg.getOutboundProperty(HTTP_PREFIX + "auth.scope.scheme", AuthScope.ANY_SCHEME);
376 client.getState().setCredentials(
377 new AuthScope(authScopeHost, authScopePort, authScopeRealm, authScopeScheme),
378 new UsernamePasswordCredentials(event.getCredentials().getUsername(), new String(
379 event.getCredentials().getPassword())));
380 }
381 else if (endpoint.getEndpointURI().getUserInfo() != null
382 && endpoint.getProperty(HttpConstants.HEADER_AUTHORIZATION) == null)
383 {
384
385 StringBuffer header = new StringBuffer(128);
386 header.append("Basic ");
387 header.append(new String(Base64.encodeBase64(endpoint.getEndpointURI().getUserInfo().getBytes(
388 endpoint.getEncoding()))));
389 httpMethod.addRequestHeader(HttpConstants.HEADER_AUTHORIZATION, header.toString());
390 }
391
392 else if (event!=null && event.getMessage().getOutboundProperty(HttpConstants.HEADER_AUTHORIZATION) != null &&
393 httpMethod.getRequestHeader(HttpConstants.HEADER_AUTHORIZATION)==null)
394 {
395 String auth = event.getMessage().getOutboundProperty(HttpConstants.HEADER_AUTHORIZATION);
396 httpMethod.addRequestHeader(HttpConstants.HEADER_AUTHORIZATION, auth);
397 }
398 else
399 {
400
401 client.getParams().setAuthenticationPreemptive(false);
402 }
403 }
404
405
406
407
408 public static String normalizeUrl(String url)
409 {
410 if (url == null)
411 {
412 url = "/";
413 }
414 else if (!url.startsWith("/"))
415 {
416 url = "/" + url;
417 }
418 return url;
419 }
420
421 public boolean isProxyNtlmAuthentication()
422 {
423 return proxyNtlmAuthentication;
424 }
425
426 public void setProxyNtlmAuthentication(boolean proxyNtlmAuthentication)
427 {
428 this.proxyNtlmAuthentication = proxyNtlmAuthentication;
429 }
430 }