KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > transport > http > CommonsHTTPSender


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
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 package org.apache.axis.transport.http;
17
18 import org.apache.axis.AxisFault;
19 import org.apache.axis.Constants;
20 import org.apache.axis.Message;
21 import org.apache.axis.MessageContext;
22 import org.apache.axis.components.logger.LogFactory;
23 import org.apache.axis.components.net.CommonsHTTPClientProperties;
24 import org.apache.axis.components.net.CommonsHTTPClientPropertiesFactory;
25 import org.apache.axis.components.net.TransportClientProperties;
26 import org.apache.axis.components.net.TransportClientPropertiesFactory;
27 import org.apache.axis.handlers.BasicHandler;
28 import org.apache.axis.soap.SOAP12Constants;
29 import org.apache.axis.soap.SOAPConstants;
30 import org.apache.axis.utils.Messages;
31 import org.apache.axis.utils.NetworkUtils;
32 import org.apache.axis.utils.JavaUtils;
33 import org.apache.commons.httpclient.Cookie;
34 import org.apache.commons.httpclient.Credentials;
35 import org.apache.commons.httpclient.Header;
36 import org.apache.commons.httpclient.HostConfiguration;
37 import org.apache.commons.httpclient.HttpClient;
38 import org.apache.commons.httpclient.HttpConnectionManager;
39 import org.apache.commons.httpclient.HttpMethodBase;
40 import org.apache.commons.httpclient.HttpState;
41 import org.apache.commons.httpclient.HttpVersion;
42 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
43 import org.apache.commons.httpclient.NTCredentials;
44 import org.apache.commons.httpclient.UsernamePasswordCredentials;
45 import org.apache.commons.httpclient.auth.AuthScope;
46 import org.apache.commons.httpclient.cookie.CookiePolicy;
47 import org.apache.commons.httpclient.methods.GetMethod;
48 import org.apache.commons.httpclient.methods.PostMethod;
49 import org.apache.commons.httpclient.methods.RequestEntity;
50 import org.apache.commons.httpclient.params.HttpMethodParams;
51 import org.apache.commons.logging.Log;
52
53 import javax.xml.soap.MimeHeader JavaDoc;
54 import javax.xml.soap.MimeHeaders JavaDoc;
55 import javax.xml.soap.SOAPException JavaDoc;
56 import java.io.FilterInputStream JavaDoc;
57 import java.io.IOException JavaDoc;
58 import java.io.InputStream JavaDoc;
59 import java.io.OutputStream JavaDoc;
60 import java.net.URL JavaDoc;
61 import java.util.Hashtable JavaDoc;
62 import java.util.Iterator JavaDoc;
63 import java.util.Map JavaDoc;
64 import java.util.StringTokenizer JavaDoc;
65 import java.util.ArrayList JavaDoc;
66
67 /**
68  * This class uses Jakarta Commons's HttpClient to call a SOAP server.
69  *
70  * @author Davanum Srinivas (dims@yahoo.com)
71  * History: By Chandra Talluri
72  * Modifications done for maintaining sessions. Cookies needed to be set on
73  * HttpState not on MessageContext, since ttpMethodBase overwrites the cookies
74  * from HttpState. Also we need to setCookiePolicy on HttpState to
75  * CookiePolicy.COMPATIBILITY else it is defaulting to RFC2109Spec and adding
76  * Version information to it and tomcat server not recognizing it
77  */

