1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty.client;
16
17 import java.io.IOException;
18 import java.net.InetAddress;
19 import java.net.InetSocketAddress;
20 import java.net.UnknownHostException;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.Set;
24
25 import javax.net.ssl.HostnameVerifier;
26 import javax.net.ssl.SSLContext;
27 import javax.net.ssl.SSLSession;
28 import javax.net.ssl.TrustManager;
29 import javax.net.ssl.X509TrustManager;
30
31 import org.mortbay.component.LifeCycle;
32 import org.mortbay.io.Buffer;
33 import org.mortbay.io.Buffers;
34 import org.mortbay.io.ByteArrayBuffer;
35 import org.mortbay.io.nio.NIOBuffer;
36 import org.mortbay.jetty.AbstractBuffers;
37 import org.mortbay.jetty.HttpSchemes;
38 import org.mortbay.jetty.client.security.DefaultRealmResolver;
39 import org.mortbay.jetty.client.security.SecurityRealm;
40 import org.mortbay.jetty.client.security.SecurityRealmResolver;
41 import org.mortbay.thread.QueuedThreadPool;
42 import org.mortbay.thread.ThreadPool;
43 import org.mortbay.thread.Timeout;
44
45
46
47
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 public class HttpClient extends AbstractBuffers
74 {
75 public static final int CONNECTOR_SOCKET=0;
76 public static final int CONNECTOR_SELECT_CHANNEL=2;
77
78 private int _connectorType=CONNECTOR_SOCKET;
79 private boolean _useDirectBuffers=true;
80 private int _maxConnectionsPerAddress=32;
81 private Map<InetSocketAddress, HttpDestination> _destinations=new HashMap<InetSocketAddress, HttpDestination>();
82 ThreadPool _threadPool;
83 Connector _connector;
84 private long _idleTimeout=20000;
85 private long _timeout=320000;
86 int _soTimeout = 10000;
87 private Timeout _timeoutQ = new Timeout();
88 private InetSocketAddress _proxy;
89 private Set<InetAddress> _noProxy;
90
91 private SecurityRealmResolver _realmResolver;
92
93
94
95
96 public void send(HttpExchange exchange) throws IOException
97 {
98 boolean ssl=HttpSchemes.HTTPS_BUFFER.equalsIgnoreCase(exchange.getScheme());
99 exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_CONNECTION);
100 HttpDestination destination=getDestination(exchange.getAddress(),ssl);
101 destination.send(exchange);
102 }
103
104
105
106
107
108 public ThreadPool getThreadPool()
109 {
110 return _threadPool;
111 }
112
113
114
115
116
117 public void setThreadPool(ThreadPool threadPool)
118 {
119 _threadPool=threadPool;
120 }
121
122
123 public HttpDestination getDestination(InetSocketAddress remote, boolean ssl) throws UnknownHostException, IOException
124 {
125 if (remote==null)
126 throw new UnknownHostException("Remote socket address cannot be null.");
127
128 synchronized (_destinations)
129 {
130 HttpDestination destination=_destinations.get(remote);
131 if (destination==null)
132 {
133 destination=new HttpDestination(this,remote,ssl,_maxConnectionsPerAddress);
134 if (_proxy!=null && (_noProxy==null || !_noProxy.contains(remote.getAddress())))
135 destination.setProxy(_proxy);
136 _destinations.put(remote,destination);
137 }
138 return destination;
139 }
140 }
141
142
143 public void schedule(Timeout.Task task)
144 {
145 _timeoutQ.schedule(task);
146 }
147
148
149 public void cancel(Timeout.Task task)
150 {
151 task.cancel();
152 }
153
154
155
156
157
158 public boolean getUseDirectBuffers()
159 {
160 return _useDirectBuffers;
161 }
162
163
164 public void setSecurityRealmResolver( SecurityRealmResolver resolver )
165 {
166 _realmResolver = resolver;
167 }
168
169
170
171
172
173
174
175 public SecurityRealmResolver getSecurityRealmResolver()
176 {
177 return _realmResolver;
178 }
179
180
181 public boolean hasRealms()
182 {
183 return _realmResolver==null?false:true;
184 }
185
186
187
188
189
190
191
192
193
194
195 public void setUseDirectBuffers(boolean direct)
196 {
197 _useDirectBuffers=direct;
198 }
199
200
201
202
203
204 public int getConnectorType()
205 {
206 return _connectorType;
207 }
208
209
210 public void setConnectorType(int connectorType)
211 {
212 this._connectorType=connectorType;
213 }
214
215
216
217
218
219
220 @Override
221 protected Buffer newBuffer(int size)
222 {
223 if (_connectorType!=CONNECTOR_SOCKET)
224 {
225 Buffer buf=null;
226 if (size==getHeaderBufferSize())
227 buf=new NIOBuffer(size,NIOBuffer.INDIRECT);
228 else
229 buf=new NIOBuffer(size,_useDirectBuffers?NIOBuffer.DIRECT:NIOBuffer.INDIRECT);
230 return buf;
231 }
232 else
233 {
234 return new ByteArrayBuffer(size);
235 }
236 }
237
238
239 public int getMaxConnectionsPerAddress()
240 {
241 return _maxConnectionsPerAddress;
242 }
243
244
245 public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress)
246 {
247 _maxConnectionsPerAddress=maxConnectionsPerAddress;
248 }
249
250
251 protected void doStart() throws Exception
252 {
253 super.doStart();
254
255 _timeoutQ.setNow();
256 _timeoutQ.setDuration(_timeout);
257
258 if(_threadPool==null)
259 {
260 QueuedThreadPool pool = new QueuedThreadPool();
261 pool.setMaxThreads(16);
262 pool.setDaemon(true);
263 _threadPool=pool;
264 }
265
266
267 if (_threadPool instanceof QueuedThreadPool)
268 {
269 ((QueuedThreadPool)_threadPool).setName("HttpClient");
270 }
271 if (_threadPool instanceof LifeCycle)
272 {
273 ((LifeCycle)_threadPool).start();
274 }
275
276
277 if (_connectorType==CONNECTOR_SELECT_CHANNEL)
278 {
279
280 _connector=new SelectConnector(this);
281 }
282 else
283 {
284 _connector=new SocketConnector(this);
285 }
286 _connector.start();
287
288 _threadPool.dispatch(new Runnable(){
289 public void run()
290 {
291 while (isStarted())
292 {
293 _timeoutQ.setNow();
294 _timeoutQ.tick();
295 try
296 {
297 Thread.sleep(1000);
298 }
299 catch (InterruptedException e)
300 {
301 }
302 }
303 }
304 });
305
306 }
307
308
309 protected void doStop() throws Exception
310 {
311 _connector.stop();
312 _connector=null;
313 if (_threadPool instanceof LifeCycle)
314 {
315 ((LifeCycle)_threadPool).stop();
316 }
317 for (HttpDestination destination : _destinations.values())
318 {
319 destination.close();
320 }
321
322 _timeoutQ.cancelAll();
323 super.doStop();
324 }
325
326
327 interface Connector extends LifeCycle
328 {
329 public void startConnection(HttpDestination destination) throws IOException;
330
331 }
332
333 SSLContext getLooseSSLContext() throws IOException
334 {
335
336
337 TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager()
338 {
339 public java.security.cert.X509Certificate[] getAcceptedIssuers()
340 {
341 return null;
342 }
343
344 public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType )
345 {
346 }
347
348 public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType )
349 {
350 }
351 } };
352
353 HostnameVerifier hostnameVerifier = new HostnameVerifier()
354 {
355 public boolean verify( String urlHostName, SSLSession session )
356 {
357 System.out.println( "Warning: URL Host: " + urlHostName + " vs." + session.getPeerHost() );
358 return true;
359 }
360 };
361
362
363 try
364 {
365
366 SSLContext sslContext = SSLContext.getInstance( "SSL" );
367 sslContext.init( null, trustAllCerts, new java.security.SecureRandom() );
368 return sslContext;
369 }
370 catch ( Exception e )
371 {
372 throw new IOException( "issue ignoring certs" );
373 }
374 }
375
376
377
378
379
380 public long getIdleTimeout()
381 {
382 return _idleTimeout;
383 }
384
385
386
387
388
389 public void setIdleTimeout(long ms)
390 {
391 _idleTimeout=ms;
392 }
393
394
395 public int getSoTimeout()
396 {
397 return _soTimeout;
398 }
399
400
401 public void setSoTimeout(int so)
402 {
403 _soTimeout = so;
404 }
405
406
407
408
409
410 public long getTimeout()
411 {
412 return _timeout;
413 }
414
415
416
417
418
419 public void setTimeout(long ms)
420 {
421 _timeout=ms;
422 }
423
424
425 public InetSocketAddress getProxy()
426 {
427 return _proxy;
428 }
429
430
431 public void setProxy(InetSocketAddress proxy)
432 {
433 this._proxy = proxy;
434 }
435
436
437 public boolean isProxied()
438 {
439 return this._proxy!=null;
440 }
441
442
443 public Set<InetAddress> getNoProxy()
444 {
445 return _noProxy;
446 }
447
448
449 public void setNoProxy(Set<InetAddress> noProxyAddresses)
450 {
451 _noProxy = noProxyAddresses;
452 }
453
454
455 public int maxRetries()
456 {
457
458 return 3;
459 }
460
461
462
463 }