1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.client;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.net.URI;
19 import java.util.concurrent.atomic.AtomicInteger;
20
21 import org.eclipse.jetty.client.security.SecurityListener;
22 import org.eclipse.jetty.http.HttpFields;
23 import org.eclipse.jetty.http.HttpHeaders;
24 import org.eclipse.jetty.http.HttpMethods;
25 import org.eclipse.jetty.http.HttpSchemes;
26 import org.eclipse.jetty.http.HttpURI;
27 import org.eclipse.jetty.http.HttpVersions;
28 import org.eclipse.jetty.io.Buffer;
29 import org.eclipse.jetty.io.BufferCache.CachedBuffer;
30 import org.eclipse.jetty.io.ByteArrayBuffer;
31 import org.eclipse.jetty.io.Connection;
32 import org.eclipse.jetty.io.EndPoint;
33 import org.eclipse.jetty.util.log.Log;
34 import org.eclipse.jetty.util.log.Logger;
35 import org.eclipse.jetty.util.thread.Timeout;
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
67
68
69
70
71
72
73 public class HttpExchange
74 {
75 static final Logger LOG = Log.getLogger(HttpExchange.class);
76
77 public static final int STATUS_START = 0;
78 public static final int STATUS_WAITING_FOR_CONNECTION = 1;
79 public static final int STATUS_WAITING_FOR_COMMIT = 2;
80 public static final int STATUS_SENDING_REQUEST = 3;
81 public static final int STATUS_WAITING_FOR_RESPONSE = 4;
82 public static final int STATUS_PARSING_HEADERS = 5;
83 public static final int STATUS_PARSING_CONTENT = 6;
84 public static final int STATUS_COMPLETED = 7;
85 public static final int STATUS_EXPIRED = 8;
86 public static final int STATUS_EXCEPTED = 9;
87 public static final int STATUS_CANCELLING = 10;
88 public static final int STATUS_CANCELLED = 11;
89
90
91 private String _method = HttpMethods.GET;
92 private Buffer _scheme = HttpSchemes.HTTP_BUFFER;
93 private String _uri;
94 private int _version = HttpVersions.HTTP_1_1_ORDINAL;
95 private Address _address;
96 private final HttpFields _requestFields = new HttpFields();
97 private Buffer _requestContent;
98 private InputStream _requestContentSource;
99
100 private AtomicInteger _status = new AtomicInteger(STATUS_START);
101 private boolean _retryStatus = false;
102
103 private boolean _configureListeners = true;
104 private HttpEventListener _listener = new Listener();
105 private volatile AbstractHttpConnection _connection;
106
107 private Address _localAddress = null;
108
109
110 private long _timeout = -1;
111 private volatile Timeout.Task _timeoutTask;
112 private long _lastStateChange=System.currentTimeMillis();
113 private long _sent=-1;
114 private int _lastState=-1;
115 private int _lastStatePeriod=-1;
116
117 boolean _onRequestCompleteDone;
118 boolean _onResponseCompleteDone;
119 boolean _onDone;
120
121 protected void expire(HttpDestination destination)
122 {
123 if (getStatus() < HttpExchange.STATUS_COMPLETED)
124 setStatus(HttpExchange.STATUS_EXPIRED);
125 destination.exchangeExpired(this);
126 AbstractHttpConnection connection = _connection;
127 if (connection != null)
128 connection.exchangeExpired(this);
129 }
130
131 public int getStatus()
132 {
133 return _status.get();
134 }
135
136
137
138
139
140
141
142
143 @Deprecated
144 public void waitForStatus(int status) throws InterruptedException
145 {
146 throw new UnsupportedOperationException();
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160 public int waitForDone() throws InterruptedException
161 {
162 synchronized (this)
163 {
164 while (!isDone())
165 this.wait();
166 return _status.get();
167 }
168 }
169
170 public void reset()
171 {
172
173
174 synchronized (this)
175 {
176 _timeoutTask = null;
177 _onRequestCompleteDone = false;
178 _onResponseCompleteDone = false;
179 _onDone = false;
180 setStatus(STATUS_START);
181 }
182 }
183
184
185
186
187
188
189 boolean setStatus(int newStatus)
190 {
191 boolean set = false;
192 try
193 {
194 int oldStatus = _status.get();
195 boolean ignored = false;
196 if (oldStatus != newStatus)
197 {
198 long now = System.currentTimeMillis();
199 _lastStatePeriod=(int)(now-_lastStateChange);
200 _lastState=oldStatus;
201 _lastStateChange=now;
202 if (newStatus==STATUS_SENDING_REQUEST)
203 _sent=_lastStateChange;
204 }
205
206
207 switch (oldStatus)
208 {
209 case STATUS_START:
210 switch (newStatus)
211 {
212 case STATUS_START:
213 case STATUS_WAITING_FOR_CONNECTION:
214 case STATUS_WAITING_FOR_COMMIT:
215 case STATUS_CANCELLING:
216 case STATUS_EXCEPTED:
217 set = _status.compareAndSet(oldStatus,newStatus);
218 break;
219 case STATUS_EXPIRED:
220 set = setStatusExpired(newStatus,oldStatus);
221 break;
222 }
223 break;
224 case STATUS_WAITING_FOR_CONNECTION:
225 switch (newStatus)
226 {
227 case STATUS_WAITING_FOR_COMMIT:
228 case STATUS_CANCELLING:
229 case STATUS_EXCEPTED:
230 set = _status.compareAndSet(oldStatus,newStatus);
231 break;
232 case STATUS_EXPIRED:
233 set = setStatusExpired(newStatus,oldStatus);
234 break;
235 }
236 break;
237 case STATUS_WAITING_FOR_COMMIT:
238 switch (newStatus)
239 {
240 case STATUS_SENDING_REQUEST:
241 case STATUS_CANCELLING:
242 case STATUS_EXCEPTED:
243 set = _status.compareAndSet(oldStatus,newStatus);
244 break;
245 case STATUS_EXPIRED:
246 set = setStatusExpired(newStatus,oldStatus);
247 break;
248 }
249 break;
250 case STATUS_SENDING_REQUEST:
251 switch (newStatus)
252 {
253 case STATUS_WAITING_FOR_RESPONSE:
254 if (set = _status.compareAndSet(oldStatus,newStatus))
255 getEventListener().onRequestCommitted();
256 break;
257 case STATUS_CANCELLING:
258 case STATUS_EXCEPTED:
259 set = _status.compareAndSet(oldStatus,newStatus);
260 break;
261 case STATUS_EXPIRED:
262 set = setStatusExpired(newStatus,oldStatus);
263 break;
264 }
265 break;
266 case STATUS_WAITING_FOR_RESPONSE:
267 switch (newStatus)
268 {
269 case STATUS_PARSING_HEADERS:
270 case STATUS_CANCELLING:
271 case STATUS_EXCEPTED:
272 set = _status.compareAndSet(oldStatus,newStatus);
273 break;
274 case STATUS_EXPIRED:
275 set = setStatusExpired(newStatus,oldStatus);
276 break;
277 }
278 break;
279 case STATUS_PARSING_HEADERS:
280 switch (newStatus)
281 {
282 case STATUS_PARSING_CONTENT:
283 if (set = _status.compareAndSet(oldStatus,newStatus))
284 getEventListener().onResponseHeaderComplete();
285 break;
286 case STATUS_CANCELLING:
287 case STATUS_EXCEPTED:
288 set = _status.compareAndSet(oldStatus,newStatus);
289 break;
290 case STATUS_EXPIRED:
291 set = setStatusExpired(newStatus,oldStatus);
292 break;
293 }
294 break;
295 case STATUS_PARSING_CONTENT:
296 switch (newStatus)
297 {
298 case STATUS_COMPLETED:
299 if (set = _status.compareAndSet(oldStatus,newStatus))
300 getEventListener().onResponseComplete();
301 break;
302 case STATUS_CANCELLING:
303 case STATUS_EXCEPTED:
304 set = _status.compareAndSet(oldStatus,newStatus);
305 break;
306 case STATUS_EXPIRED:
307 set = setStatusExpired(newStatus,oldStatus);
308 break;
309 }
310 break;
311 case STATUS_COMPLETED:
312 switch (newStatus)
313 {
314 case STATUS_START:
315 case STATUS_EXCEPTED:
316 case STATUS_WAITING_FOR_RESPONSE:
317 set = _status.compareAndSet(oldStatus,newStatus);
318 break;
319 case STATUS_CANCELLING:
320 case STATUS_EXPIRED:
321
322 ignored = true;
323 break;
324 }
325 break;
326 case STATUS_CANCELLING:
327 switch (newStatus)
328 {
329 case STATUS_EXCEPTED:
330 case STATUS_CANCELLED:
331 if (set = _status.compareAndSet(oldStatus,newStatus))
332 done();
333 break;
334 default:
335
336 ignored = true;
337 break;
338 }
339 break;
340 case STATUS_EXCEPTED:
341 case STATUS_EXPIRED:
342 case STATUS_CANCELLED:
343 switch (newStatus)
344 {
345 case STATUS_START:
346 set = _status.compareAndSet(oldStatus,newStatus);
347 break;
348
349 case STATUS_COMPLETED:
350 ignored = true;
351 done();
352 break;
353
354 default:
355 ignored = true;
356 break;
357 }
358 break;
359 default:
360
361 throw new AssertionError(oldStatus + " => " + newStatus);
362 }
363
364 if (!set && !ignored)
365 throw new IllegalStateException(toState(oldStatus) + " => " + toState(newStatus));
366 LOG.debug("setStatus {} {}",newStatus,this);
367 }
368 catch (IOException x)
369 {
370 LOG.warn(x);
371 }
372 return set;
373 }
374
375 private boolean setStatusExpired(int newStatus, int oldStatus)
376 {
377 boolean set;
378 if (set = _status.compareAndSet(oldStatus,newStatus))
379 getEventListener().onExpire();
380 return set;
381 }
382
383 public boolean isDone()
384 {
385 synchronized (this)
386 {
387 return _onDone;
388 }
389 }
390
391
392
393
394 @Deprecated
395 public boolean isDone(int status)
396 {
397 return isDone();
398 }
399
400 public HttpEventListener getEventListener()
401 {
402 return _listener;
403 }
404
405 public void setEventListener(HttpEventListener listener)
406 {
407 _listener = listener;
408 }
409
410 public void setTimeout(long timeout)
411 {
412 _timeout = timeout;
413 }
414
415 public long getTimeout()
416 {
417 return _timeout;
418 }
419
420
421
422
423
424 public void setURL(String url)
425 {
426 setURI(URI.create(url));
427 }
428
429
430
431
432
433 public void setAddress(Address address)
434 {
435 _address = address;
436 }
437
438
439
440
441 public Address getAddress()
442 {
443 return _address;
444 }
445
446
447
448
449
450
451
452
453 public Address getLocalAddress()
454 {
455 return _localAddress;
456 }
457
458
459
460
461
462 public void setScheme(Buffer scheme)
463 {
464 _scheme = scheme;
465 }
466
467
468
469
470
471 public void setScheme(String scheme)
472 {
473 if (scheme != null)
474 {
475 if (HttpSchemes.HTTP.equalsIgnoreCase(scheme))
476 setScheme(HttpSchemes.HTTP_BUFFER);
477 else if (HttpSchemes.HTTPS.equalsIgnoreCase(scheme))
478 setScheme(HttpSchemes.HTTPS_BUFFER);
479 else
480 setScheme(new ByteArrayBuffer(scheme));
481 }
482 }
483
484
485
486
487 public Buffer getScheme()
488 {
489 return _scheme;
490 }
491
492
493
494
495
496 public void setVersion(int version)
497 {
498 _version = version;
499 }
500
501
502
503
504
505 public void setVersion(String version)
506 {
507 CachedBuffer v = HttpVersions.CACHE.get(version);
508 if (v == null)
509 _version = 10;
510 else
511 _version = v.getOrdinal();
512 }
513
514
515
516
517
518 public int getVersion()
519 {
520 return _version;
521 }
522
523
524
525
526
527 public void setMethod(String method)
528 {
529 _method = method;
530 }
531
532
533
534
535 public String getMethod()
536 {
537 return _method;
538 }
539
540
541
542
543
544
545 @Deprecated
546 public String getURI()
547 {
548 return getRequestURI();
549 }
550
551
552
553
554 public String getRequestURI()
555 {
556 return _uri;
557 }
558
559
560
561
562
563
564
565
566
567 @Deprecated
568 public void setURI(String uri)
569 {
570 setRequestURI(uri);
571 }
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590 public void setRequestURI(String uri)
591 {
592 _uri = uri;
593 }
594
595
596
597
598
599
600 public void setURI(URI uri)
601 {
602 if (!uri.isAbsolute())
603 throw new IllegalArgumentException("!Absolute URI: " + uri);
604
605 if (uri.isOpaque())
606 throw new IllegalArgumentException("Opaque URI: " + uri);
607
608 if (LOG.isDebugEnabled())
609 LOG.debug("URI = {}",uri.toASCIIString());
610
611 String scheme = uri.getScheme();
612 int port = uri.getPort();
613 if (port <= 0)
614 port = "https".equalsIgnoreCase(scheme)?443:80;
615
616 setScheme(scheme);
617 setAddress(new Address(uri.getHost(),port));
618
619 HttpURI httpUri = new HttpURI(uri);
620 String completePath = httpUri.getCompletePath();
621 setRequestURI(completePath == null?"/":completePath);
622 }
623
624
625
626
627
628
629
630
631
632 public void addRequestHeader(String name, String value)
633 {
634 getRequestFields().add(name,value);
635 }
636
637
638
639
640
641
642
643
644
645 public void addRequestHeader(Buffer name, Buffer value)
646 {
647 getRequestFields().add(name,value);
648 }
649
650
651
652
653
654
655
656
657
658 public void setRequestHeader(String name, String value)
659 {
660 getRequestFields().put(name,value);
661 }
662
663
664
665
666
667
668
669
670
671 public void setRequestHeader(Buffer name, Buffer value)
672 {
673 getRequestFields().put(name,value);
674 }
675
676
677
678
679
680 public void setRequestContentType(String value)
681 {
682 getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,value);
683 }
684
685
686
687
688 public HttpFields getRequestFields()
689 {
690 return _requestFields;
691 }
692
693
694
695
696
697 public void setRequestContent(Buffer requestContent)
698 {
699 _requestContent = requestContent;
700 }
701
702
703
704
705
706 public void setRequestContentSource(InputStream stream)
707 {
708 _requestContentSource = stream;
709 if (_requestContentSource != null && _requestContentSource.markSupported())
710 _requestContentSource.mark(Integer.MAX_VALUE);
711 }
712
713
714
715
716 public InputStream getRequestContentSource()
717 {
718 return _requestContentSource;
719 }
720
721 public Buffer getRequestContentChunk(Buffer buffer) throws IOException
722 {
723 synchronized (this)
724 {
725 if (_requestContentSource!=null)
726 {
727 if (buffer == null)
728 buffer = new ByteArrayBuffer(8192);
729
730 int space = buffer.space();
731 int length = _requestContentSource.read(buffer.array(),buffer.putIndex(),space);
732 if (length >= 0)
733 {
734 buffer.setPutIndex(buffer.putIndex()+length);
735 return buffer;
736 }
737 }
738 return null;
739 }
740 }
741
742
743
744
745 public Buffer getRequestContent()
746 {
747 return _requestContent;
748 }
749
750
751
752
753 public boolean getRetryStatus()
754 {
755 return _retryStatus;
756 }
757
758
759
760
761
762 public void setRetryStatus(boolean retryStatus)
763 {
764 _retryStatus = retryStatus;
765 }
766
767
768
769
770
771
772
773 public void cancel()
774 {
775 setStatus(STATUS_CANCELLING);
776 abort();
777 }
778
779 private void done()
780 {
781 synchronized (this)
782 {
783 disassociate();
784 _onDone = true;
785 notifyAll();
786 }
787 }
788
789 private void abort()
790 {
791 AbstractHttpConnection httpConnection = _connection;
792 if (httpConnection != null)
793 {
794 try
795 {
796
797
798 httpConnection.close();
799 }
800 catch (IOException x)
801 {
802 LOG.debug(x);
803 }
804 finally
805 {
806 disassociate();
807 }
808 }
809 }
810
811 void associate(AbstractHttpConnection connection)
812 {
813 if (connection.getEndPoint().getLocalHost() != null)
814 _localAddress = new Address(connection.getEndPoint().getLocalHost(),connection.getEndPoint().getLocalPort());
815
816 _connection = connection;
817 if (getStatus() == STATUS_CANCELLING)
818 abort();
819 }
820
821 boolean isAssociated()
822 {
823 return this._connection != null;
824 }
825
826 AbstractHttpConnection disassociate()
827 {
828 AbstractHttpConnection result = _connection;
829 this._connection = null;
830 if (getStatus() == STATUS_CANCELLING)
831 setStatus(STATUS_CANCELLED);
832 return result;
833 }
834
835 public static String toState(int s)
836 {
837 String state;
838 switch (s)
839 {
840 case STATUS_START:
841 state = "START";
842 break;
843 case STATUS_WAITING_FOR_CONNECTION:
844 state = "CONNECTING";
845 break;
846 case STATUS_WAITING_FOR_COMMIT:
847 state = "CONNECTED";
848 break;
849 case STATUS_SENDING_REQUEST:
850 state = "SENDING";
851 break;
852 case STATUS_WAITING_FOR_RESPONSE:
853 state = "WAITING";
854 break;
855 case STATUS_PARSING_HEADERS:
856 state = "HEADERS";
857 break;
858 case STATUS_PARSING_CONTENT:
859 state = "CONTENT";
860 break;
861 case STATUS_COMPLETED:
862 state = "COMPLETED";
863 break;
864 case STATUS_EXPIRED:
865 state = "EXPIRED";
866 break;
867 case STATUS_EXCEPTED:
868 state = "EXCEPTED";
869 break;
870 case STATUS_CANCELLING:
871 state = "CANCELLING";
872 break;
873 case STATUS_CANCELLED:
874 state = "CANCELLED";
875 break;
876 default:
877 state = "UNKNOWN";
878 }
879 return state;
880 }
881
882 @Override
883 public String toString()
884 {
885 String state=toState(getStatus());
886 long now=System.currentTimeMillis();
887 long forMs = now -_lastStateChange;
888 String s= _lastState>=0
889 ?String.format("%s@%x=%s//%s%s#%s(%dms)->%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,toState(_lastState),_lastStatePeriod,state,forMs)
890 :String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs);
891 if (getStatus()>=STATUS_SENDING_REQUEST && _sent>0)
892 s+="sent="+(now-_sent)+"ms";
893 return s;
894 }
895
896
897
898 protected Connection onSwitchProtocol(EndPoint endp) throws IOException
899 {
900 return null;
901 }
902
903
904
905
906
907
908
909 protected void onRequestCommitted() throws IOException
910 {
911 }
912
913
914
915
916
917
918
919 protected void onRequestComplete() throws IOException
920 {
921 }
922
923
924
925
926
927
928
929
930
931
932
933
934
935 protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
936 {
937 }
938
939
940
941
942
943
944
945
946
947
948
949 protected void onResponseHeader(Buffer name, Buffer value) throws IOException
950 {
951 }
952
953
954
955
956
957
958
959 protected void onResponseHeaderComplete() throws IOException
960 {
961 }
962
963
964
965
966
967
968
969
970
971 protected void onResponseContent(Buffer content) throws IOException
972 {
973 }
974
975
976
977
978
979
980
981 protected void onResponseComplete() throws IOException
982 {
983 }
984
985
986
987
988
989
990
991
992 protected void onConnectionFailed(Throwable x)
993 {
994 LOG.warn("CONNECTION FAILED " + this,x);
995 }
996
997
998
999
1000
1001
1002
1003 protected void onException(Throwable x)
1004 {
1005 LOG.warn("EXCEPTION " + this,x);
1006 }
1007
1008
1009
1010
1011 protected void onExpire()
1012 {
1013 LOG.warn("EXPIRED " + this);
1014 }
1015
1016
1017
1018
1019
1020
1021
1022 protected void onRetry() throws IOException
1023 {
1024 if (_requestContentSource != null)
1025 {
1026 if (_requestContentSource.markSupported())
1027 {
1028 _requestContent = null;
1029 _requestContentSource.reset();
1030 }
1031 else
1032 {
1033 throw new IOException("Unsupported retry attempt");
1034 }
1035 }
1036 }
1037
1038
1039
1040
1041
1042 public boolean configureListeners()
1043 {
1044 return _configureListeners;
1045 }
1046
1047
1048
1049
1050
1051 public void setConfigureListeners(boolean autoConfigure)
1052 {
1053 this._configureListeners = autoConfigure;
1054 }
1055
1056 protected void scheduleTimeout(final HttpDestination destination)
1057 {
1058 assert _timeoutTask == null;
1059
1060 _timeoutTask = new Timeout.Task()
1061 {
1062 @Override
1063 public void expired()
1064 {
1065 HttpExchange.this.expire(destination);
1066 }
1067 };
1068
1069 HttpClient httpClient = destination.getHttpClient();
1070 long timeout = getTimeout();
1071 if (timeout > 0)
1072 httpClient.schedule(_timeoutTask,timeout);
1073 else
1074 httpClient.schedule(_timeoutTask);
1075 }
1076
1077 protected void cancelTimeout(HttpClient httpClient)
1078 {
1079 Timeout.Task task = _timeoutTask;
1080 if (task != null)
1081 httpClient.cancel(task);
1082 _timeoutTask = null;
1083 }
1084
1085 private class Listener implements HttpEventListener
1086 {
1087 public void onConnectionFailed(Throwable ex)
1088 {
1089 try
1090 {
1091 HttpExchange.this.onConnectionFailed(ex);
1092 }
1093 finally
1094 {
1095 done();
1096 }
1097 }
1098
1099 public void onException(Throwable ex)
1100 {
1101 try
1102 {
1103 HttpExchange.this.onException(ex);
1104 }
1105 finally
1106 {
1107 done();
1108 }
1109 }
1110
1111 public void onExpire()
1112 {
1113 try
1114 {
1115 HttpExchange.this.onExpire();
1116 }
1117 finally
1118 {
1119 done();
1120 }
1121 }
1122
1123 public void onRequestCommitted() throws IOException
1124 {
1125 HttpExchange.this.onRequestCommitted();
1126 }
1127
1128 public void onRequestComplete() throws IOException
1129 {
1130 try
1131 {
1132 HttpExchange.this.onRequestComplete();
1133 }
1134 finally
1135 {
1136 synchronized (HttpExchange.this)
1137 {
1138 _onRequestCompleteDone = true;
1139
1140
1141 _onDone |= _onResponseCompleteDone;
1142 if (_onDone)
1143 disassociate();
1144 HttpExchange.this.notifyAll();
1145 }
1146 }
1147 }
1148
1149 public void onResponseComplete() throws IOException
1150 {
1151 try
1152 {
1153 HttpExchange.this.onResponseComplete();
1154 }
1155 finally
1156 {
1157 synchronized (HttpExchange.this)
1158 {
1159 _onResponseCompleteDone = true;
1160
1161
1162 _onDone |= _onRequestCompleteDone;
1163 if (_onDone)
1164 disassociate();
1165 HttpExchange.this.notifyAll();
1166 }
1167 }
1168 }
1169
1170 public void onResponseContent(Buffer content) throws IOException
1171 {
1172 HttpExchange.this.onResponseContent(content);
1173 }
1174
1175 public void onResponseHeader(Buffer name, Buffer value) throws IOException
1176 {
1177 HttpExchange.this.onResponseHeader(name,value);
1178 }
1179
1180 public void onResponseHeaderComplete() throws IOException
1181 {
1182 HttpExchange.this.onResponseHeaderComplete();
1183 }
1184
1185 public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
1186 {
1187 HttpExchange.this.onResponseStatus(version,status,reason);
1188 }
1189
1190 public void onRetry()
1191 {
1192 HttpExchange.this.setRetryStatus(true);
1193 try
1194 {
1195 HttpExchange.this.onRetry();
1196 }
1197 catch (IOException e)
1198 {
1199 LOG.debug(e);
1200 }
1201 }
1202 }
1203
1204
1205
1206
1207 @Deprecated
1208 public static class CachedExchange extends org.eclipse.jetty.client.CachedExchange
1209 {
1210 public CachedExchange(boolean cacheFields)
1211 {
1212 super(cacheFields);
1213 }
1214 }
1215
1216
1217
1218
1219 @Deprecated
1220 public static class ContentExchange extends org.eclipse.jetty.client.ContentExchange
1221 {
1222 }
1223 }