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