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 getPath(String url) {
472                    if (Validator.isNull(url)) {
473                            return url;
474                    }
475    
476                    if (url.startsWith(Http.HTTP)) {
477                            int pos = url.indexOf(
478                                    StringPool.SLASH, Http.HTTPS_WITH_SLASH.length());
479    
480                            url = url.substring(pos, url.length());
481                    }
482    
483                    int pos = url.indexOf(CharPool.QUESTION);
484    
485                    if (pos == -1) {
486                            return url;
487                    }
488                    else {
489                            return url.substring(0, pos);
490                    }
491            }
492    
493            public String getProtocol(ActionRequest actionRequest) {
494                    return getProtocol(actionRequest.isSecure());
495            }
496    
497            public String getProtocol(boolean secure) {
498                    if (!secure) {
499                            return Http.HTTP;
500                    }
501                    else {
502                            return Http.HTTPS;
503                    }
504            }
505    
506            public String getProtocol(HttpServletRequest request) {
507                    return getProtocol(request.isSecure());
508            }
509    
510            public String getProtocol(RenderRequest renderRequest) {
511                    return getProtocol(renderRequest.isSecure());
512            }
513    
514            public String getProtocol(String url) {
515                    int pos = url.indexOf(Http.PROTOCOL_DELIMITER);
516    
517                    if (pos != -1) {
518                            return url.substring(0, pos);
519                    }
520                    else {
521                            return Http.HTTP;
522                    }
523            }
524    
525            public String getQueryString(String url) {
526                    if (Validator.isNull(url)) {
527                            return url;
528                    }
529    
530                    int pos = url.indexOf(CharPool.QUESTION);
531    
532                    if (pos == -1) {
533                            return StringPool.BLANK;
534                    }
535                    else {
536                            return url.substring(pos + 1, url.length());
537                    }
538            }
539    
540            public String getRequestURL(HttpServletRequest request) {
541                    return request.getRequestURL().toString();
542            }
543    
544            public boolean hasDomain(String url) {
545                    return Validator.isNotNull(getDomain(url));
546            }
547    
548            public boolean hasProtocol(String url) {
549                    int pos = url.indexOf(Http.PROTOCOL_DELIMITER);
550    
551                    if (pos != -1) {
552                            return true;
553                    }
554                    else {
555                            return false;
556                    }
557            }
558    
559            public boolean hasProxyConfig() {
560                    if (Validator.isNotNull(_PROXY_HOST) && (_PROXY_PORT > 0)) {
561                            return true;
562                    }
563                    else {
564                            return false;
565                    }
566            }
567    
568            public boolean isNonProxyHost(String host) {
569                    if (_nonProxyHostsPattern != null) {
570                            Matcher matcher = _nonProxyHostsPattern.matcher(host);
571    
572                            if (matcher.matches()) {
573                                    return true;
574                            }
575                    }
576    
577                    return false;
578            }
579    
580            public boolean isProxyHost(String host) {
581                    if (hasProxyConfig() && !isNonProxyHost(host)) {
582                            return true;
583                    }
584                    else {
585                            return false;
586                    }
587            }
588    
589            public Map<String, String[]> parameterMapFromString(String queryString) {
590                    Map<String, String[]> parameterMap =
591                            new LinkedHashMap<String, String[]>();
592    
593                    if (Validator.isNull(queryString)) {
594                            return parameterMap;
595                    }
596    
597                    Map<String, List<String>> tempParameterMap =
598                            new LinkedHashMap<String, List<String>>();
599    
600                    String[] parameters = StringUtil.split(queryString, CharPool.AMPERSAND);
601    
602                    for (String parameter : parameters) {
603                            if (parameter.length() > 0) {
604                                    String[] kvp = StringUtil.split(parameter, CharPool.EQUAL);
605    
606                                    String key = kvp[0];
607    
608                                    String value = StringPool.BLANK;
609    
610                                    if (kvp.length > 1) {
611                                            value = decodeURL(kvp[1]);
612                                    }
613    
614                                    List<String> values = tempParameterMap.get(key);
615    
616                                    if (values == null) {
617                                            values = new ArrayList<String>();
618    
619                                            tempParameterMap.put(key, values);
620                                    }
621    
622                                    values.add(value);
623                            }
624                    }
625    
626                    for (Map.Entry<String, List<String>> entry :
627                                    tempParameterMap.entrySet()) {
628    
629                            String key = entry.getKey();
630                            List<String> values = entry.getValue();
631    
632                            parameterMap.put(key, values.toArray(new String[values.size()]));
633                    }
634    
635                    return parameterMap;
636            }
637    
638            public String parameterMapToString(Map<String, String[]> parameterMap) {
639                    return parameterMapToString(parameterMap, true);
640            }
641    
642            public String parameterMapToString(
643                    Map<String, String[]> parameterMap, boolean addQuestion) {
644    
645                    if (parameterMap.isEmpty()) {
646                            return StringPool.BLANK;
647                    }
648    
649                    StringBundler sb = new StringBundler();
650    
651                    if (addQuestion) {
652                            sb.append(StringPool.QUESTION);
653                    }
654    
655                    for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
656                            String name = entry.getKey();
657                            String[] values = entry.getValue();
658    
659                            for (String value : values) {
660                                    sb.append(name);
661                                    sb.append(StringPool.EQUAL);
662                                    sb.append(encodeURL(value));
663                                    sb.append(StringPool.AMPERSAND);
664                            }
665                    }
666    
667                    if (sb.index() > 1) {
668                            sb.setIndex(sb.index() - 1);
669                    }
670    
671                    return sb.toString();
672            }
673    
674            public String protocolize(String url, ActionRequest actionRequest) {
675                    return protocolize(url, actionRequest.isSecure());
676            }
677    
678            public String protocolize(String url, boolean secure) {
679                    if (secure) {
680                            if (url.startsWith(Http.HTTP_WITH_SLASH)) {
681                                    return StringUtil.replace(
682                                            url, Http.HTTP_WITH_SLASH, Http.HTTPS_WITH_SLASH);
683                            }
684                    }
685                    else {
686                            if (url.startsWith(Http.HTTPS_WITH_SLASH)) {
687                                    return StringUtil.replace(
688                                            url, Http.HTTPS_WITH_SLASH, Http.HTTP_WITH_SLASH);
689                            }
690                    }
691    
692                    return url;
693            }
694    
695            public String protocolize(String url, HttpServletRequest request) {
696                    return protocolize(url, request.isSecure());
697            }
698    
699            public String protocolize(String url, RenderRequest renderRequest) {
700                    return protocolize(url, renderRequest.isSecure());
701            }
702    
703            public void proxifyState(
704                    HttpState httpState, HostConfiguration hostConfiguration) {
705    
706                    Credentials proxyCredentials = _proxyCredentials;
707    
708                    String host = hostConfiguration.getHost();
709    
710                    if (isProxyHost(host) && (proxyCredentials != null)) {
711                            AuthScope scope = new AuthScope(_PROXY_HOST, _PROXY_PORT, null);
712    
713                            httpState.setProxyCredentials(scope, proxyCredentials);
714                    }
715            }
716    
717            public String removeDomain(String url) {
718                    url = removeProtocol(url);
719    
720                    int pos = url.indexOf(CharPool.SLASH);
721    
722                    if (pos > 0) {
723                            return url.substring(pos);
724                    }
725                    else {
726                            return url;
727                    }
728            }
729    
730            public String removeParameter(String url, String name) {
731                    int pos = url.indexOf(CharPool.QUESTION);
732    
733                    if (pos == -1) {
734                            return url;
735                    }
736    
737                    String[] array = PortalUtil.stripURLAnchor(url, StringPool.POUND);
738    
739                    url = array[0];
740    
741                    String anchor = array[1];
742    
743                    StringBundler sb = new StringBundler();
744    
745                    sb.append(url.substring(0, pos + 1));
746    
747                    String[] parameters = StringUtil.split(
748                            url.substring(pos + 1, url.length()), CharPool.AMPERSAND);
749    
750                    for (String parameter : parameters) {
751                            if (parameter.length() > 0) {
752                                    String[] kvp = StringUtil.split(parameter, CharPool.EQUAL);
753    
754                                    String key = kvp[0];
755    
756                                    String value = StringPool.BLANK;
757    
758                                    if (kvp.length > 1) {
759                                            value = kvp[1];
760                                    }
761    
762                                    if (!key.equals(name)) {
763                                            sb.append(key);
764                                            sb.append(StringPool.EQUAL);
765                                            sb.append(value);
766                                            sb.append(StringPool.AMPERSAND);
767                                    }
768                            }
769                    }
770    
771                    url = StringUtil.replace(
772                            sb.toString(), StringPool.AMPERSAND + StringPool.AMPERSAND,
773                            StringPool.AMPERSAND);
774    
775                    if (url.endsWith(StringPool.AMPERSAND)) {
776                            url = url.substring(0, url.length() - 1);
777                    }
778    
779                    if (url.endsWith(StringPool.QUESTION)) {
780                            url = url.substring(0, url.length() - 1);
781                    }
782    
783                    return url + anchor;
784            }
785    
786            public String removeProtocol(String url) {
787                    if (url.startsWith(Http.HTTP_WITH_SLASH)) {
788                            return url.substring(Http.HTTP_WITH_SLASH.length(), url.length());
789                    }
790                    else if (url.startsWith(Http.HTTPS_WITH_SLASH)) {
791                            return url.substring(Http.HTTPS_WITH_SLASH.length(), url.length());
792                    }
793                    else {
794                            return url;
795                    }
796            }
797    
798            public String setParameter(String url, String name, boolean value) {
799                    return setParameter(url, name, String.valueOf(value));
800            }
801    
802            public String setParameter(String url, String name, double value) {
803                    return setParameter(url, name, String.valueOf(value));
804            }
805    
806            public String setParameter(String url, String name, int value) {
807                    return setParameter(url, name, String.valueOf(value));
808            }
809    
810            public String setParameter(String url, String name, long value) {
811                    return setParameter(url, name, String.valueOf(value));
812            }
813    
814            public String setParameter(String url, String name, short value) {
815                    return setParameter(url, name, String.valueOf(value));
816            }
817    
818            public String setParameter(String url, String name, String value) {
819                    if (url == null) {
820                            return null;
821                    }
822    
823                    url = removeParameter(url, name);
824    
825                    return addParameter(url, name, value);
826            }
827    
828            public byte[] URLtoByteArray(Http.Options options) throws IOException {
829                    return URLtoByteArray(
830                            options.getLocation(), options.getMethod(), options.getHeaders(),
831                            options.getCookies(), options.getAuth(), options.getBody(),
832                            options.getFileParts(), options.getParts(), options.getResponse(),
833                            options.isFollowRedirects());
834            }
835    
836            public byte[] URLtoByteArray(String location) throws IOException {
837                    Http.Options options = new Http.Options();
838    
839                    options.setLocation(location);
840    
841                    return URLtoByteArray(options);
842            }
843    
844            public byte[] URLtoByteArray(String location, boolean post)
845                    throws IOException {
846    
847                    Http.Options options = new Http.Options();
848    
849                    options.setLocation(location);
850                    options.setPost(post);
851    
852                    return URLtoByteArray(options);
853            }
854    
855            public String URLtoString(Http.Options options) throws IOException {
856                    return new String(URLtoByteArray(options));
857            }
858    
859            public String URLtoString(String location) throws IOException {
860                    return new String(URLtoByteArray(location));
861            }
862    
863            public String URLtoString(String location, boolean post)
864                    throws IOException {
865    
866                    return new String(URLtoByteArray(location, post));
867            }
868    
869            /**
870             * This method only uses the default Commons HttpClient implementation when
871             * the URL object represents a HTTP resource. The URL object could also
872             * represent a file or some JNDI resource. In that case, the default Java
873             * implementation is used.
874             *
875             * @return A string representation of the resource referenced by the URL
876             *         object
877             */
878            public String URLtoString(URL url) throws IOException {
879                    String xml = null;
880    
881                    if (url != null) {
882                            String protocol = url.getProtocol().toLowerCase();
883    
884                            if (protocol.startsWith(Http.HTTP) ||
885                                    protocol.startsWith(Http.HTTPS)) {
886    
887                                    return URLtoString(url.toString());
888                            }
889    
890                            URLConnection urlConnection = url.openConnection();
891    
892                            InputStream inputStream = urlConnection.getInputStream();
893    
894                            UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
895                                    new UnsyncByteArrayOutputStream();
896    
897                            byte[] bytes = new byte[512];
898    
899                            for (int i = inputStream.read(bytes, 0, 512); i != -1;
900                                            i = inputStream.read(bytes, 0, 512)) {
901    
902                                    unsyncByteArrayOutputStream.write(bytes, 0, i);
903                            }
904    
905                            xml = new String(
906                                    unsyncByteArrayOutputStream.unsafeGetByteArray(), 0,
907                                    unsyncByteArrayOutputStream.size());
908    
909                            inputStream.close();
910    
911                            unsyncByteArrayOutputStream.close();
912                    }
913    
914                    return xml;
915            }
916    
917            protected boolean hasRequestHeader(HttpMethod httpMethod, String name) {
918                    Header[] headers = httpMethod.getRequestHeaders(name);
919    
920                    if (headers.length == 0) {
921                            return false;
922                    }
923                    else {
924                            return true;
925                    }
926            }
927    
928            protected void processPostMethod(
929                    PostMethod postMethod, List<Http.FilePart> fileParts,
930                    Map<String, String> parts) {
931    
932                    if ((fileParts == null) || fileParts.isEmpty()) {
933                            if (parts != null) {
934                                    for (Map.Entry<String, String> entry : parts.entrySet()) {
935                                            String value = entry.getValue();
936    
937                                            if (Validator.isNotNull(value)) {
938                                                    postMethod.addParameter(entry.getKey(), value);
939                                            }
940                                    }
941                            }
942                    }
943                    else {
944                            List<Part> partsList = new ArrayList<Part>();
945    
946                            if (parts != null) {
947                                    for (Map.Entry<String, String> entry : parts.entrySet()) {
948                                            String value = entry.getValue();
949    
950                                            if (Validator.isNotNull(value)) {
951                                                    StringPart stringPart = new StringPart(
952                                                            entry.getKey(), value);
953    
954                                                    partsList.add(stringPart);
955                                            }
956                                    }
957                            }
958    
959                            for (Http.FilePart filePart : fileParts) {
960                                    partsList.add(toCommonsFilePart(filePart));
961                            }
962    
963                            MultipartRequestEntity multipartRequestEntity =
964                                    new MultipartRequestEntity(
965                                            partsList.toArray(new Part[0]), postMethod.getParams());
966    
967                            postMethod.setRequestEntity(multipartRequestEntity);
968                    }
969            }
970    
971            protected org.apache.commons.httpclient.Cookie toCommonsCookie(
972                    Cookie cookie) {
973    
974                    org.apache.commons.httpclient.Cookie commonsCookie =
975                            new org.apache.commons.httpclient.Cookie(
976                            cookie.getDomain(), cookie.getName(), cookie.getValue(),
977                            cookie.getPath(), cookie.getMaxAge(), cookie.getSecure());
978    
979                    commonsCookie.setVersion(cookie.getVersion());
980    
981                    return commonsCookie;
982            }
983    
984            protected org.apache.commons.httpclient.Cookie[] toCommonsCookies(
985                    Cookie[] cookies) {
986    
987                    if (cookies == null) {
988                            return null;
989                    }
990    
991                    org.apache.commons.httpclient.Cookie[] commonCookies =
992                            new org.apache.commons.httpclient.Cookie[cookies.length];
993    
994                    for (int i = 0; i < cookies.length; i++) {
995                            commonCookies[i] = toCommonsCookie(cookies[i]);
996                    }
997    
998                    return commonCookies;
999            }
1000    
1001            protected org.apache.commons.httpclient.methods.multipart.FilePart
1002                    toCommonsFilePart(Http.FilePart filePart) {
1003    
1004                    return new org.apache.commons.httpclient.methods.multipart.FilePart(
1005                            filePart.getName(),
1006                            new ByteArrayPartSource(
1007                                    filePart.getFileName(), filePart.getValue()),
1008                            filePart.getContentType(), filePart.getCharSet());
1009            }
1010    
1011            protected Cookie toServletCookie(
1012                    org.apache.commons.httpclient.Cookie commonsCookie) {
1013    
1014                    Cookie cookie = new Cookie(
1015                            commonsCookie.getName(), commonsCookie.getValue());
1016    
1017                    String domain = commonsCookie.getDomain();
1018    
1019                    if (Validator.isNotNull(domain)) {
1020                            cookie.setDomain(domain);
1021                    }
1022    
1023                    Date expiryDate = commonsCookie.getExpiryDate();
1024    
1025                    if (expiryDate != null) {
1026                            int maxAge =
1027                                    (int)(expiryDate.getTime() - System.currentTimeMillis());
1028    
1029                            maxAge = maxAge / 1000;
1030    
1031                            if (maxAge > -1) {
1032                                    cookie.setMaxAge(maxAge);
1033                            }
1034                    }
1035    
1036                    String path = commonsCookie.getPath();
1037    
1038                    if (Validator.isNotNull(path)) {
1039                            cookie.setPath(path);
1040                    }
1041    
1042                    cookie.setSecure(commonsCookie.getSecure());
1043                    cookie.setVersion(commonsCookie.getVersion());
1044    
1045                    return cookie;
1046            }
1047    
1048            protected Cookie[] toServletCookies(
1049                    org.apache.commons.httpclient.Cookie[] commonsCookies) {
1050    
1051                    if (commonsCookies == null) {
1052                            return null;
1053                    }
1054    
1055                    Cookie[] cookies = new Cookie[commonsCookies.length];
1056    
1057                    for (int i = 0; i < commonsCookies.length; i++) {
1058                            cookies[i] = toServletCookie(commonsCookies[i]);
1059                    }
1060    
1061                    return cookies;
1062            }
1063    
1064            protected byte[] URLtoByteArray(
1065                            String location, Http.Method method, Map<String, String> headers,
1066                            Cookie[] cookies, Http.Auth auth, Http.Body body,
1067                            List<Http.FilePart> fileParts, Map<String, String> parts,
1068                            Http.Response response, boolean followRedirects)
1069                    throws IOException {
1070    
1071                    byte[] bytes = null;
1072    
1073                    HttpMethod httpMethod = null;
1074                    HttpState httpState = null;
1075    
1076                    try {
1077                            _cookies.set(null);
1078    
1079                            if (location == null) {
1080                                    return null;
1081                            }
1082                            else if (!location.startsWith(Http.HTTP_WITH_SLASH) &&
1083                                             !location.startsWith(Http.HTTPS_WITH_SLASH)) {
1084    
1085                                    location = Http.HTTP_WITH_SLASH + location;
1086                            }
1087    
1088                            HostConfiguration hostConfiguration = getHostConfiguration(
1089                                    location);
1090    
1091                            HttpClient httpClient = getClient(hostConfiguration);
1092    
1093                            if (method.equals(Http.Method.POST) ||
1094                                    method.equals(Http.Method.PUT)) {
1095    
1096                                    if (method.equals(Http.Method.POST)) {
1097                                            httpMethod = new PostMethod(location);
1098                                    }
1099                                    else {
1100                                            httpMethod = new PutMethod(location);
1101                                    }
1102    
1103                                    if (body != null) {
1104                                            RequestEntity requestEntity = new StringRequestEntity(
1105                                                    body.getContent(), body.getContentType(),
1106                                                    body.getCharset());
1107    
1108                                            EntityEnclosingMethod entityEnclosingMethod =
1109                                                    (EntityEnclosingMethod)httpMethod;
1110    
1111                                            entityEnclosingMethod.setRequestEntity(requestEntity);
1112                                    }
1113                                    else if (method.equals(Http.Method.POST)) {
1114                                            PostMethod postMethod = (PostMethod)httpMethod;
1115    
1116                                            processPostMethod(postMethod, fileParts, parts);
1117                                    }
1118                            }
1119                            else if (method.equals(Http.Method.DELETE)) {
1120                                    httpMethod = new DeleteMethod(location);
1121                            }
1122                            else if (method.equals(Http.Method.HEAD)) {
1123                                    httpMethod = new HeadMethod(location);
1124                            }
1125                            else {
1126                                    httpMethod = new GetMethod(location);
1127                            }
1128    
1129                            if (headers != null) {
1130                                    for (Map.Entry<String, String> header : headers.entrySet()) {
1131                                            httpMethod.addRequestHeader(
1132                                                    header.getKey(), header.getValue());
1133                                    }
1134                            }
1135    
1136                            if ((method.equals(Http.Method.POST) ||
1137                                     method.equals(Http.Method.PUT)) &&
1138                                    ((body != null) ||
1139                                     ((fileParts != null) && !fileParts.isEmpty()) |
1140                                     ((parts != null) && !parts.isEmpty()))) {
1141                            }
1142                            else if (!hasRequestHeader(httpMethod, HttpHeaders.CONTENT_TYPE)) {
1143                                    httpMethod.addRequestHeader(
1144                                            HttpHeaders.CONTENT_TYPE,
1145                                            ContentTypes.APPLICATION_X_WWW_FORM_URLENCODED);
1146                            }
1147    
1148                            if (!hasRequestHeader(httpMethod, HttpHeaders.USER_AGENT)) {
1149                                    httpMethod.addRequestHeader(
1150                                            HttpHeaders.USER_AGENT, _DEFAULT_USER_AGENT);
1151                            }
1152    
1153                            httpState = new HttpState();
1154    
1155                            if ((cookies != null) && (cookies.length > 0)) {
1156                                    org.apache.commons.httpclient.Cookie[] commonsCookies =
1157                                            toCommonsCookies(cookies);
1158    
1159                                    httpState.addCookies(commonsCookies);
1160    
1161                                    HttpMethodParams httpMethodParams = httpMethod.getParams();
1162    
1163                                    httpMethodParams.setCookiePolicy(
1164                                            CookiePolicy.BROWSER_COMPATIBILITY);
1165                            }
1166    
1167                            if (auth != null) {
1168                                    httpMethod.setDoAuthentication(true);
1169    
1170                                    httpState.setCredentials(
1171                                            new AuthScope(
1172                                                    auth.getHost(), auth.getPort(), auth.getRealm()),
1173                                            new UsernamePasswordCredentials(
1174                                                    auth.getUsername(), auth.getPassword()));
1175                            }
1176    
1177                            proxifyState(httpState, hostConfiguration);
1178    
1179                            httpClient.executeMethod(hostConfiguration, httpMethod, httpState);
1180    
1181                            Header locationHeader = httpMethod.getResponseHeader("location");
1182    
1183                            if ((locationHeader != null) && !locationHeader.equals(location)) {
1184                                    String redirect = locationHeader.getValue();
1185    
1186                                    if (followRedirects) {
1187                                            return URLtoByteArray(
1188                                                    redirect, Http.Method.GET, headers, cookies, auth, body,
1189                                                    fileParts, parts, response, followRedirects);
1190                                    }
1191                                    else {
1192                                            response.setRedirect(redirect);
1193                                    }
1194                            }
1195    
1196                            InputStream inputStream = httpMethod.getResponseBodyAsStream();
1197    
1198                            if (inputStream != null) {
1199                                    Header contentLength = httpMethod.getResponseHeader(
1200                                            HttpHeaders.CONTENT_LENGTH);
1201    
1202                                    if (contentLength != null) {
1203                                            response.setContentLength(
1204                                                    GetterUtil.getInteger(contentLength.getValue()));
1205                                    }
1206    
1207                                    Header contentType = httpMethod.getResponseHeader(
1208                                            HttpHeaders.CONTENT_TYPE);
1209    
1210                                    if (contentType != null) {
1211                                            response.setContentType(contentType.getValue());
1212                                    }
1213    
1214                                    bytes = FileUtil.getBytes(inputStream);
1215                            }
1216    
1217                            for (Header header : httpMethod.getResponseHeaders()) {
1218                                    response.addHeader(header.getName(), header.getValue());
1219                            }
1220    
1221                            return bytes;
1222                    }
1223                    finally {
1224                            try {
1225                                    if (httpState != null) {
1226                                            _cookies.set(toServletCookies(httpState.getCookies()));
1227                                    }
1228                            }
1229                            catch (Exception e) {
1230                                    _log.error(e, e);
1231                            }
1232    
1233                            try {
1234                                    if (httpMethod != null) {
1235                                            httpMethod.releaseConnection();
1236                                    }
1237                            }
1238                            catch (Exception e) {
1239                                    _log.error(e, e);
1240                            }
1241                    }
1242            }
1243    
1244            private static final String _DEFAULT_USER_AGENT =
1245                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
1246    
1247            private static final int _MAX_CONNECTIONS_PER_HOST = GetterUtil.getInteger(
1248                    PropsUtil.get(HttpImpl.class.getName() + ".max.connections.per.host"),
1249                    2);
1250    
1251            private static final int _MAX_TOTAL_CONNECTIONS = GetterUtil.getInteger(
1252                    PropsUtil.get(HttpImpl.class.getName() + ".max.total.connections"), 20);
1253    
1254            private static final String _NON_PROXY_HOSTS = SystemProperties.get(
1255                    "http.nonProxyHosts");
1256    
1257            private static final String _PROXY_AUTH_TYPE = GetterUtil.getString(
1258                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.auth.type"));
1259    
1260            private static final String _PROXY_HOST = GetterUtil.getString(
1261                    SystemProperties.get("http.proxyHost"));
1262    
1263            private static final String _PROXY_NTLM_DOMAIN = GetterUtil.getString(
1264                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.ntlm.domain"));
1265    
1266            private static final String _PROXY_NTLM_HOST = GetterUtil.getString(
1267                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.ntlm.host"));
1268    
1269            private static final String _PROXY_PASSWORD = GetterUtil.getString(
1270                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.password"));
1271    
1272            private static final int _PROXY_PORT = GetterUtil.getInteger(
1273                    SystemProperties.get("http.proxyPort"));
1274    
1275            private static final String _PROXY_USERNAME = GetterUtil.getString(
1276                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.username"));
1277    
1278            private static final String _TEMP_SLASH = "_LIFERAY_TEMP_SLASH_";
1279    
1280            private static final int _TIMEOUT = GetterUtil.getInteger(
1281                    PropsUtil.get(HttpImpl.class.getName() + ".timeout"), 5000);
1282    
1283            private static Log _log = LogFactoryUtil.getLog(HttpImpl.class);
1284    
1285            private static ThreadLocal<Cookie[]> _cookies = new ThreadLocal<Cookie[]>();
1286    
1287            private HttpClient _httpClient = new HttpClient();
1288            private Pattern _nonProxyHostsPattern;
1289            private Credentials _proxyCredentials;
1290            private HttpClient _proxyHttpClient = new HttpClient();
1291    
1292    }