78 public class CommonsHTTPSender extends BasicHandler {
79     
80     /** Field log */
81     protected static Log log =
82         LogFactory.getLog(CommonsHTTPSender.class.getName());
83     
84     protected HttpConnectionManager connectionManager;
85     protected CommonsHTTPClientProperties clientProperties;
86     boolean httpChunkStream = true; //Use HTTP chunking or not.
87

88     public CommonsHTTPSender() {
89         initialize();
90     }
91
92     protected void initialize() {
93         MultiThreadedHttpConnectionManager cm = new MultiThreadedHttpConnectionManager();
94         this.clientProperties = CommonsHTTPClientPropertiesFactory.create();
95         cm.getParams().setDefaultMaxConnectionsPerHost(clientProperties.getMaximumConnectionsPerHost());
96         cm.getParams().setMaxTotalConnections(clientProperties.getMaximumTotalConnections());
97         // If defined, set the default timeouts
98
// Can be overridden by the MessageContext
99
if(this.clientProperties.getDefaultConnectionTimeout()>0) {
100            cm.getParams().setConnectionTimeout(this.clientProperties.getDefaultConnectionTimeout());
101         }
102         if(this.clientProperties.getDefaultSoTimeout()>0) {
103            cm.getParams().setSoTimeout(this.clientProperties.getDefaultSoTimeout());
104         }
105         this.connectionManager = cm;
106     }
107     
108     /**
109      * invoke creates a socket connection, sends the request SOAP message and then
110      * reads the response SOAP message back from the SOAP server
111      *
112      * @param msgContext the messsage context
113      *
114      * @throws AxisFault
115      */

116     public void invoke(MessageContext msgContext) throws AxisFault {
117         HttpMethodBase method = null;
118         if (log.isDebugEnabled()) {
119             log.debug(Messages.getMessage("enter00",
120                                           "CommonsHTTPSender::invoke"));
121         }
122         try {
123             URL JavaDoc targetURL =
124                 new URL JavaDoc(msgContext.getStrProp(MessageContext.TRANS_URL));
125             
126             // no need to retain these, as the cookies/credentials are
127
// stored in the message context across multiple requests.
128
// the underlying connection manager, however, is retained
129
// so sockets get recycled when possible.
130
HttpClient httpClient = new HttpClient(this.connectionManager);
131             // the timeout value for allocation of connections from the pool
132
httpClient.getParams().setConnectionManagerTimeout(this.clientProperties.getConnectionPoolTimeout());
133
134             HostConfiguration hostConfiguration =
135                 getHostConfiguration(httpClient, msgContext, targetURL);
136             
137             boolean posting = true;
138             
139             // If we're SOAP 1.2, allow the web method to be set from the
140
// MessageContext.
141
if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS) {
142                 String JavaDoc webMethod = msgContext.getStrProp(SOAP12Constants.PROP_WEBMETHOD);
143                 if (webMethod != null) {
144                     posting = webMethod.equals(HTTPConstants.HEADER_POST);
145                 }
146             }
147
148             if (posting) {
149                 Message reqMessage = msgContext.getRequestMessage();
150                 method = new PostMethod(targetURL.toString());
151
152                 // set false as default, addContetInfo can overwrite
153
method.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE,
154                                                        false);
155                 
156                 addContextInfo(method, httpClient, msgContext, targetURL);
157
158                 ((PostMethod)method).setRequestEntity(
159                                                new MessageRequestEntity(method, reqMessage, httpChunkStream));
160             } else {
161                 method = new GetMethod(targetURL.toString());
162                 addContextInfo(method, httpClient, msgContext, targetURL);
163             }
164
165             String JavaDoc httpVersion =
166                 msgContext.getStrProp(MessageContext.HTTP_TRANSPORT_VERSION);
167             if (httpVersion != null) {
168                 if (httpVersion.equals(HTTPConstants.HEADER_PROTOCOL_V10)) {
169                     method.getParams().setVersion(HttpVersion.HTTP_1_0);
170                 }
171                 // assume 1.1
172
}
173             
174             // don't forget the cookies!
175
// Cookies need to be set on HttpState, since HttpMethodBase
176
// overwrites the cookies from HttpState
177
if (msgContext.getMaintainSession()) {
178                 HttpState state = httpClient.getState();
179                 method.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
180                 String JavaDoc host = hostConfiguration.getHost();
181                 String JavaDoc path = targetURL.getPath();
182                 boolean secure = hostConfiguration.getProtocol().isSecure();
183                 fillHeaders(msgContext, state, HTTPConstants.HEADER_COOKIE, host, path, secure);
184                 fillHeaders(msgContext, state, HTTPConstants.HEADER_COOKIE2, host, path, secure);
185                 httpClient.setState(state);
186             }
187
188             int returnCode = httpClient.executeMethod(hostConfiguration, method, null);
189
190             String JavaDoc contentType =
191                 getHeader(method, HTTPConstants.HEADER_CONTENT_TYPE);
192             String JavaDoc contentLocation =
193                 getHeader(method, HTTPConstants.HEADER_CONTENT_LOCATION);
194             String JavaDoc contentLength =
195                 getHeader(method, HTTPConstants.HEADER_CONTENT_LENGTH);
196
197             if ((returnCode > 199) && (returnCode < 300)) {
198                 
199                 // SOAP return is OK - so fall through
200
} else if (msgContext.getSOAPConstants() ==
201                        SOAPConstants.SOAP12_CONSTANTS) {
202                 // For now, if we're SOAP 1.2, fall through, since the range of
203
// valid result codes is much greater
204
} else if ((contentType != null) && !contentType.equals("text/html")
205                        && ((returnCode > 499) && (returnCode < 600))) {
206                 
207                 // SOAP Fault should be in here - so fall through
208
} else {
209                 String JavaDoc statusMessage = method.getStatusText();
210                 AxisFault fault = new AxisFault("HTTP",
211                                                 "(" + returnCode + ")"
212                                                 + statusMessage, null,
213                                                 null);
214                 
215                 try {
216                     fault.setFaultDetailString(
217                          Messages.getMessage("return01",
218                                              "" + returnCode,
219                                              method.getResponseBodyAsString()));
220                     fault.addFaultDetail(Constants.QNAME_FAULTDETAIL_HTTPERRORCODE,
221                                          Integer.toString(returnCode));
222                     throw fault;
223                 } finally {
224                     method.releaseConnection(); // release connection back to pool.
225
}
226             }
227             
228             // wrap the response body stream so that close() also releases
229
// the connection back to the pool.
230
InputStream JavaDoc releaseConnectionOnCloseStream =
231                 createConnectionReleasingInputStream(method);
232
233             Message outMsg = new Message(releaseConnectionOnCloseStream,
234                                          false, contentType, contentLocation);
235             // Transfer HTTP headers of HTTP message to MIME headers of SOAP message
236
Header[] responseHeaders = method.getResponseHeaders();
237             MimeHeaders JavaDoc responseMimeHeaders = outMsg.getMimeHeaders();
238             for (int i = 0; i < responseHeaders.length; i++) {
239                 Header responseHeader = responseHeaders[i];
240                 responseMimeHeaders.addHeader(responseHeader.getName(),
241                                               responseHeader.getValue());
242             }
243             outMsg.setMessageType(Message.RESPONSE);
244             msgContext.setResponseMessage(outMsg);
245             if (log.isDebugEnabled()) {
246                 if (null == contentLength) {
247                     log.debug("\n"
248                     + Messages.getMessage("no00", "Content-Length"));
249                 }
250                 log.debug("\n" + Messages.getMessage("xmlRecd00"));
251                 log.debug("-----------------------------------------------");
252                 log.debug(outMsg.getSOAPPartAsString());
253             }
254             
255             // if we are maintaining session state,
256
// handle cookies (if any)
257
if (msgContext.getMaintainSession()) {
258                 Header[] headers = method.getResponseHeaders();
259
260                 for (int i = 0; i < headers.length; i++) {
261                     if (headers[i].getName().equalsIgnoreCase(HTTPConstants.HEADER_SET_COOKIE)) {
262                         handleCookie(HTTPConstants.HEADER_COOKIE, headers[i].getValue(), msgContext);
263                     } else if (headers[i].getName().equalsIgnoreCase(HTTPConstants.HEADER_SET_COOKIE2)) {
264                         handleCookie(HTTPConstants.HEADER_COOKIE2, headers[i].getValue(), msgContext);
265                     }
266                 }
267             }
268
269             // always release the connection back to the pool if
270
// it was one way invocation
271
if (msgContext.isPropertyTrue("axis.one.way")) {
272                 method.releaseConnection();
273             }
274             
275         } catch (Exception JavaDoc e) {
276             log.debug(e);
277             throw AxisFault.makeFault(e);
278         }
279         
280         if (log.isDebugEnabled()) {
281             log.debug(Messages.getMessage("exit00",
282                                           "CommonsHTTPSender::invoke"));
283         }
284     }
285
286     /**
287      * little helper function for cookies. fills up the message context with
288      * a string or an array of strings (if there are more than one Set-Cookie)
289      *
290      * @param cookieName
291      * @param setCookieName
292      * @param cookie
293      * @param msgContext
294      */

