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 import javax.servlet.ServletInputStream;
20 import javax.servlet.ServletOutputStream;
21 import javax.servlet.http.HttpServletResponse;
22
23 import org.eclipse.jetty.continuation.ContinuationThrowable;
24 import org.eclipse.jetty.http.AbstractGenerator;
25 import org.eclipse.jetty.http.EncodedHttpURI;
26 import org.eclipse.jetty.http.Generator;
27 import org.eclipse.jetty.http.HttpBuffers;
28 import org.eclipse.jetty.http.HttpContent;
29 import org.eclipse.jetty.http.HttpException;
30 import org.eclipse.jetty.http.HttpFields;
31 import org.eclipse.jetty.http.HttpGenerator;
32 import org.eclipse.jetty.http.HttpHeaderValues;
33 import org.eclipse.jetty.http.HttpHeaders;
34 import org.eclipse.jetty.http.HttpMethods;
35 import org.eclipse.jetty.http.HttpParser;
36 import org.eclipse.jetty.http.HttpStatus;
37 import org.eclipse.jetty.http.HttpURI;
38 import org.eclipse.jetty.http.HttpVersions;
39 import org.eclipse.jetty.http.MimeTypes;
40 import org.eclipse.jetty.http.Parser;
41 import org.eclipse.jetty.io.Buffer;
42 import org.eclipse.jetty.io.BufferCache.CachedBuffer;
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.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 UncheckedPrintWriter(_writer);
347 }
348 _writer.setCharacterEncoding(encoding);
349 return _printWriter;
350 }
351
352
353 public boolean isResponseCommitted()
354 {
355 return _generator.isCommitted();
356 }
357
358
359 public void handle() throws IOException
360 {
361
362 boolean more_in_buffer =true;
363 boolean progress=true;
364
365 try
366 {
367 assert getCurrentConnection()==null;
368 assert _handling==false;
369 _handling=true;
370 setCurrentConnection(this);
371
372 while (more_in_buffer)
373 {
374 try
375 {
376 if (_request._async.isAsync())
377 {
378
379
380
381 Log.debug("async request",_request);
382 if (!_request._async.isComplete())
383 handleRequest();
384 else if (!_parser.isComplete())
385 {
386 long parsed=_parser.parseAvailable();
387 progress|=parsed>0;
388 }
389
390 if (_generator.isCommitted() && !_generator.isComplete())
391 progress|=_generator.flushBuffer()>0;
392 if (_endp.isBufferingOutput())
393 _endp.flush();
394 }
395 else
396 {
397
398 if (!_parser.isComplete())
399 progress|=_parser.parseAvailable()>0;
400
401
402
403
404
405 while (_generator.isCommitted() && !_generator.isComplete())
406 {
407 long written=_generator.flushBuffer();
408 if (written<=0)
409 break;
410 progress=true;
411 if (_endp.isBufferingOutput())
412 _endp.flush();
413 }
414
415
416 if (_endp.isBufferingOutput())
417 {
418 _endp.flush();
419 if (!_endp.isBufferingOutput())
420 progress=true;
421 }
422
423 if (!progress)
424 return;
425 }
426 progress=false;
427 }
428 catch (HttpException e)
429 {
430 if (Log.isDebugEnabled())
431 {
432 Log.debug("uri="+_uri);
433 Log.debug("fields="+_requestFields);
434 Log.debug(e);
435 }
436 _generator.sendError(e.getStatus(), e.getReason(), null, true);
437
438 _parser.reset(true);
439 _endp.close();
440 throw e;
441 }
442 finally
443 {
444 more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
445
446 if (_parser.isComplete() && _generator.isComplete() && !_endp.isBufferingOutput())
447 {
448 if (!_generator.isPersistent())
449 {
450 _parser.reset(true);
451 more_in_buffer=false;
452 }
453
454 reset(!more_in_buffer);
455 progress=true;
456 }
457
458 if (_request.isAsyncStarted())
459 {
460 Log.debug("return with suspended request");
461 more_in_buffer=false;
462 }
463 else if (_generator.isCommitted() && !_generator.isComplete() && _endp instanceof SelectChannelEndPoint)
464 ((SelectChannelEndPoint)_endp).setWritable(false);
465 }
466 }
467 }
468 finally
469 {
470 setCurrentConnection(null);
471 _handling=false;
472 }
473 }
474
475
476 public void scheduleTimeout(Timeout.Task task, long timeoutMs)
477 {
478 throw new UnsupportedOperationException();
479 }
480
481
482 public void cancelTimeout(Timeout.Task task)
483 {
484 throw new UnsupportedOperationException();
485 }
486
487
488 public void reset(boolean returnBuffers)
489 {
490 _parser.reset(returnBuffers);
491 _requestFields.clear();
492 _request.recycle();
493
494 _generator.reset(returnBuffers);
495 _responseFields.clear();
496 _response.recycle();
497
498 _uri.clear();
499 }
500
501
502 protected void handleRequest() throws IOException
503 {
504 boolean error = false;
505
506 String threadName=null;
507 try
508 {
509 if (Log.isDebugEnabled())
510 {
511 threadName=Thread.currentThread().getName();
512 Thread.currentThread().setName(threadName+" - "+_uri);
513 }
514
515
516
517
518
519
520
521
522
523
524 final Server server=_server;
525 boolean handling=_request._async.handling() && server!=null && server.isRunning();
526 while (handling)
527 {
528 _request.setHandled(false);
529
530 String info=null;
531 try
532 {
533 _uri.getPort();
534 info=URIUtil.canonicalPath(_uri.getDecodedPath());
535 if (info==null)
536 throw new HttpException(400);
537 _request.setPathInfo(info);
538
539 if (_out!=null)
540 _out.reopen();
541
542 if (_request._async.isInitial())
543 {
544 _request.setDispatcherType(DispatcherType.REQUEST);
545 _connector.customize(_endp, _request);
546 server.handle(this);
547 }
548 else
549 {
550 _request.setDispatcherType(DispatcherType.ASYNC);
551 server.handleAsync(this);
552 }
553 }
554 catch (ContinuationThrowable e)
555 {
556 Log.ignore(e);
557 }
558 catch (EofException e)
559 {
560 Log.debug(e);
561 _request.setHandled(true);
562 error=true;
563 }
564 catch (RuntimeIOException e)
565 {
566 Log.debug(e);
567 _request.setHandled(true);
568 error=true;
569 }
570 catch (HttpException e)
571 {
572 Log.debug(e);
573 _request.setHandled(true);
574 _response.sendError(e.getStatus(), e.getReason());
575 error=true;
576 }
577 catch (Throwable e)
578 {
579 if (e instanceof ThreadDeath)
580 throw (ThreadDeath)e;
581
582 error=true;
583 if (info==null)
584 {
585 Log.debug(_uri+": "+e);
586 _request.setHandled(true);
587 _generator.sendError(400, null, null, true);
588 }
589 else
590 {
591 Log.debug(""+_uri,e);
592 _request.setHandled(true);
593 _generator.sendError(500, null, null, true);
594 }
595 }
596 finally
597 {
598 handling = !_request._async.unhandle() && server.isRunning() && _server!=null;
599 }
600 }
601 }
602 finally
603 {
604 if (threadName!=null)
605 Thread.currentThread().setName(threadName);
606
607 if (_request._async.isUncompleted())
608 {
609 _request._async.doComplete();
610
611 if (_expect100Continue)
612 {
613
614 _expect100Continue = false;
615 if (_parser instanceof HttpParser)
616 ((HttpParser)_parser).setState(HttpParser.STATE_END);
617 }
618
619 if(_endp.isOpen())
620 {
621 if (_generator.isPersistent())
622 _connector.persist(_endp);
623
624 if (error)
625 _endp.close();
626 else
627 {
628 if (!_response.isCommitted() && !_request.isHandled())
629 _response.sendError(HttpServletResponse.SC_NOT_FOUND);
630 _response.complete();
631 }
632 }
633 else
634 {
635 _response.complete();
636 }
637
638 _request.setHandled(true);
639 }
640 }
641 }
642
643
644 public void commitResponse(boolean last) throws IOException
645 {
646 if (!_generator.isCommitted())
647 {
648 _generator.setResponse(_response.getStatus(), _response.getReason());
649 try
650 {
651 _generator.completeHeader(_responseFields, last);
652 }
653 catch(IOException io)
654 {
655 throw io;
656 }
657 catch(RuntimeException e)
658 {
659 Log.warn("header full: "+e);
660 Log.debug(e);
661
662 _response.reset();
663 _generator.reset(true);
664 _generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500,null);
665 _generator.completeHeader(_responseFields,HttpGenerator.LAST);
666 _generator.complete();
667 throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500);
668 }
669
670 }
671 if (last)
672 _generator.complete();
673 }
674
675
676 public void completeResponse() throws IOException
677 {
678 if (!_generator.isCommitted())
679 {
680 _generator.setResponse(_response.getStatus(), _response.getReason());
681 try
682 {
683 _generator.completeHeader(_responseFields, HttpGenerator.LAST);
684 }
685 catch(IOException io)
686 {
687 throw io;
688 }
689 catch(RuntimeException e)
690 {
691 Log.warn("header full: "+e);
692 Log.debug(e);
693
694 _response.reset();
695 _generator.reset(true);
696 _generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500,null);
697 _generator.completeHeader(_responseFields,HttpGenerator.LAST);
698 _generator.complete();
699 throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500);
700 }
701 }
702
703 _generator.complete();
704 }
705
706
707 public void flushResponse() throws IOException
708 {
709 try
710 {
711 commitResponse(HttpGenerator.MORE);
712 _generator.flushBuffer();
713 }
714 catch(IOException e)
715 {
716 throw (e instanceof EofException) ? e:new EofException(e);
717 }
718 }
719
720
721 public Generator getGenerator()
722 {
723 return _generator;
724 }
725
726
727 public boolean isIncluding()
728 {
729 return _include>0;
730 }
731
732
733 public void include()
734 {
735 _include++;
736 }
737
738
739 public void included()
740 {
741 _include--;
742 if (_out!=null)
743 _out.reopen();
744 }
745
746
747 public boolean isIdle()
748 {
749 return _generator.isIdle() && (_parser.isIdle() || _delayedHandling);
750 }
751
752
753
754
755
756 public boolean isSuspended()
757 {
758 return _request.getAsyncContinuation().isSuspended();
759 }
760
761
762 public boolean isExpecting100Continues()
763 {
764 return _expect100Continue;
765 }
766
767
768 public boolean isExpecting102Processing()
769 {
770 return _expect102Processing;
771 }
772
773
774
775
776 private class RequestHandler extends HttpParser.EventHandler
777 {
778 private String _charset;
779
780
781
782
783
784
785 public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException
786 {
787 _host = false;
788 _expect = false;
789 _expect100Continue=false;
790 _expect102Processing=false;
791 _delayedHandling=false;
792 _charset=null;
793
794 if(_request.getTimeStamp()==0)
795 _request.setTimeStamp(System.currentTimeMillis());
796 _request.setMethod(method.toString());
797
798 try
799 {
800 _uri.parse(uri.array(), uri.getIndex(), uri.length());
801 _request.setUri(_uri);
802
803 if (version==null)
804 {
805 _request.setProtocol(HttpVersions.HTTP_0_9);
806 _version=HttpVersions.HTTP_0_9_ORDINAL;
807 }
808 else
809 {
810 version= HttpVersions.CACHE.get(version);
811 _version = HttpVersions.CACHE.getOrdinal(version);
812 if (_version <= 0) _version = HttpVersions.HTTP_1_0_ORDINAL;
813 _request.setProtocol(version.toString());
814 }
815
816 _head = method == HttpMethods.HEAD_BUFFER;
817 }
818 catch (Exception e)
819 {
820 Log.debug(e);
821 throw new HttpException(HttpStatus.BAD_REQUEST_400,null,e);
822 }
823 }
824
825
826
827
828 public void parsedHeader(Buffer name, Buffer value)
829 {
830 int ho = HttpHeaders.CACHE.getOrdinal(name);
831 switch (ho)
832 {
833 case HttpHeaders.HOST_ORDINAL:
834
835 _host = true;
836 break;
837
838 case HttpHeaders.EXPECT_ORDINAL:
839 value = HttpHeaderValues.CACHE.lookup(value);
840 switch(HttpHeaderValues.CACHE.getOrdinal(value))
841 {
842 case HttpHeaderValues.CONTINUE_ORDINAL:
843 _expect100Continue=_generator instanceof HttpGenerator;
844 break;
845
846 case HttpHeaderValues.PROCESSING_ORDINAL:
847 _expect102Processing=_generator instanceof HttpGenerator;
848 break;
849
850 default:
851 String[] values = value.toString().split(",");
852 for (int i=0;values!=null && i<values.length;i++)
853 {
854 CachedBuffer cb=HttpHeaderValues.CACHE.get(values[i].trim());
855 if (cb==null)
856 _expect=true;
857 else
858 {
859 switch(cb.getOrdinal())
860 {
861 case HttpHeaderValues.CONTINUE_ORDINAL:
862 _expect100Continue=_generator instanceof HttpGenerator;
863 break;
864 case HttpHeaderValues.PROCESSING_ORDINAL:
865 _expect102Processing=_generator instanceof HttpGenerator;
866 break;
867 default:
868 _expect=true;
869 }
870 }
871 }
872 }
873 break;
874
875 case HttpHeaders.ACCEPT_ENCODING_ORDINAL:
876 case HttpHeaders.USER_AGENT_ORDINAL:
877 value = HttpHeaderValues.CACHE.lookup(value);
878 break;
879
880 case HttpHeaders.CONTENT_TYPE_ORDINAL:
881 value = MimeTypes.CACHE.lookup(value);
882 _charset=MimeTypes.getCharsetFromContentType(value);
883 break;
884
885 case HttpHeaders.CONNECTION_ORDINAL:
886
887 switch(HttpHeaderValues.CACHE.getOrdinal(value))
888 {
889 case -1:
890 {
891 String[] values = value.toString().split(",");
892 for (int i=0;values!=null && i<values.length;i++)
893 {
894 CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim());
895
896 if (cb!=null)
897 {
898 switch(cb.getOrdinal())
899 {
900 case HttpHeaderValues.CLOSE_ORDINAL:
901 _responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
902 _generator.setPersistent(false);
903 break;
904
905 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
906 if (_version==HttpVersions.HTTP_1_0_ORDINAL)
907 _responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
908 break;
909 }
910 }
911 }
912 break;
913 }
914 case HttpHeaderValues.CLOSE_ORDINAL:
915 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
916 _generator.setPersistent(false);
917 break;
918
919 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
920 if (_version==HttpVersions.HTTP_1_0_ORDINAL)
921 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
922 break;
923 }
924 }
925
926 _requestFields.add(name, value);
927 }
928
929
930
931
932 public void headerComplete() throws IOException
933 {
934 _requests++;
935 _generator.setVersion(_version);
936 switch (_version)
937 {
938 case HttpVersions.HTTP_0_9_ORDINAL:
939 break;
940 case HttpVersions.HTTP_1_0_ORDINAL:
941 _generator.setHead(_head);
942 break;
943 case HttpVersions.HTTP_1_1_ORDINAL:
944 _generator.setHead(_head);
945
946 if (_server.getSendDateHeader())
947 _responseFields.put(HttpHeaders.DATE_BUFFER, _request.getTimeStampBuffer(),_request.getTimeStamp());
948
949 if (!_host)
950 {
951 _generator.setResponse(HttpStatus.BAD_REQUEST_400, null);
952 _responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
953 _generator.completeHeader(_responseFields, true);
954 _generator.complete();
955 return;
956 }
957
958 if (_expect)
959 {
960 _generator.sendError(HttpStatus.EXPECTATION_FAILED_417, null, null, true);
961 return;
962 }
963
964 break;
965 default:
966 }
967
968 if(_charset!=null)
969 _request.setCharacterEncodingUnchecked(_charset);
970
971
972 if ((((HttpParser)_parser).getContentLength()<=0 && !((HttpParser)_parser).isChunking())||_expect100Continue)
973 handleRequest();
974 else
975 _delayedHandling=true;
976 }
977
978
979
980
981
982 public void content(Buffer ref) throws IOException
983 {
984 if (_delayedHandling)
985 {
986 _delayedHandling=false;
987 handleRequest();
988 }
989 }
990
991
992
993
994
995
996
997 public void messageComplete(long contentLength) throws IOException
998 {
999 if (_delayedHandling)
1000 {
1001 _delayedHandling=false;
1002 handleRequest();
1003 }
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013 public void startResponse(Buffer version, int status, Buffer reason)
1014 {
1015 Log.debug("Bad request!: "+version+" "+status+" "+reason);
1016 }
1017 }
1018
1019
1020
1021
1022
1023 public class Output extends HttpOutput
1024 {
1025 Output()
1026 {
1027 super((AbstractGenerator)HttpConnection.this._generator,
1028 _connector.isLowResources()?_connector.getLowResourceMaxIdleTime():_connector.getMaxIdleTime());
1029 }
1030
1031
1032
1033
1034
1035 public void close() throws IOException
1036 {
1037 if (_closed)
1038 return;
1039
1040 if (!isIncluding() && !super._generator.isCommitted())
1041 commitResponse(HttpGenerator.LAST);
1042 else
1043 flushResponse();
1044
1045 super.close();
1046 }
1047
1048
1049
1050
1051
1052
1053 public void flush() throws IOException
1054 {
1055 if (!super._generator.isCommitted())
1056 commitResponse(HttpGenerator.MORE);
1057 super.flush();
1058 }
1059
1060
1061
1062
1063
1064 public void print(String s) throws IOException
1065 {
1066 if (_closed)
1067 throw new IOException("Closed");
1068 PrintWriter writer=getPrintWriter(null);
1069 writer.print(s);
1070 }
1071
1072
1073 public void sendResponse(Buffer response) throws IOException
1074 {
1075 ((HttpGenerator)super._generator).sendResponse(response);
1076 }
1077
1078
1079 public void sendContent(Object content) throws IOException
1080 {
1081 Resource resource=null;
1082
1083 if (_closed)
1084 throw new IOException("Closed");
1085
1086 if (super._generator.getContentWritten() > 0)
1087 throw new IllegalStateException("!empty");
1088
1089 if (content instanceof HttpContent)
1090 {
1091 HttpContent c = (HttpContent) content;
1092 Buffer contentType = c.getContentType();
1093 if (contentType != null && !_responseFields.containsKey(HttpHeaders.CONTENT_TYPE_BUFFER))
1094 {
1095 String enc = _response.getSetCharacterEncoding();
1096 if(enc==null)
1097 _responseFields.add(HttpHeaders.CONTENT_TYPE_BUFFER, contentType);
1098 else
1099 {
1100 if(contentType instanceof CachedBuffer)
1101 {
1102 CachedBuffer content_type = ((CachedBuffer)contentType).getAssociate(enc);
1103 if(content_type!=null)
1104 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER, content_type);
1105 else
1106 {
1107 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
1108 contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
1109 }
1110 }
1111 else
1112 {
1113 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
1114 contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
1115 }
1116 }
1117 }
1118 if (c.getContentLength() > 0)
1119 _responseFields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER, c.getContentLength());
1120 Buffer lm = c.getLastModified();
1121 long lml=c.getResource().lastModified();
1122 if (lm != null)
1123 _responseFields.put(HttpHeaders.LAST_MODIFIED_BUFFER, lm,lml);
1124 else if (c.getResource()!=null)
1125 {
1126 if (lml!=-1)
1127 _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, lml);
1128 }
1129
1130 content = c.getBuffer();
1131 if (content==null)
1132 content=c.getInputStream();
1133 }
1134 else if (content instanceof Resource)
1135 {
1136 resource=(Resource)content;
1137 _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, resource.lastModified());
1138 content=resource.getInputStream();
1139 }
1140
1141
1142 if (content instanceof Buffer)
1143 {
1144 super._generator.addContent((Buffer) content, HttpGenerator.LAST);
1145 commitResponse(HttpGenerator.LAST);
1146 }
1147 else if (content instanceof InputStream)
1148 {
1149 InputStream in = (InputStream)content;
1150
1151 try
1152 {
1153 int max = super._generator.prepareUncheckedAddContent();
1154 Buffer buffer = super._generator.getUncheckedBuffer();
1155
1156 int len=buffer.readFrom(in,max);
1157
1158 while (len>=0)
1159 {
1160 super._generator.completeUncheckedAddContent();
1161 _out.flush();
1162
1163 max = super._generator.prepareUncheckedAddContent();
1164 buffer = super._generator.getUncheckedBuffer();
1165 len=buffer.readFrom(in,max);
1166 }
1167 super._generator.completeUncheckedAddContent();
1168 _out.flush();
1169 }
1170 finally
1171 {
1172 if (resource!=null)
1173 resource.release();
1174 else
1175 in.close();
1176
1177 }
1178 }
1179 else
1180 throw new IllegalArgumentException("unknown content type?");
1181
1182
1183 }
1184 }
1185
1186
1187
1188
1189 public class OutputWriter extends HttpWriter
1190 {
1191 OutputWriter()
1192 {
1193 super(HttpConnection.this._out);
1194 }
1195 }
1196
1197 }