1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.util;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.servlet.HttpHeaders;
28  import com.liferay.portal.kernel.util.ByteArrayMaker;
29  import com.liferay.portal.kernel.util.ContentTypes;
30  import com.liferay.portal.kernel.util.FileUtil;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.Http;
33  import com.liferay.portal.kernel.util.StringPool;
34  import com.liferay.portal.kernel.util.StringUtil;
35  import com.liferay.portal.kernel.util.Validator;
36  import com.liferay.util.SystemProperties;
37  
38  import java.io.IOException;
39  import java.io.InputStream;
40  import java.io.UnsupportedEncodingException;
41  
42  import java.net.URL;
43  import java.net.URLConnection;
44  import java.net.URLDecoder;
45  import java.net.URLEncoder;
46  
47  import java.util.ArrayList;
48  import java.util.Date;
49  import java.util.LinkedHashMap;
50  import java.util.List;
51  import java.util.Map;
52  import java.util.StringTokenizer;
53  import java.util.regex.Pattern;
54  
55  import javax.portlet.ActionRequest;
56  import javax.portlet.RenderRequest;
57  
58  import javax.servlet.http.Cookie;
59  import javax.servlet.http.HttpServletRequest;
60  
61  import org.apache.commons.httpclient.Credentials;
62  import org.apache.commons.httpclient.Header;
63  import org.apache.commons.httpclient.HostConfiguration;
64  import org.apache.commons.httpclient.HttpClient;
65  import org.apache.commons.httpclient.HttpMethod;
66  import org.apache.commons.httpclient.HttpState;
67  import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
68  import org.apache.commons.httpclient.NTCredentials;
69  import org.apache.commons.httpclient.NameValuePair;
70  import org.apache.commons.httpclient.URI;
71  import org.apache.commons.httpclient.UsernamePasswordCredentials;
72  import org.apache.commons.httpclient.auth.AuthPolicy;
73  import org.apache.commons.httpclient.auth.AuthScope;
74  import org.apache.commons.httpclient.cookie.CookiePolicy;
75  import org.apache.commons.httpclient.methods.DeleteMethod;
76  import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
77  import org.apache.commons.httpclient.methods.GetMethod;
78  import org.apache.commons.httpclient.methods.PostMethod;
79  import org.apache.commons.httpclient.methods.PutMethod;
80  import org.apache.commons.httpclient.methods.RequestEntity;
81  import org.apache.commons.httpclient.methods.StringRequestEntity;
82  import org.apache.commons.httpclient.params.HttpClientParams;
83  import org.apache.commons.httpclient.params.HttpConnectionParams;
84  
85  /**
86   * <a href="HttpImpl.java.html"><b><i>View Source</i></b></a>
87   *
88   * @author Brian Wing Shun Chan
89   *
90   */
91  public class HttpImpl implements Http {
92  
93      public HttpImpl() {
94  
95          // Mimic behavior found in
96          // http://java.sun.com/j2se/1.5.0/docs/guide/net/properties.html
97  
98          if (Validator.isNotNull(_NON_PROXY_HOSTS)) {
99              String nonProxyHostsRegEx = _NON_PROXY_HOSTS;
100 
101             nonProxyHostsRegEx = nonProxyHostsRegEx.replaceAll(
102                 "\\.", "\\\\.");
103             nonProxyHostsRegEx = nonProxyHostsRegEx.replaceAll(
104                 "\\*", ".*?");
105             nonProxyHostsRegEx = nonProxyHostsRegEx.replaceAll(
106                 "\\|", ")|(");
107 
108             nonProxyHostsRegEx = "(" + nonProxyHostsRegEx + ")";
109 
110             _nonProxyHostsPattern = Pattern.compile(nonProxyHostsRegEx);
111         }
112 
113         MultiThreadedHttpConnectionManager connectionManager =
114             new MultiThreadedHttpConnectionManager();
115 
116         HttpConnectionParams params = connectionManager.getParams();
117 
118         params.setParameter(
119             "maxConnectionsPerHost", new Integer(_MAX_CONNECTIONS_PER_HOST));
120         params.setParameter(
121             "maxTotalConnections", new Integer(_MAX_TOTAL_CONNECTIONS));
122         params.setConnectionTimeout(_TIMEOUT);
123         params.setSoTimeout(_TIMEOUT);
124 
125         _client.setHttpConnectionManager(connectionManager);
126         _proxyClient.setHttpConnectionManager(connectionManager);
127 
128         if (hasProxyConfig() && Validator.isNotNull(_PROXY_USERNAME)) {
129             if (_PROXY_AUTH_TYPE.equals("username-password")) {
130                 _proxyCredentials = new UsernamePasswordCredentials(
131                     _PROXY_USERNAME, _PROXY_PASSWORD);
132             }
133             else if (_PROXY_AUTH_TYPE.equals("ntlm")) {
134                 _proxyCredentials = new NTCredentials(
135                     _PROXY_USERNAME, _PROXY_PASSWORD, _PROXY_NTLM_HOST,
136                     _PROXY_NTLM_DOMAIN);
137 
138                 List<String> authPrefs = new ArrayList<String>();
139 
140                 authPrefs.add(AuthPolicy.NTLM);
141                 authPrefs.add(AuthPolicy.BASIC);
142                 authPrefs.add(AuthPolicy.DIGEST);
143 
144                 _proxyClient.getParams().setParameter(
145                     AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
146             }
147         }
148     }
149 
150     public String addParameter(String url, String name, boolean value) {
151         return addParameter(url, name, String.valueOf(value));
152     }
153 
154     public String addParameter(String url, String name, double value) {
155         return addParameter(url, name, String.valueOf(value));
156     }
157 
158     public String addParameter(String url, String name, int value) {
159         return addParameter(url, name, String.valueOf(value));
160     }
161 
162     public String addParameter(String url, String name, long value) {
163         return addParameter(url, name, String.valueOf(value));
164     }
165 
166     public String addParameter(String url, String name, short value) {
167         return addParameter(url, name, String.valueOf(value));
168     }
169 
170     public String addParameter(String url, String name, String value) {
171         if (url == null) {
172             return null;
173         }
174 
175         String anchor = StringPool.BLANK;
176 
177         int pos = url.indexOf(StringPool.POUND);
178 
179         if (pos != -1) {
180             anchor = url.substring(pos);
181             url = url.substring(0, pos);
182         }
183 
184         if (url.indexOf(StringPool.QUESTION) == -1) {
185             url += StringPool.QUESTION;
186         }
187 
188         if (!url.endsWith(StringPool.QUESTION) &&
189             !url.endsWith(StringPool.AMPERSAND)) {
190 
191             url += StringPool.AMPERSAND;
192         }
193 
194         return url + name + StringPool.EQUAL + encodeURL(value) + anchor;
195     }
196 
197     public String decodeURL(String url) {
198         return decodeURL(url, false);
199     }
200 
201     public String decodeURL(String url, boolean unescapeSpace) {
202         if (url == null) {
203             return null;
204         }
205 
206         try {
207             url = URLDecoder.decode(url, StringPool.UTF8);
208 
209             if (unescapeSpace) {
210                 url = StringUtil.replace(url, "%20", StringPool.PLUS);
211             }
212 
213             return url;
214         }
215         catch (UnsupportedEncodingException uee) {
216             _log.error(uee, uee);
217 
218             return StringPool.BLANK;
219         }
220     }
221 
222     public String encodeURL(String url) {
223         return encodeURL(url, false);
224     }
225 
226     public String encodeURL(String url, boolean escapeSpaces) {
227         if (url == null) {
228             return null;
229         }
230 
231         try {
232             url = URLEncoder.encode(url, StringPool.UTF8);
233 
234             if (escapeSpaces) {
235                 url = StringUtil.replace(url, StringPool.PLUS, "%20");
236             }
237 
238             return url;
239         }
240         catch (UnsupportedEncodingException uee) {
241             _log.error(uee, uee);
242 
243             return StringPool.BLANK;
244         }
245     }
246 
247     public HttpClient getClient(HostConfiguration hostConfig) {
248         if (isProxyHost(hostConfig.getHost())) {
249             return _proxyClient;
250         }
251         else {
252             return _client;
253         }
254     }
255 
256     public String getCompleteURL(HttpServletRequest request) {
257         StringBuffer sb = request.getRequestURL();
258 
259         if (sb == null) {
260             sb = new StringBuffer();
261         }
262 
263         if (request.getQueryString() != null) {
264             sb.append(StringPool.QUESTION);
265             sb.append(request.getQueryString());
266         }
267 
268         String completeURL = sb.toString();
269 
270         if (_log.isWarnEnabled()) {
271             if (completeURL.contains("?&")) {
272                 _log.warn("Invalid url " + completeURL);
273             }
274         }
275 
276         return completeURL;
277     }
278 
279     public Cookie[] getCookies() {
280         return _cookies.get();
281     }
282 
283     public String getDomain(String url) {
284         url = removeProtocol(url);
285 
286         int pos = url.indexOf(StringPool.SLASH);
287 
288         if (pos != -1) {
289             return url.substring(0, pos);
290         }
291         else {
292             return url;
293         }
294     }
295 
296     public HostConfiguration getHostConfig(String location) throws IOException {
297         if (_log.isDebugEnabled()) {
298             _log.debug("Location is " + location);
299         }
300 
301         HostConfiguration hostConfig = new HostConfiguration();
302 
303         hostConfig.setHost(new URI(location, false));
304 
305         if (isProxyHost(hostConfig.getHost())) {
306             hostConfig.setProxy(_PROXY_HOST, _PROXY_PORT);
307         }
308 
309         return hostConfig;
310     }
311 
312     public String getParameter(String url, String name) {
313         return getParameter(url, name, true);
314     }
315 
316     public String getParameter(String url, String name, boolean escaped) {
317         if (Validator.isNull(url) || Validator.isNull(name)) {
318             return StringPool.BLANK;
319         }
320 
321         String[] parts = StringUtil.split(url, StringPool.QUESTION);
322 
323         if (parts.length == 2) {
324             String[] params = null;
325 
326             if (escaped) {
327                 params = StringUtil.split(parts[1], "&amp;");
328             }
329             else {
330                 params = StringUtil.split(parts[1], StringPool.AMPERSAND);
331             }
332 
333             for (int i = 0; i < params.length; i++) {
334                 String[] kvp = StringUtil.split(params[i], StringPool.EQUAL);
335 
336                 if ((kvp.length == 2) && kvp[0].equals(name)) {
337                     return kvp[1];
338                 }
339             }
340         }
341 
342         return StringPool.BLANK;
343     }
344 
345     public Map<String, String[]> getParameterMap(String queryString) {
346         return parameterMapFromString(queryString);
347     }
348 
349     public String getProtocol(ActionRequest actionRequest) {
350         return getProtocol(actionRequest.isSecure());
351     }
352 
353     public String getProtocol(boolean secure) {
354         if (!secure) {
355             return Http.HTTP;
356         }
357         else {
358             return Http.HTTPS;
359         }
360     }
361 
362     public String getProtocol(HttpServletRequest request) {
363         return getProtocol(request.isSecure());
364     }
365 
366     public String getProtocol(RenderRequest renderRequest) {
367         return getProtocol(renderRequest.isSecure());
368     }
369 
370     public String getProtocol(String url) {
371         int pos = url.indexOf(Http.PROTOCOL_DELIMITER);
372 
373         if (pos != -1) {
374             return url.substring(0, pos);
375         }
376         else {
377             return Http.HTTP;
378         }
379     }
380 
381     public String getQueryString(String url) {
382         if (Validator.isNull(url)) {
383             return url;
384         }
385 
386         int pos = url.indexOf(StringPool.QUESTION);
387 
388         if (pos == -1) {
389             return StringPool.BLANK;
390         }
391         else {
392             return url.substring(pos + 1, url.length());
393         }
394     }
395 
396     public String getRequestURL(HttpServletRequest request) {
397         return request.getRequestURL().toString();
398     }
399 
400     public boolean hasDomain(String url) {
401         return Validator.isNotNull(getDomain(url));
402     }
403 
404     public boolean hasProtocol(String url) {
405         int pos = url.indexOf(Http.PROTOCOL_DELIMITER);
406 
407         if (pos != -1) {
408             return true;
409         }
410         else {
411             return false;
412         }
413     }
414 
415     public boolean hasProxyConfig() {
416         if (Validator.isNotNull(_PROXY_HOST) && (_PROXY_PORT > 0)) {
417             return true;
418         }
419         else {
420             return false;
421         }
422     }
423 
424     public boolean isNonProxyHost(String host) {
425         if (_nonProxyHostsPattern == null ||
426             _nonProxyHostsPattern.matcher(host).matches()) {
427 
428             return true;
429         }
430         else {
431             return false;
432         }
433     }
434 
435     public boolean isProxyHost(String host) {
436         if (hasProxyConfig() && !isNonProxyHost(host)) {
437             return true;
438         }
439         else {
440             return false;
441         }
442     }
443 
444     public Map<String, String[]> parameterMapFromString(String queryString) {
445         Map<String, String[]> parameterMap =
446             new LinkedHashMap<String, String[]>();
447 
448         if (Validator.isNull(queryString)) {
449             return parameterMap;
450         }
451 
452         Map<String, List<String>> tempParameterMap =
453             new LinkedHashMap<String, List<String>>();
454 
455         StringTokenizer st = new StringTokenizer(
456             queryString, StringPool.AMPERSAND);
457 
458         while (st.hasMoreTokens()) {
459             String token = st.nextToken();
460 
461             if (Validator.isNotNull(token)) {
462                 String[] kvp = StringUtil.split(token, StringPool.EQUAL);
463 
464                 String key = kvp[0];
465 
466                 String value = StringPool.BLANK;
467 
468                 if (kvp.length > 1) {
469                     value = kvp[1];
470                 }
471 
472                 List<String> values = tempParameterMap.get(key);
473 
474                 if (values == null) {
475                     values = new ArrayList<String>();
476 
477                     tempParameterMap.put(key, values);
478                 }
479 
480                 values.add(value);
481             }
482         }
483 
484         for (Map.Entry<String, List<String>> entry :
485                 tempParameterMap.entrySet()) {
486 
487             String key = entry.getKey();
488             List<String> values = entry.getValue();
489 
490             parameterMap.put(key, values.toArray(new String[values.size()]));
491         }
492 
493         return parameterMap;
494     }
495 
496     public String parameterMapToString(Map<String, String[]> parameterMap) {
497         return parameterMapToString(parameterMap, true);
498     }
499 
500     public String parameterMapToString(
501         Map<String, String[]> parameterMap, boolean addQuestion) {
502 
503         StringBuilder sb = new StringBuilder();
504 
505         if (parameterMap.size() > 0) {
506             if (addQuestion) {
507                 sb.append(StringPool.QUESTION);
508             }
509 
510             for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
511                 String name = entry.getKey();
512                 String[] values = entry.getValue();
513 
514                 for (String value : values) {
515                     sb.append(name);
516                     sb.append(StringPool.EQUAL);
517                     sb.append(encodeURL(value));
518                     sb.append(StringPool.AMPERSAND);
519                 }
520             }
521 
522             sb.deleteCharAt(sb.length() - 1);
523         }
524 
525         return sb.toString();
526     }
527 
528     public String protocolize(String url, ActionRequest actionRequest) {
529         return protocolize(url, actionRequest.isSecure());
530     }
531 
532     public String protocolize(String url, boolean secure) {
533         if (secure) {
534             if (url.startsWith(Http.HTTP_WITH_SLASH)) {
535                 return StringUtil.replace(
536                     url, Http.HTTP_WITH_SLASH, Http.HTTPS_WITH_SLASH);
537             }
538         }
539         else {
540             if (url.startsWith(Http.HTTPS_WITH_SLASH)) {
541                 return StringUtil.replace(
542                     url, Http.HTTPS_WITH_SLASH, Http.HTTP_WITH_SLASH);
543             }
544         }
545 
546         return url;
547     }
548 
549     public String protocolize(String url, HttpServletRequest request) {
550         return protocolize(url, request.isSecure());
551     }
552 
553     public String protocolize(String url, RenderRequest renderRequest) {
554         return protocolize(url, renderRequest.isSecure());
555     }
556 
557     public String removeDomain(String url) {
558         url = removeProtocol(url);
559 
560         int pos = url.indexOf(StringPool.SLASH);
561 
562         if (pos > 0) {
563             return url.substring(pos);
564         }
565         else {
566             return url;
567         }
568     }
569 
570     public String removeParameter(String url, String name) {
571         int pos = url.indexOf(StringPool.QUESTION);
572 
573         if (pos == -1) {
574             return url;
575         }
576 
577         String anchor = StringPool.BLANK;
578 
579         int anchorPos = url.indexOf(StringPool.POUND);
580 
581         if (anchorPos != -1) {
582             anchor = url.substring(anchorPos);
583             url = url.substring(0, anchorPos);
584         }
585 
586         StringBuilder sb = new StringBuilder();
587 
588         sb.append(url.substring(0, pos + 1));
589 
590         StringTokenizer st = new StringTokenizer(
591             url.substring(pos + 1, url.length()), StringPool.AMPERSAND);
592 
593         while (st.hasMoreTokens()) {
594             String token = st.nextToken();
595 
596             if (Validator.isNotNull(token)) {
597                 String[] kvp = StringUtil.split(token, StringPool.EQUAL);
598 
599                 String key = kvp[0];
600 
601                 String value = StringPool.BLANK;
602 
603                 if (kvp.length > 1) {
604                     value = kvp[1];
605                 }
606 
607                 if (!key.equals(name)) {
608                     sb.append(key);
609                     sb.append(StringPool.EQUAL);
610                     sb.append(value);
611                     sb.append(StringPool.AMPERSAND);
612                 }
613             }
614         }
615 
616         url = StringUtil.replace(
617             sb.toString(), StringPool.AMPERSAND + StringPool.AMPERSAND,
618             StringPool.AMPERSAND);
619 
620         if (url.endsWith(StringPool.AMPERSAND)) {
621             url = url.substring(0, url.length() - 1);
622         }
623 
624         if (url.endsWith(StringPool.QUESTION)) {
625             url = url.substring(0, url.length() - 1);
626         }
627 
628         return url + anchor;
629     }
630 
631     public String removeProtocol(String url) {
632         if (url.startsWith(Http.HTTP_WITH_SLASH)) {
633             return url.substring(Http.HTTP_WITH_SLASH.length() , url.length());
634         }
635         else if (url.startsWith(Http.HTTPS_WITH_SLASH)) {
636             return url.substring(Http.HTTPS_WITH_SLASH.length() , url.length());
637         }
638         else {
639             return url;
640         }
641     }
642 
643     public String setParameter(String url, String name, boolean value) {
644         return setParameter(url, name, String.valueOf(value));
645     }
646 
647     public String setParameter(String url, String name, double value) {
648         return setParameter(url, name, String.valueOf(value));
649     }
650 
651     public String setParameter(String url, String name, int value) {
652         return setParameter(url, name, String.valueOf(value));
653     }
654 
655     public String setParameter(String url, String name, long value) {
656         return setParameter(url, name, String.valueOf(value));
657     }
658 
659     public String setParameter(String url, String name, short value) {
660         return setParameter(url, name, String.valueOf(value));
661     }
662 
663     public String setParameter(String url, String name, String value) {
664         if (url == null) {
665             return null;
666         }
667 
668         url = removeParameter(url, name);
669 
670         return addParameter(url, name, value);
671     }
672 
673     /**
674      * @deprecated
675      */
676     public void submit(String location) throws IOException {
677         URLtoByteArray(location);
678     }
679 
680     /**
681      * @deprecated
682      */
683     public void submit(String location, boolean post) throws IOException {
684         URLtoByteArray(location, post);
685     }
686 
687     /**
688      * @deprecated
689      */
690     public void submit(String location, Cookie[] cookies) throws IOException {
691         URLtoByteArray(location, cookies);
692     }
693 
694     /**
695      * @deprecated
696      */
697     public void submit(String location, Cookie[] cookies, boolean post)
698         throws IOException {
699 
700         URLtoByteArray(location, cookies, post);
701     }
702 
703     /**
704      * @deprecated
705      */
706     public void submit(
707             String location, Cookie[] cookies, Http.Body body, boolean post)
708         throws IOException {
709 
710         URLtoByteArray(location, cookies, body, post);
711     }
712 
713     /**
714      * @deprecated
715      */
716     public void submit(
717             String location, Cookie[] cookies, Map<String, String> parts,
718             boolean post)
719         throws IOException {
720 
721         URLtoByteArray(location, cookies, parts, post);
722     }
723 
724     public byte[] URLtoByteArray(Http.Options options) throws IOException {
725         return URLtoByteArray(
726             options.getLocation(), options.getMethod(), options.getHeaders(),
727             options.getCookies(), options.getAuth(), options.getBody(),
728             options.getParts());
729     }
730 
731     public byte[] URLtoByteArray(String location) throws IOException {
732         Http.Options options = new Http.Options();
733 
734         options.setLocation(location);
735 
736         return URLtoByteArray(options);
737     }
738 
739     public byte[] URLtoByteArray(String location, boolean post)
740         throws IOException {
741 
742         Http.Options options = new Http.Options();
743 
744         options.setLocation(location);
745         options.setPost(post);
746 
747         return URLtoByteArray(options);
748     }
749 
750     /**
751      * @deprecated
752      */
753     public byte[] URLtoByteArray(String location, Cookie[] cookies)
754         throws IOException {
755 
756         Http.Options options = new Http.Options();
757 
758         options.setCookies(cookies);
759         options.setLocation(location);
760 
761         return URLtoByteArray(options);
762     }
763 
764     /**
765      * @deprecated
766      */
767     public byte[] URLtoByteArray(
768             String location, Cookie[] cookies, boolean post)
769         throws IOException {
770 
771         Http.Options options = new Http.Options();
772 
773         options.setCookies(cookies);
774         options.setLocation(location);
775         options.setPost(post);
776 
777         return URLtoByteArray(options);
778     }
779 
780     /**
781      * @deprecated
782      */
783     public byte[] URLtoByteArray(
784             String location, Cookie[] cookies, Http.Auth auth, Http.Body body,
785             boolean post)
786         throws IOException {
787 
788         Http.Options options = new Http.Options();
789 
790         options.setAuth(auth);
791         options.setBody(body);
792         options.setCookies(cookies);
793         options.setLocation(location);
794         options.setPost(post);
795 
796         return URLtoByteArray(options);
797     }
798 
799     /**
800      * @deprecated
801      */
802     public byte[] URLtoByteArray(
803             String location, Cookie[] cookies, Http.Auth auth,
804             Map<String, String> parts, boolean post)
805         throws IOException {
806 
807         Http.Options options = new Http.Options();
808 
809         options.setAuth(auth);
810         options.setCookies(cookies);
811         options.setLocation(location);
812         options.setParts(parts);
813         options.setPost(post);
814 
815         return URLtoByteArray(options);
816     }
817 
818     /**
819      * @deprecated
820      */
821     public byte[] URLtoByteArray(
822             String location, Cookie[] cookies, Http.Body body, boolean post)
823         throws IOException {
824 
825         Http.Options options = new Http.Options();
826 
827         options.setBody(body);
828         options.setCookies(cookies);
829         options.setLocation(location);
830         options.setPost(post);
831 
832         return URLtoByteArray(options);
833     }
834 
835     /**
836      * @deprecated
837      */
838     public byte[] URLtoByteArray(
839             String location, Cookie[] cookies, Map<String, String> parts,
840             boolean post)
841         throws IOException {
842 
843         Http.Options options = new Http.Options();
844 
845         options.setCookies(cookies);
846         options.setLocation(location);
847         options.setParts(parts);
848         options.setPost(post);
849 
850         return URLtoByteArray(options);
851     }
852 
853     public String URLtoString(Http.Options options) throws IOException {
854         return new String(URLtoByteArray(options));
855     }
856 
857     public String URLtoString(String location) throws IOException {
858         return new String(URLtoByteArray(location));
859     }
860 
861     public String URLtoString(String location, boolean post)
862         throws IOException {
863 
864         return new String(URLtoByteArray(location, post));
865     }
866 
867     /**
868      * @deprecated
869      */
870     public String URLtoString(String location, Cookie[] cookies)
871         throws IOException {
872 
873         return new String(URLtoByteArray(location, cookies));
874     }
875 
876     /**
877      * @deprecated
878      */
879     public String URLtoString(
880             String location, Cookie[] cookies, boolean post)
881         throws IOException {
882 
883         return new String(URLtoByteArray(location, cookies, post));
884     }
885 
886     /**
887      * @deprecated
888      */
889     public String URLtoString(
890             String location, Cookie[] cookies, Http.Auth auth, Http.Body body,
891             boolean post)
892         throws IOException {
893 
894         return new String(URLtoByteArray(location, cookies, auth, body, post));
895     }
896 
897     /**
898      * @deprecated
899      */
900     public String URLtoString(
901             String location, Cookie[] cookies, Http.Auth auth,
902             Map<String, String> parts, boolean post)
903         throws IOException {
904 
905         return new String(URLtoByteArray(location, cookies, auth, parts, post));
906     }
907 
908     /**
909      * @deprecated
910      */
911     public String URLtoString(
912             String location, Cookie[] cookies, Http.Body body, boolean post)
913         throws IOException {
914 
915         return new String(URLtoByteArray(location, cookies, body, post));
916     }
917 
918     /**
919      * @deprecated
920      */
921     public String URLtoString(
922             String location, Cookie[] cookies, Map<String, String> parts,
923             boolean post)
924         throws IOException {
925 
926         return new String(URLtoByteArray(location, cookies, null, parts, post));
927     }
928 
929     /**
930      * @deprecated
931      */
932     public String URLtoString(
933             String location, String host, int port, String realm,
934             String username, String password)
935         throws IOException {
936 
937         return URLtoString(
938             location, (Cookie[])null,
939             new Http.Auth(host, port, realm, username, password),
940             (Http.Body)null, false);
941     }
942 
943     /**
944      * This method only uses the default Commons HttpClient implementation when
945      * the URL object represents a HTTP resource. The URL object could also
946      * represent a file or some JNDI resource. In that case, the default Java
947      * implementation is used.
948      *
949      * @param       url URL object
950      * @return      A string representation of the resource referenced by the
951      *              URL object
952      * @throws      IOException
953      */
954     public String URLtoString(URL url) throws IOException {
955         String xml = null;
956 
957         if (url != null) {
958             String protocol = url.getProtocol().toLowerCase();
959 
960             if (protocol.startsWith(Http.HTTP) ||
961                 protocol.startsWith(Http.HTTPS)) {
962 
963                 return URLtoString(url.toString());
964             }
965 
966             URLConnection con = url.openConnection();
967 
968             InputStream is = con.getInputStream();
969 
970             ByteArrayMaker bam = new ByteArrayMaker();
971             byte[] bytes = new byte[512];
972 
973             for (int i = is.read(bytes, 0, 512); i != -1;
974                     i = is.read(bytes, 0, 512)) {
975 
976                 bam.write(bytes, 0, i);
977             }
978 
979             xml = new String(bam.toByteArray());
980 
981             is.close();
982             bam.close();
983         }
984 
985         return xml;
986     }
987 
988     protected void proxifyState(HttpState state, HostConfiguration hostConfig) {
989         Credentials proxyCredentials = _proxyCredentials;
990 
991         String host = hostConfig.getHost();
992 
993         if (isProxyHost(host) && (proxyCredentials != null)) {
994             AuthScope scope = new AuthScope(_PROXY_HOST, _PROXY_PORT, null);
995 
996             state.setProxyCredentials(scope, proxyCredentials);
997         }
998     }
999 
1000    protected org.apache.commons.httpclient.Cookie toCommonsCookie(
1001        Cookie cookie) {
1002
1003        org.apache.commons.httpclient.Cookie commonsCookie =
1004            new org.apache.commons.httpclient.Cookie(
1005            cookie.getDomain(), cookie.getName(), cookie.getValue(),
1006            cookie.getPath(), cookie.getMaxAge(), cookie.getSecure());
1007
1008        commonsCookie.setVersion(cookie.getVersion());
1009
1010        return commonsCookie;
1011    }
1012
1013    protected org.apache.commons.httpclient.Cookie[] toCommonsCookies(
1014        Cookie[] cookies) {
1015
1016        if (cookies == null) {
1017            return null;
1018        }
1019
1020        org.apache.commons.httpclient.Cookie[] commonCookies =
1021            new org.apache.commons.httpclient.Cookie[cookies.length];
1022
1023        for (int i = 0; i < cookies.length; i++) {
1024            commonCookies[i] = toCommonsCookie(cookies[i]);
1025        }
1026
1027        return commonCookies;
1028    }
1029
1030    protected Cookie toServletCookie(
1031        org.apache.commons.httpclient.Cookie commonsCookie) {
1032
1033        Cookie cookie = new Cookie(
1034            commonsCookie.getName(), commonsCookie.getValue());
1035
1036        cookie.setDomain(commonsCookie.getDomain());
1037
1038        Date expiryDate = commonsCookie.getExpiryDate();
1039
1040        if (expiryDate != null) {
1041            int maxAge =
1042                (int)(expiryDate.getTime() - System.currentTimeMillis());
1043
1044            maxAge = maxAge / 1000;
1045
1046            if (maxAge > -1) {
1047                cookie.setMaxAge(maxAge);
1048            }
1049        }
1050
1051        cookie.setPath(commonsCookie.getPath());
1052        cookie.setSecure(commonsCookie.getSecure());
1053        cookie.setVersion(commonsCookie.getVersion());
1054
1055        return cookie;
1056    }
1057
1058    protected Cookie[] toServletCookies(
1059        org.apache.commons.httpclient.Cookie[] commonsCookies) {
1060
1061        if (commonsCookies == null) {
1062            return null;
1063        }
1064
1065        Cookie[] cookies = new Cookie[commonsCookies.length];
1066
1067        for (int i = 0; i < commonsCookies.length; i++) {
1068            cookies[i] = toServletCookie(commonsCookies[i]);
1069        }
1070
1071        return cookies;
1072    }
1073
1074    protected byte[] URLtoByteArray(
1075            String location, Http.Method method, Map<String, String> headers,
1076            Cookie[] cookies, Http.Auth auth, Http.Body body, Map<String,
1077            String> parts)
1078        throws IOException {
1079
1080        byte[] bytes = null;
1081
1082        HttpMethod httpMethod = null;
1083        HttpState httpState = null;
1084
1085        try {
1086            _cookies.set(null);
1087
1088            if (location == null) {
1089                return bytes;
1090            }
1091            else if (!location.startsWith(Http.HTTP_WITH_SLASH) &&
1092                     !location.startsWith(Http.HTTPS_WITH_SLASH)) {
1093
1094                location = Http.HTTP_WITH_SLASH + location;
1095            }
1096
1097            HostConfiguration hostConfig = getHostConfig(location);
1098
1099            HttpClient httpClient = getClient(hostConfig);
1100
1101            if ((method == Http.Method.POST) ||
1102                (method == Http.Method.PUT)) {
1103
1104                if (method == Http.Method.POST) {
1105                    httpMethod = new PostMethod(location);
1106                }
1107                else {
1108                    httpMethod = new PutMethod(location);
1109                }
1110
1111                if (body != null) {
1112                    RequestEntity requestEntity = new StringRequestEntity(
1113                        body.getContent(), body.getContentType(),
1114                        body.getCharset());
1115
1116                    EntityEnclosingMethod entityEnclosingMethod =
1117                        (EntityEnclosingMethod)httpMethod;
1118
1119                    entityEnclosingMethod.setRequestEntity(requestEntity);
1120                }
1121                else if ((parts != null) && (parts.size() > 0) &&
1122                         (method == Http.Method.POST)) {
1123
1124                    List<NameValuePair> nvpList =
1125                        new ArrayList<NameValuePair>();
1126
1127                    for (Map.Entry<String, String> entry : parts.entrySet()) {
1128                        String key = entry.getKey();
1129                        String value = entry.getValue();
1130
1131                        if (value != null) {
1132                            nvpList.add(new NameValuePair(key, value));
1133                        }
1134                    }
1135
1136                    NameValuePair[] nvpArray = nvpList.toArray(
1137                        new NameValuePair[nvpList.size()]);
1138
1139                    PostMethod postMethod = (PostMethod)httpMethod;
1140
1141                    postMethod.setRequestBody(nvpArray);
1142                }
1143            }
1144            else if (method == Http.Method.DELETE) {
1145                httpMethod = new DeleteMethod(location);
1146            }
1147            else {
1148                httpMethod = new GetMethod(location);
1149            }
1150
1151            if ((method == Http.Method.POST) || (method == Http.Method.PUT) &&
1152                (body != null)) {
1153            }
1154            else if (!_hasRequestHeader(httpMethod, HttpHeaders.CONTENT_TYPE)) {
1155                httpMethod.addRequestHeader(
1156                    HttpHeaders.CONTENT_TYPE,
1157                    ContentTypes.APPLICATION_X_WWW_FORM_URLENCODED);
1158            }
1159
1160            if (!_hasRequestHeader(httpMethod, HttpHeaders.USER_AGENT)) {
1161                httpMethod.addRequestHeader(
1162                    HttpHeaders.USER_AGENT, _DEFAULT_USER_AGENT);
1163            }
1164
1165            if (headers != null) {
1166                for (Map.Entry<String, String> header : headers.entrySet()) {
1167                    httpMethod.addRequestHeader(
1168                        header.getKey(), header.getValue());
1169                }
1170            }
1171
1172            httpMethod.getParams().setIntParameter(
1173                HttpClientParams.SO_TIMEOUT, 0);
1174
1175            //httpMethod.setFollowRedirects(true);
1176
1177            httpState = new HttpState();
1178
1179            if ((cookies != null) && (cookies.length > 0)) {
1180                org.apache.commons.httpclient.Cookie[] commonsCookies =
1181                    toCommonsCookies(cookies);
1182
1183                httpState.addCookies(commonsCookies);
1184
1185                httpMethod.getParams().setCookiePolicy(
1186                    CookiePolicy.BROWSER_COMPATIBILITY);
1187            }
1188
1189            if (auth != null) {
1190                httpMethod.setDoAuthentication(true);
1191
1192                httpState.setCredentials(
1193                    new AuthScope(
1194                        auth.getHost(), auth.getPort(), auth.getRealm()),
1195                    new UsernamePasswordCredentials(
1196                        auth.getUsername(), auth.getPassword()));
1197            }
1198
1199            proxifyState(httpState, hostConfig);
1200
1201            httpClient.executeMethod(hostConfig, httpMethod, httpState);
1202
1203            Header locationHeader = httpMethod.getResponseHeader("location");
1204
1205            if ((locationHeader != null) && !locationHeader.equals(location)) {
1206                return URLtoByteArray(
1207                    locationHeader.getValue(), Http.Method.GET, headers,
1208                    cookies, auth, body, parts);
1209            }
1210
1211            InputStream is = httpMethod.getResponseBodyAsStream();
1212
1213            if (is != null) {
1214                bytes = FileUtil.getBytes(is);
1215
1216                is.close();
1217            }
1218
1219            return bytes;
1220        }
1221        finally {
1222            try {
1223                if (httpState != null) {
1224                    _cookies.set(toServletCookies(httpState.getCookies()));
1225                }
1226            }
1227            catch (Exception e) {
1228                _log.error(e, e);
1229            }
1230
1231            try {
1232                if (httpMethod != null) {
1233                    httpMethod.releaseConnection();
1234                }
1235            }
1236            catch (Exception e) {
1237                _log.error(e, e);
1238            }
1239        }
1240    }
1241
1242    private boolean _hasRequestHeader(HttpMethod httpMethod, String name) {
1243        if (httpMethod.getRequestHeaders(name).length == 0) {
1244            return false;
1245        }
1246        else {
1247            return true;
1248        }
1249    }
1250
1251    private static final String _DEFAULT_USER_AGENT =
1252        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
1253
1254    private static final int _MAX_CONNECTIONS_PER_HOST = GetterUtil.getInteger(
1255        PropsUtil.get(HttpImpl.class.getName() + ".max.connections.per.host"),
1256        2);
1257
1258    private static final int _MAX_TOTAL_CONNECTIONS = GetterUtil.getInteger(
1259        PropsUtil.get(HttpImpl.class.getName() + ".max.total.connections"),
1260        20);
1261
1262    private static final String _NON_PROXY_HOSTS =
1263        SystemProperties.get("http.nonProxyHosts");
1264
1265    private static final String _PROXY_AUTH_TYPE = GetterUtil.getString(
1266        PropsUtil.get(HttpImpl.class.getName() + ".proxy.auth.type"));
1267
1268    private static final String _PROXY_HOST = GetterUtil.getString(
1269        SystemProperties.get("http.proxyHost"));
1270
1271    private static final String _PROXY_NTLM_DOMAIN = GetterUtil.getString(
1272        PropsUtil.get(HttpImpl.class.getName() + ".proxy.ntlm.domain"));
1273
1274    private static final String _PROXY_NTLM_HOST = GetterUtil.getString(
1275        PropsUtil.get(HttpImpl.class.getName() + ".proxy.ntlm.host"));
1276
1277    private static final String _PROXY_PASSWORD = GetterUtil.getString(
1278        PropsUtil.get(HttpImpl.class.getName() + ".proxy.password"));
1279
1280    private static final int _PROXY_PORT = GetterUtil.getInteger(
1281        SystemProperties.get("http.proxyPort"));
1282
1283    private static final String _PROXY_USERNAME = GetterUtil.getString(
1284        PropsUtil.get(HttpImpl.class.getName() + ".proxy.username"));
1285
1286    private static final int _TIMEOUT = GetterUtil.getInteger(
1287        PropsUtil.get(HttpImpl.class.getName() + ".timeout"), 5000);
1288
1289    private static Log _log = LogFactoryUtil.getLog(HttpImpl.class);
1290
1291    private static ThreadLocal<Cookie[]> _cookies = new ThreadLocal<Cookie[]>();
1292
1293    private HttpClient _client = new HttpClient();
1294    private Pattern _nonProxyHostsPattern;
1295    private HttpClient _proxyClient = new HttpClient();
1296    private Credentials _proxyCredentials;
1297
1298}