View Javadoc

1   // ========================================================================
2   // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses.
12  // ========================================================================
13  
14  package org.eclipse.jetty.client;
15  
16  import java.io.ByteArrayInputStream;
17  import java.io.ByteArrayOutputStream;
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.net.UnknownHostException;
21  import java.security.KeyStore;
22  import java.security.SecureRandom;
23  import java.security.Security;
24  import java.util.Enumeration;
25  import java.util.LinkedList;
26  import java.util.Map;
27  import java.util.Set;
28  import java.util.concurrent.ConcurrentHashMap;
29  import java.util.concurrent.ConcurrentMap;
30  import javax.net.ssl.KeyManager;
31  import javax.net.ssl.KeyManagerFactory;
32  import javax.net.ssl.SSLContext;
33  import javax.net.ssl.TrustManager;
34  import javax.net.ssl.TrustManagerFactory;
35  import javax.net.ssl.X509TrustManager;
36  
37  import org.eclipse.jetty.client.security.Authentication;
38  import org.eclipse.jetty.client.security.RealmResolver;
39  import org.eclipse.jetty.client.security.SecurityListener;
40  import org.eclipse.jetty.http.HttpBuffers;
41  import org.eclipse.jetty.http.HttpSchemes;
42  import org.eclipse.jetty.http.security.Password;
43  import org.eclipse.jetty.io.Buffer;
44  import org.eclipse.jetty.io.ByteArrayBuffer;
45  import org.eclipse.jetty.io.nio.DirectNIOBuffer;
46  import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
47  import org.eclipse.jetty.util.Attributes;
48  import org.eclipse.jetty.util.AttributesMap;
49  import org.eclipse.jetty.util.component.LifeCycle;
50  import org.eclipse.jetty.util.log.Log;
51  import org.eclipse.jetty.util.resource.Resource;
52  import org.eclipse.jetty.util.thread.QueuedThreadPool;
53  import org.eclipse.jetty.util.thread.ThreadPool;
54  import org.eclipse.jetty.util.thread.Timeout;
55  
56  /**
57   * Http Client.
58   * <p/>
59   * HttpClient is the main active component of the client API implementation.
60   * It is the opposite of the Connectors in standard Jetty, in that it listens
61   * for responses rather than requests.   Just like the connectors, there is a
62   * blocking socket version and a non-blocking NIO version (implemented as nested classes
63   * selected by {@link #setConnectorType(int)}).
64   * <p/>
65   * The an instance of {@link HttpExchange} is passed to the {@link #send(HttpExchange)} method
66   * to send a request.  The exchange contains both the headers and content (source) of the request
67   * plus the callbacks to handle responses.   A HttpClient can have many exchanges outstanding
68   * and they may be queued on the {@link HttpDestination} waiting for a {@link HttpConnection},
69   * queued in the {@link HttpConnection} waiting to be transmitted or pipelined on the actual
70   * TCP/IP connection waiting for a response.
71   * <p/>
72   * The {@link HttpDestination} class is an aggregation of {@link HttpConnection}s for the
73   * same host, port and protocol.   A destination may limit the number of connections
74   * open and they provide a pool of open connections that may be reused.   Connections may also
75   * be allocated from a destination, so that multiple request sources are not multiplexed
76   * over the same connection.
77   *
78   * @see HttpExchange
79   * @see HttpDestination
80   */
81  public class HttpClient extends HttpBuffers implements Attributes
82  {
83      public static final int CONNECTOR_SOCKET = 0;
84      public static final int CONNECTOR_SELECT_CHANNEL = 2;
85  
86      private int _connectorType = CONNECTOR_SELECT_CHANNEL;
87      private boolean _useDirectBuffers = true;
88      private int _maxConnectionsPerAddress = Integer.MAX_VALUE;
89      private ConcurrentMap<Address, HttpDestination> _destinations = new ConcurrentHashMap<Address, HttpDestination>();
90      ThreadPool _threadPool;
91      Connector _connector;
92      private long _idleTimeout = 20000;
93      private long _timeout = 320000;
94      private int _connectTimeout = 75000;
95      private Timeout _timeoutQ = new Timeout();
96      private Timeout _idleTimeoutQ = new Timeout();
97      private Address _proxy;
98      private Authentication _proxyAuthentication;
99      private Set<String> _noProxy;
100     private int _maxRetries = 3;
101     private int _maxRedirects = 20;
102     private LinkedList<String> _registeredListeners;
103 
104     private String _keyStoreLocation;
105     private InputStream _keyStoreInputStream;
106     private String _keyStoreType = "JKS";
107     private String _keyStorePassword;
108     private String _keyManagerAlgorithm = (Security.getProperty("ssl.KeyManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.KeyManagerFactory.algorithm"));
109     private String _keyManagerPassword;
110     private String _trustStoreLocation;
111     private InputStream _trustStoreInputStream;
112     private String _trustStoreType = "JKS";
113     private String _trustStorePassword;
114     private String _trustManagerAlgorithm = (Security.getProperty("ssl.TrustManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.TrustManagerFactory.algorithm"));
115     private String _protocol = "TLS";
116     private String _provider;
117     private String _secureRandomAlgorithm;
118 
119     private SSLContext _sslContext;
120 
121     private RealmResolver _realmResolver;
122 
123     private AttributesMap _attributes=new AttributesMap();
124 
125     /* ------------------------------------------------------------------------------- */
126     public void dump()
127     {
128         try
129         {
130             for (Map.Entry<Address, HttpDestination> entry : _destinations.entrySet())
131             {
132                 Log.info("\n" + entry.getKey() + ":");
133                 entry.getValue().dump();
134             }
135         }
136         catch(Exception e)
137         {
138             Log.warn(e);
139         }
140     }
141 
142     /* ------------------------------------------------------------------------------- */
143     public void send(HttpExchange exchange) throws IOException
144     {
145         boolean ssl = HttpSchemes.HTTPS_BUFFER.equalsIgnoreCase(exchange.getScheme());
146         exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_CONNECTION);
147         HttpDestination destination = getDestination(exchange.getAddress(), ssl);
148         destination.send(exchange);
149     }
150 
151     /* ------------------------------------------------------------ */
152     /**
153      * @return the threadPool
154      */
155     public ThreadPool getThreadPool()
156     {
157         return _threadPool;
158     }
159 
160     /* ------------------------------------------------------------ */
161     /**
162      * @param threadPool the threadPool to set
163      */
164     public void setThreadPool(ThreadPool threadPool)
165     {
166         _threadPool = threadPool;
167     }
168 
169 
170     /* ------------------------------------------------------------ */
171     /**
172      * @param name
173      * @return Attribute associated with client
174      */
175     public Object getAttribute(String name)
176     {
177         return _attributes.getAttribute(name);
178     }
179 
180     /* ------------------------------------------------------------ */
181     /**
182      * @return names of attributes associated with client
183      */
184     public Enumeration getAttributeNames()
185     {
186         return _attributes.getAttributeNames();
187     }
188 
189     /* ------------------------------------------------------------ */
190     /**
191      * @param name
192      */
193     public void removeAttribute(String name)
194     {
195         _attributes.removeAttribute(name);
196     }
197 
198     /* ------------------------------------------------------------ */
199     /**
200      * Set an attribute on the HttpClient.
201      * Attributes are not used by the client, but are provided for
202      * so that users of a shared HttpClient may share other structures.
203      * @param name
204      * @param attribute
205      */
206     public void setAttribute(String name, Object attribute)
207     {
208         _attributes.setAttribute(name,attribute);
209     }
210 
211     /* ------------------------------------------------------------ */
212     public void clearAttributes()
213     {
214         _attributes.clearAttributes();
215     }
216 
217     /* ------------------------------------------------------------------------------- */
218     public HttpDestination getDestination(Address remote, boolean ssl) throws UnknownHostException, IOException
219     {
220         if (remote == null)
221             throw new UnknownHostException("Remote socket address cannot be null.");
222 
223         HttpDestination destination = _destinations.get(remote);
224         if (destination == null)
225         {
226             destination = new HttpDestination(this, remote, ssl, _maxConnectionsPerAddress);
227             if (_proxy != null && (_noProxy == null || !_noProxy.contains(remote.getHost())))
228             {
229                 destination.setProxy(_proxy);
230                 if (_proxyAuthentication != null)
231                     destination.setProxyAuthentication(_proxyAuthentication);
232             }
233             HttpDestination other =_destinations.putIfAbsent(remote, destination);
234             if (other!=null)
235                 destination=other;
236         }
237         return destination;
238     }
239 
240     /* ------------------------------------------------------------ */
241     public void schedule(Timeout.Task task)
242     {
243         _timeoutQ.schedule(task);
244     }
245 
246     public void schedule(Timeout.Task task, long timeout)
247     {
248         _timeoutQ.schedule(task, timeout);
249     }
250 
251     /* ------------------------------------------------------------ */
252     public void scheduleIdle(Timeout.Task task)
253     {
254         _idleTimeoutQ.schedule(task);
255     }
256 
257     /* ------------------------------------------------------------ */
258     public void cancel(Timeout.Task task)
259     {
260         task.cancel();
261     }
262 
263     /* ------------------------------------------------------------ */
264     /**
265      * Get whether the connector can use direct NIO buffers.
266      */
267     public boolean getUseDirectBuffers()
268     {
269         return _useDirectBuffers;
270     }
271 
272     /* ------------------------------------------------------------ */
273     /** Set a RealmResolver for client Authentication.
274      * If a realmResolver is set, then the HttpDestinations created by
275      * this client will instantiate a {@link SecurityListener} so that
276      * BASIC and DIGEST authentication can be performed.
277      * @param resolver
278      */
279     public void setRealmResolver(RealmResolver resolver)
280     {
281         _realmResolver = resolver;
282     }
283 
284     /* ------------------------------------------------------------ */
285     /**
286      * returns the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
287      *
288      * @return the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
289      */
290     public RealmResolver getRealmResolver()
291     {
292         return _realmResolver;
293     }
294 
295     /* ------------------------------------------------------------ */
296     public boolean hasRealms()
297     {
298         return _realmResolver == null ? false : true;
299     }
300 
301 
302     /**
303      * Registers a listener that can listen to the stream of execution between the client and the
304      * server and influence events.  Sequential calls to the method wrapper sequentially wrap the preceding
305      * listener in a delegation model.
306      * <p/>
307      * NOTE: the SecurityListener is a special listener which doesn't need to be added via this
308      * mechanic, if you register security realms then it will automatically be added as the top listener of the
309      * delegation stack.
310      *
311      * @param listenerClass
312      */
313     public void registerListener(String listenerClass)
314     {
315         if (_registeredListeners == null)
316         {
317             _registeredListeners = new LinkedList<String>();
318         }
319         _registeredListeners.add(listenerClass);
320     }
321 
322     /* ------------------------------------------------------------ */
323     public LinkedList<String> getRegisteredListeners()
324     {
325         return _registeredListeners;
326     }
327 
328 
329     /* ------------------------------------------------------------ */
330     /**
331      * Set to use NIO direct buffers.
332      *
333      * @param direct If True (the default), the connector can use NIO direct
334      *               buffers. Some JVMs have memory management issues (bugs) with
335      *               direct buffers.
336      */
337     public void setUseDirectBuffers(boolean direct)
338     {
339         _useDirectBuffers = direct;
340     }
341 
342     /* ------------------------------------------------------------ */
343     /**
344      * Get the type of connector (socket, blocking or select) in use.
345      */
346     public int getConnectorType()
347     {
348         return _connectorType;
349     }
350 
351     /* ------------------------------------------------------------ */
352     public void setConnectorType(int connectorType)
353     {
354         this._connectorType = connectorType;
355     }
356 
357     /* ------------------------------------------------------------ */
358     /**
359      * @see org.eclipse.jetty.http.HttpBuffers#newRequestBuffer(int)
360      */
361     @Override
362     protected Buffer newRequestBuffer(int size)
363     {
364         if (_connectorType == CONNECTOR_SOCKET)
365             return new ByteArrayBuffer(size);
366         return _useDirectBuffers?new DirectNIOBuffer(size):new IndirectNIOBuffer(size);
367     }
368 
369     /* ------------------------------------------------------------ */
370     /**
371      * @see org.eclipse.jetty.http.HttpBuffers#newRequestHeader(int)
372      */
373     @Override
374     protected Buffer newRequestHeader(int size)
375     {
376         if (_connectorType == CONNECTOR_SOCKET)
377             return new ByteArrayBuffer(size);
378         return new IndirectNIOBuffer(size);
379     }
380 
381     /* ------------------------------------------------------------ */
382     /**
383      * @see org.eclipse.jetty.http.HttpBuffers#newResponseBuffer(int)
384      */
385     @Override
386     protected Buffer newResponseBuffer(int size)
387     {
388         if (_connectorType == CONNECTOR_SOCKET)
389             return new ByteArrayBuffer(size);
390         return _useDirectBuffers?new DirectNIOBuffer(size):new IndirectNIOBuffer(size);
391     }
392 
393     /* ------------------------------------------------------------ */
394     /**
395      * @see org.eclipse.jetty.http.HttpBuffers#newResponseHeader(int)
396      */
397     @Override
398     protected Buffer newResponseHeader(int size)
399     {
400         if (_connectorType == CONNECTOR_SOCKET)
401             return new ByteArrayBuffer(size);
402         return new IndirectNIOBuffer(size);
403     }
404 
405     /* ------------------------------------------------------------------------------- */
406     @Override
407     protected boolean isRequestHeader(Buffer buffer)
408     {
409         if (_connectorType == CONNECTOR_SOCKET)
410             return buffer instanceof ByteArrayBuffer;
411         return buffer instanceof IndirectNIOBuffer;
412     }
413 
414     /* ------------------------------------------------------------------------------- */
415     @Override
416     protected boolean isResponseHeader(Buffer buffer)
417     {
418         if (_connectorType == CONNECTOR_SOCKET)
419             return buffer instanceof ByteArrayBuffer;
420         return buffer instanceof IndirectNIOBuffer;
421     }
422 
423 
424     /* ------------------------------------------------------------ */
425     public int getMaxConnectionsPerAddress()
426     {
427         return _maxConnectionsPerAddress;
428     }
429 
430     /* ------------------------------------------------------------ */
431     public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress)
432     {
433         _maxConnectionsPerAddress = maxConnectionsPerAddress;
434     }
435 
436     /* ------------------------------------------------------------ */
437     @Override
438     protected void doStart() throws Exception
439     {
440         super.doStart();
441 
442         _timeoutQ.setDuration(_timeout);
443         _timeoutQ.setNow();
444         _idleTimeoutQ.setDuration(_idleTimeout);
445         _idleTimeoutQ.setNow();
446 
447         if (_threadPool == null)
448         {
449             QueuedThreadPool pool = new QueuedThreadPool();
450             pool.setMaxThreads(16);
451             pool.setDaemon(true);
452             pool.setName("HttpClient");
453             _threadPool = pool;
454         }
455 
456         if (_threadPool instanceof LifeCycle)
457         {
458             ((LifeCycle)_threadPool).start();
459         }
460 
461 
462         if (_connectorType == CONNECTOR_SELECT_CHANNEL)
463         {
464 
465             _connector = new SelectConnector(this);
466         }
467         else
468         {
469             _connector = new SocketConnector(this);
470         }
471         _connector.start();
472 
473         _threadPool.dispatch(new Runnable()
474         {
475             public void run()
476             {
477                 while (isRunning())
478                 {
479                     _timeoutQ.tick(System.currentTimeMillis());
480                     _idleTimeoutQ.tick(_timeoutQ.getNow());
481                     try
482                     {
483                         Thread.sleep(200);
484                     }
485                     catch (InterruptedException e)
486                     {
487                     }
488                 }
489             }
490         });
491 
492     }
493 
494     /* ------------------------------------------------------------ */
495     long getNow()
496     {
497         return _timeoutQ.getNow();
498     }
499 
500     /* ------------------------------------------------------------ */
501     @Override
502     protected void doStop() throws Exception
503     {
504         _connector.stop();
505         _connector = null;
506         if (_threadPool instanceof LifeCycle)
507         {
508             ((LifeCycle)_threadPool).stop();
509         }
510         for (HttpDestination destination : _destinations.values())
511         {
512             destination.close();
513         }
514 
515         _timeoutQ.cancelAll();
516         _idleTimeoutQ.cancelAll();
517         super.doStop();
518     }
519 
520     /* ------------------------------------------------------------ */
521     interface Connector extends LifeCycle
522     {
523         public void startConnection(HttpDestination destination) throws IOException;
524     }
525 
526     /**
527      * if a keystore location has been provided then client will attempt to use it as the keystore,
528      * otherwise we simply ignore certificates and run with a loose ssl context.
529      *
530      * @return the SSL context
531      * @throws IOException
532      */
533     protected SSLContext getSSLContext() throws IOException
534     {
535         if (_sslContext == null)
536         {
537             if (_keyStoreInputStream == null && _keyStoreLocation == null &&
538                 _trustStoreInputStream == null && _trustStoreLocation == null )
539             {
540                 _sslContext = getLooseSSLContext();
541             }
542             else
543             {
544                 _sslContext = getStrictSSLContext();
545             }
546         }
547         return _sslContext;
548     }
549 
550     protected SSLContext getStrictSSLContext() throws IOException
551     {
552         try
553         {
554             /*
555              * if the keystore exists but the trust store doesn't use the keystore as the trust store
556              */
557             if (_keyStoreInputStream != null || _keyStoreLocation != null)
558             {
559                 if (_trustStoreInputStream == null && _trustStoreLocation == null)
560                 {
561                     _trustStoreLocation = _keyStoreLocation;
562                     _trustStoreInputStream = _keyStoreInputStream;
563                     _trustStoreType = _keyStoreType;
564                 }
565             }
566             
567             
568             InputStream keyStoreInputStream = null;
569             InputStream trustStoreInputStream = null;
570 
571             // It's the same stream and we cannot read it twice, so we read it once in memory
572             if (_keyStoreInputStream != null && _keyStoreInputStream == _trustStoreInputStream)
573             {
574                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
575                 byte[] buffer = new byte[1024];
576                 int read;
577                 while ((read = _keyStoreInputStream.read(buffer)) >= 0)
578                 {
579                     baos.write(buffer, 0, read);
580                 }
581                 
582                 _keyStoreInputStream.close();
583 
584                 keyStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
585                 trustStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
586             }
587 
588             /*
589              * set the keystore input stream if it isn't set
590              */
591             if (keyStoreInputStream == null && _keyStoreLocation != null )
592             {
593                 keyStoreInputStream = _keyStoreInputStream == null ? Resource.newResource(_keyStoreLocation).getInputStream() : _keyStoreInputStream;
594             }
595            
596             /*
597              * work out the key managers for the keystore, null if its not configured
598              */
599             KeyManager[] keyManagers = null;
600 
601             if (keyStoreInputStream != null)
602             {
603                 KeyStore keyStore = KeyStore.getInstance(_keyStoreType);
604                 keyStore.load(keyStoreInputStream,_keyStorePassword == null?null:_keyStorePassword.toCharArray());
605                 keyStoreInputStream.close();
606 
607                 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerAlgorithm);
608                 keyManagerFactory.init(keyStore,_keyManagerPassword == null?null:_keyManagerPassword.toCharArray());
609                 keyManagers = keyManagerFactory.getKeyManagers();
610             }
611             
612             /*
613              * trust store will always exist if this method has been called, either by being the only store specified or by being
614              * a duplicate of the keystore..
615              * 
616              * this is behavior consistent with other aspects of jetty I believe so maintaining that consistency
617              */
618             if (trustStoreInputStream == null)
619             {
620                 trustStoreInputStream = _trustStoreInputStream == null ? Resource.newResource(_trustStoreLocation).getInputStream() : _trustStoreInputStream;
621             }
622             
623             KeyStore trustStore = KeyStore.getInstance(_trustStoreType);
624             trustStore.load(trustStoreInputStream, _trustStorePassword == null ? null : _trustStorePassword.toCharArray());
625             trustStoreInputStream.close();
626 
627             TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerAlgorithm);
628             trustManagerFactory.init(trustStore);
629             TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
630 
631             SecureRandom secureRandom = _secureRandomAlgorithm == null ? null : SecureRandom.getInstance(_secureRandomAlgorithm);
632             SSLContext context = _provider == null ? SSLContext.getInstance(_protocol) : SSLContext.getInstance(_protocol, _provider);
633             context.init(keyManagers, trustManagers, secureRandom);
634             
635             return context;
636         }
637         catch (Exception x)
638         {
639             throw (IOException)new IOException("Error generating SSLContext for keystore " + _keyStoreLocation).initCause(x);
640         }
641     }
642 
643     protected SSLContext getLooseSSLContext() throws IOException
644     {
645         // Create a trust manager that does not validate certificate chains
646         TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager()
647         {
648             public java.security.cert.X509Certificate[] getAcceptedIssuers()
649             {
650                 return null;
651             }
652 
653             public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
654             {
655             }
656 
657             public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
658             {
659             }
660         }};
661 
662         // Install the all-trusting trust manager
663         try
664         {
665             SSLContext sslContext = SSLContext.getInstance(_protocol);
666             sslContext.init(null, trustAllCerts, null);
667             return sslContext;
668         }
669         catch (Exception x)
670         {
671             throw (IOException)new IOException("Error generating loose SSLContext").initCause(x);
672         }
673     }
674 
675     /* ------------------------------------------------------------ */
676     /**
677      * @return the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
678      */
679     public long getIdleTimeout()
680     {
681         return _idleTimeout;
682     }
683 
684     /* ------------------------------------------------------------ */
685     /**
686      * @param ms the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
687      */
688     public void setIdleTimeout(long ms)
689     {
690         _idleTimeout = ms;
691     }
692 
693     /**
694      * @return the period in ms that an exchange will wait for a response from the server.
695      * @deprecated use {@link #getTimeout()} instead.
696      */
697     @Deprecated
698     public int getSoTimeout()
699     {
700         return Long.valueOf(getTimeout()).intValue();
701     }
702 
703     /**
704      * @deprecated use {@link #setTimeout(long)} instead.
705      * @param timeout the period in ms that an exchange will wait for a response from the server.
706      */
707     @Deprecated
708     public void setSoTimeout(int timeout)
709     {
710         setTimeout(timeout);
711     }
712 
713     /* ------------------------------------------------------------ */
714     /**
715      * @return the period in ms that an exchange will wait for a response from the server.
716      */
717     public long getTimeout()
718     {
719         return _timeout;
720     }
721 
722     /* ------------------------------------------------------------ */
723     /**
724      * @param timeout the period in ms that an exchange will wait for a response from the server.
725      */
726     public void setTimeout(long timeout)
727     {
728         _timeout = timeout;
729     }
730 
731     /**
732      * @return the period in ms before timing out an attempt to connect
733      */
734     public int getConnectTimeout()
735     {
736         return _connectTimeout;
737     }
738 
739     /**
740      * @param connectTimeout the period in ms before timing out an attempt to connect
741      */
742     public void setConnectTimeout(int connectTimeout)
743     {
744         this._connectTimeout = connectTimeout;
745     }
746 
747     /* ------------------------------------------------------------ */
748     public Address getProxy()
749     {
750         return _proxy;
751     }
752 
753     /* ------------------------------------------------------------ */
754     public void setProxy(Address proxy)
755     {
756         this._proxy = proxy;
757     }
758 
759     /* ------------------------------------------------------------ */
760     public Authentication getProxyAuthentication()
761     {
762         return _proxyAuthentication;
763     }
764 
765     /* ------------------------------------------------------------ */
766     public void setProxyAuthentication(Authentication authentication)
767     {
768         _proxyAuthentication = authentication;
769     }
770 
771     /* ------------------------------------------------------------ */
772     public boolean isProxied()
773     {
774         return this._proxy != null;
775     }
776 
777     /* ------------------------------------------------------------ */
778     public Set<String> getNoProxy()
779     {
780         return _noProxy;
781     }
782 
783     /* ------------------------------------------------------------ */
784     public void setNoProxy(Set<String> noProxyAddresses)
785     {
786         _noProxy = noProxyAddresses;
787     }
788 
789     /* ------------------------------------------------------------ */
790     public int maxRetries()
791     {
792         return _maxRetries;
793     }
794 
795     /* ------------------------------------------------------------ */
796     public void setMaxRetries(int retries)
797     {
798         _maxRetries = retries;
799     }
800 
801     /* ------------------------------------------------------------ */
802     public int maxRedirects()
803     {
804         return _maxRedirects;
805     }
806 
807     /* ------------------------------------------------------------ */
808     public void setMaxRedirects(int redirects)
809     {
810         _maxRedirects = redirects;
811     }
812 
813     /* ------------------------------------------------------------ */
814     public String getTrustStoreLocation()
815     {
816         return _trustStoreLocation;
817     }
818 
819     /* ------------------------------------------------------------ */
820     public void setTrustStoreLocation(String trustStoreLocation)
821     {
822         this._trustStoreLocation = trustStoreLocation;
823     }
824 
825     public InputStream getTrustStoreInputStream()
826     {
827         return _trustStoreInputStream;
828     }
829 
830     public void setTrustStoreInputStream(InputStream trustStoreInputStream)
831     {
832         this._trustStoreInputStream = trustStoreInputStream;
833     }
834 
835     /* ------------------------------------------------------------ */
836     public String getKeyStoreLocation()
837     {
838         return _keyStoreLocation;
839     }
840 
841     /* ------------------------------------------------------------ */
842     public void setKeyStoreLocation(String keyStoreLocation)
843     {
844         this._keyStoreLocation = keyStoreLocation;
845     }
846 
847     public InputStream getKeyStoreInputStream()
848     {
849         return _keyStoreInputStream;
850     }
851 
852     public void setKeyStoreInputStream(InputStream keyStoreInputStream)
853     {
854         this._keyStoreInputStream = keyStoreInputStream;
855     }
856 
857     /* ------------------------------------------------------------ */
858     public void setKeyStorePassword(String keyStorePassword)
859     {
860         this._keyStorePassword = new Password(keyStorePassword).toString();
861     }
862 
863     /* ------------------------------------------------------------ */
864     public void setKeyManagerPassword(String keyManagerPassword)
865     {
866         this._keyManagerPassword = new Password(keyManagerPassword).toString();
867     }
868 
869     /* ------------------------------------------------------------ */
870     public void setTrustStorePassword(String trustStorePassword)
871     {
872         this._trustStorePassword = new Password(trustStorePassword).toString();
873     }
874 
875     /* ------------------------------------------------------------ */
876     public String getKeyStoreType()
877     {
878         return this._keyStoreType;
879     }
880 
881     /* ------------------------------------------------------------ */
882     public void setKeyStoreType(String keyStoreType)
883     {
884         this._keyStoreType = keyStoreType;
885     }
886 
887     /* ------------------------------------------------------------ */
888     public String getTrustStoreType()
889     {
890         return this._trustStoreType;
891     }
892 
893     /* ------------------------------------------------------------ */
894     public void setTrustStoreType(String trustStoreType)
895     {
896         this._trustStoreType = trustStoreType;
897     }
898 
899     /* ------------------------------------------------------------ */
900     public String getKeyManagerAlgorithm()
901     {
902         return _keyManagerAlgorithm;
903     }
904 
905     /* ------------------------------------------------------------ */
906     public void setKeyManagerAlgorithm(String keyManagerAlgorithm)
907     {
908         this._keyManagerAlgorithm = keyManagerAlgorithm;
909     }
910 
911     /* ------------------------------------------------------------ */
912     public String getTrustManagerAlgorithm()
913     {
914         return _trustManagerAlgorithm;
915     }
916 
917     /* ------------------------------------------------------------ */
918     public void setTrustManagerAlgorithm(String trustManagerAlgorithm)
919     {
920         this._trustManagerAlgorithm = trustManagerAlgorithm;
921     }
922 
923     /* ------------------------------------------------------------ */
924     public String getProtocol()
925     {
926         return _protocol;
927     }
928 
929     /* ------------------------------------------------------------ */
930     public void setProtocol(String protocol)
931     {
932         this._protocol = protocol;
933     }
934 
935     /* ------------------------------------------------------------ */
936     public String getProvider()
937     {
938         return _provider;
939     }
940 
941     /* ------------------------------------------------------------ */
942     public void setProvider(String provider)
943     {
944         this._provider = provider;
945     }
946 
947     /* ------------------------------------------------------------ */
948     public String getSecureRandomAlgorithm()
949     {
950         return _secureRandomAlgorithm;
951     }
952 
953     /* ------------------------------------------------------------ */
954     public void setSecureRandomAlgorithm(String secureRandomAlgorithm)
955     {
956         this._secureRandomAlgorithm = secureRandomAlgorithm;
957     }
958 }