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