295     public void handleCookie(String JavaDoc cookieName, String JavaDoc cookie,
296             MessageContext msgContext) {
297         
298         cookie = cleanupCookie(cookie);
299         int keyIndex = cookie.indexOf("=");
300         String JavaDoc key = (keyIndex != -1) ? cookie.substring(0, keyIndex) : cookie;
301         
302         ArrayList JavaDoc cookies = new ArrayList JavaDoc();
303         Object JavaDoc oldCookies = msgContext.getProperty(cookieName);
304         boolean alreadyExist = false;
305         if(oldCookies != null) {
306             if(oldCookies instanceof String JavaDoc[]) {
307                 String JavaDoc[] oldCookiesArray = (String JavaDoc[])oldCookies;
308                 for(int i = 0; i < oldCookiesArray.length; i++) {
309                     String JavaDoc anOldCookie = oldCookiesArray[i];
310                     if (key != null && anOldCookie.indexOf(key) == 0) { // same cookie key
311
anOldCookie = cookie; // update to new one
312
alreadyExist = true;
313                     }
314                     cookies.add(anOldCookie);
315                 }
316             } else {
317                 String JavaDoc oldCookie = (String JavaDoc)oldCookies;
318                 if (key != null && oldCookie.indexOf(key) == 0) { // same cookie key
319
oldCookie = cookie; // update to new one
320
alreadyExist = true;
321                 }
322                 cookies.add(oldCookie);
323             }
324         }
325         
326         if (!alreadyExist) {
327             cookies.add(cookie);
328         }
329         
330         if(cookies.size()==1) {
331             msgContext.setProperty(cookieName, cookies.get(0));
332         } else if (cookies.size() > 1) {
333             msgContext.setProperty(cookieName, cookies.toArray(new String JavaDoc[cookies.size()]));
334         }
335     }
336     
337     /**
338      * Add cookies from message context
339      *
340      * @param msgContext
341      * @param state
342      * @param header
343      * @param host
344      * @param path
345      * @param secure
346      */

