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