001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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             * @return A string representation of the resource referenced by the URL
896             *         object
897             */
898            public String URLtoString(URL url) throws IOException {
899                    String xml = null;
900    
901                    if (url != null) {
902                            String protocol = url.getProtocol().toLowerCase();
903    
904                            if (protocol.startsWith(Http.HTTP) ||
905                                    protocol.startsWith(Http.HTTPS)) {
906    
907                                    return URLtoString(url.toString());
908                            }
909    
910                            URLConnection urlConnection = url.openConnection();
911    
912                            InputStream inputStream = urlConnection.getInputStream();
913    
914                            UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
915                                    new UnsyncByteArrayOutputStream();
916    
917                            byte[] bytes = new byte[512];
918    
919                            for (int i = inputStream.read(bytes, 0, 512); i != -1;
920                                            i = inputStream.read(bytes, 0, 512)) {
921    
922                                    unsyncByteArrayOutputStream.write(bytes, 0, i);
923                            }
924    
925                            xml = new String(
926                                    unsyncByteArrayOutputStream.unsafeGetByteArray(), 0,
927                                    unsyncByteArrayOutputStream.size());
928    
929                            inputStream.close();
930    
931                            unsyncByteArrayOutputStream.close();
932                    }
933    
934                    return xml;
935            }
936    
937            protected boolean hasRequestHeader(HttpMethod httpMethod, String name) {
938                    Header[] headers = httpMethod.getRequestHeaders(name);
939    
940                    if (headers.length == 0) {
941                            return false;
942                    }
943                    else {
944                            return true;
945                    }
946            }
947    
948            protected void processPostMethod(
949                    PostMethod postMethod, List<Http.FilePart> fileParts,
950                    Map<String, String> parts) {
951    
952                    if ((fileParts == null) || fileParts.isEmpty()) {
953                            if (parts != null) {
954                                    for (Map.Entry<String, String> entry : parts.entrySet()) {
955                                            String value = entry.getValue();
956    
957                                            if (value != null) {
958                                                    postMethod.addParameter(entry.getKey(), value);
959                                            }
960                                    }
961                            }
962                    }
963                    else {
964                            List<Part> partsList = new ArrayList<Part>();
965    
966                            if (parts != null) {
967                                    for (Map.Entry<String, String> entry : parts.entrySet()) {
968                                            String value = entry.getValue();
969    
970                                            if (value != null) {
971                                                    StringPart stringPart = new StringPart(
972                                                            entry.getKey(), value);
973    
974                                                    partsList.add(stringPart);
975                                            }
976                                    }
977                            }
978    
979                            for (Http.FilePart filePart : fileParts) {
980                                    partsList.add(toCommonsFilePart(filePart));
981                            }
982    
983                            MultipartRequestEntity multipartRequestEntity =
984                                    new MultipartRequestEntity(
985                                            partsList.toArray(new Part[partsList.size()]),
986                                            postMethod.getParams());
987    
988                            postMethod.setRequestEntity(multipartRequestEntity);
989                    }
990            }
991    
992            protected org.apache.commons.httpclient.Cookie toCommonsCookie(
993                    Cookie cookie) {
994    
995                    org.apache.commons.httpclient.Cookie commonsCookie =
996                            new org.apache.commons.httpclient.Cookie(
997                            cookie.getDomain(), cookie.getName(), cookie.getValue(),
998                            cookie.getPath(), cookie.getMaxAge(), cookie.getSecure());
999    
1000                    commonsCookie.setVersion(cookie.getVersion());
1001    
1002                    return commonsCookie;
1003            }
1004    
1005            protected org.apache.commons.httpclient.Cookie[] toCommonsCookies(
1006                    Cookie[] cookies) {
1007    
1008                    if (cookies == null) {
1009                            return null;
1010                    }
1011    
1012                    org.apache.commons.httpclient.Cookie[] commonCookies =
1013                            new org.apache.commons.httpclient.Cookie[cookies.length];
1014    
1015                    for (int i = 0; i < cookies.length; i++) {
1016                            commonCookies[i] = toCommonsCookie(cookies[i]);
1017                    }
1018    
1019                    return commonCookies;
1020            }
1021    
1022            protected org.apache.commons.httpclient.methods.multipart.FilePart
1023                    toCommonsFilePart(Http.FilePart filePart) {
1024    
1025                    return new org.apache.commons.httpclient.methods.multipart.FilePart(
1026                            filePart.getName(),
1027                            new ByteArrayPartSource(
1028                                    filePart.getFileName(), filePart.getValue()),
1029                            filePart.getContentType(), filePart.getCharSet());
1030            }
1031    
1032            protected Cookie toServletCookie(
1033                    org.apache.commons.httpclient.Cookie commonsCookie) {
1034    
1035                    Cookie cookie = new Cookie(
1036                            commonsCookie.getName(), commonsCookie.getValue());
1037    
1038                    String domain = commonsCookie.getDomain();
1039    
1040                    if (Validator.isNotNull(domain)) {
1041                            cookie.setDomain(domain);
1042                    }
1043    
1044                    Date expiryDate = commonsCookie.getExpiryDate();
1045    
1046                    if (expiryDate != null) {
1047                            int maxAge =
1048                                    (int)(expiryDate.getTime() - System.currentTimeMillis());
1049    
1050                            maxAge = maxAge / 1000;
1051    
1052                            if (maxAge > -1) {
1053                                    cookie.setMaxAge(maxAge);
1054                            }
1055                    }
1056    
1057                    String path = commonsCookie.getPath();
1058    
1059                    if (Validator.isNotNull(path)) {
1060                            cookie.setPath(path);
1061                    }
1062    
1063                    cookie.setSecure(commonsCookie.getSecure());
1064                    cookie.setVersion(commonsCookie.getVersion());
1065    
1066                    return cookie;
1067            }
1068    
1069            protected Cookie[] toServletCookies(
1070                    org.apache.commons.httpclient.Cookie[] commonsCookies) {
1071    
1072                    if (commonsCookies == null) {
1073                            return null;
1074                    }
1075    
1076                    Cookie[] cookies = new Cookie[commonsCookies.length];
1077    
1078                    for (int i = 0; i < commonsCookies.length; i++) {
1079                            cookies[i] = toServletCookie(commonsCookies[i]);
1080                    }
1081    
1082                    return cookies;
1083            }
1084    
1085            protected byte[] URLtoByteArray(
1086                            String location, Http.Method method, Map<String, String> headers,
1087                            Cookie[] cookies, Http.Auth auth, Http.Body body,
1088                            List<Http.FilePart> fileParts, Map<String, String> parts,
1089                            Http.Response response, boolean followRedirects)
1090                    throws IOException {
1091    
1092                    byte[] bytes = null;
1093    
1094                    HttpMethod httpMethod = null;
1095                    HttpState httpState = null;
1096    
1097                    try {
1098                            _cookies.set(null);
1099    
1100                            if (location == null) {
1101                                    return null;
1102                            }
1103                            else if (!location.startsWith(Http.HTTP_WITH_SLASH) &&
1104                                             !location.startsWith(Http.HTTPS_WITH_SLASH)) {
1105    
1106                                    location = Http.HTTP_WITH_SLASH + location;
1107                            }
1108    
1109                            HostConfiguration hostConfiguration = getHostConfiguration(
1110                                    location);
1111    
1112                            HttpClient httpClient = getClient(hostConfiguration);
1113    
1114                            if (method.equals(Http.Method.POST) ||
1115                                    method.equals(Http.Method.PUT)) {
1116    
1117                                    if (method.equals(Http.Method.POST)) {
1118                                            httpMethod = new PostMethod(location);
1119                                    }
1120                                    else {
1121                                            httpMethod = new PutMethod(location);
1122                                    }
1123    
1124                                    if (body != null) {
1125                                            RequestEntity requestEntity = new StringRequestEntity(
1126                                                    body.getContent(), body.getContentType(),
1127                                                    body.getCharset());
1128    
1129                                            EntityEnclosingMethod entityEnclosingMethod =
1130                                                    (EntityEnclosingMethod)httpMethod;
1131    
1132                                            entityEnclosingMethod.setRequestEntity(requestEntity);
1133                                    }
1134                                    else if (method.equals(Http.Method.POST)) {
1135                                            PostMethod postMethod = (PostMethod)httpMethod;
1136    
1137                                            processPostMethod(postMethod, fileParts, parts);
1138                                    }
1139                            }
1140                            else if (method.equals(Http.Method.DELETE)) {
1141                                    httpMethod = new DeleteMethod(location);
1142                            }
1143                            else if (method.equals(Http.Method.HEAD)) {
1144                                    httpMethod = new HeadMethod(location);
1145                            }
1146                            else {
1147                                    httpMethod = new GetMethod(location);
1148                            }
1149    
1150                            if (headers != null) {
1151                                    for (Map.Entry<String, String> header : headers.entrySet()) {
1152                                            httpMethod.addRequestHeader(
1153                                                    header.getKey(), header.getValue());
1154                                    }
1155                            }
1156    
1157                            if ((method.equals(Http.Method.POST) ||
1158                                     method.equals(Http.Method.PUT)) &&
1159                                    ((body != null) ||
1160                                     ((fileParts != null) && !fileParts.isEmpty()) |
1161                                     ((parts != null) && !parts.isEmpty()))) {
1162                            }
1163                            else if (!hasRequestHeader(httpMethod, HttpHeaders.CONTENT_TYPE)) {
1164                                    httpMethod.addRequestHeader(
1165                                            HttpHeaders.CONTENT_TYPE,
1166                                            ContentTypes.APPLICATION_X_WWW_FORM_URLENCODED);
1167                            }
1168    
1169                            if (!hasRequestHeader(httpMethod, HttpHeaders.USER_AGENT)) {
1170                                    httpMethod.addRequestHeader(
1171                                            HttpHeaders.USER_AGENT, _DEFAULT_USER_AGENT);
1172                            }
1173    
1174                            httpState = new HttpState();
1175    
1176                            if ((cookies != null) && (cookies.length > 0)) {
1177                                    org.apache.commons.httpclient.Cookie[] commonsCookies =
1178                                            toCommonsCookies(cookies);
1179    
1180                                    httpState.addCookies(commonsCookies);
1181    
1182                                    HttpMethodParams httpMethodParams = httpMethod.getParams();
1183    
1184                                    httpMethodParams.setCookiePolicy(
1185                                            CookiePolicy.BROWSER_COMPATIBILITY);
1186                            }
1187    
1188                            if (auth != null) {
1189                                    httpMethod.setDoAuthentication(true);
1190    
1191                                    httpState.setCredentials(
1192                                            new AuthScope(
1193                                                    auth.getHost(), auth.getPort(), auth.getRealm()),
1194                                            new UsernamePasswordCredentials(
1195                                                    auth.getUsername(), auth.getPassword()));
1196                            }
1197    
1198                            proxifyState(httpState, hostConfiguration);
1199    
1200                            boolean checkReadFileDescriptor =
1201                                    PortalSecurityManagerThreadLocal.isCheckReadFileDescriptor();
1202                            boolean checkWriteFileDescriptor =
1203                                    PortalSecurityManagerThreadLocal.isCheckWriteFileDescriptor();
1204    
1205                            try {
1206                                    PortalSecurityManagerThreadLocal.setCheckReadFileDescriptor(
1207                                            false);
1208                                    PortalSecurityManagerThreadLocal.setCheckWriteFileDescriptor(
1209                                            false);
1210    
1211                                    httpClient.executeMethod(
1212                                            hostConfiguration, httpMethod, httpState);
1213                            }
1214                            finally {
1215                                    PortalSecurityManagerThreadLocal.setCheckReadFileDescriptor(
1216                                            checkReadFileDescriptor);
1217                                    PortalSecurityManagerThreadLocal.setCheckWriteFileDescriptor(
1218                                            checkWriteFileDescriptor);
1219                            }
1220    
1221                            Header locationHeader = httpMethod.getResponseHeader("location");
1222    
1223                            if ((locationHeader != null) && !locationHeader.equals(location)) {
1224                                    String redirect = locationHeader.getValue();
1225    
1226                                    if (followRedirects) {
1227                                            return URLtoByteArray(
1228                                                    redirect, Http.Method.GET, headers, cookies, auth, body,
1229                                                    fileParts, parts, response, followRedirects);
1230                                    }
1231                                    else {
1232                                            response.setRedirect(redirect);
1233                                    }
1234                            }
1235    
1236                            InputStream inputStream = httpMethod.getResponseBodyAsStream();
1237    
1238                            if (inputStream != null) {
1239                                    Header contentLength = httpMethod.getResponseHeader(
1240                                            HttpHeaders.CONTENT_LENGTH);
1241    
1242                                    if (contentLength != null) {
1243                                            response.setContentLength(
1244                                                    GetterUtil.getInteger(contentLength.getValue()));
1245                                    }
1246    
1247                                    Header contentType = httpMethod.getResponseHeader(
1248                                            HttpHeaders.CONTENT_TYPE);
1249    
1250                                    if (contentType != null) {
1251                                            response.setContentType(contentType.getValue());
1252                                    }
1253    
1254                                    bytes = FileUtil.getBytes(inputStream);
1255                            }
1256    
1257                            for (Header header : httpMethod.getResponseHeaders()) {
1258                                    response.addHeader(header.getName(), header.getValue());
1259                            }
1260    
1261                            return bytes;
1262                    }
1263                    finally {
1264                            try {
1265                                    if (httpState != null) {
1266                                            _cookies.set(toServletCookies(httpState.getCookies()));
1267                                    }
1268                            }
1269                            catch (Exception e) {
1270                                    _log.error(e, e);
1271                            }
1272    
1273                            try {
1274                                    if (httpMethod != null) {
1275                                            httpMethod.releaseConnection();
1276                                    }
1277                            }
1278                            catch (Exception e) {
1279                                    _log.error(e, e);
1280                            }
1281                    }
1282            }
1283    
1284            private static final String _DEFAULT_USER_AGENT =
1285                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
1286    
1287            private static final int _MAX_CONNECTIONS_PER_HOST = GetterUtil.getInteger(
1288                    PropsUtil.get(HttpImpl.class.getName() + ".max.connections.per.host"),
1289                    2);
1290    
1291            private static final int _MAX_TOTAL_CONNECTIONS = GetterUtil.getInteger(
1292                    PropsUtil.get(HttpImpl.class.getName() + ".max.total.connections"), 20);
1293    
1294            private static final String _NON_PROXY_HOSTS = SystemProperties.get(
1295                    "http.nonProxyHosts");
1296    
1297            private static final String _PROXY_AUTH_TYPE = GetterUtil.getString(
1298                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.auth.type"));
1299    
1300            private static final String _PROXY_HOST = GetterUtil.getString(
1301                    SystemProperties.get("http.proxyHost"));
1302    
1303            private static final String _PROXY_NTLM_DOMAIN = GetterUtil.getString(
1304                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.ntlm.domain"));
1305    
1306            private static final String _PROXY_NTLM_HOST = GetterUtil.getString(
1307                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.ntlm.host"));
1308    
1309            private static final String _PROXY_PASSWORD = GetterUtil.getString(
1310                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.password"));
1311    
1312            private static final int _PROXY_PORT = GetterUtil.getInteger(
1313                    SystemProperties.get("http.proxyPort"));
1314    
1315            private static final String _PROXY_USERNAME = GetterUtil.getString(
1316                    PropsUtil.get(HttpImpl.class.getName() + ".proxy.username"));
1317    
1318            private static final String _TEMP_SLASH = "_LIFERAY_TEMP_SLASH_";
1319    
1320            private static final int _TIMEOUT = GetterUtil.getInteger(
1321                    PropsUtil.get(HttpImpl.class.getName() + ".timeout"), 5000);
1322    
1323            private static Log _log = LogFactoryUtil.getLog(HttpImpl.class);
1324    
1325            private static ThreadLocal<Cookie[]> _cookies = new ThreadLocal<Cookie[]>();
1326    
1327            private HttpClient _httpClient = new HttpClient();
1328            private Pattern _nonProxyHostsPattern;
1329            private Credentials _proxyCredentials;
1330            private HttpClient _proxyHttpClient = new HttpClient();
1331    
1332            private class FastProtocolSocketFactory
1333                    extends DefaultProtocolSocketFactory {
1334    
1335                    @Override
1336                    public Socket createSocket(
1337                                    final String host, final int port,
1338                                    final InetAddress localInetAddress, final int localPort,
1339                                    final HttpConnectionParams httpConnectionParams)
1340                            throws ConnectTimeoutException, IOException, UnknownHostException {
1341    
1342                            int connectionTimeout = httpConnectionParams.getConnectionTimeout();
1343    
1344                            if (connectionTimeout == 0) {
1345                                    return createSocket(host, port, localInetAddress, localPort);
1346                            }
1347    
1348                            SocketFactory socketFactory = SocketFactory.getDefault();
1349    
1350                            Socket socket = socketFactory.createSocket();
1351    
1352                            SocketAddress localSocketAddress = new InetSocketAddress(
1353                                    localInetAddress, localPort);
1354    
1355                            SocketAddress remoteSocketAddress = new InetSocketAddress(
1356                                    host, port);
1357    
1358                            socket.bind(localSocketAddress);
1359    
1360                            socket.connect(remoteSocketAddress, connectionTimeout);
1361    
1362                            return socket;
1363                    }
1364    
1365            }
1366    
1367    }