347     private void fillHeaders(MessageContext msgContext, HttpState state, String JavaDoc header, String JavaDoc host, String JavaDoc path, boolean secure) {
348         Object JavaDoc ck1 = msgContext.getProperty(header);
349         if (ck1 != null) {
350             if (ck1 instanceof String JavaDoc[]) {
351                 String JavaDoc [] cookies = (String JavaDoc[]) ck1;
352                 for (int i = 0; i < cookies.length; i++) {
353                     addCookie(state, cookies[i], host, path, secure);
354                 }
355             } else {
356                 addCookie(state, (String JavaDoc) ck1, host, path, secure);
357             }
358         }
359     }
360
361     /**
362      * add cookie to state
363      * @param state
364      * @param cookie
365      */

366     private void addCookie(HttpState state, String JavaDoc cookie,String JavaDoc host, String JavaDoc path, boolean secure) {
367         int index = cookie.indexOf('=');
368         state.addCookie(new Cookie(host, cookie.substring(0, index),
369                 cookie.substring(index + 1), path,
370                 null, secure));
371     }
372
373     /**
374      * cleanup the cookie value.
375      *
376      * @param cookie initial cookie value
377      *
378      * @return a cleaned up cookie value.
379      */

380     private String JavaDoc cleanupCookie(String JavaDoc cookie) {
381         cookie = cookie.trim();
382         // chop after first ; a la Apache SOAP (see HTTPUtils.java there)
383
int index = cookie.indexOf(';');
384         if (index != -1) {
385             cookie = cookie.substring(0, index);
386         }
387         return cookie;
388     }
389     
390     protected HostConfiguration getHostConfiguration(HttpClient client,
391                                                      MessageContext context,
392                                                      URL JavaDoc targetURL) {
393         TransportClientProperties tcp =
394             TransportClientPropertiesFactory.create(targetURL.getProtocol()); // http or https
395
int port = targetURL.getPort();
396         boolean hostInNonProxyList =
397             isHostInNonProxyList(targetURL.getHost(), tcp.getNonProxyHosts());
398         
399         HostConfiguration config = new HostConfiguration();
400         
401         if (port == -1) {
402             port = 80; // even for https
403
}
404         
405         if(hostInNonProxyList){
406             config.setHost(targetURL.getHost(), port, targetURL.getProtocol());
407         } else {
408             if (tcp.getProxyHost().length() == 0 ||
409                 tcp.getProxyPort().length() == 0) {
410                 config.setHost(targetURL.getHost(), port, targetURL.getProtocol());
411             } else {
412                 if (tcp.getProxyUser().length() != 0) {
413                     Credentials proxyCred =
414                         new UsernamePasswordCredentials(tcp.getProxyUser(),
415                                                         tcp.getProxyPassword());
416                     // if the username is in the form "user\domain"
417
// then use NTCredentials instead.
418
int domainIndex = tcp.getProxyUser().indexOf("\\");
419                     if (domainIndex > 0) {
420                         String JavaDoc domain = tcp.getProxyUser().substring(0, domainIndex);
421                         if (tcp.getProxyUser().length() > domainIndex + 1) {
422                             String JavaDoc user = tcp.getProxyUser().substring(domainIndex + 1);
423                             proxyCred = new NTCredentials(user,
424                                             tcp.getProxyPassword(),
425                                             tcp.getProxyHost(), domain);
426                         }
427                     }
428                     client.getState().setProxyCredentials(AuthScope.ANY, proxyCred);
429                 }
430                 int proxyPort = new Integer JavaDoc(tcp.getProxyPort()).intValue();
431                 config.setProxy(tcp.getProxyHost(), proxyPort);
432             }
433         }
434         return config;
435     }
436     
437     /**
438      * Extracts info from message context.
439      *
440      * @param method Post method
441      * @param httpClient The client used for posting
442      * @param msgContext the message context
443      * @param tmpURL the url to post to.
444      *
445      * @throws Exception
446      */

