1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights 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.InetAddress;
43  import java.net.URL;
44  import java.net.URLConnection;
45  import java.net.URLDecoder;
46  import java.net.URLEncoder;
47  
48  import java.util.ArrayList;
49  import java.util.Date;
50  import java.util.LinkedHashMap;
51  import java.util.List;
52  import java.util.Map;
53  import java.util.StringTokenizer;
54  import java.util.regex.Pattern;
55  
56  import javax.portlet.ActionRequest;
57  import javax.portlet.RenderRequest;
58  
59  import javax.servlet.http.Cookie;
60  import javax.servlet.http.HttpServletRequest;
61  
62  import org.apache.commons.httpclient.Credentials;
63  import org.apache.commons.httpclient.Header;
64  import org.apache.commons.httpclient.HostConfiguration;
65  import org.apache.commons.httpclient.HttpClient;
66  import org.apache.commons.httpclient.HttpMethod;
67  import org.apache.commons.httpclient.HttpState;
68  import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
69  import org.apache.commons.httpclient.NTCredentials;
70  import org.apache.commons.httpclient.NameValuePair;
71  import org.apache.commons.httpclient.URI;
72  import org.apache.commons.httpclient.UsernamePasswordCredentials;
73  import org.apache.commons.httpclient.auth.AuthPolicy;
74  import org.apache.commons.httpclient.auth.AuthScope;
75  import org.apache.commons.httpclient.cookie.CookiePolicy;
76  import org.apache.commons.httpclient.methods.DeleteMethod;
77  import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
78  import org.apache.commons.httpclient.methods.GetMethod;
79  import org.apache.commons.httpclient.methods.PostMethod;
80  import org.apache.commons.httpclient.methods.PutMethod;
81  import org.apache.commons.httpclient.methods.RequestEntity;
82  import org.apache.commons.httpclient.methods.StringRequestEntity;
83  import org.apache.commons.httpclient.params.HttpClientParams;
84  import org.apache.commons.httpclient.params.HttpConnectionParams;
85  
86  /**
87   * <a href="HttpImpl.java.html"><b><i>View Source</i></b></a>
88   *
89   * @author Brian Wing Shun Chan
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 getIpAddress(String url) {
313         try {
314             URL urlObj = new URL(url);
315 
316             InetAddress address = InetAddress.getByName(urlObj.getHost());
317 
318             return address.getHostAddress();
319         }
320         catch (Exception e) {
321             return url;
322         }
323     }
324 
325     public String getParameter(String url, String name) {
326         return getParameter(url, name, true);
327     }
328 
329     public String getParameter(String url, String name, boolean escaped) {
330         if (Validator.isNull(url) || Validator.isNull(name)) {
331             return StringPool.BLANK;
332         }
333 
334         String[] parts = StringUtil.split(url, StringPool.QUESTION);
335 
336         if (parts.length == 2) {
337             String[] params = null;
338 
339             if (escaped) {
340                 params = StringUtil.split(parts[1], "&amp;");
341             }
342             else {
343                 params = StringUtil.split(parts[1], StringPool.AMPERSAND);
344             }
345 
346             for (int i = 0; i < params.length; i++) {
347                 String[] kvp = StringUtil.split(params[i], StringPool.EQUAL);
348 
349                 if ((kvp.length == 2) && kvp[0].equals(name)) {
350                     return kvp[1];
351                 }
352             }
353         }
354 
355         return StringPool.BLANK;
356     }
357 
358     public Map<String, String[]> getParameterMap(String queryString) {
359         return parameterMapFromString(queryString);
360     }
361 
362     public String getProtocol(ActionRequest actionRequest) {
363         return getProtocol(actionRequest.isSecure());
364     }
365 
366     public String getProtocol(boolean secure) {
367         if (!secure) {
368             return Http.HTTP;
369         }
370         else {
371             return Http.HTTPS;
372         }
373     }
374 
375     public String getProtocol(HttpServletRequest request) {
376         return getProtocol(request.isSecure());
377     }
378 
379     public String getProtocol(RenderRequest renderRequest) {
380         return getProtocol(renderRequest.isSecure());
381     }
382 
383     public String getProtocol(String url) {
384         int pos = url.indexOf(Http.PROTOCOL_DELIMITER);
385 
386         if (pos != -1) {
387             return url.substring(0, pos);
388         }
389         else {
390             return Http.HTTP;
391         }
392     }
393 
394     public String getQueryString(String url) {
395         if (Validator.isNull(url)) {
396             return url;
397         }
398 
399         int pos = url.indexOf(StringPool.QUESTION);
400 
401         if (pos == -1) {
402             return StringPool.BLANK;
403         }
404         else {
405             return url.substring(pos + 1, url.length());
406         }
407     }
408 
409     public String getRequestURL(HttpServletRequest request) {
410         return request.getRequestURL().toString();
411     }
412 
413     public boolean hasDomain(String url) {
414         return Validator.isNotNull(getDomain(url));
415     }
416 
417     public boolean hasProtocol(String url) {
418         int pos = url.indexOf(Http.PROTOCOL_DELIMITER);
419 
420         if (pos != -1) {
421             return true;
422         }
423         else {
424             return false;
425         }
426     }
427 
428     public boolean hasProxyConfig() {
429         if (Validator.isNotNull(_PROXY_HOST) && (_PROXY_PORT > 0)) {
430             return true;
431         }
432         else {
433             return false;
434         }
435     }
436 
437     public boolean isNonProxyHost(String host) {
438         if (_nonProxyHostsPattern == null ||
439             _nonProxyHostsPattern.matcher(host).matches()) {
440 
441             return true;
442         }
443         else {
444             return false;
445         }
446     }
447 
448     public boolean isProxyHost(String host) {
449         if (hasProxyConfig() && !isNonProxyHost(host)) {
450             return true;
451         }
452         else {
453             return false;
454         }
455     }
456 
457     public Map<String, String[]> parameterMapFromString(String queryString) {
458         Map<String, String[]> parameterMap =
459             new LinkedHashMap<String, String[]>();
460 
461         if (Validator.isNull(queryString)) {
462             return parameterMap;
463         }
464 
465         Map<String, List<String>> tempParameterMap =
466             new LinkedHashMap<String, List<String>>();
467 
468         StringTokenizer st = new StringTokenizer(
469             queryString, StringPool.AMPERSAND);
470 
471         while (st.hasMoreTokens()) {
472             String token = st.nextToken();
473 
474             if (Validator.isNotNull(token)) {
475                 String[] kvp = StringUtil.split(token, StringPool.EQUAL);
476 
477                 String key = kvp[0];
478 
479                 String value = StringPool.BLANK;
480 
481                 if (kvp.length > 1) {
482                     value = kvp[1];
483                 }
484 
485                 List<String> values = tempParameterMap.get(key);
486 
487                 if (values == null) {
488                     values = new ArrayList<String>();
489 
490                     tempParameterMap.put(key, values);
491                 }
492 
493                 values.add(value);
494             }
495         }
496 
497         for (Map.Entry<String, List<String>> entry :
498                 tempParameterMap.entrySet()) {
499 
500             String key = entry.getKey();
501             List<String> values = entry.getValue();
502 
503             parameterMap.put(key, values.toArray(new String[values.size()]));
504         }
505 
506         return parameterMap;
507     }
508 
509     public String parameterMapToString(Map<String, String[]> parameterMap) {
510         return parameterMapToString(parameterMap, true);
511     }
512 
513     public String parameterMapToString(
514         Map<String, String[]> parameterMap, boolean addQuestion) {
515 
516         StringBuilder sb = new StringBuilder();
517 
518         if (parameterMap.size() > 0) {
519             if (addQuestion) {
520                 sb.append(StringPool.QUESTION);
521             }
522 
523             for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
524                 String name = entry.getKey();
525                 String[] values = entry.getValue();
526 
527                 for (String value : values) {
528                     sb.append(name);
529                     sb.append(StringPool.EQUAL);
530                     sb.append(encodeURL(value));
531                     sb.append(StringPool.AMPERSAND);
532                 }
533             }
534 
535             sb.deleteCharAt(sb.length() - 1);
536         }
537 
538         return sb.toString();
539     }
540 
541     public String protocolize(String url, ActionRequest actionRequest) {
542         return protocolize(url, actionRequest.isSecure());
543     }
544 
545     public String protocolize(String url, boolean secure) {
546         if (secure) {
547             if (url.startsWith(Http.HTTP_WITH_SLASH)) {
548                 return StringUtil.replace(
549                     url, Http.HTTP_WITH_SLASH, Http.HTTPS_WITH_SLASH);
550             }
551         }
552         else {
553             if (url.startsWith(Http.HTTPS_WITH_SLASH)) {
554                 return StringUtil.replace(
555                     url, Http.HTTPS_WITH_SLASH, Http.HTTP_WITH_SLASH);
556             }
557         }
558 
559         return url;
560     }
561 
562     public String protocolize(String url, HttpServletRequest request) {
563         return protocolize(url, request.isSecure());
564     }
565 
566     public String protocolize(String url, RenderRequest renderRequest) {
567         return protocolize(url, renderRequest.isSecure());
568     }
569 
570     public String removeDomain(String url) {
571         url = removeProtocol(url);
572 
573         int pos = url.indexOf(StringPool.SLASH);
574 
575         if (pos > 0) {
576             return url.substring(pos);
577         }
578         else {
579             return url;
580         }
581     }
582 
583     public String removeParameter(String url, String name) {
584         int pos = url.indexOf(StringPool.QUESTION);
585 
586         if (pos == -1) {
587             return url;
588         }
589 
590         String anchor = StringPool.BLANK;
591 
592         int anchorPos = url.indexOf(StringPool.POUND);
593 
594         if (anchorPos != -1) {
595             anchor = url.substring(anchorPos);
596             url = url.substring(0, anchorPos);
597         }
598 
599         StringBuilder sb = new StringBuilder();
600 
601         sb.append(url.substring(0, pos + 1));
602 
603         StringTokenizer st = new StringTokenizer(
604             url.substring(pos + 1, url.length()), StringPool.AMPERSAND);
605 
606         while (st.hasMoreTokens()) {
607             String token = st.nextToken();
608 
609             if (Validator.isNotNull(token)) {
610                 String[] kvp = StringUtil.split(token, StringPool.EQUAL);
611 
612                 String key = kvp[0];
613 
614                 String value = StringPool.BLANK;
615 
616                 if (kvp.length > 1) {
617                     value = kvp[1];
618                 }
619 
620                 if (!key.equals(name)) {
621                     sb.append(key);
622                     sb.append(StringPool.EQUAL);
623                     sb.append(value);
624                     sb.append(StringPool.AMPERSAND);
625                 }
626             }
627         }
628 
629         url = StringUtil.replace(
630             sb.toString(), StringPool.AMPERSAND + StringPool.AMPERSAND,
631             StringPool.AMPERSAND);
632 
633         if (url.endsWith(StringPool.AMPERSAND)) {
634             url = url.substring(0, url.length() - 1);
635         }
636 
637         if (url.endsWith(StringPool.QUESTION)) {
638             url = url.substring(0, url.length() - 1);
639         }
640 
641         return url + anchor;
642     }
643 
644     public String removeProtocol(String url) {
645         if (url.startsWith(Http.HTTP_WITH_SLASH)) {
646             return url.substring(Http.HTTP_WITH_SLASH.length() , url.length());
647         }
648         else if (url.startsWith(Http.HTTPS_WITH_SLASH)) {
649             return url.substring(Http.HTTPS_WITH_SLASH.length() , url.length());
650         }
651         else {
652             return url;
653         }
654     }
655 
656     public String setParameter(String url, String name, boolean value) {
657         return setParameter(url, name, String.valueOf(value));
658     }
659 
660     public String setParameter(String url, String name, double value) {
661         return setParameter(url, name, String.valueOf(value));
662     }
663 
664     public String setParameter(String url, String name, int value) {
665         return setParameter(url, name, String.valueOf(value));
666     }
667 
668     public String setParameter(String url, String name, long value) {
669         return setParameter(url, name, String.valueOf(value));
670     }
671 
672     public String setParameter(String url, String name, short value) {
673         return setParameter(url, name, String.valueOf(value));
674     }
675 
676     public String setParameter(String url, String name, String value) {
677         if (url == null) {
678             return null;
679         }
680 
681         url = removeParameter(url, name);
682 
683         return addParameter(url, name, value);
684     }
685 
686     /**
687      * @deprecated
688      */
689     public void submit(String location) throws IOException {
690         URLtoByteArray(location);
691     }
692 
693     /**
694      * @deprecated
695      */
696     public void submit(String location, boolean post) throws IOException {
697         URLtoByteArray(location, post);
698     }
699 
700     /**
701      * @deprecated
702      */
703     public void submit(String location, Cookie[] cookies) throws IOException {
704         URLtoByteArray(location, cookies);
705     }
706 
707     /**
708      * @deprecated
709      */
710     public void submit(String location, Cookie[] cookies, boolean post)
711         throws IOException {
712 
713         URLtoByteArray(location, cookies, post);
714     }
715 
716     /**
717      * @deprecated
718      */
719     public void submit(
720             String location, Cookie[] cookies, Http.Body body, boolean post)
721         throws IOException {
722 
723         URLtoByteArray(location, cookies, body, post);
724     }
725 
726     /**
727      * @deprecated
728      */
729     public void submit(
730             String location, Cookie[] cookies, Map<String, String> parts,
731             boolean post)
732         throws IOException {
733 
734         URLtoByteArray(location, cookies, parts, post);
735     }
736 
737     public byte[] URLtoByteArray(Http.Options options) throws IOException {
738         return URLtoByteArray(
739             options.getLocation(), options.getMethod(), options.getHeaders(),
740             options.getCookies(), options.getAuth(), options.getBody(),
741             options.getParts());
742     }
743 
744     public byte[] URLtoByteArray(String location) throws IOException {
745         Http.Options options = new Http.Options();
746 
747         options.setLocation(location);
748 
749         return URLtoByteArray(options);
750     }
751 
752     public byte[] URLtoByteArray(String location, boolean post)
753         throws IOException {
754 
755         Http.Options options = new Http.Options();
756 
757         options.setLocation(location);
758         options.setPost(post);
759 
760         return URLtoByteArray(options);
761     }
762 
763     /**
764      * @deprecated
765      */
766     public byte[] URLtoByteArray(String location, Cookie[] cookies)
767         throws IOException {
768 
769         Http.Options options = new Http.Options();
770 
771         options.setCookies(cookies);
772         options.setLocation(location);
773 
774         return URLtoByteArray(options);
775     }
776 
777     /**
778      * @deprecated
779      */
780     public byte[] URLtoByteArray(
781             String location, Cookie[] cookies, boolean post)
782         throws IOException {
783 
784         Http.Options options = new Http.Options();
785 
786         options.setCookies(cookies);
787         options.setLocation(location);
788         options.setPost(post);
789 
790         return URLtoByteArray(options);
791     }
792 
793     /**
794      * @deprecated
795      */
796     public byte[] URLtoByteArray(
797             String location, Cookie[] cookies, Http.Auth auth, Http.Body body,
798             boolean post)
799         throws IOException {
800 
801         Http.Options options = new Http.Options();
802 
803         options.setAuth(auth);
804         options.setBody(body);
805         options.setCookies(cookies);
806         options.setLocation(location);
807         options.setPost(post);
808 
809         return URLtoByteArray(options);
810     }
811 
812     /**
813      * @deprecated
814      */
815     public byte[] URLtoByteArray(
816             String location, Cookie[] cookies, Http.Auth auth,
817             Map<String, String> parts, boolean post)
818         throws IOException {
819 
820         Http.Options options = new Http.Options();
821 
822         options.setAuth(auth);
823         options.setCookies(cookies);
824         options.setLocation(location);
825         options.setParts(parts);
826         options.setPost(post);
827 
828         return URLtoByteArray(options);
829     }
830 
831     /**
832      * @deprecated
833      */
834     public byte[] URLtoByteArray(
835             String location, Cookie[] cookies, Http.Body body, boolean post)
836         throws IOException {
837 
838         Http.Options options = new Http.Options();
839 
840         options.setBody(body);
841         options.setCookies(cookies);
842         options.setLocation(location);
843         options.setPost(post);
844 
845         return URLtoByteArray(options);
846     }
847 
848     /**
849      * @deprecated
850      */
851     public byte[] URLtoByteArray(
852             String location, Cookie[] cookies, Map<String, String> parts,
853             boolean post)
854         throws IOException {
855 
856         Http.Options options = new Http.Options();
857 
858         options.setCookies(cookies);
859         options.setLocation(location);
860         options.setParts(parts);
861         options.setPost(post);
862 
863         return URLtoByteArray(options);
864     }
865 
866     public String URLtoString(Http.Options options) throws IOException {
867         return new String(URLtoByteArray(options));
868     }
869 
870     public String URLtoString(String location) throws IOException {
871         return new String(URLtoByteArray(location));
872     }
873 
874     public String URLtoString(String location, boolean post)
875         throws IOException {
876 
877         return new String(URLtoByteArray(location, post));
878     }
879 
880     /**
881      * @deprecated
882      */
883     public String URLtoString(String location, Cookie[] cookies)
884         throws IOException {
885 
886         return new String(URLtoByteArray(location, cookies));
887     }
888 
889     /**
890      * @deprecated
891      */
892     public String URLtoString(
893             String location, Cookie[] cookies, boolean post)
894         throws IOException {
895 
896         return new String(URLtoByteArray(location, cookies, post));
897     }
898 
899     /**
900      * @deprecated
901      */
902     public String URLtoString(
903             String location, Cookie[] cookies, Http.Auth auth, Http.Body body,
904             boolean post)
905         throws IOException {
906 
907         return new String(URLtoByteArray(location, cookies, auth, body, post));
908     }
909 
910     /**
911      * @deprecated
912      */
913     public String URLtoString(
914             String location, Cookie[] cookies, Http.Auth auth,
915             Map<String, String> parts, boolean post)
916         throws IOException {
917 
918         return new String(URLtoByteArray(location, cookies, auth, parts, post));
919     }
920 
921     /**
922      * @deprecated
923      */
924     public String URLtoString(
925             String location, Cookie[] cookies, Http.Body body, boolean post)
926         throws IOException {
927 
928         return new String(URLtoByteArray(location, cookies, body, post));
929     }
930 
931     /**
932      * @deprecated
933      */
934     public String URLtoString(
935             String location, Cookie[] cookies, Map<String, String> parts,
936             boolean post)
937         throws IOException {
938 
939         return new String(URLtoByteArray(location, cookies, null, parts, post));
940     }
941 
942     /**
943      * @deprecated
944      */
945     public String URLtoString(
946             String location, String host, int port, String realm,
947             String username, String password)
948         throws IOException {
949 
950         return URLtoString(
951             location, (Cookie[])null,
952             new Http.Auth(host, port, realm, username, password),
953             (Http.Body)null, false);
954     }
955 
956     /**
957      * This method only uses the default Commons HttpClient implementation when
958      * the URL object represents a HTTP resource. The URL object could also
959      * represent a file or some JNDI resource. In that case, the default Java
960      * implementation is used.
961      *
962      * @param  url URL object
963      * @return A string representation of the resource referenced by the
964      *         URL object
965      */
966     public String URLtoString(URL url) throws IOException {
967         String xml = null;
968 
969         if (url != null) {
970             String protocol = url.getProtocol().toLowerCase();
971 
972             if (protocol.startsWith(Http.HTTP) ||
973                 protocol.startsWith(Http.HTTPS)) {
974 
975                 return URLtoString(url.toString());
976             }
977 
978             URLConnection con = url.openConnection();
979 
980             InputStream is = con.getInputStream();
981 
982             ByteArrayMaker bam = new ByteArrayMaker();
983             byte[] bytes = new byte[512];
984 
985             for (int i = is.read(bytes, 0, 512); i != -1;
986                     i = is.read(bytes, 0, 512)) {
987 
988                 bam.write(bytes, 0, i);
989             }
990 
991             xml = new String(bam.toByteArray());
992 
993             is.close();
994             bam.close();
995         }
996 
997         return xml;
998     }
999 
1000    protected void proxifyState(HttpState state, HostConfiguration hostConfig) {
1001        Credentials proxyCredentials = _proxyCredentials;
1002
1003        String host = hostConfig.getHost();
1004
1005        if (isProxyHost(host) && (proxyCredentials != null)) {
1006            AuthScope scope = new AuthScope(_PROXY_HOST, _PROXY_PORT, null);
1007
1008            state.setProxyCredentials(scope, proxyCredentials);
1009        }
1010    }
1011
1012    protected org.apache.commons.httpclient.Cookie toCommonsCookie(
1013        Cookie cookie) {
1014
1015        org.apache.commons.httpclient.Cookie commonsCookie =
1016            new org.apache.commons.httpclient.Cookie(
1017            cookie.getDomain(), cookie.getName(), cookie.getValue(),
1018            cookie.getPath(), cookie.getMaxAge(), cookie.getSecure());
1019
1020        commonsCookie.setVersion(cookie.getVersion());
1021
1022        return commonsCookie;
1023    }
1024
1025    protected org.apache.commons.httpclient.Cookie[] toCommonsCookies(
1026        Cookie[] cookies) {
1027
1028        if (cookies == null) {
1029            return null;
1030        }
1031
1032        org.apache.commons.httpclient.Cookie[] commonCookies =
1033            new org.apache.commons.httpclient.Cookie[cookies.length];
1034
1035        for (int i = 0; i < cookies.length; i++) {
1036            commonCookies[i] = toCommonsCookie(cookies[i]);
1037        }
1038
1039        return commonCookies;
1040    }
1041
1042    protected Cookie toServletCookie(
1043        org.apache.commons.httpclient.Cookie commonsCookie) {
1044
1045        Cookie cookie = new Cookie(
1046            commonsCookie.getName(), commonsCookie.getValue());
1047
1048        cookie.setDomain(commonsCookie.getDomain());
1049
1050        Date expiryDate = commonsCookie.getExpiryDate();
1051
1052        if (expiryDate != null) {
1053            int maxAge =
1054                (int)(expiryDate.getTime() - System.currentTimeMillis());
1055
1056            maxAge = maxAge / 1000;
1057
1058            if (maxAge > -1) {
1059                cookie.setMaxAge(maxAge);
1060            }
1061        }
1062
1063        cookie.setPath(commonsCookie.getPath());
1064        cookie.setSecure(commonsCookie.getSecure());
1065        cookie.setVersion(commonsCookie.getVersion());
1066
1067        return cookie;
1068    }
1069
1070    protected Cookie[] toServletCookies(
1071        org.apache.commons.httpclient.Cookie[] commonsCookies) {
1072
1073        if (commonsCookies == null) {
1074            return null;
1075        }
1076
1077        Cookie[] cookies = new Cookie[commonsCookies.length];
1078
1079        for (int i = 0; i < commonsCookies.length; i++) {
1080            cookies[i] = toServletCookie(commonsCookies[i]);
1081        }
1082
1083        return cookies;
1084    }
1085
1086    protected byte[] URLtoByteArray(
1087            String location, Http.Method method, Map<String, String> headers,
1088            Cookie[] cookies, Http.Auth auth, Http.Body body, Map<String,
1089            String> parts)
1090        throws IOException {
1091
1092        byte[] bytes = null;
1093
1094        HttpMethod httpMethod = null;
1095        HttpState httpState = null;
1096
1097        try {
1098            _cookies.set(null);
1099
1100            if (location == null) {
1101                return bytes;
1102            }
1103            else if (!location.startsWith(Http.HTTP_WITH_SLASH) &&
1104                     !location.startsWith(Http.HTTPS_WITH_SLASH)) {
1105
1106                location = Http.HTTP_WITH_SLASH + location;
1107            }
1108
1109            HostConfiguration hostConfig = getHostConfig(location);
1110
1111            HttpClient httpClient = getClient(hostConfig);
1112
1113            if ((method == Http.Method.POST) ||
1114                (method == Http.Method.PUT)) {
1115
1116                if (method == Http.Method.POST) {
1117                    httpMethod = new PostMethod(location);
1118                }
1119                else {
1120                    httpMethod = new PutMethod(location);
1121                }
1122
1123                if (body != null) {
1124                    RequestEntity requestEntity = new StringRequestEntity(
1125                        body.getContent(), body.getContentType(),
1126                        body.getCharset());
1127
1128                    EntityEnclosingMethod entityEnclosingMethod =
1129                        (EntityEnclosingMethod)httpMethod;
1130
1131                    entityEnclosingMethod.setRequestEntity(requestEntity);
1132                }
1133                else if ((parts != null) && (parts.size() > 0) &&
1134                         (method == Http.Method.POST)) {
1135
1136                    List<NameValuePair> nvpList =
1137                        new ArrayList<NameValuePair>();
1138
1139                    for (Map.Entry<String, String> entry : parts.entrySet()) {
1140                        String key = entry.getKey();
1141                        String value = entry.getValue();
1142
1143                        if (value != null) {
1144                            nvpList.add(new NameValuePair(key, value));
1145                        }
1146                    }
1147
1148                    NameValuePair[] nvpArray = nvpList.toArray(
1149                        new NameValuePair[nvpList.size()]);
1150
1151                    PostMethod postMethod = (PostMethod)httpMethod;
1152
1153                    postMethod.setRequestBody(nvpArray);
1154                }
1155            }
1156            else if (method == Http.Method.DELETE) {
1157                httpMethod = new DeleteMethod(location);
1158            }
1159            else {
1160                httpMethod = new GetMethod(location);
1161            }
1162
1163            if ((method == Http.Method.POST) || (method == Http.Method.PUT) &&
1164                (body != null)) {
1165            }
1166            else if (!_hasRequestHeader(httpMethod, HttpHeaders.CONTENT_TYPE)) {
1167                httpMethod.addRequestHeader(
1168                    HttpHeaders.CONTENT_TYPE,
1169                    ContentTypes.APPLICATION_X_WWW_FORM_URLENCODED);
1170            }
1171
1172            if (!_hasRequestHeader(httpMethod, HttpHeaders.USER_AGENT)) {
1173                httpMethod.addRequestHeader(
1174                    HttpHeaders.USER_AGENT, _DEFAULT_USER_AGENT);
1175            }
1176
1177            if (headers != null) {
1178                for (Map.Entry<String, String> header : headers.entrySet()) {
1179                    httpMethod.addRequestHeader(
1180                        header.getKey(), header.getValue());
1181                }
1182            }
1183
1184            httpMethod.getParams().setIntParameter(
1185                HttpClientParams.SO_TIMEOUT, 0);
1186
1187            //httpMethod.setFollowRedirects(true);
1188
1189            httpState = new HttpState();
1190
1191            if ((cookies != null) && (cookies.length > 0)) {
1192                org.apache.commons.httpclient.Cookie[] commonsCookies =
1193                    toCommonsCookies(cookies);
1194
1195                httpState.addCookies(commonsCookies);
1196
1197                httpMethod.getParams().setCookiePolicy(
1198                    CookiePolicy.BROWSER_COMPATIBILITY);
1199            }
1200
1201            if (auth != null) {
1202                httpMethod.setDoAuthentication(true);
1203
1204                httpState.setCredentials(
1205                    new AuthScope(
1206                        auth.getHost(), auth.getPort(), auth.getRealm()),
1207                    new UsernamePasswordCredentials(
1208                        auth.getUsername(), auth.getPassword()));
1209            }
1210
1211            proxifyState(httpState, hostConfig);
1212
1213            httpClient.executeMethod(hostConfig, httpMethod, httpState);
1214
1215            Header locationHeader = httpMethod.getResponseHeader("location");
1216
1217            if ((locationHeader != null) && !locationHeader.equals(location)) {
1218                return URLtoByteArray(
1219                    locationHeader.getValue(), Http.Method.GET, headers,
1220                    cookies, auth, body, parts);
1221            }
1222
1223            InputStream is = httpMethod.getResponseBodyAsStream();
1224
1225            if (is != null) {
1226                bytes = FileUtil.getBytes(is);
1227
1228                is.close();
1229            }
1230
1231            return bytes;
1232        }
1233        finally {
1234            try {
1235                if (httpState != null) {
1236                    _cookies.set(toServletCookies(httpState.getCookies()));
1237                }
1238            }
1239            catch (Exception e) {
1240                _log.error(e, e);
1241            }
1242
1243            try {
1244                if (httpMethod != null) {
1245                    httpMethod.releaseConnection();
1246                }
1247            }
1248            catch (Exception e) {
1249                _log.error(e, e);
1250            }
1251        }
1252    }
1253
1254    private boolean _hasRequestHeader(HttpMethod httpMethod, String name) {
1255        if (httpMethod.getRequestHeaders(name).length == 0) {
1256            return false;
1257        }
1258        else {
1259            return true;
1260        }
1261    }
1262
1263    private static final String _DEFAULT_USER_AGENT =
1264        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
1265
1266    private static final int _MAX_CONNECTIONS_PER_HOST = GetterUtil.getInteger(
1267        PropsUtil.get(HttpImpl.class.getName() + ".max.connections.per.host"),
1268        2);
1269
1270    private static final int _MAX_TOTAL_CONNECTIONS = GetterUtil.getInteger(
1271        PropsUtil.get(HttpImpl.class.getName() + ".max.total.connections"),
1272        20);
1273
1274    private static final String _NON_PROXY_HOSTS =
1275        SystemProperties.get("http.nonProxyHosts");
1276
1277    private static final String _PROXY_AUTH_TYPE = GetterUtil.getString(
1278        PropsUtil.get(HttpImpl.class.getName() + ".proxy.auth.type"));
1279
1280    private static final String _PROXY_HOST = GetterUtil.getString(
1281        SystemProperties.get("http.proxyHost"));
1282
1283    private static final String _PROXY_NTLM_DOMAIN = GetterUtil.getString(
1284        PropsUtil.get(HttpImpl.class.getName() + ".proxy.ntlm.domain"));
1285
1286    private static final String _PROXY_NTLM_HOST = GetterUtil.getString(
1287        PropsUtil.get(HttpImpl.class.getName() + ".proxy.ntlm.host"));
1288
1289    private static final String _PROXY_PASSWORD = GetterUtil.getString(
1290        PropsUtil.get(HttpImpl.class.getName() + ".proxy.password"));
1291
1292    private static final int _PROXY_PORT = GetterUtil.getInteger(
1293        SystemProperties.get("http.proxyPort"));
1294
1295    private static final String _PROXY_USERNAME = GetterUtil.getString(
1296        PropsUtil.get(HttpImpl.class.getName() + ".proxy.username"));
1297
1298    private static final int _TIMEOUT = GetterUtil.getInteger(
1299        PropsUtil.get(HttpImpl.class.getName() + ".timeout"), 5000);
1300
1301    private static Log _log = LogFactoryUtil.getLog(HttpImpl.class);
1302
1303    private static ThreadLocal<Cookie[]> _cookies = new ThreadLocal<Cookie[]>();
1304
1305    private HttpClient _client = new HttpClient();
1306    private Pattern _nonProxyHostsPattern;
1307    private HttpClient _proxyClient = new HttpClient();
1308    private Credentials _proxyCredentials;
1309
1310}