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