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