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