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