447     private void addContextInfo(HttpMethodBase method,
448                                 HttpClient httpClient,
449                                 MessageContext msgContext,
450                                 URL JavaDoc tmpURL)
451         throws Exception JavaDoc {
452         
453         // optionally set a timeout for the request
454
if (msgContext.getTimeout() != 0) {
455             /* ISSUE: these are not the same, but MessageContext has only one
456                       definition of timeout */

457             // SO_TIMEOUT -- timeout for blocking reads
458
httpClient.getHttpConnectionManager().getParams().setSoTimeout(msgContext.getTimeout());
459             // timeout for initial connection
460
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(msgContext.getTimeout());
461         }
462         
463         // Get SOAPAction, default to ""
464
String JavaDoc action = msgContext.useSOAPAction()
465             ? msgContext.getSOAPActionURI()
466             : "";
467         
468         if (action == null) {
469             action = "";
470         }
471
472         Message msg = msgContext.getRequestMessage();
473         if (msg != null){
474             method.setRequestHeader(new Header(HTTPConstants.HEADER_CONTENT_TYPE,
475                                                msg.getContentType(msgContext.getSOAPConstants())));
476         }
477         method.setRequestHeader(new Header(HTTPConstants.HEADER_SOAP_ACTION,
478                                            "\"" + action + "\""));
479
480         String JavaDoc userID = msgContext.getUsername();
481         String JavaDoc passwd = msgContext.getPassword();
482         
483         // if UserID is not part of the context, but is in the URL, use
484
// the one in the URL.
485
if ((userID == null) && (tmpURL.getUserInfo() != null)) {
486             String JavaDoc info = tmpURL.getUserInfo();
487             int sep = info.indexOf(':');
488             
489             if ((sep >= 0) && (sep + 1 < info.length())) {
490                 userID = info.substring(0, sep);
491                 passwd = info.substring(sep + 1);
492             } else {
493                 userID = info;
494             }
495         }
496         if (userID != null) {
497             Credentials proxyCred =
498                 new UsernamePasswordCredentials(userID,
499                                                 passwd);
500             // if the username is in the form "user\domain"
501
// then use NTCredentials instead.
502
int domainIndex = userID.indexOf("\\");
503             if (domainIndex > 0) {
504                 String JavaDoc domain = userID.substring(0, domainIndex);
505                 if (userID.length() > domainIndex + 1) {
506                     String JavaDoc user = userID.substring(domainIndex + 1);
507                     proxyCred = new NTCredentials(user,
508                                     passwd,
509                                     NetworkUtils.getLocalHostname(), domain);
510                 }
511             }
512             httpClient.getState().setCredentials(AuthScope.ANY, proxyCred);
513         }
514         
515         // Transfer MIME headers of SOAPMessage to HTTP headers.
516
MimeHeaders JavaDoc mimeHeaders = msg.getMimeHeaders();
517         if (mimeHeaders != null) {
518             for (Iterator JavaDoc i = mimeHeaders.getAllHeaders(); i.hasNext(); ) {
519                 MimeHeader JavaDoc mimeHeader = (MimeHeader JavaDoc) i.next();
520                 //HEADER_CONTENT_TYPE and HEADER_SOAP_ACTION are already set.
521
//Let's not duplicate them.
522
String JavaDoc headerName = mimeHeader.getName();
523                 if (headerName.equals(HTTPConstants.HEADER_CONTENT_TYPE)
524                         || headerName.equals(HTTPConstants.HEADER_SOAP_ACTION)) {
525                         continue;
526                 }
527                 method.addRequestHeader(mimeHeader.getName(),
528                                         mimeHeader.getValue());
529             }
530         }
531
532         // process user defined headers for information.
533
Hashtable JavaDoc userHeaderTable =
534             (Hashtable JavaDoc) msgContext.getProperty(HTTPConstants.REQUEST_HEADERS);
535         
536         if (userHeaderTable != null) {
537             for (Iterator JavaDoc e = userHeaderTable.entrySet().iterator();
538                  e.hasNext();) {
539                 Map.Entry JavaDoc me = (Map.Entry JavaDoc) e.next();
540                 Object JavaDoc keyObj = me.getKey();
541                 
542                 if (null == keyObj) {
543                     continue;
544                 }
545                 String JavaDoc key = keyObj.toString().trim();
546                 String JavaDoc value = me.getValue().toString().trim();
547                 
548                 if (key.equalsIgnoreCase(HTTPConstants.HEADER_EXPECT) &&
549                     value.equalsIgnoreCase(HTTPConstants.HEADER_EXPECT_100_Continue)) {
550                     method.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE,
551                                                            true);
552                 } else if (key.equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED)) {
553                     String JavaDoc val = me.getValue().toString();
554                     if (null != val) {
555                         httpChunkStream = JavaUtils.isTrue(val);
556                     }
557                 } else {
558                     method.addRequestHeader(key, value);
559                 }
560             }
561         }
562     }
563     
564     /**
565      * Check if the specified host is in the list of non proxy hosts.
566      *
567      * @param host host name
568      * @param nonProxyHosts string containing the list of non proxy hosts
569      *
570      * @return true/false
571      */

