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