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.io.InputStream;
19 import java.net.InetSocketAddress;
20
21 import org.mortbay.io.Buffer;
22 import org.mortbay.io.BufferCache.CachedBuffer;
23 import org.mortbay.io.nio.ChannelEndPoint;
24 import org.mortbay.io.ByteArrayBuffer;
25 import org.mortbay.jetty.HttpFields;
26 import org.mortbay.jetty.HttpHeaders;
27 import org.mortbay.jetty.HttpMethods;
28 import org.mortbay.jetty.HttpSchemes;
29 import org.mortbay.jetty.HttpURI;
30 import org.mortbay.jetty.HttpVersions;
31 import org.mortbay.log.Log;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public class HttpExchange
67 {
68 public static final int STATUS_START = 0;
69 public static final int STATUS_WAITING_FOR_CONNECTION = 1;
70 public static final int STATUS_WAITING_FOR_COMMIT = 2;
71 public static final int STATUS_SENDING_REQUEST = 3;
72 public static final int STATUS_WAITING_FOR_RESPONSE = 4;
73 public static final int STATUS_PARSING_HEADERS = 5;
74 public static final int STATUS_PARSING_CONTENT = 6;
75 public static final int STATUS_COMPLETED = 7;
76 public static final int STATUS_EXPIRED = 8;
77 public static final int STATUS_EXCEPTED = 9;
78
79 String _method = HttpMethods.GET;
80 Buffer _scheme = HttpSchemes.HTTP_BUFFER;
81 String _uri;
82 int _version = HttpVersions.HTTP_1_1_ORDINAL;
83 Address _address;
84 HttpFields _requestFields = new HttpFields();
85 Buffer _requestContent;
86 InputStream _requestContentSource;
87
88 volatile int _status = STATUS_START;
89 Buffer _requestContentChunk;
90 boolean _retryStatus = false;
91
92 boolean _configureListeners = true;
93 private HttpEventListener _listener = new Listener();
94
95 boolean _onRequestCompleteDone;
96 boolean _onResponseCompleteDone;
97 boolean _onDone;
98
99
100 public int getStatus()
101 {
102 return _status;
103 }
104
105
106
107
108
109 public void waitForStatus(int status) throws InterruptedException
110 {
111 synchronized (this)
112 {
113 while (_status < status)
114 {
115 this.wait();
116 }
117 }
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 public int waitForDone () throws InterruptedException
137 {
138 synchronized (this)
139 {
140 while (!isDone(_status))
141 this.wait();
142 return _status;
143 }
144 }
145
146
147
148
149
150 public void reset()
151 {
152
153
154 synchronized(this)
155 {
156 _onRequestCompleteDone=false;
157 _onResponseCompleteDone=false;
158 _onDone=false;
159 setStatus(STATUS_START);
160 }
161 }
162
163
164 void setStatus(int status)
165 {
166
167 _status = status;
168
169 try
170 {
171 switch (status)
172 {
173 case STATUS_WAITING_FOR_CONNECTION:
174 break;
175
176 case STATUS_WAITING_FOR_COMMIT:
177 break;
178
179 case STATUS_SENDING_REQUEST:
180 break;
181
182 case HttpExchange.STATUS_WAITING_FOR_RESPONSE:
183 getEventListener().onRequestCommitted();
184 break;
185
186 case STATUS_PARSING_HEADERS:
187 break;
188
189 case STATUS_PARSING_CONTENT:
190 getEventListener().onResponseHeaderComplete();
191 break;
192
193 case STATUS_COMPLETED:
194 getEventListener().onResponseComplete();
195 break;
196
197 case STATUS_EXPIRED:
198 getEventListener().onExpire();
199 break;
200
201 }
202 }
203 catch (IOException e)
204 {
205 Log.warn(e);
206 }
207 }
208
209
210 public boolean isDone (int status)
211 {
212 synchronized (this)
213 {
214 return _onDone;
215 }
216 }
217
218
219 public HttpEventListener getEventListener()
220 {
221 return _listener;
222 }
223
224
225 public void setEventListener(HttpEventListener listener)
226 {
227 _listener=listener;
228 }
229
230
231
232
233
234 public void setURL(String url)
235 {
236 HttpURI uri = new HttpURI(url);
237 String scheme = uri.getScheme();
238 if (scheme != null)
239 {
240 if (HttpSchemes.HTTP.equalsIgnoreCase(scheme))
241 setScheme(HttpSchemes.HTTP_BUFFER);
242 else if (HttpSchemes.HTTPS.equalsIgnoreCase(scheme))
243 setScheme(HttpSchemes.HTTPS_BUFFER);
244 else
245 setScheme(new ByteArrayBuffer(scheme));
246 }
247
248 int port = uri.getPort();
249 if (port <= 0)
250 port = "https".equalsIgnoreCase(scheme)?443:80;
251
252 setAddress(new Address(uri.getHost(),port));
253
254 String completePath = uri.getCompletePath();
255 if (completePath == null)
256 completePath = "/";
257
258 setURI(completePath);
259 }
260
261
262
263
264
265 public void setAddress(Address address)
266 {
267 _address = address;
268 }
269
270
271
272
273
274 public Address getAddress()
275 {
276 return _address;
277 }
278
279
280
281
282
283 public void setScheme(Buffer scheme)
284 {
285 _scheme = scheme;
286 }
287
288
289
290
291
292 public Buffer getScheme()
293 {
294 return _scheme;
295 }
296
297
298
299
300
301 public void setVersion(int version)
302 {
303 _version = version;
304 }
305
306
307 public void setVersion(String version)
308 {
309 CachedBuffer v = HttpVersions.CACHE.get(version);
310 if (v == null)
311 _version = 10;
312 else
313 _version = v.getOrdinal();
314 }
315
316
317
318
319
320 public int getVersion()
321 {
322 return _version;
323 }
324
325
326
327
328
329 public void setMethod(String method)
330 {
331 _method = method;
332 }
333
334
335
336
337
338 public String getMethod()
339 {
340 return _method;
341 }
342
343
344
345
346
347 public String getURI()
348 {
349 return _uri;
350 }
351
352
353
354
355
356 public void setURI(String uri)
357 {
358 _uri = uri;
359 }
360
361
362
363
364
365
366 public void addRequestHeader(String name, String value)
367 {
368 getRequestFields().add(name,value);
369 }
370
371
372
373
374
375
376 public void addRequestHeader(Buffer name, Buffer value)
377 {
378 getRequestFields().add(name,value);
379 }
380
381
382
383
384
385
386 public void setRequestHeader(String name, String value)
387 {
388 getRequestFields().put(name,value);
389 }
390
391
392
393
394
395
396 public void setRequestHeader(Buffer name, Buffer value)
397 {
398 getRequestFields().put(name,value);
399 }
400
401
402
403
404
405 public void setRequestContentType(String value)
406 {
407 getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,value);
408 }
409
410
411
412
413
414 public HttpFields getRequestFields()
415 {
416 return _requestFields;
417 }
418
419
420
421
422
423
424
425
426
427
428 public void setRequestContent(Buffer requestContent)
429 {
430 _requestContent = requestContent;
431 }
432
433
434
435
436
437 public void setRequestContentSource(InputStream in)
438 {
439 _requestContentSource = in;
440 if (_requestContentSource.markSupported())
441 _requestContentSource.mark(Integer.MAX_VALUE);
442 }
443
444
445 public InputStream getRequestContentSource()
446 {
447 return _requestContentSource;
448 }
449
450
451 public Buffer getRequestContentChunk() throws IOException
452 {
453 synchronized (this)
454 {
455 if (_requestContentChunk == null)
456 _requestContentChunk = new ByteArrayBuffer(4096);
457 else
458 {
459 if (_requestContentChunk.hasContent())
460 throw new IllegalStateException();
461 _requestContentChunk.clear();
462 }
463
464 int read = _requestContentChunk.capacity();
465 int length = _requestContentSource.read(_requestContentChunk.array(),0,read);
466 if (length >= 0)
467 {
468 _requestContentChunk.setPutIndex(length);
469 return _requestContentChunk;
470 }
471 return null;
472 }
473 }
474
475
476 public Buffer getRequestContent()
477 {
478 return _requestContent;
479 }
480
481
482 public boolean getRetryStatus()
483 {
484 return _retryStatus;
485 }
486
487
488 public void setRetryStatus( boolean retryStatus )
489 {
490 _retryStatus = retryStatus;
491 }
492
493
494
495
496
497 public void cancel()
498 {
499
500 }
501
502
503 public String toString()
504 {
505 return getClass().getName() + "@" + hashCode() + "=" + _method + "//" + _address + _uri + "#" + _status;
506 }
507
508
509
510
511
512
513
514
515
516
517
518
519 protected void onRequestCommitted() throws IOException
520 {
521 }
522
523
524
525
526
527 protected void onRequestComplete() throws IOException
528 {
529 }
530
531
532
533
534
535
536
537
538 protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
539 {
540 }
541
542
543
544
545
546
547
548 protected void onResponseHeader(Buffer name, Buffer value) throws IOException
549 {
550 }
551
552
553
554
555
556 protected void onResponseHeaderComplete() throws IOException
557 {
558 }
559
560
561
562
563
564
565 protected void onResponseContent(Buffer content) throws IOException
566 {
567 }
568
569
570
571
572
573 protected void onResponseComplete() throws IOException
574 {
575 }
576
577
578
579
580
581 protected void onConnectionFailed(Throwable ex)
582 {
583 Log.warn("CONNECTION FAILED on " + this,ex);
584 }
585
586
587
588
589
590 protected void onException(Throwable ex)
591 {
592 Log.warn("EXCEPTION on " + this,ex);
593 }
594
595
596
597
598 protected void onExpire()
599 {
600 Log.warn("EXPIRED " + this);
601 }
602
603
604
605
606
607
608
609 protected void onRetry() throws IOException
610 {
611 if (_requestContentSource != null)
612 {
613 if (_requestContentSource.markSupported())
614 {
615 _requestContent = null;
616 _requestContentSource.reset();
617 }
618 else
619 {
620 throw new IOException("Unsupported retry attempt");
621 }
622 }
623 }
624
625
626
627
628
629
630
631
632 public boolean configureListeners()
633 {
634 return _configureListeners;
635 }
636
637 public void setConfigureListeners(boolean autoConfigure )
638 {
639 this._configureListeners = autoConfigure;
640 }
641
642 private class Listener implements HttpEventListener
643 {
644 public void onConnectionFailed(Throwable ex)
645 {
646 try
647 {
648 HttpExchange.this.onConnectionFailed(ex);
649 }
650 finally
651 {
652 synchronized(HttpExchange.this)
653 {
654 _onDone=true;
655 HttpExchange.this.notifyAll();
656 }
657 }
658 }
659
660 public void onException(Throwable ex)
661 {
662 try
663 {
664 HttpExchange.this.onException(ex);
665 }
666 finally
667 {
668 synchronized(HttpExchange.this)
669 {
670 _onDone=true;
671 HttpExchange.this.notifyAll();
672 }
673 }
674 }
675
676 public void onExpire()
677 {
678 try
679 {
680 HttpExchange.this.onExpire();
681 }
682 finally
683 {
684 synchronized(HttpExchange.this)
685 {
686 _onDone=true;
687 HttpExchange.this.notifyAll();
688 }
689 }
690 }
691
692 public void onRequestCommitted() throws IOException
693 {
694 HttpExchange.this.onRequestCommitted();
695 }
696
697 public void onRequestComplete() throws IOException
698 {
699 try
700 {
701 HttpExchange.this.onRequestComplete();
702 }
703 finally
704 {
705 synchronized(HttpExchange.this)
706 {
707 _onRequestCompleteDone=true;
708 _onDone=_onResponseCompleteDone;
709 HttpExchange.this.notifyAll();
710 }
711 }
712 }
713
714 public void onResponseComplete() throws IOException
715 {
716 try
717 {
718 HttpExchange.this.onResponseComplete();
719 }
720 finally
721 {
722 synchronized(HttpExchange.this)
723 {
724 _onResponseCompleteDone=true;
725 _onDone=_onRequestCompleteDone;
726 HttpExchange.this.notifyAll();
727 }
728 }
729 }
730
731 public void onResponseContent(Buffer content) throws IOException
732 {
733 HttpExchange.this.onResponseContent(content);
734 }
735
736 public void onResponseHeader(Buffer name, Buffer value) throws IOException
737 {
738 HttpExchange.this.onResponseHeader(name,value);
739 }
740
741 public void onResponseHeaderComplete() throws IOException
742 {
743 HttpExchange.this.onResponseHeaderComplete();
744 }
745
746 public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
747 {
748 HttpExchange.this.onResponseStatus(version,status,reason);
749 }
750
751 public void onRetry()
752 {
753 HttpExchange.this.setRetryStatus( true );
754 try
755 {
756 HttpExchange.this.onRetry();
757 }
758 catch (IOException e)
759 {
760 onException(e);
761 }
762 }
763 }
764
765
766
767
768
769 public static class CachedExchange extends org.mortbay.jetty.client.CachedExchange
770 {
771 public CachedExchange(boolean cacheFields)
772 {
773 super(cacheFields);
774 }
775 }
776
777
778
779
780
781 public static class ContentExchange extends org.mortbay.jetty.client.ContentExchange
782 {
783
784 }
785
786
787
788 }