572     protected boolean isHostInNonProxyList(String JavaDoc host, String JavaDoc nonProxyHosts) {
573         
574         if ((nonProxyHosts == null) || (host == null)) {
575             return false;
576         }
577         
578         /*
579          * The http.nonProxyHosts system property is a list enclosed in
580          * double quotes with items separated by a vertical bar.
581          */

582         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(nonProxyHosts, "|\"");
583         
584         while (tokenizer.hasMoreTokens()) {
585             String JavaDoc pattern = tokenizer.nextToken();
586             
587             if (log.isDebugEnabled()) {
588                 log.debug(Messages.getMessage("match00",
589                 new String JavaDoc[]{"HTTPSender",
590                 host,
591                 pattern}));
592             }
593             if (match(pattern, host, false)) {
594                 return true;
595             }
596         }
597         return false;
598     }
599     
600     /**
601      * Matches a string against a pattern. The pattern contains two special
602      * characters:
603      * '*' which means zero or more characters,
604      *
605      * @param pattern the (non-null) pattern to match against
606      * @param str the (non-null) string that must be matched against the
607      * pattern
608      * @param isCaseSensitive
609      *
610      * @return <code>true</code> when the string matches against the pattern,
611      * <code>false</code> otherwise.
612      */

613     protected static boolean match(String JavaDoc pattern, String JavaDoc str,
614                                    boolean isCaseSensitive) {
615         
616         char[] patArr = pattern.toCharArray();
617         char[] strArr = str.toCharArray();
618         int patIdxStart = 0;
619         int patIdxEnd = patArr.length - 1;
620         int strIdxStart = 0;
621         int strIdxEnd = strArr.length - 1;
622         char ch;
623         boolean containsStar = false;
624         
625         for (int i = 0; i < patArr.length; i++) {
626             if (patArr[i] == '*') {
627                 containsStar = true;
628                 break;
629             }
630         }
631         if (!containsStar) {
632             
633             // No '*'s, so we make a shortcut
634
if (patIdxEnd != strIdxEnd) {
635                 return false; // Pattern and string do not have the same size
636
}
637             for (int i = 0; i <= patIdxEnd; i++) {
638                 ch = patArr[i];
639                 if (isCaseSensitive && (ch != strArr[i])) {
640                     return false; // Character mismatch
641
}
642                 if (!isCaseSensitive
643                 && (Character.toUpperCase(ch)
644                 != Character.toUpperCase(strArr[i]))) {
645                     return false; // Character mismatch
646
}
647             }
648             return true; // String matches against pattern
649
}
650         if (patIdxEnd == 0) {
651             return true; // Pattern contains only '*', which matches anything
652
}
653         
654         // Process characters before first star
655
while ((ch = patArr[patIdxStart]) != '*'
656         && (strIdxStart <= strIdxEnd)) {
657             if (isCaseSensitive && (ch != strArr[strIdxStart])) {
658                 return false; // Character mismatch
659
}
660             if (!isCaseSensitive
661             && (Character.toUpperCase(ch)
662             != Character.toUpperCase(strArr[strIdxStart]))) {
663                 return false; // Character mismatch
664
}
665             patIdxStart++;
666             strIdxStart++;
667         }
668         if (strIdxStart > strIdxEnd) {
669             
670             // All characters in the string are used. Check if only '*'s are
671
// left in the pattern. If so, we succeeded. Otherwise failure.
672
for (int i = patIdxStart; i <= patIdxEnd; i++) {
673                 if (patArr[i] != '*') {
674                     return false;
675                 }
676             }
677             return true;
678         }
679         
680         // Process characters after last star
681
while ((ch = patArr[patIdxEnd]) != '*' && (strIdxStart <= strIdxEnd)) {
682             if (isCaseSensitive && (ch != strArr[strIdxEnd])) {
683                 return false; // Character mismatch
684
}
685             if (!isCaseSensitive
686             && (Character.toUpperCase(ch)
687             != Character.toUpperCase(strArr[strIdxEnd]))) {
688                 return false; // Character mismatch
689
}
690             patIdxEnd--;
691             strIdxEnd--;
692         }
693         if (strIdxStart > strIdxEnd) {
694             
695             // All characters in the string are used. Check if only '*'s are
696
// left in the pattern. If so, we succeeded. Otherwise failure.
697
for (int i = patIdxStart; i <= patIdxEnd; i++) {
698                 if (patArr[i] != '*') {
699                     return false;
700                 }
701             }
702             return true;
703         }
704         
705         // process pattern between stars. padIdxStart and patIdxEnd point
706
// always to a '*'.
707
while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) {
708             int patIdxTmp = -1;
709             
710             for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
711                 if (patArr[i] == '*') {
712                     patIdxTmp = i;
713                     break;
714                 }
715             }
716             if (patIdxTmp == patIdxStart + 1) {
717                 
718                 // Two stars next to each other, skip the first one.
719
patIdxStart++;
720                 continue;
721             }
722             
723             // Find the pattern between padIdxStart & padIdxTmp in str between
724
// strIdxStart & strIdxEnd
725
int patLength = (patIdxTmp - patIdxStart - 1);
726             int strLength = (strIdxEnd - strIdxStart + 1);
727             int foundIdx = -1;
728             
729             strLoop:
730                 for (int i = 0; i <= strLength - patLength; i++) {
731                     for (int j = 0; j < patLength; j++) {
732                         ch = patArr[patIdxStart + j + 1];
733                         if (isCaseSensitive
734                         && (ch != strArr[strIdxStart + i + j])) {
735                             continue strLoop;
736                         }
737                         if (!isCaseSensitive && (Character
738                         .toUpperCase(ch) != Character
739                         .toUpperCase(strArr[strIdxStart + i + j]))) {
740                             continue strLoop;
741                         }
742                     }
743                     foundIdx = strIdxStart + i;
744                     break;
745                 }
746                 if (foundIdx == -1) {
747                     return false;
748                 }
749                 patIdxStart = patIdxTmp;
750                 strIdxStart = foundIdx + patLength;
751         }
752         
753         // All characters in the string are used. Check if only '*'s are left
754
// in the pattern. If so, we succeeded. Otherwise failure.
755
for (int i = patIdxStart; i <= patIdxEnd; i++) {
756             if (patArr[i] != '*') {
757                 return false;
758             }
759         }
760         return true;
761     }
762
763     private static String JavaDoc getHeader(HttpMethodBase method, String JavaDoc headerName) {
764         Header header = method.getResponseHeader(headerName);
765         return (header == null) ? null : header.getValue().trim();
766     }
767
768     private InputStream JavaDoc createConnectionReleasingInputStream(final HttpMethodBase method) throws IOException JavaDoc {
769         return new FilterInputStream JavaDoc(method.getResponseBodyAsStream()) {
770                 public void close() throws IOException JavaDoc {
771                     try {
772                         super.close();
773                     } finally {
774                         method.releaseConnection();
775                     }
776                 }
777             };
778     }
779
780     private static class MessageRequestEntity implements RequestEntity {
781         
782         private HttpMethodBase method;
783         private Message message;
784         boolean httpChunkStream = true; //Use HTTP chunking or not.
785

786         public MessageRequestEntity(HttpMethodBase method, Message message) {
787             this.message = message;
788             this.method = method;
789         }
790
791         public MessageRequestEntity(HttpMethodBase method, Message message, boolean httpChunkStream) {
792             this.message = message;
793             this.method = method;
794             this.httpChunkStream = httpChunkStream;
795         }
796
797         public boolean isRepeatable() {
798             return true;
799         }
800
801         public void writeRequest(OutputStream JavaDoc out) throws IOException JavaDoc {
802             try {
803                 this.message.writeTo(out);
804             } catch (SOAPException JavaDoc e) {
805                 throw new IOException JavaDoc(e.getMessage());
806             }
807         }
808
809         public long getContentLength() {
810             if (this.method.getParams().getVersion() == HttpVersion.HTTP_1_0 || !httpChunkStream) {
811                 try {
812                     return message.getContentLength();
813                 } catch (Exception JavaDoc e) {
814                     return -1; /* -1 for chunked */
815                 }
816             } else {
817                 return -1; /* -1 for chunked */
818             }
819         }
820
821         public String JavaDoc getContentType() {
822             return null; // a separate header is added
823
}
824         
825     }
826 }
827
828
Popular Tags