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