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