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