1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.PrintWriter;
19
20 import javax.servlet.ServletInputStream;
21 import javax.servlet.ServletOutputStream;
22 import javax.servlet.http.HttpServletResponse;
23
24 import org.eclipse.jetty.continuation.ContinuationThrowable;
25 import org.eclipse.jetty.http.AbstractGenerator;
26 import org.eclipse.jetty.http.EncodedHttpURI;
27 import org.eclipse.jetty.http.Generator;
28 import org.eclipse.jetty.http.HttpBuffers;
29 import org.eclipse.jetty.http.HttpContent;
30 import org.eclipse.jetty.http.HttpException;
31 import org.eclipse.jetty.http.HttpFields;
32 import org.eclipse.jetty.http.HttpGenerator;
33 import org.eclipse.jetty.http.HttpHeaderValues;
34 import org.eclipse.jetty.http.HttpHeaders;
35 import org.eclipse.jetty.http.HttpMethods;
36 import org.eclipse.jetty.http.HttpParser;
37 import org.eclipse.jetty.http.HttpStatus;
38 import org.eclipse.jetty.http.HttpURI;
39 import org.eclipse.jetty.http.HttpVersions;
40 import org.eclipse.jetty.http.MimeTypes;
41 import org.eclipse.jetty.http.Parser;
42 import org.eclipse.jetty.io.Buffer;
43 import org.eclipse.jetty.io.Connection;
44 import org.eclipse.jetty.io.EndPoint;
45 import org.eclipse.jetty.io.EofException;
46 import org.eclipse.jetty.io.RuntimeIOException;
47 import org.eclipse.jetty.io.UncheckedPrintWriter;
48 import org.eclipse.jetty.io.BufferCache.CachedBuffer;
49 import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
50 import org.eclipse.jetty.util.QuotedStringTokenizer;
51 import org.eclipse.jetty.util.StringUtil;
52 import org.eclipse.jetty.util.URIUtil;
53 import org.eclipse.jetty.util.log.Log;
54 import org.eclipse.jetty.util.resource.Resource;
55 import org.eclipse.jetty.util.thread.Timeout;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public class HttpConnection implements Connection
89 {
90 private static final int UNKNOWN = -2;
91 private static final ThreadLocal<HttpConnection> __currentConnection = new ThreadLocal<HttpConnection>();
92
93 private final long _timeStamp=System.currentTimeMillis();
94 private int _requests;
95 private volatile boolean _handling;
96
97 protected final Connector _connector;
98 protected final EndPoint _endp;
99 protected final Server _server;
100 protected final HttpURI _uri;
101
102 protected final Parser _parser;
103 protected final HttpFields _requestFields;
104 protected final Request _request;
105 protected ServletInputStream _in;
106
107 protected final Generator _generator;
108 protected final HttpFields _responseFields;
109 protected final Response _response;
110 protected Output _out;
111 protected OutputWriter _writer;
112 protected PrintWriter _printWriter;
113
114 int _include;
115
116 private Object _associatedObject;
117
118 private int _version = UNKNOWN;
119
120 private boolean _expect = false;
121 private boolean _expect100Continue = false;
122 private boolean _expect102Processing = false;
123 private boolean _head = false;
124 private boolean _host = false;
125 private boolean _delayedHandling=false;
126
127
128 public static HttpConnection getCurrentConnection()
129 {
130 return __currentConnection.get();
131 }
132
133
134 protected static void setCurrentConnection(HttpConnection connection)
135 {
136 __currentConnection.set(connection);
137 }
138
139
140
141
142
143 public HttpConnection(Connector connector, EndPoint endpoint, Server server)
144 {
145 _uri = StringUtil.__UTF8.equals(URIUtil.__CHARSET)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET);
146 _connector = connector;
147 _endp = endpoint;
148 HttpBuffers ab = (HttpBuffers)_connector;
149 _parser = new HttpParser(ab.getRequestBuffers(), endpoint, new RequestHandler());
150 _requestFields = new HttpFields();
151 _responseFields = new HttpFields();
152 _request = new Request(this);
153 _response = new Response(this);
154 _generator = new HttpGenerator(ab.getResponseBuffers(), _endp);
155 _generator.setSendServerVersion(server.getSendServerVersion());
156 _server = server;
157 }
158
159
160 protected HttpConnection(Connector connector, EndPoint endpoint, Server server,
161 Parser parser, Generator generator, Request request)
162 {
163 _uri = URIUtil.__CHARSET.equals(StringUtil.__UTF8)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET);
164 _connector = connector;
165 _endp = endpoint;
166 _parser = parser;
167 _requestFields = new HttpFields();
168 _responseFields = new HttpFields();
169 _request = request;
170 _response = new Response(this);
171 _generator = generator;
172 _generator.setSendServerVersion(server.getSendServerVersion());
173 _server = server;
174 }
175
176
177
178
179
180 public Parser getParser()
181 {
182 return _parser;
183 }
184
185
186
187
188
189 public int getRequests()
190 {
191 return _requests;
192 }
193
194
195
196
197
198 public long getTimeStamp()
199 {
200 return _timeStamp;
201 }
202
203
204
205
206
207 public Object getAssociatedObject()
208 {
209 return _associatedObject;
210 }
211
212
213
214
215
216 public void setAssociatedObject(Object associatedObject)
217 {
218 _associatedObject = associatedObject;
219 }
220
221
222
223
224
225 public Connector getConnector()
226 {
227 return _connector;
228 }
229
230
231
232
233
234 public HttpFields getRequestFields()
235 {
236 return _requestFields;
237 }
238
239
240
241
242
243 public HttpFields getResponseFields()
244 {
245 return _responseFields;
246 }
247
248
249
250
251
252
253 public boolean isConfidential(Request request)
254 {
255 if (_connector!=null)
256 return _connector.isConfidential(request);
257 return false;
258 }
259
260
261
262
263
264
265
266
267 public boolean isIntegral(Request request)
268 {
269 if (_connector!=null)
270 return _connector.isIntegral(request);
271 return false;
272 }
273
274
275
276
277
278 public EndPoint getEndPoint()
279 {
280 return _endp;
281 }
282
283
284
285
286
287 public boolean getResolveNames()
288 {
289 return _connector.getResolveNames();
290 }
291
292
293
294
295
296 public Request getRequest()
297 {
298 return _request;
299 }
300
301
302
303
304
305 public Response getResponse()
306 {
307 return _response;
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321 public ServletInputStream getInputStream() throws IOException
322 {
323
324 if (_expect100Continue)
325 {
326
327 if (((HttpParser)_parser).getHeaderBuffer()==null || ((HttpParser)_parser).getHeaderBuffer().length()<2)
328 {
329 if (_generator.isCommitted())
330 throw new IllegalStateException("Committed before 100 Continues");
331
332 ((HttpGenerator)_generator).send1xx(HttpStatus.CONTINUE_100);
333 }
334 _expect100Continue=false;
335 }
336
337 if (_in == null)
338 _in = new HttpInput(((HttpParser)_parser),_connector.getMaxIdleTime());
339 return _in;
340 }
341
342
343
344
345
346 public ServletOutputStream getOutputStream()
347 {
348 if (_out == null)
349 _out = new Output();
350 return _out;
351 }
352
353
354
355
356
357
358 public PrintWriter getPrintWriter(String encoding)
359 {
360 getOutputStream();
361 if (_writer==null)
362 {
363 _writer=new OutputWriter();
364 _printWriter=new UncheckedPrintWriter(_writer);
365 }
366 _writer.setCharacterEncoding(encoding);
367 return _printWriter;
368 }
369
370
371 public boolean isResponseCommitted()
372 {
373 return _generator.isCommitted();
374 }
375
376
377 public Connection handle() throws IOException
378 {
379
380 boolean more_in_buffer =true;
381 boolean progress=true;
382
383 try
384 {
385 assert getCurrentConnection()==null;
386 assert _handling==false;
387 _handling=true;
388 setCurrentConnection(this);
389
390 while (more_in_buffer)
391 {
392 try
393 {
394 if (_request._async.isAsync())
395 {
396
397
398
399 Log.debug("async request",_request);
400 if (!_request._async.isComplete())
401 handleRequest();
402 else if (!_parser.isComplete())
403 {
404 long parsed=_parser.parseAvailable();
405 progress|=parsed>0;
406 }
407
408 if (_generator.isCommitted() && !_generator.isComplete())
409 progress|=_generator.flushBuffer()>0;
410 if (_endp.isBufferingOutput())
411 _endp.flush();
412 }
413 else
414 {
415
416 if (!_parser.isComplete())
417 progress|=_parser.parseAvailable()>0;
418
419
420
421
422
423 while (_generator.isCommitted() && !_generator.isComplete())
424 {
425 long written=_generator.flushBuffer();
426 if (written<=0)
427 break;
428 progress=true;
429 if (_endp.isBufferingOutput())
430 _endp.flush();
431 }
432
433
434 if (_endp.isBufferingOutput())
435 {
436 _endp.flush();
437 if (!_endp.isBufferingOutput())
438 progress=true;
439 }
440
441 if (!progress)
442 return this;
443 }
444 progress=false;
445 }
446 catch (HttpException e)
447 {
448 if (Log.isDebugEnabled())
449 {
450 Log.debug("uri="+_uri);
451 Log.debug("fields="+_requestFields);
452 Log.debug(e);
453 }
454 _generator.sendError(e.getStatus(), e.getReason(), null, true);
455
456 _parser.reset(true);
457 _endp.close();
458 throw e;
459 }
460 finally
461 {
462 more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
463
464 if (_parser.isComplete() && _generator.isComplete() && !_endp.isBufferingOutput())
465 {
466 if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
467 {
468 Connection connection = (Connection)_request.getAttribute("org.eclipse.jetty.io.Connection");
469 if (connection!=null)
470 {
471 _parser.reset(true);
472 return connection;
473 }
474 }
475
476 if (!_generator.isPersistent())
477 {
478 _parser.reset(true);
479 more_in_buffer=false;
480 }
481
482 if (more_in_buffer)
483 {
484 reset(false);
485 more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
486 }
487 else
488 reset(true);
489 progress=true;
490 }
491
492 if (_request.isAsyncStarted())
493 {
494 Log.debug("return with suspended request");
495 more_in_buffer=false;
496 }
497 else if (_generator.isCommitted() && !_generator.isComplete() && _endp instanceof SelectChannelEndPoint)
498 ((SelectChannelEndPoint)_endp).setWritable(false);
499 }
500 }
501 }
502 finally
503 {
504 setCurrentConnection(null);
505 _handling=false;
506 }
507 return this;
508 }
509
510
511 public void scheduleTimeout(Timeout.Task task, long timeoutMs)
512 {
513 throw new UnsupportedOperationException();
514 }
515
516
517 public void cancelTimeout(Timeout.Task task)
518 {
519 throw new UnsupportedOperationException();
520 }
521
522
523 public void reset(boolean returnBuffers)
524 {
525 _parser.reset(returnBuffers);
526 _requestFields.clear();
527 _request.recycle();
528
529 _generator.reset(returnBuffers);
530 _responseFields.clear();
531 _response.recycle();
532
533 _uri.clear();
534 }
535
536
537 protected void handleRequest() throws IOException
538 {
539 boolean error = false;
540
541 String threadName=null;
542 try
543 {
544 if (Log.isDebugEnabled())
545 {
546 threadName=Thread.currentThread().getName();
547 Thread.currentThread().setName(threadName+" - "+_uri);
548 }
549
550
551
552
553
554
555
556
557
558
559 final Server server=_server;
560 boolean handling=_request._async.handling() && server!=null && server.isRunning();
561 while (handling)
562 {
563 _request.setHandled(false);
564
565 String info=null;
566 try
567 {
568 _uri.getPort();
569 info=URIUtil.canonicalPath(_uri.getDecodedPath());
570 if (info==null)
571 throw new HttpException(400);
572 _request.setPathInfo(info);
573
574 if (_out!=null)
575 _out.reopen();
576
577 if (_request._async.isInitial())
578 {
579 _request.setDispatcherType(DispatcherType.REQUEST);
580 _connector.customize(_endp, _request);
581 server.handle(this);
582 }
583 else
584 {
585 _request.setDispatcherType(DispatcherType.ASYNC);
586 server.handleAsync(this);
587 }
588 }
589 catch (ContinuationThrowable e)
590 {
591 Log.ignore(e);
592 }
593 catch (EofException e)
594 {
595 Log.debug(e);
596 _request.setHandled(true);
597 error=true;
598 }
599 catch (RuntimeIOException e)
600 {
601 Log.debug(e);
602 _request.setHandled(true);
603 error=true;
604 }
605 catch (HttpException e)
606 {
607 Log.debug(e);
608 _request.setHandled(true);
609 _response.sendError(e.getStatus(), e.getReason());
610 error=true;
611 }
612 catch (Throwable e)
613 {
614 if (e instanceof ThreadDeath)
615 throw (ThreadDeath)e;
616
617 error=true;
618 Log.warn(_uri+": "+e);
619 Log.debug(e);
620 _request.setHandled(true);
621 _generator.sendError(info==null?400:500, null, null, true);
622
623 }
624 finally
625 {
626 handling = !_request._async.unhandle() && server.isRunning() && _server!=null;
627 }
628 }
629 }
630 finally
631 {
632 if (threadName!=null)
633 Thread.currentThread().setName(threadName);
634
635 if (_request._async.isUncompleted())
636 {
637 _request._async.doComplete();
638
639 if (_expect100Continue)
640 {
641 Log.debug("100 continues not sent");
642
643
644
645
646 _expect100Continue = false;
647 }
648
649 if(_endp.isOpen())
650 {
651 if (_generator.isPersistent())
652 _connector.persist(_endp);
653
654 if (error)
655 _endp.close();
656 else
657 {
658 if (!_response.isCommitted() && !_request.isHandled())
659 _response.sendError(HttpServletResponse.SC_NOT_FOUND);
660 _response.complete();
661 }
662 }
663 else
664 {
665 _response.complete();
666 }
667
668 _request.setHandled(true);
669 }
670 }
671 }
672
673
674 public void commitResponse(boolean last) throws IOException
675 {
676 if (!_generator.isCommitted())
677 {
678 _generator.setResponse(_response.getStatus(), _response.getReason());
679 try
680 {
681 _generator.completeHeader(_responseFields, last);
682 }
683 catch(IOException io)
684 {
685 throw io;
686 }
687 catch(RuntimeException e)
688 {
689 Log.warn("header full: "+e);
690
691 _response.reset();
692 _generator.reset(true);
693 _generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500,null);
694 _generator.completeHeader(_responseFields,Generator.LAST);
695 _generator.complete();
696 throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500);
697 }
698
699 }
700 if (last)
701 _generator.complete();
702 }
703
704
705 public void completeResponse() throws IOException
706 {
707 if (!_generator.isCommitted())
708 {
709 _generator.setResponse(_response.getStatus(), _response.getReason());
710 try
711 {
712 _generator.completeHeader(_responseFields, Generator.LAST);
713 }
714 catch(IOException io)
715 {
716 throw io;
717 }
718 catch(RuntimeException e)
719 {
720 Log.warn("header full: "+e);
721 Log.debug(e);
722
723 _response.reset();
724 _generator.reset(true);
725 _generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500,null);
726 _generator.completeHeader(_responseFields,Generator.LAST);
727 _generator.complete();
728 throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500);
729 }
730 }
731
732 _generator.complete();
733 }
734
735
736 public void flushResponse() throws IOException
737 {
738 try
739 {
740 commitResponse(Generator.MORE);
741 _generator.flushBuffer();
742 }
743 catch(IOException e)
744 {
745 throw (e instanceof EofException) ? e:new EofException(e);
746 }
747 }
748
749
750 public Generator getGenerator()
751 {
752 return _generator;
753 }
754
755
756 public boolean isIncluding()
757 {
758 return _include>0;
759 }
760
761
762 public void include()
763 {
764 _include++;
765 }
766
767
768 public void included()
769 {
770 _include--;
771 if (_out!=null)
772 _out.reopen();
773 }
774
775
776 public boolean isIdle()
777 {
778 return _generator.isIdle() && (_parser.isIdle() || _delayedHandling);
779 }
780
781
782
783
784
785 public boolean isSuspended()
786 {
787 return _request.getAsyncContinuation().isSuspended();
788 }
789
790
791 public boolean isExpecting100Continues()
792 {
793 return _expect100Continue;
794 }
795
796
797 public boolean isExpecting102Processing()
798 {
799 return _expect102Processing;
800 }
801
802
803
804
805 private class RequestHandler extends HttpParser.EventHandler
806 {
807 private String _charset;
808
809
810
811
812
813
814 @Override
815 public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException
816 {
817 _host = false;
818 _expect = false;
819 _expect100Continue=false;
820 _expect102Processing=false;
821 _delayedHandling=false;
822 _charset=null;
823
824 if(_request.getTimeStamp()==0)
825 _request.setTimeStamp(System.currentTimeMillis());
826 _request.setMethod(method.toString());
827
828 try
829 {
830 _uri.parse(uri.array(), uri.getIndex(), uri.length());
831 _request.setUri(_uri);
832
833 if (version==null)
834 {
835 _request.setProtocol(HttpVersions.HTTP_0_9);
836 _version=HttpVersions.HTTP_0_9_ORDINAL;
837 }
838 else
839 {
840 version= HttpVersions.CACHE.get(version);
841 _version = HttpVersions.CACHE.getOrdinal(version);
842 if (_version <= 0) _version = HttpVersions.HTTP_1_0_ORDINAL;
843 _request.setProtocol(version.toString());
844 }
845
846 _head = method == HttpMethods.HEAD_BUFFER;
847 }
848 catch (Exception e)
849 {
850 Log.debug(e);
851 throw new HttpException(HttpStatus.BAD_REQUEST_400,null,e);
852 }
853 }
854
855
856
857
858 @Override
859 public void parsedHeader(Buffer name, Buffer value)
860 {
861 int ho = HttpHeaders.CACHE.getOrdinal(name);
862 switch (ho)
863 {
864 case HttpHeaders.HOST_ORDINAL:
865
866 _host = true;
867 break;
868
869 case HttpHeaders.EXPECT_ORDINAL:
870 value = HttpHeaderValues.CACHE.lookup(value);
871 switch(HttpHeaderValues.CACHE.getOrdinal(value))
872 {
873 case HttpHeaderValues.CONTINUE_ORDINAL:
874 _expect100Continue=_generator instanceof HttpGenerator;
875 break;
876
877 case HttpHeaderValues.PROCESSING_ORDINAL:
878 _expect102Processing=_generator instanceof HttpGenerator;
879 break;
880
881 default:
882 String[] values = value.toString().split(",");
883 for (int i=0;values!=null && i<values.length;i++)
884 {
885 CachedBuffer cb=HttpHeaderValues.CACHE.get(values[i].trim());
886 if (cb==null)
887 _expect=true;
888 else
889 {
890 switch(cb.getOrdinal())
891 {
892 case HttpHeaderValues.CONTINUE_ORDINAL:
893 _expect100Continue=_generator instanceof HttpGenerator;
894 break;
895 case HttpHeaderValues.PROCESSING_ORDINAL:
896 _expect102Processing=_generator instanceof HttpGenerator;
897 break;
898 default:
899 _expect=true;
900 }
901 }
902 }
903 }
904 break;
905
906 case HttpHeaders.ACCEPT_ENCODING_ORDINAL:
907 case HttpHeaders.USER_AGENT_ORDINAL:
908 value = HttpHeaderValues.CACHE.lookup(value);
909 break;
910
911 case HttpHeaders.CONTENT_TYPE_ORDINAL:
912 value = MimeTypes.CACHE.lookup(value);
913 _charset=MimeTypes.getCharsetFromContentType(value);
914 break;
915
916 case HttpHeaders.CONNECTION_ORDINAL:
917
918 switch(HttpHeaderValues.CACHE.getOrdinal(value))
919 {
920 case -1:
921 {
922 String[] values = value.toString().split(",");
923 for (int i=0;values!=null && i<values.length;i++)
924 {
925 CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim());
926
927 if (cb!=null)
928 {
929 switch(cb.getOrdinal())
930 {
931 case HttpHeaderValues.CLOSE_ORDINAL:
932 _responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
933 _generator.setPersistent(false);
934 break;
935
936 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
937 if (_version==HttpVersions.HTTP_1_0_ORDINAL)
938 _responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
939 break;
940 }
941 }
942 }
943 break;
944 }
945 case HttpHeaderValues.CLOSE_ORDINAL:
946 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
947 _generator.setPersistent(false);
948 break;
949
950 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
951 if (_version==HttpVersions.HTTP_1_0_ORDINAL)
952 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
953 break;
954 }
955 }
956
957 _requestFields.add(name, value);
958 }
959
960
961
962
963 @Override
964 public void headerComplete() throws IOException
965 {
966 _requests++;
967 _generator.setVersion(_version);
968 switch (_version)
969 {
970 case HttpVersions.HTTP_0_9_ORDINAL:
971 break;
972 case HttpVersions.HTTP_1_0_ORDINAL:
973 _generator.setHead(_head);
974 break;
975 case HttpVersions.HTTP_1_1_ORDINAL:
976 _generator.setHead(_head);
977
978 if (_server.getSendDateHeader())
979 _generator.setDate(_request.getTimeStampBuffer());
980
981 if (!_host)
982 {
983 _generator.setResponse(HttpStatus.BAD_REQUEST_400, null);
984 _responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
985 _generator.completeHeader(_responseFields, true);
986 _generator.complete();
987 return;
988 }
989
990 if (_expect)
991 {
992 _generator.sendError(HttpStatus.EXPECTATION_FAILED_417, null, null, true);
993 return;
994 }
995
996 break;
997 default:
998 }
999
1000 if(_charset!=null)
1001 _request.setCharacterEncodingUnchecked(_charset);
1002
1003
1004 if ((((HttpParser)_parser).getContentLength()<=0 && !((HttpParser)_parser).isChunking())||_expect100Continue)
1005 handleRequest();
1006 else
1007 _delayedHandling=true;
1008 }
1009
1010
1011
1012
1013
1014 @Override
1015 public void content(Buffer ref) throws IOException
1016 {
1017 if (_delayedHandling)
1018 {
1019 _delayedHandling=false;
1020 handleRequest();
1021 }
1022 }
1023
1024
1025
1026
1027
1028
1029
1030 @Override
1031 public void messageComplete(long contentLength) throws IOException
1032 {
1033 if (_delayedHandling)
1034 {
1035 _delayedHandling=false;
1036 handleRequest();
1037 }
1038 }
1039
1040
1041
1042
1043
1044
1045
1046
1047 @Override
1048 public void startResponse(Buffer version, int status, Buffer reason)
1049 {
1050 Log.debug("Bad request!: "+version+" "+status+" "+reason);
1051 }
1052 }
1053
1054
1055
1056
1057
1058 public class Output extends HttpOutput
1059 {
1060 Output()
1061 {
1062 super((AbstractGenerator)HttpConnection.this._generator,
1063 _connector.isLowResources()?_connector.getLowResourceMaxIdleTime():_connector.getMaxIdleTime());
1064 }
1065
1066
1067
1068
1069
1070 @Override
1071 public void close() throws IOException
1072 {
1073 if (_closed)
1074 return;
1075
1076 if (!isIncluding() && !super._generator.isCommitted())
1077 commitResponse(Generator.LAST);
1078 else
1079 flushResponse();
1080
1081 super.close();
1082 }
1083
1084
1085
1086
1087
1088
1089 @Override
1090 public void flush() throws IOException
1091 {
1092 if (!super._generator.isCommitted())
1093 commitResponse(Generator.MORE);
1094 super.flush();
1095 }
1096
1097
1098
1099
1100
1101 @Override
1102 public void print(String s) throws IOException
1103 {
1104 if (_closed)
1105 throw new IOException("Closed");
1106 PrintWriter writer=getPrintWriter(null);
1107 writer.print(s);
1108 }
1109
1110
1111 public void sendResponse(Buffer response) throws IOException
1112 {
1113 ((HttpGenerator)super._generator).sendResponse(response);
1114 }
1115
1116
1117 public void sendContent(Object content) throws IOException
1118 {
1119 Resource resource=null;
1120
1121 if (_closed)
1122 throw new IOException("Closed");
1123
1124 if (super._generator.getContentWritten() > 0)
1125 throw new IllegalStateException("!empty");
1126
1127 if (content instanceof HttpContent)
1128 {
1129 HttpContent c = (HttpContent) content;
1130 Buffer contentType = c.getContentType();
1131 if (contentType != null && !_responseFields.containsKey(HttpHeaders.CONTENT_TYPE_BUFFER))
1132 {
1133 String enc = _response.getSetCharacterEncoding();
1134 if(enc==null)
1135 _responseFields.add(HttpHeaders.CONTENT_TYPE_BUFFER, contentType);
1136 else
1137 {
1138 if(contentType instanceof CachedBuffer)
1139 {
1140 CachedBuffer content_type = ((CachedBuffer)contentType).getAssociate(enc);
1141 if(content_type!=null)
1142 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER, content_type);
1143 else
1144 {
1145 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
1146 contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
1147 }
1148 }
1149 else
1150 {
1151 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
1152 contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
1153 }
1154 }
1155 }
1156 if (c.getContentLength() > 0)
1157 _responseFields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER, c.getContentLength());
1158 Buffer lm = c.getLastModified();
1159 long lml=c.getResource().lastModified();
1160 if (lm != null)
1161 _responseFields.put(HttpHeaders.LAST_MODIFIED_BUFFER, lm,lml);
1162 else if (c.getResource()!=null)
1163 {
1164 if (lml!=-1)
1165 _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, lml);
1166 }
1167
1168 content = c.getBuffer();
1169 if (content==null)
1170 content=c.getInputStream();
1171 }
1172 else if (content instanceof Resource)
1173 {
1174 resource=(Resource)content;
1175 _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, resource.lastModified());
1176 content=resource.getInputStream();
1177 }
1178
1179
1180 if (content instanceof Buffer)
1181 {
1182 super._generator.addContent((Buffer) content, Generator.LAST);
1183 commitResponse(Generator.LAST);
1184 }
1185 else if (content instanceof InputStream)
1186 {
1187 InputStream in = (InputStream)content;
1188
1189 try
1190 {
1191 int max = super._generator.prepareUncheckedAddContent();
1192 Buffer buffer = super._generator.getUncheckedBuffer();
1193
1194 int len=buffer.readFrom(in,max);
1195
1196 while (len>=0)
1197 {
1198 super._generator.completeUncheckedAddContent();
1199 _out.flush();
1200
1201 max = super._generator.prepareUncheckedAddContent();
1202 buffer = super._generator.getUncheckedBuffer();
1203 len=buffer.readFrom(in,max);
1204 }
1205 super._generator.completeUncheckedAddContent();
1206 _out.flush();
1207 }
1208 finally
1209 {
1210 if (resource!=null)
1211 resource.release();
1212 else
1213 in.close();
1214
1215 }
1216 }
1217 else
1218 throw new IllegalArgumentException("unknown content type?");
1219
1220
1221 }
1222 }
1223
1224
1225
1226
1227 public class OutputWriter extends HttpWriter
1228 {
1229 OutputWriter()
1230 {
1231 super(HttpConnection.this._out);
1232 }
1233 }
1234
1235 }