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