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