1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.util;
24  
25  import com.liferay.portal.kernel.util.ByteArrayMaker;
26  import com.liferay.portal.kernel.util.GetterUtil;
27  import com.liferay.portal.kernel.util.StringMaker;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.StringUtil;
30  import com.liferay.portal.kernel.util.Validator;
31  
32  import java.io.IOException;
33  import java.io.InputStream;
34  
35  import java.net.URL;
36  import java.net.URLConnection;
37  
38  import java.util.ArrayList;
39  import java.util.Iterator;
40  import java.util.List;
41  import java.util.Map;
42  import java.util.StringTokenizer;
43  import java.util.regex.Pattern;
44  
45  import javax.portlet.ActionRequest;
46  import javax.portlet.RenderRequest;
47  
48  import javax.servlet.http.HttpServletRequest;
49  
50  import org.apache.commons.httpclient.Cookie;
51  import org.apache.commons.httpclient.Credentials;
52  import org.apache.commons.httpclient.Header;
53  import org.apache.commons.httpclient.HostConfiguration;
54  import org.apache.commons.httpclient.HttpClient;
55  import org.apache.commons.httpclient.HttpMethod;
56  import org.apache.commons.httpclient.HttpState;
57  import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
58  import org.apache.commons.httpclient.NTCredentials;
59  import org.apache.commons.httpclient.NameValuePair;
60  import org.apache.commons.httpclient.URI;
61  import org.apache.commons.httpclient.UsernamePasswordCredentials;
62  import org.apache.commons.httpclient.auth.AuthPolicy;
63  import org.apache.commons.httpclient.auth.AuthScope;
64  import org.apache.commons.httpclient.cookie.CookiePolicy;
65  import org.apache.commons.httpclient.methods.GetMethod;
66  import org.apache.commons.httpclient.methods.PostMethod;
67  import org.apache.commons.httpclient.params.HttpConnectionParams;
68  import org.apache.commons.logging.Log;
69  import org.apache.commons.logging.LogFactory;
70  
71  /**
72   * <a href="Http.java.html"><b><i>View Source</i></b></a>
73   *
74   * @author Brian Wing Shun Chan
75   *
76   */
77  public class Http {
78  
79      public static final String HTTP = "http";
80  
81      public static final String HTTPS = "https";
82  
83      public static final String HTTP_WITH_SLASH = "http://";
84  
85      public static final String HTTPS_WITH_SLASH = "https://";
86  
87      public static final int HTTP_PORT = 80;
88  
89      public static final int HTTPS_PORT = 443;
90  
91      public static final String LIFERAY_PROXY_HOST = GetterUtil.getString(
92          SystemProperties.get(Http.class.getName() + ".proxy.host"));
93  
94      public static final int LIFERAY_PROXY_PORT = GetterUtil.getInteger(
95          SystemProperties.get(Http.class.getName() + ".proxy.port"));
96  
97      private static final int MAX_CONNECTIONS_PER_HOST = GetterUtil.getInteger(
98          SystemProperties.get(
99              Http.class.getName() + ".max.connections.per.host"),
100         2);
101 
102     private static final int MAX_TOTAL_CONNECTIONS = GetterUtil.getInteger(
103         SystemProperties.get(Http.class.getName() + ".max.total.connections"),
104         20);
105 
106     public static final String PROXY_HOST = GetterUtil.getString(
107         SystemProperties.get("http.proxyHost"), LIFERAY_PROXY_HOST);
108 
109     public static final int PROXY_PORT = GetterUtil.getInteger(
110         SystemProperties.get("http.proxyPort"), LIFERAY_PROXY_PORT);
111 
112     public static final String NON_PROXY_HOSTS =
113         SystemProperties.get("http.nonProxyHosts");
114 
115     public static final String PROXY_AUTH_TYPE = GetterUtil.getString(
116         SystemProperties.get(Http.class.getName() + ".proxy.auth.type"));
117 
118     public static final String PROXY_USERNAME = GetterUtil.getString(
119         SystemProperties.get(Http.class.getName() + ".proxy.username"));
120 
121     public static final String PROXY_PASSWORD = GetterUtil.getString(
122         SystemProperties.get(Http.class.getName() + ".proxy.password"));
123 
124     public static final String PROXY_NTLM_DOMAIN = GetterUtil.getString(
125         SystemProperties.get(Http.class.getName() + ".proxy.ntlm.domain"));
126 
127     public static final String PROXY_NTLM_HOST = GetterUtil.getString(
128         SystemProperties.get(Http.class.getName() + ".proxy.ntlm.host"));
129 
130     public static final int TIMEOUT = GetterUtil.getInteger(
131         SystemProperties.get(Http.class.getName() + ".timeout"), 5000);
132 
133     public static String addParameter(String url, String name, boolean value) {
134         return addParameter(url, name, String.valueOf(value));
135     }
136 
137     public static String addParameter(String url, String name, double value) {
138         return addParameter(url, name, String.valueOf(value));
139     }
140 
141     public static String addParameter(String url, String name, int value) {
142         return addParameter(url, name, String.valueOf(value));
143     }
144 
145     public static String addParameter(String url, String name, long value) {
146         return addParameter(url, name, String.valueOf(value));
147     }
148 
149     public static String addParameter(String url, String name, short value) {
150         return addParameter(url, name, String.valueOf(value));
151     }
152 
153     public static String addParameter(String url, String name, String value) {
154         if (url == null) {
155             return null;
156         }
157 
158         if (url.indexOf(StringPool.QUESTION) == -1) {
159             url += StringPool.QUESTION;
160         }
161 
162         if (!url.endsWith(StringPool.QUESTION) &&
163             !url.endsWith(StringPool.AMPERSAND)) {
164 
165             url += StringPool.AMPERSAND;
166         }
167 
168         return url + name + StringPool.EQUAL + HttpUtil.encodeURL(value);
169     }
170 
171     /**
172      * @deprecated This method has been moved to
173      * <code>com.liferay.util.HttpUtil</code>.
174      */
175     public static String decodeURL(String url) {
176         return HttpUtil.decodeURL(url);
177     }
178 
179     /**
180      * @deprecated This method has been moved to
181      * <code>com.liferay.util.HttpUtil</code>.
182      */
183     public static String encodeURL(String url) {
184         return HttpUtil.encodeURL(url);
185     }
186 
187     public static HttpClient getClient(HostConfiguration hostConfig)
188         throws IOException {
189 
190         return _instance._getClient(hostConfig);
191     }
192 
193     public static String getCompleteURL(HttpServletRequest req) {
194         StringBuffer completeURL = req.getRequestURL();
195 
196         if (completeURL == null) {
197             completeURL = new StringBuffer();
198         }
199 
200         if (req.getQueryString() != null) {
201             completeURL.append(StringPool.QUESTION);
202             completeURL.append(req.getQueryString());
203         }
204 
205         return completeURL.toString();
206     }
207 
208     public static HostConfiguration getHostConfig(String location)
209         throws IOException {
210 
211         if (_log.isDebugEnabled()) {
212             _log.debug("Location is " + location);
213         }
214 
215         HostConfiguration hostConfig = new HostConfiguration();
216 
217         hostConfig.setHost(new URI(location, false));
218 
219         if (isProxyHost(hostConfig.getHost())) {
220             hostConfig.setProxy(PROXY_HOST, PROXY_PORT);
221         }
222 
223         return hostConfig;
224     }
225 
226     public static String getParameter(String url, String name) {
227         return getParameter(url, name, true);
228     }
229 
230     public static String getParameter(
231         String url, String name, boolean escaped) {
232 
233         if (Validator.isNull(url) || Validator.isNull(name)) {
234             return StringPool.BLANK;
235         }
236 
237         String[] parts = StringUtil.split(url, StringPool.QUESTION);
238 
239         if (parts.length == 2) {
240             String[] params = null;
241 
242             if (escaped) {
243                 params = StringUtil.split(parts[1], "&amp;");
244             }
245             else {
246                 params = StringUtil.split(parts[1], StringPool.AMPERSAND);
247             }
248 
249             for (int i = 0; i < params.length; i++) {
250                 String[] kvp = StringUtil.split(params[i], StringPool.EQUAL);
251 
252                 if ((kvp.length == 2) && kvp[0].equals(name)) {
253                     return kvp[1];
254                 }
255             }
256         }
257 
258         return StringPool.BLANK;
259     }
260 
261     /**
262      * @deprecated This method has been moved to
263      * <code>com.liferay.util.HttpUtil</code>.
264      */
265     public static Map getParameterMap(String queryString) {
266         return HttpUtil.parameterMapFromString(queryString);
267     }
268 
269     public static String getProtocol(boolean secure) {
270         if (!secure) {
271             return HTTP;
272         }
273         else {
274             return HTTPS;
275         }
276     }
277 
278     public static String getProtocol(HttpServletRequest req) {
279         return getProtocol(req.isSecure());
280     }
281 
282     public static String getProtocol(ActionRequest req) {
283         return getProtocol(req.isSecure());
284     }
285 
286     public static String getProtocol(RenderRequest req) {
287         return getProtocol(req.isSecure());
288     }
289 
290     public static String getQueryString(String url) {
291         if (Validator.isNull(url)) {
292             return url;
293         }
294 
295         int pos = url.indexOf(StringPool.QUESTION);
296 
297         if (pos == -1) {
298             return StringPool.BLANK;
299         }
300         else {
301             return url.substring(pos + 1, url.length());
302         }
303     }
304 
305     public static String getRequestURL(HttpServletRequest req) {
306         return req.getRequestURL().toString();
307     }
308 
309     public static boolean hasProxyConfig() {
310         if (Validator.isNotNull(PROXY_HOST) && (PROXY_PORT > 0)) {
311             return true;
312         }
313         else {
314             return false;
315         }
316     }
317 
318     public static boolean isNonProxyHost(String host) {
319         return _instance._isNonProxyHost(host);
320     }
321 
322     public static boolean isProxyHost(String host) {
323         if (hasProxyConfig() && !isNonProxyHost(host)) {
324             return true;
325         }
326         else {
327             return false;
328         }
329     }
330 
331     /**
332      * @deprecated This method has been moved to
333      * <code>com.liferay.util.HttpUtil</code>.
334      */
335     public static String parameterMapToString(Map parameterMap) {
336         return HttpUtil.parameterMapToString(parameterMap);
337     }
338 
339     /**
340      * @deprecated This method has been moved to
341      * <code>com.liferay.util.HttpUtil</code>.
342      */
343     public static String parameterMapToString(
344         Map parameterMap, boolean addQuestion) {
345 
346         return HttpUtil.parameterMapToString(parameterMap, addQuestion);
347     }
348 
349     public static String protocolize(String url, boolean secure) {
350         if (secure) {
351             if (url.startsWith(HTTP_WITH_SLASH)) {
352                 return StringUtil.replace(
353                     url, HTTP_WITH_SLASH, HTTPS_WITH_SLASH);
354             }
355         }
356         else {
357             if (url.startsWith(HTTPS_WITH_SLASH)) {
358                 return StringUtil.replace(
359                     url, HTTPS_WITH_SLASH, HTTP_WITH_SLASH);
360             }
361         }
362 
363         return url;
364     }
365 
366     public static String protocolize(String url, HttpServletRequest req) {
367         return protocolize(url, req.isSecure());
368     }
369 
370     public static String protocolize(String url, ActionRequest req) {
371         return protocolize(url, req.isSecure());
372     }
373 
374     public static String protocolize(String url, RenderRequest req) {
375         return protocolize(url, req.isSecure());
376     }
377 
378     public static void proxifyState(
379         HttpState state, HostConfiguration hostConfig) {
380 
381         Credentials proxyCredentials = _instance._proxyCredentials;
382 
383         String host = hostConfig.getHost();
384 
385         if (isProxyHost(host) && (proxyCredentials != null)) {
386             AuthScope scope = new AuthScope(PROXY_HOST, PROXY_PORT, null);
387 
388             state.setProxyCredentials(scope, proxyCredentials);
389         }
390     }
391 
392     public static String removeParameter(String url, String name) {
393         int pos = url.indexOf(StringPool.QUESTION);
394 
395         if (pos == -1) {
396             return url;
397         }
398 
399         StringMaker sm = new StringMaker();
400 
401         sm.append(url.substring(0, pos + 1));
402 
403         StringTokenizer st = new StringTokenizer(
404             url.substring(pos + 1, url.length()), StringPool.AMPERSAND);
405 
406         while (st.hasMoreTokens()) {
407             String token = st.nextToken();
408 
409             if (Validator.isNotNull(token)) {
410                 String[] kvp = StringUtil.split(token, StringPool.EQUAL);
411 
412                 String key = kvp[0];
413 
414                 String value = StringPool.BLANK;
415 
416                 if (kvp.length > 1) {
417                     value = kvp[1];
418                 }
419 
420                 if (!key.equals(name)) {
421                     sm.append(key);
422                     sm.append(StringPool.EQUAL);
423                     sm.append(value);
424                     sm.append(StringPool.AMPERSAND);
425                 }
426             }
427         }
428 
429         url = StringUtil.replace(
430             sm.toString(), StringPool.AMPERSAND + StringPool.AMPERSAND,
431             StringPool.AMPERSAND);
432 
433         return url;
434     }
435 
436     public static String removeProtocol(String url) {
437         if (url.startsWith(HTTP_WITH_SLASH)) {
438             return url.substring(HTTP_WITH_SLASH.length() , url.length());
439         }
440         else if (url.startsWith(HTTPS_WITH_SLASH)) {
441             return url.substring(HTTPS_WITH_SLASH.length() , url.length());
442         }
443         else {
444             return url;
445         }
446     }
447 
448     public static void submit(String location) throws IOException {
449         submit(location, null);
450     }
451 
452     public static void submit(String location, Cookie[] cookies)
453         throws IOException {
454 
455         submit(location, cookies, false);
456     }
457 
458     public static void submit(String location, boolean post)
459         throws IOException {
460 
461         submit(location, null, post);
462     }
463 
464     public static void submit(
465             String location, Cookie[] cookies, boolean post)
466         throws IOException {
467 
468         URLtoByteArray(location, cookies, post);
469     }
470 
471     public static void submit(
472             String location, Cookie[] cookies, Map parts, boolean post)
473         throws IOException {
474 
475         URLtoByteArray(location, cookies, parts, post);
476     }
477 
478     public static byte[] URLtoByteArray(String location)
479         throws IOException {
480 
481         return URLtoByteArray(location, null);
482     }
483 
484     public static byte[] URLtoByteArray(String location, Cookie[] cookies)
485         throws IOException {
486 
487         return URLtoByteArray(location, cookies, false);
488     }
489 
490     public static byte[] URLtoByteArray(String location, boolean post)
491         throws IOException {
492 
493         return URLtoByteArray(location, null, post);
494     }
495 
496     public static byte[] URLtoByteArray(
497             String location, Cookie[] cookies, boolean post)
498         throws IOException {
499 
500         return URLtoByteArray(location, cookies, null, post);
501     }
502 
503     public static byte[] URLtoByteArray(
504             String location, Cookie[] cookies, Map parts, boolean post)
505         throws IOException {
506 
507         byte[] byteArray = null;
508 
509         HttpMethod method = null;
510 
511         try {
512             if (location == null) {
513                 return byteArray;
514             }
515             else if (!location.startsWith(HTTP_WITH_SLASH) &&
516                      !location.startsWith(HTTPS_WITH_SLASH)) {
517 
518                 location = HTTP_WITH_SLASH + location;
519             }
520 
521             HostConfiguration hostConfig = getHostConfig(location);
522 
523             HttpClient client = getClient(hostConfig);
524 
525             if (post) {
526                 method = new PostMethod(location);
527 
528                 if ((parts != null) && (parts.size() > 0)) {
529                     List nvpList = new ArrayList();
530 
531                     Iterator itr = parts.entrySet().iterator();
532 
533                     while (itr.hasNext()) {
534                         Map.Entry entry = (Map.Entry)itr.next();
535 
536                         String key = (String)entry.getKey();
537                         String value = (String)entry.getValue();
538 
539                         if (value != null) {
540                             nvpList.add(new NameValuePair(key, value));
541                         }
542                     }
543 
544                     NameValuePair[] nvpArray = (NameValuePair[])nvpList.toArray(
545                         new NameValuePair[nvpList.size()]);
546 
547                     PostMethod postMethod = (PostMethod)method;
548 
549                     postMethod.setRequestBody(nvpArray);
550                 }
551             }
552             else {
553                 method = new GetMethod(location);
554             }
555 
556             method.addRequestHeader(
557                 "Content-Type", "application/x-www-form-urlencoded");
558 
559             method.addRequestHeader(
560                 "User-agent",
561                 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
562 
563             //method.setFollowRedirects(true);
564 
565             HttpState state = new HttpState();
566 
567             if ((cookies != null) && (cookies.length > 0)) {
568                 state.addCookies(cookies);
569 
570                 method.getParams().setCookiePolicy(
571                     CookiePolicy.BROWSER_COMPATIBILITY);
572             }
573 
574             proxifyState(state, hostConfig);
575 
576             client.executeMethod(hostConfig, method, state);
577 
578             Header locationHeader = method.getResponseHeader("location");
579 
580             if (locationHeader != null) {
581                 return URLtoByteArray(locationHeader.getValue(), cookies, post);
582             }
583 
584             InputStream is = method.getResponseBodyAsStream();
585 
586             if (is != null) {
587                 ByteArrayMaker bam = new ByteArrayMaker();
588                 byte[] bytes = new byte[512];
589 
590                 for (int i = is.read(bytes, 0, 512); i != -1;
591                         i = is.read(bytes, 0, 512)) {
592 
593                     bam.write(bytes, 0, i);
594                 }
595 
596                 byteArray = bam.toByteArray();
597 
598                 is.close();
599                 bam.close();
600             }
601 
602             return byteArray;
603         }
604         finally {
605             try {
606                 if (method != null) {
607                     method.releaseConnection();
608                 }
609             }
610             catch (Exception e) {
611                 _log.error(e, e);
612             }
613         }
614     }
615 
616     public static String URLtoString(String location)
617         throws IOException {
618 
619         return URLtoString(location, null);
620     }
621 
622     public static String URLtoString(String location, Cookie[] cookies)
623         throws IOException {
624 
625         return URLtoString(location, cookies, false);
626     }
627 
628     public static String URLtoString(String location, boolean post)
629         throws IOException {
630 
631         return URLtoString(location, null, post);
632     }
633 
634     public static String URLtoString(
635             String location, Cookie[] cookies, boolean post)
636         throws IOException {
637 
638         return new String(URLtoByteArray(location, cookies, post));
639     }
640 
641     public static String URLtoString(
642             String location, Cookie[] cookies, Map parts, boolean post)
643         throws IOException {
644 
645         return new String(URLtoByteArray(location, cookies, parts, post));
646     }
647 
648     /**
649      * This method only uses the default Commons HttpClient implementation when
650      * the URL object represents a HTTP resource. The URL object could also
651      * represent a file or some JNDI resource. In that case, the default Java
652      * implementation is used.
653      *
654      * @param       url URL object
655      * @return      A string representation of the resource referenced by the
656      *              URL object
657      * @throws      IOException
658      */
659     public static String URLtoString(URL url) throws IOException {
660         String xml = null;
661 
662         if (url != null) {
663             String protocol = url.getProtocol().toLowerCase();
664 
665             if (protocol.startsWith(HTTP) || protocol.startsWith(HTTPS)) {
666                 return URLtoString(url.toString());
667             }
668 
669             URLConnection con = url.openConnection();
670 
671             InputStream is = con.getInputStream();
672 
673             ByteArrayMaker bam = new ByteArrayMaker();
674             byte[] bytes = new byte[512];
675 
676             for (int i = is.read(bytes, 0, 512); i != -1;
677                     i = is.read(bytes, 0, 512)) {
678 
679                 bam.write(bytes, 0, i);
680             }
681 
682             xml = new String(bam.toByteArray());
683 
684             is.close();
685             bam.close();
686         }
687 
688         return xml;
689     }
690 
691     private Http() {
692 
693         // Mimic behavior found in
694         // http://java.sun.com/j2se/1.5.0/docs/guide/net/properties.html
695 
696         if (Validator.isNotNull(NON_PROXY_HOSTS)) {
697             String nonProxyHostsRegEx = NON_PROXY_HOSTS;
698 
699             nonProxyHostsRegEx = nonProxyHostsRegEx.replaceAll(
700                 "\\.", "\\\\.");
701             nonProxyHostsRegEx = nonProxyHostsRegEx.replaceAll(
702                 "\\*", ".*?");
703             nonProxyHostsRegEx = nonProxyHostsRegEx.replaceAll(
704                 "\\|", ")|(");
705 
706             nonProxyHostsRegEx = "(" + nonProxyHostsRegEx + ")";
707 
708             _nonProxyHostsPattern = Pattern.compile(nonProxyHostsRegEx);
709         }
710 
711         MultiThreadedHttpConnectionManager connectionManager =
712             new MultiThreadedHttpConnectionManager();
713 
714         HttpConnectionParams params = connectionManager.getParams();
715 
716         params.setParameter(
717             "maxConnectionsPerHost", new Integer(MAX_CONNECTIONS_PER_HOST));
718         params.setParameter(
719             "maxTotalConnections", new Integer(MAX_TOTAL_CONNECTIONS));
720         params.setConnectionTimeout(TIMEOUT);
721         params.setSoTimeout(TIMEOUT);
722 
723         _client.setHttpConnectionManager(connectionManager);
724         _proxyClient.setHttpConnectionManager(connectionManager);
725 
726         if (hasProxyConfig() && Validator.isNotNull(PROXY_USERNAME)) {
727             if (PROXY_AUTH_TYPE.equals("username-password")) {
728                 _proxyCredentials = new UsernamePasswordCredentials(
729                     PROXY_USERNAME, PROXY_PASSWORD);
730             }
731             else if (PROXY_AUTH_TYPE.equals("ntlm")) {
732                 _proxyCredentials = new NTCredentials(
733                     PROXY_USERNAME, PROXY_PASSWORD, PROXY_NTLM_HOST,
734                     PROXY_NTLM_DOMAIN);
735 
736                 List authPrefs = new ArrayList();
737 
738                 authPrefs.add(AuthPolicy.NTLM);
739                 authPrefs.add(AuthPolicy.BASIC);
740                 authPrefs.add(AuthPolicy.DIGEST);
741 
742                 _proxyClient.getParams().setParameter(
743                     AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
744             }
745         }
746     }
747 
748     private HttpClient _getClient(HostConfiguration hostConfig)
749         throws IOException {
750 
751         if (isProxyHost(hostConfig.getHost())) {
752             return _proxyClient;
753         }
754         else {
755             return _client;
756         }
757     }
758 
759     private boolean _isNonProxyHost(String host) {
760         if (_nonProxyHostsPattern == null ||
761             _nonProxyHostsPattern.matcher(host).matches()) {
762 
763             return true;
764         }
765         else {
766             return false;
767         }
768     }
769 
770     private static Log _log = LogFactory.getLog(Http.class);
771 
772     private static Http _instance = new Http();
773 
774     private HttpClient _client = new HttpClient();
775     private HttpClient _proxyClient = new HttpClient();
776     private Credentials _proxyCredentials;
777     private Pattern _nonProxyHostsPattern;
778 
779 }