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.IOException;
17  import java.io.InputStream;
18  import java.net.UnknownHostException;
19  import java.util.Enumeration;
20  import java.util.LinkedList;
21  import java.util.Map;
22  import java.util.Set;
23  import java.util.concurrent.ConcurrentHashMap;
24  import java.util.concurrent.ConcurrentMap;
25  import javax.net.ssl.SSLContext;
26  
27  import org.eclipse.jetty.client.security.Authentication;
28  import org.eclipse.jetty.client.security.RealmResolver;
29  import org.eclipse.jetty.client.security.SecurityListener;
30  import org.eclipse.jetty.http.HttpBuffers;
31  import org.eclipse.jetty.http.HttpSchemes;
32  import org.eclipse.jetty.http.ssl.SslContextFactory;
33  import org.eclipse.jetty.io.Buffers.Type;
34  import org.eclipse.jetty.util.Attributes;
35  import org.eclipse.jetty.util.AttributesMap;
36  import org.eclipse.jetty.util.component.LifeCycle;
37  import org.eclipse.jetty.util.log.Log;
38  import org.eclipse.jetty.util.thread.QueuedThreadPool;
39  import org.eclipse.jetty.util.thread.ThreadPool;
40  import org.eclipse.jetty.util.thread.Timeout;
41  
42  /**
43   * Http Client.
44   * <p/>
45   * HttpClient is the main active component of the client API implementation.
46   * It is the opposite of the Connectors in standard Jetty, in that it listens
47   * for responses rather than requests.   Just like the connectors, there is a
48   * blocking socket version and a non-blocking NIO version (implemented as nested classes
49   * selected by {@link #setConnectorType(int)}).
50   * <p/>
51   * The an instance of {@link HttpExchange} is passed to the {@link #send(HttpExchange)} method
52   * to send a request.  The exchange contains both the headers and content (source) of the request
53   * plus the callbacks to handle responses.   A HttpClient can have many exchanges outstanding
54   * and they may be queued on the {@link HttpDestination} waiting for a {@link HttpConnection},
55   * queued in the {@link HttpConnection} waiting to be transmitted or pipelined on the actual
56   * TCP/IP connection waiting for a response.
57   * <p/>
58   * The {@link HttpDestination} class is an aggregation of {@link HttpConnection}s for the
59   * same host, port and protocol.   A destination may limit the number of connections
60   * open and they provide a pool of open connections that may be reused.   Connections may also
61   * be allocated from a destination, so that multiple request sources are not multiplexed
62   * over the same connection.
63   *
64   * @see HttpExchange
65   * @see HttpDestination
66   */
67  public class HttpClient extends HttpBuffers implements Attributes
68  {
69      public static final int CONNECTOR_SOCKET = 0;
70      public static final int CONNECTOR_SELECT_CHANNEL = 2;
71  
72      private int _connectorType = CONNECTOR_SELECT_CHANNEL;
73      private boolean _useDirectBuffers = true;
74      private boolean _connectBlocking = true;
75      private int _maxConnectionsPerAddress = Integer.MAX_VALUE;
76      private int _maxQueueSizePerAddress = Integer.MAX_VALUE;
77      private ConcurrentMap<Address, HttpDestination> _destinations = new ConcurrentHashMap<Address, HttpDestination>();
78      ThreadPool _threadPool;
79      Connector _connector;
80      private long _idleTimeout = 20000;
81      private long _timeout = 320000;
82      private int _connectTimeout = 75000;
83      private Timeout _timeoutQ = new Timeout();
84      private Timeout _idleTimeoutQ = new Timeout();
85      private Address _proxy;
86      private Authentication _proxyAuthentication;
87      private Set<String> _noProxy;
88      private int _maxRetries = 3;
89      private int _maxRedirects = 20;
90      private LinkedList<String> _registeredListeners;
91  
92      private SslContextFactory _sslContextFactory;
93  
94      private RealmResolver _realmResolver;
95  
96      private AttributesMap _attributes=new AttributesMap();
97  
98  
99      /* ------------------------------------------------------------------------------- */
100     private void setBufferTypes()
101     {
102         if (_connectorType==CONNECTOR_SOCKET)
103         {
104             setRequestBufferType(Type.BYTE_ARRAY);
105             setRequestHeaderType(Type.BYTE_ARRAY);
106             setResponseBufferType(Type.BYTE_ARRAY);
107             setResponseHeaderType(Type.BYTE_ARRAY);
108         }
109         else
110         {
111             setRequestBufferType(Type.DIRECT);
112             setRequestHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
113             setResponseBufferType(Type.DIRECT);
114             setResponseHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
115         }
116     }
117 
118     /* ------------------------------------------------------------------------------- */
119     public HttpClient()
120     {
121         this(new SslContextFactory());
122         setBufferTypes();
123     }
124 
125     /* ------------------------------------------------------------------------------- */
126     public HttpClient(SslContextFactory sslContextFactory)
127     {
128         _sslContextFactory = sslContextFactory;
129         setBufferTypes();
130     }
131 
132     /* ------------------------------------------------------------------------------- */
133     /**
134      * @return True if connects will be in blocking mode.
135      */
136     public boolean isConnectBlocking()
137     {
138         return _connectBlocking;
139     }
140 
141     /* ------------------------------------------------------------------------------- */
142     /**
143      * @param connectBlocking True if connects will be in blocking mode.
144      */
145     public void setConnectBlocking(boolean connectBlocking)
146     {
147         _connectBlocking = connectBlocking;
148     }
149 
150     /* ------------------------------------------------------------------------------- */
151     public void dump()
152     {
153         try
154         {
155             for (Map.Entry<Address, HttpDestination> entry : _destinations.entrySet())
156             {
157                 Log.info("\n" + entry.getKey() + ":");
158                 entry.getValue().dump();
159             }
160         }
161         catch(Exception e)
162         {
163             Log.warn(e);
164         }
165     }
166 
167     /* ------------------------------------------------------------------------------- */
168     public void send(HttpExchange exchange) throws IOException
169     {
170         boolean ssl = HttpSchemes.HTTPS_BUFFER.equalsIgnoreCase(exchange.getScheme());
171         exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_CONNECTION);
172         HttpDestination destination = getDestination(exchange.getAddress(), ssl);
173         destination.send(exchange);
174     }
175 
176     /* ------------------------------------------------------------ */
177     /**
178      * @return the threadPool
179      */
180     public ThreadPool getThreadPool()
181     {
182         return _threadPool;
183     }
184 
185     /* ------------------------------------------------------------ */
186     /**
187      * @param threadPool the threadPool to set
188      */
189     public void setThreadPool(ThreadPool threadPool)
190     {
191         _threadPool = threadPool;
192     }
193 
194 
195     /* ------------------------------------------------------------ */
196     /**
197      * @param name
198      * @return Attribute associated with client
199      */
200     public Object getAttribute(String name)
201     {
202         return _attributes.getAttribute(name);
203     }
204 
205     /* ------------------------------------------------------------ */
206     /**
207      * @return names of attributes associated with client
208      */
209     public Enumeration getAttributeNames()
210     {
211         return _attributes.getAttributeNames();
212     }
213 
214     /* ------------------------------------------------------------ */
215     /**
216      * @param name
217      */
218     public void removeAttribute(String name)
219     {
220         _attributes.removeAttribute(name);
221     }
222 
223     /* ------------------------------------------------------------ */
224     /**
225      * Set an attribute on the HttpClient.
226      * Attributes are not used by the client, but are provided for
227      * so that users of a shared HttpClient may share other structures.
228      * @param name
229      * @param attribute
230      */
231     public void setAttribute(String name, Object attribute)
232     {
233         _attributes.setAttribute(name,attribute);
234     }
235 
236     /* ------------------------------------------------------------ */
237     public void clearAttributes()
238     {
239         _attributes.clearAttributes();
240     }
241 
242     /* ------------------------------------------------------------------------------- */
243     public HttpDestination getDestination(Address remote, boolean ssl) throws IOException
244     {
245         if (remote == null)
246             throw new UnknownHostException("Remote socket address cannot be null.");
247 
248         HttpDestination destination = _destinations.get(remote);
249         if (destination == null)
250         {
251             destination = new HttpDestination(this, remote, ssl);
252             if (_proxy != null && (_noProxy == null || !_noProxy.contains(remote.getHost())))
253             {
254                 destination.setProxy(_proxy);
255                 if (_proxyAuthentication != null)
256                     destination.setProxyAuthentication(_proxyAuthentication);
257             }
258             HttpDestination other =_destinations.putIfAbsent(remote, destination);
259             if (other!=null)
260                 destination=other;
261         }
262         return destination;
263     }
264 
265     /* ------------------------------------------------------------ */
266     public void schedule(Timeout.Task task)
267     {
268         _timeoutQ.schedule(task);
269     }
270 
271     /* ------------------------------------------------------------ */
272     public void schedule(Timeout.Task task, long timeout)
273     {
274         _timeoutQ.schedule(task, timeout - _timeoutQ.getDuration());
275     }
276 
277     /* ------------------------------------------------------------ */
278     public void scheduleIdle(Timeout.Task task)
279     {
280         _idleTimeoutQ.schedule(task);
281     }
282 
283     /* ------------------------------------------------------------ */
284     public void cancel(Timeout.Task task)
285     {
286         task.cancel();
287     }
288 
289     /* ------------------------------------------------------------ */
290     /**
291      * Get whether the connector can use direct NIO buffers.
292      */
293     public boolean getUseDirectBuffers()
294     {
295         return _useDirectBuffers;
296     }
297 
298     /* ------------------------------------------------------------ */
299     /** Set a RealmResolver for client Authentication.
300      * If a realmResolver is set, then the HttpDestinations created by
301      * this client will instantiate a {@link SecurityListener} so that
302      * BASIC and DIGEST authentication can be performed.
303      * @param resolver
304      */
305     public void setRealmResolver(RealmResolver resolver)
306     {
307         _realmResolver = resolver;
308     }
309 
310     /* ------------------------------------------------------------ */
311     /**
312      * returns the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
313      *
314      * @return the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
315      */
316     public RealmResolver getRealmResolver()
317     {
318         return _realmResolver;
319     }
320 
321     /* ------------------------------------------------------------ */
322     public boolean hasRealms()
323     {
324         return _realmResolver == null ? false : true;
325     }
326 
327 
328     /**
329      * Registers a listener that can listen to the stream of execution between the client and the
330      * server and influence events.  Sequential calls to the method wrapper sequentially wrap the preceding
331      * listener in a delegation model.
332      * <p/>
333      * NOTE: the SecurityListener is a special listener which doesn't need to be added via this
334      * mechanic, if you register security realms then it will automatically be added as the top listener of the
335      * delegation stack.
336      *
337      * @param listenerClass
338      */
339     public void registerListener(String listenerClass)
340     {
341         if (_registeredListeners == null)
342         {
343             _registeredListeners = new LinkedList<String>();
344         }
345         _registeredListeners.add(listenerClass);
346     }
347 
348     /* ------------------------------------------------------------ */
349     public LinkedList<String> getRegisteredListeners()
350     {
351         return _registeredListeners;
352     }
353 
354 
355     /* ------------------------------------------------------------ */
356     /**
357      * Set to use NIO direct buffers.
358      *
359      * @param direct If True (the default), the connector can use NIO direct
360      *               buffers. Some JVMs have memory management issues (bugs) with
361      *               direct buffers.
362      */
363     public void setUseDirectBuffers(boolean direct)
364     {
365         _useDirectBuffers = direct;
366         setBufferTypes();
367     }
368 
369     /* ------------------------------------------------------------ */
370     /**
371      * Get the type of connector (socket, blocking or select) in use.
372      */
373     public int getConnectorType()
374     {
375         return _connectorType;
376     }
377 
378     /* ------------------------------------------------------------ */
379     public void setConnectorType(int connectorType)
380     {
381         this._connectorType = connectorType;
382         setBufferTypes();
383     }
384 
385     /* ------------------------------------------------------------ */
386     public int getMaxConnectionsPerAddress()
387     {
388         return _maxConnectionsPerAddress;
389     }
390 
391     /* ------------------------------------------------------------ */
392     public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress)
393     {
394         _maxConnectionsPerAddress = maxConnectionsPerAddress;
395     }
396 
397     public int getMaxQueueSizePerAddress()
398     {
399         return _maxQueueSizePerAddress;
400     }
401 
402     public void setMaxQueueSizePerAddress(int maxQueueSizePerAddress)
403     {
404         this._maxQueueSizePerAddress = maxQueueSizePerAddress;
405     }
406 
407     /* ------------------------------------------------------------ */
408     @Override
409     protected void doStart() throws Exception
410     {
411         setBufferTypes();
412         super.doStart();
413 
414         _timeoutQ.setDuration(_timeout);
415         _timeoutQ.setNow();
416         _idleTimeoutQ.setDuration(_idleTimeout);
417         _idleTimeoutQ.setNow();
418 
419         if (_threadPool == null)
420         {
421             QueuedThreadPool pool = new QueuedThreadPool();
422             pool.setMaxThreads(16);
423             pool.setDaemon(true);
424             pool.setName("HttpClient");
425             _threadPool = pool;
426         }
427 
428         if (_threadPool instanceof LifeCycle)
429         {
430             ((LifeCycle)_threadPool).start();
431         }
432 
433         _sslContextFactory.start();
434 
435         if (_connectorType == CONNECTOR_SELECT_CHANNEL)
436         {
437 
438             _connector = new SelectConnector(this);
439         }
440         else
441         {
442             _connector = new SocketConnector(this);
443         }
444         _connector.start();
445 
446         _threadPool.dispatch(new Runnable()
447         {
448             public void run()
449             {
450                 while (isRunning())
451                 {
452                     _timeoutQ.tick(System.currentTimeMillis());
453                     _idleTimeoutQ.tick(_timeoutQ.getNow());
454                     try
455                     {
456                         Thread.sleep(200);
457                     }
458                     catch (InterruptedException e)
459                     {
460                     }
461                 }
462             }
463         });
464     }
465 
466     /* ------------------------------------------------------------ */
467     long getNow()
468     {
469         return _timeoutQ.getNow();
470     }
471 
472     /* ------------------------------------------------------------ */
473     @Override
474     protected void doStop() throws Exception
475     {
476         _connector.stop();
477         _connector = null;
478         _sslContextFactory.stop();
479 
480         if (_threadPool instanceof LifeCycle)
481         {
482             ((LifeCycle)_threadPool).stop();
483         }
484         for (HttpDestination destination : _destinations.values())
485         {
486             destination.close();
487         }
488 
489         _timeoutQ.cancelAll();
490         _idleTimeoutQ.cancelAll();
491         super.doStop();
492     }
493 
494     /* ------------------------------------------------------------ */
495     interface Connector extends LifeCycle
496     {
497         public void startConnection(HttpDestination destination) throws IOException;
498     }
499 
500     /* ------------------------------------------------------------ */
501     /**
502      * if a keystore location has been provided then client will attempt to use it as the keystore,
503      * otherwise we simply ignore certificates and run with a loose ssl context.
504      *
505      * @return the SSL context
506      */
507     protected SSLContext getSSLContext()
508     {
509         return _sslContextFactory.getSslContext();
510     }
511 
512     /* ------------------------------------------------------------ */
513     /**
514      * @return the instance of SslContextFactory associated with the client
515      */
516     public SslContextFactory getSslContextFactory()
517     {
518         return _sslContextFactory;
519     }
520 
521     /* ------------------------------------------------------------ */
522     /**
523      * @return the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
524      */
525     public long getIdleTimeout()
526     {
527         return _idleTimeout;
528     }
529 
530     /* ------------------------------------------------------------ */
531     /**
532      * @param ms the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
533      */
534     public void setIdleTimeout(long ms)
535     {
536         _idleTimeout = ms;
537     }
538 
539     /* ------------------------------------------------------------ */
540     /**
541      * @return the period in ms that an exchange will wait for a response from the server.
542      * @deprecated use {@link #getTimeout()} instead.
543      */
544     @Deprecated
545     public int getSoTimeout()
546     {
547         return Long.valueOf(getTimeout()).intValue();
548     }
549 
550     /* ------------------------------------------------------------ */
551     /**
552      * @deprecated use {@link #setTimeout(long)} instead.
553      * @param timeout the period in ms that an exchange will wait for a response from the server.
554      */
555     @Deprecated
556     public void setSoTimeout(int timeout)
557     {
558         setTimeout(timeout);
559     }
560 
561     /* ------------------------------------------------------------ */
562     /**
563      * @return the period in ms that an exchange will wait for a response from the server.
564      */
565     public long getTimeout()
566     {
567         return _timeout;
568     }
569 
570     /* ------------------------------------------------------------ */
571     /**
572      * @param timeout the period in ms that an exchange will wait for a response from the server.
573      */
574     public void setTimeout(long timeout)
575     {
576         _timeout = timeout;
577     }
578 
579     /* ------------------------------------------------------------ */
580     /**
581      * @return the period in ms before timing out an attempt to connect
582      */
583     public int getConnectTimeout()
584     {
585         return _connectTimeout;
586     }
587 
588     /* ------------------------------------------------------------ */
589     /**
590      * @param connectTimeout the period in ms before timing out an attempt to connect
591      */
592     public void setConnectTimeout(int connectTimeout)
593     {
594         this._connectTimeout = connectTimeout;
595     }
596 
597     /* ------------------------------------------------------------ */
598     public Address getProxy()
599     {
600         return _proxy;
601     }
602 
603     /* ------------------------------------------------------------ */
604     public void setProxy(Address proxy)
605     {
606         this._proxy = proxy;
607     }
608 
609     /* ------------------------------------------------------------ */
610     public Authentication getProxyAuthentication()
611     {
612         return _proxyAuthentication;
613     }
614 
615     /* ------------------------------------------------------------ */
616     public void setProxyAuthentication(Authentication authentication)
617     {
618         _proxyAuthentication = authentication;
619     }
620 
621     /* ------------------------------------------------------------ */
622     public boolean isProxied()
623     {
624         return this._proxy != null;
625     }
626 
627     /* ------------------------------------------------------------ */
628     public Set<String> getNoProxy()
629     {
630         return _noProxy;
631     }
632 
633     /* ------------------------------------------------------------ */
634     public void setNoProxy(Set<String> noProxyAddresses)
635     {
636         _noProxy = noProxyAddresses;
637     }
638 
639     /* ------------------------------------------------------------ */
640     public int maxRetries()
641     {
642         return _maxRetries;
643     }
644 
645     /* ------------------------------------------------------------ */
646     public void setMaxRetries(int retries)
647     {
648         _maxRetries = retries;
649     }
650 
651     /* ------------------------------------------------------------ */
652     public int maxRedirects()
653     {
654         return _maxRedirects;
655     }
656 
657     /* ------------------------------------------------------------ */
658     public void setMaxRedirects(int redirects)
659     {
660         _maxRedirects = redirects;
661     }
662 
663     /* ------------------------------------------------------------ */
664     @Deprecated
665     public String getTrustStoreLocation()
666     {
667         return _sslContextFactory.getTrustStore();
668     }
669 
670     /* ------------------------------------------------------------ */
671     @Deprecated
672     public void setTrustStoreLocation(String trustStoreLocation)
673     {
674         _sslContextFactory.setTrustStore(trustStoreLocation);
675     }
676 
677     /* ------------------------------------------------------------ */
678     @Deprecated
679     public InputStream getTrustStoreInputStream()
680     {
681         return _sslContextFactory.getTrustStoreInputStream();
682     }
683 
684     /* ------------------------------------------------------------ */
685     @Deprecated
686     public void setTrustStoreInputStream(InputStream trustStoreInputStream)
687     {
688         _sslContextFactory.setTrustStoreInputStream(trustStoreInputStream);
689     }
690 
691     /* ------------------------------------------------------------ */
692     @Deprecated
693     public String getKeyStoreLocation()
694     {
695         return _sslContextFactory.getKeyStore();
696     }
697 
698     /* ------------------------------------------------------------ */
699     @Deprecated
700     public void setKeyStoreLocation(String keyStoreLocation)
701     {
702         _sslContextFactory.setKeyStore(keyStoreLocation);
703     }
704 
705     @Deprecated
706     public InputStream getKeyStoreInputStream()
707     {
708         return _sslContextFactory.getKeyStoreInputStream();
709     }
710 
711     @Deprecated
712     public void setKeyStoreInputStream(InputStream keyStoreInputStream)
713     {
714         _sslContextFactory.setKeyStoreInputStream(keyStoreInputStream);
715     }
716 
717     /* ------------------------------------------------------------ */
718     @Deprecated
719     public void setKeyStorePassword(String keyStorePassword)
720     {
721         _sslContextFactory.setKeyStorePassword(keyStorePassword);
722     }
723 
724     /* ------------------------------------------------------------ */
725     @Deprecated
726     public void setKeyManagerPassword(String keyManagerPassword)
727     {
728         _sslContextFactory.setKeyManagerPassword(keyManagerPassword);
729     }
730 
731     /* ------------------------------------------------------------ */
732     @Deprecated
733     public void setTrustStorePassword(String trustStorePassword)
734     {
735         _sslContextFactory.setTrustStorePassword(trustStorePassword);
736     }
737 
738     /* ------------------------------------------------------------ */
739     @Deprecated
740     public String getKeyStoreType()
741     {
742         return _sslContextFactory.getKeyStoreType();
743     }
744 
745     /* ------------------------------------------------------------ */
746     @Deprecated
747     public void setKeyStoreType(String keyStoreType)
748     {
749         _sslContextFactory.setKeyStoreType(keyStoreType);
750     }
751 
752     /* ------------------------------------------------------------ */
753     @Deprecated
754     public String getTrustStoreType()
755     {
756         return _sslContextFactory.getTrustStoreType();
757     }
758 
759     /* ------------------------------------------------------------ */
760     @Deprecated
761     public void setTrustStoreType(String trustStoreType)
762     {
763         _sslContextFactory.setTrustStoreType(trustStoreType);
764     }
765 
766     /* ------------------------------------------------------------ */
767     @Deprecated
768     public String getKeyManagerAlgorithm()
769     {
770         return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
771     }
772 
773     /* ------------------------------------------------------------ */
774     @Deprecated
775     public void setKeyManagerAlgorithm(String keyManagerAlgorithm)
776     {
777         _sslContextFactory.setSslKeyManagerFactoryAlgorithm(keyManagerAlgorithm);
778     }
779 
780     /* ------------------------------------------------------------ */
781     @Deprecated
782     public String getTrustManagerAlgorithm()
783     {
784         return _sslContextFactory.getTrustManagerFactoryAlgorithm();
785     }
786 
787     /* ------------------------------------------------------------ */
788     @Deprecated
789     public void setTrustManagerAlgorithm(String trustManagerAlgorithm)
790     {
791         _sslContextFactory.setTrustManagerFactoryAlgorithm(trustManagerAlgorithm);
792     }
793 
794     /* ------------------------------------------------------------ */
795     @Deprecated
796     public String getProtocol()
797     {
798         return _sslContextFactory.getProtocol();
799     }
800 
801     /* ------------------------------------------------------------ */
802     @Deprecated
803     public void setProtocol(String protocol)
804     {
805         _sslContextFactory.setProtocol(protocol);
806     }
807 
808     /* ------------------------------------------------------------ */
809     @Deprecated
810     public String getProvider()
811     {
812         return _sslContextFactory.getProvider();
813     }
814 
815     /* ------------------------------------------------------------ */
816     @Deprecated
817     public void setProvider(String provider)
818     {
819         setProvider(provider);
820     }
821 
822     /* ------------------------------------------------------------ */
823     @Deprecated
824     public String getSecureRandomAlgorithm()
825     {
826         return _sslContextFactory.getSecureRandomAlgorithm();
827     }
828 
829     /* ------------------------------------------------------------ */
830     @Deprecated
831     public void setSecureRandomAlgorithm(String secureRandomAlgorithm)
832     {
833         _sslContextFactory.setSecureRandomAlgorithm(secureRandomAlgorithm);
834     }
835 }