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