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 QuotedStringTokenizer tok = new QuotedStringTokenizer(value.toString(), ",");
825 while(tok.hasMoreTokens())
826 {
827 CachedBuffer cb = HttpHeaderValues.CACHE.get(tok.nextToken().trim());
828 if (cb != null)
829 {
830 switch (cb.getOrdinal())
831 {
832 case HttpHeaderValues.CLOSE_ORDINAL:
833 _responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
834 _generator.setPersistent(false);
835 break;
836
837 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
838 if (_version == HttpVersions.HTTP_1_0_ORDINAL)
839 _responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
840 break;
841 }
842 }
843 }
844 break;
845 }
846 case HttpHeaderValues.CLOSE_ORDINAL:
847 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
848 _generator.setPersistent(false);
849 break;
850
851 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
852 if (_version == HttpVersions.HTTP_1_0_ORDINAL)
853 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
854 break;
855 }
856 }
857
858 _requestFields.add(name,value);
859 }
860
861
862
863
864 public void headerComplete() throws IOException
865 {
866 if (_endp instanceof SelectChannelEndPoint)
867 ((SelectChannelEndPoint)_endp).scheduleIdle();
868 _requests++;
869 _generator.setVersion(_version);
870 switch (_version)
871 {
872 case HttpVersions.HTTP_0_9_ORDINAL:
873 break;
874 case HttpVersions.HTTP_1_0_ORDINAL:
875 _generator.setHead(_head);
876 break;
877 case HttpVersions.HTTP_1_1_ORDINAL:
878 _generator.setHead(_head);
879
880 if (_server.getSendDateHeader())
881 _responseFields.put(HttpHeaders.DATE_BUFFER,_request.getTimeStampBuffer(),_request.getTimeStamp());
882
883 if (!_host)
884 {
885 _generator.setResponse(HttpStatus.ORDINAL_400_Bad_Request,null);
886 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
887 _generator.completeHeader(_responseFields,true);
888 _generator.complete();
889 return;
890 }
891
892 if (_expect != UNKNOWN)
893 {
894 if (_expect == HttpHeaderValues.CONTINUE_ORDINAL)
895 {
896
897
898 if (((HttpParser)_parser).getHeaderBuffer() == null || ((HttpParser)_parser).getHeaderBuffer().length() < 2)
899 {
900 _generator.setResponse(HttpStatus.ORDINAL_100_Continue,null);
901 _generator.completeHeader(null,true);
902 _generator.complete();
903 _generator.reset(false);
904 }
905 }
906 else if (_expect == HttpHeaderValues.PROCESSING_ORDINAL)
907 {
908 }
909 else
910 {
911 _generator.setResponse(HttpStatus.ORDINAL_417_Expectation_Failed, null);
912 _responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
913 _generator.completeHeader(_responseFields, true);
914 _generator.complete();
915 return;
916 }
917 }
918
919 break;
920 default:
921 }
922
923 if (_charset != null)
924 _request.setCharacterEncodingUnchecked(_charset);
925
926
927 if (((HttpParser)_parser).getContentLength() <= 0 && !((HttpParser)_parser).isChunking())
928 handleRequest();
929 else
930 _delayedHandling = true;
931 }
932
933
934
935
936
937
938 public void content(Buffer ref) throws IOException
939 {
940 if (_endp instanceof SelectChannelEndPoint)
941 ((SelectChannelEndPoint)_endp).scheduleIdle();
942 if (_delayedHandling)
943 {
944 _delayedHandling = false;
945 handleRequest();
946 }
947 }
948
949
950
951
952
953
954 public void messageComplete(long contentLength) throws IOException
955 {
956 if (_delayedHandling)
957 {
958 _delayedHandling = false;
959 handleRequest();
960 }
961 }
962
963
964
965
966
967
968
969
970 public void startResponse(Buffer version, int status, Buffer reason)
971 {
972 Log.debug("Bad request!: " + version + " " + status + " " + reason);
973 }
974
975 }
976
977
978
979
980 public class Output extends AbstractGenerator.Output
981 {
982 Output()
983 {
984 super((AbstractGenerator)HttpConnection.this._generator,_connector.getMaxIdleTime());
985 }
986
987
988
989
990
991 public void close() throws IOException
992 {
993 if (_closed)
994 return;
995
996 if (!isIncluding() && !_generator.isCommitted())
997 commitResponse(HttpGenerator.LAST);
998 else
999 flushResponse();
1000
1001 super.close();
1002 }
1003
1004
1005
1006
1007
1008 public void flush() throws IOException
1009 {
1010 if (!_generator.isCommitted())
1011 commitResponse(HttpGenerator.MORE);
1012 super.flush();
1013 }
1014
1015
1016
1017
1018
1019 public void print(String s) throws IOException
1020 {
1021 if (_closed)
1022 throw new IOException("Closed");
1023 PrintWriter writer = getPrintWriter(null);
1024 writer.print(s);
1025 }
1026
1027
1028 public void sendResponse(Buffer response) throws IOException
1029 {
1030 ((HttpGenerator)_generator).sendResponse(response);
1031 }
1032
1033
1034 public void sendContent(Object content) throws IOException
1035 {
1036 Resource resource = null;
1037
1038 if (_closed)
1039 throw new IOException("Closed");
1040
1041 if (_generator.getContentWritten() > 0)
1042 throw new IllegalStateException("!empty");
1043
1044 if (content instanceof HttpContent)
1045 {
1046 HttpContent c = (HttpContent)content;
1047 Buffer contentType = c.getContentType();
1048 if (contentType != null && !_responseFields.containsKey(HttpHeaders.CONTENT_TYPE_BUFFER))
1049 {
1050 String enc = _response.getSetCharacterEncoding();
1051 if(enc==null)
1052 _responseFields.add(HttpHeaders.CONTENT_TYPE_BUFFER, contentType);
1053 else
1054 {
1055 if(contentType instanceof CachedBuffer)
1056 {
1057 CachedBuffer content_type = ((CachedBuffer)contentType).getAssociate(enc);
1058 if(content_type!=null)
1059 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER, content_type);
1060 else
1061 {
1062 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
1063 contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
1064 }
1065 }
1066 else
1067 {
1068 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
1069 contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
1070 }
1071 }
1072 }
1073 if (c.getContentLength() > 0)
1074 _responseFields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER,c.getContentLength());
1075 Buffer lm = c.getLastModified();
1076 long lml = c.getResource().lastModified();
1077 if (lm != null)
1078 _responseFields.put(HttpHeaders.LAST_MODIFIED_BUFFER,lm,lml);
1079 else if (c.getResource() != null)
1080 {
1081 if (lml != -1)
1082 _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER,lml);
1083 }
1084
1085 content = c.getBuffer();
1086 if (content == null)
1087 content = c.getInputStream();
1088 }
1089 else if (content instanceof Resource)
1090 {
1091 resource = (Resource)content;
1092 _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER,resource.lastModified());
1093 content = resource.getInputStream();
1094 }
1095
1096 if (content instanceof Buffer)
1097 {
1098 _generator.addContent((Buffer)content,HttpGenerator.LAST);
1099 commitResponse(HttpGenerator.LAST);
1100 }
1101 else if (content instanceof InputStream)
1102 {
1103 InputStream in = (InputStream)content;
1104
1105 try
1106 {
1107 int max = _generator.prepareUncheckedAddContent();
1108 Buffer buffer = _generator.getUncheckedBuffer();
1109
1110 int len = buffer.readFrom(in,max);
1111
1112 while (len >= 0)
1113 {
1114 _generator.completeUncheckedAddContent();
1115 _out.flush();
1116
1117 max = _generator.prepareUncheckedAddContent();
1118 buffer = _generator.getUncheckedBuffer();
1119 len = buffer.readFrom(in,max);
1120 }
1121 _generator.completeUncheckedAddContent();
1122 _out.flush();
1123 }
1124 finally
1125 {
1126 if (resource != null)
1127 resource.release();
1128 else
1129 in.close();
1130
1131 }
1132 }
1133 else
1134 throw new IllegalArgumentException("unknown content type?");
1135
1136 }
1137 }
1138
1139
1140
1141
1142 public class OutputWriter extends AbstractGenerator.OutputWriter
1143 {
1144 OutputWriter()
1145 {
1146 super(HttpConnection.this._out);
1147 }
1148 }
1149
1150 }