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