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