1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.client;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.UnknownHostException;
24 import java.util.Enumeration;
25 import java.util.LinkedList;
26 import java.util.Set;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.concurrent.ConcurrentMap;
29 import javax.net.ssl.SSLContext;
30
31 import org.eclipse.jetty.client.security.Authentication;
32 import org.eclipse.jetty.client.security.RealmResolver;
33 import org.eclipse.jetty.client.security.SecurityListener;
34 import org.eclipse.jetty.http.HttpBuffers;
35 import org.eclipse.jetty.http.HttpBuffersImpl;
36 import org.eclipse.jetty.http.HttpSchemes;
37 import org.eclipse.jetty.io.Buffers;
38 import org.eclipse.jetty.io.Buffers.Type;
39 import org.eclipse.jetty.util.Attributes;
40 import org.eclipse.jetty.util.AttributesMap;
41 import org.eclipse.jetty.util.component.AggregateLifeCycle;
42 import org.eclipse.jetty.util.component.Dumpable;
43 import org.eclipse.jetty.util.component.LifeCycle;
44 import org.eclipse.jetty.util.ssl.SslContextFactory;
45 import org.eclipse.jetty.util.thread.QueuedThreadPool;
46 import org.eclipse.jetty.util.thread.ThreadPool;
47 import org.eclipse.jetty.util.thread.Timeout;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attributes, Dumpable
75 {
76 public static final int CONNECTOR_SOCKET = 0;
77 public static final int CONNECTOR_SELECT_CHANNEL = 2;
78
79 private int _connectorType = CONNECTOR_SELECT_CHANNEL;
80 private boolean _useDirectBuffers = true;
81 private boolean _connectBlocking = true;
82 private int _maxConnectionsPerAddress = Integer.MAX_VALUE;
83 private int _maxQueueSizePerAddress = Integer.MAX_VALUE;
84 private ConcurrentMap<Address, HttpDestination> _destinations = new ConcurrentHashMap<Address, HttpDestination>();
85 ThreadPool _threadPool;
86 Connector _connector;
87 private long _idleTimeout = 20000;
88 private long _timeout = 320000;
89 private int _connectTimeout = 75000;
90 private Timeout _timeoutQ = new Timeout();
91 private Timeout _idleTimeoutQ = new Timeout();
92 private Address _proxy;
93 private Authentication _proxyAuthentication;
94 private Set<String> _noProxy;
95 private int _maxRetries = 3;
96 private int _maxRedirects = 20;
97 private LinkedList<String> _registeredListeners;
98
99 private final SslContextFactory _sslContextFactory;
100
101 private RealmResolver _realmResolver;
102
103 private AttributesMap _attributes=new AttributesMap();
104
105 private final HttpBuffersImpl _buffers= new HttpBuffersImpl();
106
107
108 private void setBufferTypes()
109 {
110 if (_connectorType==CONNECTOR_SOCKET)
111 {
112 _buffers.setRequestBufferType(Type.BYTE_ARRAY);
113 _buffers.setRequestHeaderType(Type.BYTE_ARRAY);
114 _buffers.setResponseBufferType(Type.BYTE_ARRAY);
115 _buffers.setResponseHeaderType(Type.BYTE_ARRAY);
116 }
117 else
118 {
119 _buffers.setRequestBufferType(Type.DIRECT);
120 _buffers.setRequestHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
121 _buffers.setResponseBufferType(Type.DIRECT);
122 _buffers.setResponseHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
123 }
124
125 }
126
127
128 public HttpClient()
129 {
130 this(new SslContextFactory());
131 }
132
133
134 public HttpClient(SslContextFactory sslContextFactory)
135 {
136 _sslContextFactory = sslContextFactory;
137 addBean(_sslContextFactory);
138 addBean(_buffers);
139 }
140
141
142
143
144
145 public boolean isConnectBlocking()
146 {
147 return _connectBlocking;
148 }
149
150
151
152
153
154 public void setConnectBlocking(boolean connectBlocking)
155 {
156 _connectBlocking = connectBlocking;
157 }
158
159
160 public void send(HttpExchange exchange) throws IOException
161 {
162 boolean ssl = HttpSchemes.HTTPS_BUFFER.equalsIgnoreCase(exchange.getScheme());
163 exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_CONNECTION);
164 HttpDestination destination = getDestination(exchange.getAddress(), ssl);
165 destination.send(exchange);
166 }
167
168
169
170
171
172 public ThreadPool getThreadPool()
173 {
174 return _threadPool;
175 }
176
177
178
179
180
181
182
183 public void setThreadPool(ThreadPool threadPool)
184 {
185 removeBean(_threadPool);
186 _threadPool = threadPool;
187 addBean(_threadPool);
188 }
189
190
191
192
193
194
195
196 public Object getAttribute(String name)
197 {
198 return _attributes.getAttribute(name);
199 }
200
201
202
203
204
205 public Enumeration getAttributeNames()
206 {
207 return _attributes.getAttributeNames();
208 }
209
210
211
212
213
214 public void removeAttribute(String name)
215 {
216 _attributes.removeAttribute(name);
217 }
218
219
220
221
222
223
224
225
226
227 public void setAttribute(String name, Object attribute)
228 {
229 _attributes.setAttribute(name,attribute);
230 }
231
232
233 public void clearAttributes()
234 {
235 _attributes.clearAttributes();
236 }
237
238
239 public HttpDestination getDestination(Address remote, boolean ssl) throws IOException
240 {
241 if (remote == null)
242 throw new UnknownHostException("Remote socket address cannot be null.");
243
244 HttpDestination destination = _destinations.get(remote);
245 if (destination == null)
246 {
247 destination = new HttpDestination(this, remote, ssl);
248 if (_proxy != null && (_noProxy == null || !_noProxy.contains(remote.getHost())))
249 {
250 destination.setProxy(_proxy);
251 if (_proxyAuthentication != null)
252 destination.setProxyAuthentication(_proxyAuthentication);
253 }
254 HttpDestination other =_destinations.putIfAbsent(remote, destination);
255 if (other!=null)
256 destination=other;
257 }
258 return destination;
259 }
260
261
262 public void schedule(Timeout.Task task)
263 {
264 _timeoutQ.schedule(task);
265 }
266
267
268 public void schedule(Timeout.Task task, long timeout)
269 {
270 _timeoutQ.schedule(task, timeout - _timeoutQ.getDuration());
271 }
272
273
274 public void scheduleIdle(Timeout.Task task)
275 {
276 _idleTimeoutQ.schedule(task);
277 }
278
279
280 public void cancel(Timeout.Task task)
281 {
282 task.cancel();
283 }
284
285
286
287
288
289 public boolean getUseDirectBuffers()
290 {
291 return _useDirectBuffers;
292 }
293
294
295
296
297
298
299
300
301 public void setRealmResolver(RealmResolver resolver)
302 {
303 _realmResolver = resolver;
304 }
305
306
307
308
309
310
311
312 public RealmResolver getRealmResolver()
313 {
314 return _realmResolver;
315 }
316
317
318 public boolean hasRealms()
319 {
320 return _realmResolver == null ? false : true;
321 }
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336 public void registerListener(String listenerClass)
337 {
338 if (_registeredListeners == null)
339 {
340 _registeredListeners = new LinkedList<String>();
341 }
342 _registeredListeners.add(listenerClass);
343 }
344
345
346 public LinkedList<String> getRegisteredListeners()
347 {
348 return _registeredListeners;
349 }
350
351
352
353
354
355
356
357
358
359
360 public void setUseDirectBuffers(boolean direct)
361 {
362 _useDirectBuffers = direct;
363 setBufferTypes();
364 }
365
366
367
368
369
370 public int getConnectorType()
371 {
372 return _connectorType;
373 }
374
375
376 public void setConnectorType(int connectorType)
377 {
378 this._connectorType = connectorType;
379 setBufferTypes();
380 }
381
382
383 public int getMaxConnectionsPerAddress()
384 {
385 return _maxConnectionsPerAddress;
386 }
387
388
389 public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress)
390 {
391 _maxConnectionsPerAddress = maxConnectionsPerAddress;
392 }
393
394 public int getMaxQueueSizePerAddress()
395 {
396 return _maxQueueSizePerAddress;
397 }
398
399 public void setMaxQueueSizePerAddress(int maxQueueSizePerAddress)
400 {
401 this._maxQueueSizePerAddress = maxQueueSizePerAddress;
402 }
403
404
405 @Override
406 protected void doStart() throws Exception
407 {
408 setBufferTypes();
409
410 _timeoutQ.setDuration(_timeout);
411 _timeoutQ.setNow();
412 _idleTimeoutQ.setDuration(_idleTimeout);
413 _idleTimeoutQ.setNow();
414
415 if (_threadPool==null)
416 {
417 QueuedThreadPool pool = new LocalQueuedThreadPool();
418 pool.setMaxThreads(16);
419 pool.setDaemon(true);
420 pool.setName("HttpClient");
421 _threadPool = pool;
422 addBean(_threadPool,true);
423 }
424
425 _connector=(_connectorType == CONNECTOR_SELECT_CHANNEL)?new SelectConnector(this):new SocketConnector(this);
426 addBean(_connector,true);
427
428 super.doStart();
429
430 _threadPool.dispatch(new Runnable()
431 {
432 public void run()
433 {
434 while (isRunning())
435 {
436 _timeoutQ.tick(System.currentTimeMillis());
437 _idleTimeoutQ.tick(_timeoutQ.getNow());
438 try
439 {
440 Thread.sleep(200);
441 }
442 catch (InterruptedException ignored)
443 {
444 }
445 }
446 }
447 });
448 }
449
450
451 @Override
452 protected void doStop() throws Exception
453 {
454 for (HttpDestination destination : _destinations.values())
455 destination.close();
456
457 _timeoutQ.cancelAll();
458 _idleTimeoutQ.cancelAll();
459
460 super.doStop();
461
462 if (_threadPool instanceof LocalQueuedThreadPool)
463 {
464 removeBean(_threadPool);
465 _threadPool = null;
466 }
467
468 removeBean(_connector);
469 }
470
471
472 interface Connector extends LifeCycle
473 {
474 public void startConnection(HttpDestination destination) throws IOException;
475 }
476
477
478
479
480
481
482
483
484 protected SSLContext getSSLContext()
485 {
486 return _sslContextFactory.getSslContext();
487 }
488
489
490
491
492
493 public SslContextFactory getSslContextFactory()
494 {
495 return _sslContextFactory;
496 }
497
498
499
500
501
502 public long getIdleTimeout()
503 {
504 return _idleTimeout;
505 }
506
507
508
509
510
511 public void setIdleTimeout(long ms)
512 {
513 _idleTimeout = ms;
514 }
515
516
517
518
519
520
521 @Deprecated
522 public int getSoTimeout()
523 {
524 return Long.valueOf(getTimeout()).intValue();
525 }
526
527
528
529
530
531
532 @Deprecated
533 public void setSoTimeout(int timeout)
534 {
535 setTimeout(timeout);
536 }
537
538
539
540
541
542 public long getTimeout()
543 {
544 return _timeout;
545 }
546
547
548
549
550
551 public void setTimeout(long timeout)
552 {
553 _timeout = timeout;
554 }
555
556
557
558
559
560 public int getConnectTimeout()
561 {
562 return _connectTimeout;
563 }
564
565
566
567
568
569 public void setConnectTimeout(int connectTimeout)
570 {
571 this._connectTimeout = connectTimeout;
572 }
573
574
575 public Address getProxy()
576 {
577 return _proxy;
578 }
579
580
581 public void setProxy(Address proxy)
582 {
583 this._proxy = proxy;
584 }
585
586
587 public Authentication getProxyAuthentication()
588 {
589 return _proxyAuthentication;
590 }
591
592
593 public void setProxyAuthentication(Authentication authentication)
594 {
595 _proxyAuthentication = authentication;
596 }
597
598
599 public boolean isProxied()
600 {
601 return this._proxy != null;
602 }
603
604
605 public Set<String> getNoProxy()
606 {
607 return _noProxy;
608 }
609
610
611 public void setNoProxy(Set<String> noProxyAddresses)
612 {
613 _noProxy = noProxyAddresses;
614 }
615
616
617 public int maxRetries()
618 {
619 return _maxRetries;
620 }
621
622
623 public void setMaxRetries(int retries)
624 {
625 _maxRetries = retries;
626 }
627
628
629 public int maxRedirects()
630 {
631 return _maxRedirects;
632 }
633
634
635 public void setMaxRedirects(int redirects)
636 {
637 _maxRedirects = redirects;
638 }
639
640 public int getRequestBufferSize()
641 {
642 return _buffers.getRequestBufferSize();
643 }
644
645 public void setRequestBufferSize(int requestBufferSize)
646 {
647 _buffers.setRequestBufferSize(requestBufferSize);
648 }
649
650 public int getRequestHeaderSize()
651 {
652 return _buffers.getRequestHeaderSize();
653 }
654
655 public void setRequestHeaderSize(int requestHeaderSize)
656 {
657 _buffers.setRequestHeaderSize(requestHeaderSize);
658 }
659
660 public int getResponseBufferSize()
661 {
662 return _buffers.getResponseBufferSize();
663 }
664
665 public void setResponseBufferSize(int responseBufferSize)
666 {
667 _buffers.setResponseBufferSize(responseBufferSize);
668 }
669
670 public int getResponseHeaderSize()
671 {
672 return _buffers.getResponseHeaderSize();
673 }
674
675 public void setResponseHeaderSize(int responseHeaderSize)
676 {
677 _buffers.setResponseHeaderSize(responseHeaderSize);
678 }
679
680 public Type getRequestBufferType()
681 {
682 return _buffers.getRequestBufferType();
683 }
684
685 public Type getRequestHeaderType()
686 {
687 return _buffers.getRequestHeaderType();
688 }
689
690 public Type getResponseBufferType()
691 {
692 return _buffers.getResponseBufferType();
693 }
694
695 public Type getResponseHeaderType()
696 {
697 return _buffers.getResponseHeaderType();
698 }
699
700 public void setRequestBuffers(Buffers requestBuffers)
701 {
702 _buffers.setRequestBuffers(requestBuffers);
703 }
704
705 public void setResponseBuffers(Buffers responseBuffers)
706 {
707 _buffers.setResponseBuffers(responseBuffers);
708 }
709
710 public Buffers getRequestBuffers()
711 {
712 return _buffers.getRequestBuffers();
713 }
714
715 public Buffers getResponseBuffers()
716 {
717 return _buffers.getResponseBuffers();
718 }
719
720 public void setMaxBuffers(int maxBuffers)
721 {
722 _buffers.setMaxBuffers(maxBuffers);
723 }
724
725 public int getMaxBuffers()
726 {
727 return _buffers.getMaxBuffers();
728 }
729
730
731 @Deprecated
732 public String getTrustStoreLocation()
733 {
734 return _sslContextFactory.getTrustStore();
735 }
736
737
738 @Deprecated
739 public void setTrustStoreLocation(String trustStoreLocation)
740 {
741 _sslContextFactory.setTrustStore(trustStoreLocation);
742 }
743
744
745 @Deprecated
746 public InputStream getTrustStoreInputStream()
747 {
748 return _sslContextFactory.getTrustStoreInputStream();
749 }
750
751
752 @Deprecated
753 public void setTrustStoreInputStream(InputStream trustStoreInputStream)
754 {
755 _sslContextFactory.setTrustStoreInputStream(trustStoreInputStream);
756 }
757
758
759 @Deprecated
760 public String getKeyStoreLocation()
761 {
762 return _sslContextFactory.getKeyStorePath();
763 }
764
765
766 @Deprecated
767 public void setKeyStoreLocation(String keyStoreLocation)
768 {
769 _sslContextFactory.setKeyStorePath(keyStoreLocation);
770 }
771
772 @Deprecated
773 public InputStream getKeyStoreInputStream()
774 {
775 return _sslContextFactory.getKeyStoreInputStream();
776 }
777
778 @Deprecated
779 public void setKeyStoreInputStream(InputStream keyStoreInputStream)
780 {
781 _sslContextFactory.setKeyStoreInputStream(keyStoreInputStream);
782 }
783
784
785 @Deprecated
786 public void setKeyStorePassword(String keyStorePassword)
787 {
788 _sslContextFactory.setKeyStorePassword(keyStorePassword);
789 }
790
791
792 @Deprecated
793 public void setKeyManagerPassword(String keyManagerPassword)
794 {
795 _sslContextFactory.setKeyManagerPassword(keyManagerPassword);
796 }
797
798
799 @Deprecated
800 public void setTrustStorePassword(String trustStorePassword)
801 {
802 _sslContextFactory.setTrustStorePassword(trustStorePassword);
803 }
804
805
806 @Deprecated
807 public String getKeyStoreType()
808 {
809 return _sslContextFactory.getKeyStoreType();
810 }
811
812
813 @Deprecated
814 public void setKeyStoreType(String keyStoreType)
815 {
816 _sslContextFactory.setKeyStoreType(keyStoreType);
817 }
818
819
820 @Deprecated
821 public String getTrustStoreType()
822 {
823 return _sslContextFactory.getTrustStoreType();
824 }
825
826
827 @Deprecated
828 public void setTrustStoreType(String trustStoreType)
829 {
830 _sslContextFactory.setTrustStoreType(trustStoreType);
831 }
832
833
834 @Deprecated
835 public String getKeyManagerAlgorithm()
836 {
837 return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
838 }
839
840
841 @Deprecated
842 public void setKeyManagerAlgorithm(String keyManagerAlgorithm)
843 {
844 _sslContextFactory.setSslKeyManagerFactoryAlgorithm(keyManagerAlgorithm);
845 }
846
847
848 @Deprecated
849 public String getTrustManagerAlgorithm()
850 {
851 return _sslContextFactory.getTrustManagerFactoryAlgorithm();
852 }
853
854
855 @Deprecated
856 public void setTrustManagerAlgorithm(String trustManagerAlgorithm)
857 {
858 _sslContextFactory.setTrustManagerFactoryAlgorithm(trustManagerAlgorithm);
859 }
860
861
862 @Deprecated
863 public String getProtocol()
864 {
865 return _sslContextFactory.getProtocol();
866 }
867
868
869 @Deprecated
870 public void setProtocol(String protocol)
871 {
872 _sslContextFactory.setProtocol(protocol);
873 }
874
875
876 @Deprecated
877 public String getProvider()
878 {
879 return _sslContextFactory.getProvider();
880 }
881
882
883 @Deprecated
884 public void setProvider(String provider)
885 {
886 _sslContextFactory.setProvider(provider);
887 }
888
889
890 @Deprecated
891 public String getSecureRandomAlgorithm()
892 {
893 return _sslContextFactory.getSecureRandomAlgorithm();
894 }
895
896
897 @Deprecated
898 public void setSecureRandomAlgorithm(String secureRandomAlgorithm)
899 {
900 _sslContextFactory.setSecureRandomAlgorithm(secureRandomAlgorithm);
901 }
902
903 private static class LocalQueuedThreadPool extends QueuedThreadPool
904 {
905 }
906 }