1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.servlet;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.net.MalformedURLException;
20 import java.net.URL;
21 import java.util.Enumeration;
22 import java.util.List;
23
24 import javax.servlet.RequestDispatcher;
25 import javax.servlet.ServletContext;
26 import javax.servlet.ServletException;
27 import javax.servlet.UnavailableException;
28 import javax.servlet.http.HttpServlet;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.eclipse.jetty.http.HttpContent;
33 import org.eclipse.jetty.http.HttpFields;
34 import org.eclipse.jetty.http.HttpHeaderValues;
35 import org.eclipse.jetty.http.HttpHeaders;
36 import org.eclipse.jetty.http.HttpMethods;
37 import org.eclipse.jetty.http.MimeTypes;
38 import org.eclipse.jetty.io.Buffer;
39 import org.eclipse.jetty.io.ByteArrayBuffer;
40 import org.eclipse.jetty.io.WriterOutputStream;
41 import org.eclipse.jetty.server.Connector;
42 import org.eclipse.jetty.server.Dispatcher;
43 import org.eclipse.jetty.server.HttpConnection;
44 import org.eclipse.jetty.server.InclusiveByteRange;
45 import org.eclipse.jetty.server.ResourceCache;
46 import org.eclipse.jetty.server.Response;
47 import org.eclipse.jetty.server.handler.ContextHandler;
48 import org.eclipse.jetty.server.nio.NIOConnector;
49 import org.eclipse.jetty.util.IO;
50 import org.eclipse.jetty.util.MultiPartOutputStream;
51 import org.eclipse.jetty.util.TypeUtil;
52 import org.eclipse.jetty.util.URIUtil;
53 import org.eclipse.jetty.util.log.Log;
54 import org.eclipse.jetty.util.resource.FileResource;
55 import org.eclipse.jetty.util.resource.Resource;
56 import org.eclipse.jetty.util.resource.ResourceFactory;
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121 public class DefaultServlet extends HttpServlet implements ResourceFactory
122 {
123 private ServletContext _servletContext;
124 private ContextHandler _contextHandler;
125
126 private boolean _acceptRanges=true;
127 private boolean _dirAllowed=true;
128 private boolean _welcomeServlets=false;
129 private boolean _redirectWelcome=false;
130 private boolean _gzip=true;
131
132 private Resource _resourceBase;
133 private NIOResourceCache _nioCache;
134 private ResourceCache _bioCache;
135
136 private MimeTypes _mimeTypes;
137 private String[] _welcomes;
138 private boolean _useFileMappedBuffer=false;
139 private ByteArrayBuffer _cacheControl;
140 private String _relativeResourceBase;
141
142
143
144 @Override
145 public void init()
146 throws UnavailableException
147 {
148 _servletContext=getServletContext();
149 ContextHandler.Context scontext=ContextHandler.getCurrentContext();
150 if (scontext==null)
151 _contextHandler=((ContextHandler.Context)_servletContext).getContextHandler();
152 else
153 _contextHandler = ContextHandler.getCurrentContext().getContextHandler();
154
155 _mimeTypes = _contextHandler.getMimeTypes();
156
157 _welcomes = _contextHandler.getWelcomeFiles();
158 if (_welcomes==null)
159 _welcomes=new String[] {"index.jsp","index.html"};
160
161 _acceptRanges=getInitBoolean("acceptRanges",_acceptRanges);
162 _dirAllowed=getInitBoolean("dirAllowed",_dirAllowed);
163 _welcomeServlets=getInitBoolean("welcomeServlets", _welcomeServlets);
164 _redirectWelcome=getInitBoolean("redirectWelcome",_redirectWelcome);
165 _gzip=getInitBoolean("gzip",_gzip);
166
167 if (getInitParameter("aliases")!=null)
168 _contextHandler.setAliases(getInitBoolean("aliases",false));
169
170 boolean aliases=_contextHandler.isAliases();
171 if (!aliases && !FileResource.getCheckAliases())
172 throw new IllegalStateException("Alias checking disabled");
173 if (aliases)
174 _servletContext.log("Aliases are enabled");
175
176 _useFileMappedBuffer=getInitBoolean("useFileMappedBuffer",_useFileMappedBuffer);
177
178 _relativeResourceBase = getInitParameter("relativeResourceBase");
179
180 String rb=getInitParameter("resourceBase");
181 if (rb!=null)
182 {
183 if (_relativeResourceBase!=null)
184 throw new UnavailableException("resourceBase & relativeResourceBase");
185 try{_resourceBase=_contextHandler.newResource(rb);}
186 catch (Exception e)
187 {
188 Log.warn(Log.EXCEPTION,e);
189 throw new UnavailableException(e.toString());
190 }
191 }
192
193 String t=getInitParameter("cacheControl");
194 if (t!=null)
195 _cacheControl=new ByteArrayBuffer(t);
196
197 try
198 {
199 String cache_type =getInitParameter("cacheType");
200 int max_cache_size=getInitInt("maxCacheSize", -2);
201 int max_cached_file_size=getInitInt("maxCachedFileSize", -2);
202 int max_cached_files=getInitInt("maxCachedFiles", -2);
203
204 if (cache_type==null || "nio".equals(cache_type)|| "both".equals(cache_type))
205 {
206 if (max_cache_size==-2 || max_cache_size>0)
207 {
208 _nioCache=new NIOResourceCache(_mimeTypes);
209 _nioCache.setUseFileMappedBuffer(_useFileMappedBuffer);
210 if (max_cache_size>0)
211 _nioCache.setMaxCacheSize(max_cache_size);
212 if (max_cached_file_size>=-1)
213 _nioCache.setMaxCachedFileSize(max_cached_file_size);
214 if (max_cached_files>=-1)
215 _nioCache.setMaxCachedFiles(max_cached_files);
216 _nioCache.start();
217 }
218 }
219 if ("bio".equals(cache_type)|| "both".equals(cache_type))
220 {
221 if (max_cache_size==-2 || max_cache_size>0)
222 {
223 _bioCache=new ResourceCache(_mimeTypes);
224 if (max_cache_size>0)
225 _bioCache.setMaxCacheSize(max_cache_size);
226 if (max_cached_file_size>=-1)
227 _bioCache.setMaxCachedFileSize(max_cached_file_size);
228 if (max_cached_files>=-1)
229 _bioCache.setMaxCachedFiles(max_cached_files);
230 _bioCache.start();
231 }
232 }
233 if (_nioCache==null)
234 _bioCache=null;
235
236 }
237 catch (Exception e)
238 {
239 Log.warn(Log.EXCEPTION,e);
240 throw new UnavailableException(e.toString());
241 }
242
243 if (Log.isDebugEnabled()) Log.debug("resource base = "+_resourceBase);
244 }
245
246
247 @Override
248 public String getInitParameter(String name)
249 {
250 String value=getServletContext().getInitParameter("org.eclipse.jetty.servlet.Default."+name);
251 if (value==null)
252 value=super.getInitParameter(name);
253 return value;
254 }
255
256
257 private boolean getInitBoolean(String name, boolean dft)
258 {
259 String value=getInitParameter(name);
260 if (value==null || value.length()==0)
261 return dft;
262 return (value.startsWith("t")||
263 value.startsWith("T")||
264 value.startsWith("y")||
265 value.startsWith("Y")||
266 value.startsWith("1"));
267 }
268
269
270 private int getInitInt(String name, int dft)
271 {
272 String value=getInitParameter(name);
273 if (value==null)
274 value=getInitParameter(name);
275 if (value!=null && value.length()>0)
276 return Integer.parseInt(value);
277 return dft;
278 }
279
280
281
282
283
284
285
286
287
288 public Resource getResource(String pathInContext)
289 {
290 Resource r=null;
291 if (_relativeResourceBase!=null)
292 pathInContext=URIUtil.addPaths(_relativeResourceBase,pathInContext);
293
294 try
295 {
296 if (_resourceBase!=null)
297 r = _resourceBase.addPath(pathInContext);
298 else
299 {
300 URL u = _servletContext.getResource(pathInContext);
301 r = _contextHandler.newResource(u);
302 }
303
304 if (Log.isDebugEnabled()) Log.debug("RESOURCE="+r);
305 }
306 catch (IOException e)
307 {
308 Log.ignore(e);
309 }
310 return r;
311 }
312
313
314 @Override
315 protected void doGet(HttpServletRequest request, HttpServletResponse response)
316 throws ServletException, IOException
317 {
318 String servletPath=null;
319 String pathInfo=null;
320 Enumeration reqRanges = null;
321 boolean byteRangeRules = false;
322 Boolean included =request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI)!=null;
323 if (included!=null && included.booleanValue())
324 {
325 servletPath=(String)request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH);
326 pathInfo=(String)request.getAttribute(Dispatcher.INCLUDE_PATH_INFO);
327 if (servletPath==null)
328 {
329 servletPath=request.getServletPath();
330 pathInfo=request.getPathInfo();
331 }
332 }
333 else
334 {
335 included = Boolean.FALSE;
336 servletPath = request.getServletPath();
337 pathInfo = request.getPathInfo();
338
339
340 reqRanges = request.getHeaders(HttpHeaders.CONTENT_RANGE);
341 if (!hasDefinedRange(reqRanges))
342 {
343
344 reqRanges = request.getHeaders(HttpHeaders.RANGE);
345 if (hasDefinedRange(reqRanges))
346 {
347 byteRangeRules = true;
348 }
349 else
350 {
351 reqRanges = null;
352 }
353 }
354 }
355
356 String pathInContext=URIUtil.addPaths(servletPath,pathInfo);
357 boolean endsWithSlash=pathInContext.endsWith(URIUtil.SLASH);
358
359
360 String pathInContextGz=null;
361 boolean gzip=false;
362 if (!included.booleanValue() && _gzip && reqRanges==null && !endsWithSlash )
363 {
364 String accept=request.getHeader(HttpHeaders.ACCEPT_ENCODING);
365 if (accept!=null && accept.indexOf("gzip")>=0)
366 gzip=true;
367 }
368
369
370 Resource resource=null;
371 HttpContent content=null;
372
373 Connector connector = HttpConnection.getCurrentConnection().getConnector();
374 ResourceCache cache=(connector instanceof NIOConnector) ?_nioCache:_bioCache;
375 try
376 {
377
378 if (gzip)
379 {
380 pathInContextGz=pathInContext+".gz";
381
382 if (cache==null)
383 {
384 resource=getResource(pathInContextGz);
385 }
386 else
387 {
388 content=cache.lookup(pathInContextGz,this);
389
390 if (content!=null)
391 resource=content.getResource();
392 else
393 resource=getResource(pathInContextGz);
394 }
395
396 if (resource==null || !resource.exists()|| resource.isDirectory())
397 {
398 if (cache!=null && content==null)
399 {
400 String real_path=_servletContext.getRealPath(pathInContextGz);
401 if (real_path!=null)
402 cache.miss(pathInContextGz,_contextHandler.newResource(real_path));
403 }
404 gzip=false;
405 pathInContextGz=null;
406 }
407 }
408
409
410 if (!gzip)
411 {
412 if (cache==null)
413 resource=getResource(pathInContext);
414 else
415 {
416 content=cache.lookup(pathInContext,this);
417
418 if (content!=null)
419 resource=content.getResource();
420 else
421 resource=getResource(pathInContext);
422 }
423 }
424
425 if (Log.isDebugEnabled())
426 Log.debug("resource="+resource+(content!=null?" content":""));
427
428
429 if (resource==null || !resource.exists())
430 response.sendError(HttpServletResponse.SC_NOT_FOUND);
431 else if (!resource.isDirectory())
432 {
433 if (endsWithSlash && _contextHandler.isAliases() && pathInContext.length()>1)
434 {
435 String q=request.getQueryString();
436 pathInContext=pathInContext.substring(0,pathInContext.length()-1);
437 if (q!=null&&q.length()!=0)
438 pathInContext+="?"+q;
439 response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(_servletContext.getContextPath(),pathInContext)));
440 }
441 else
442 {
443
444 if (content==null)
445 content=new UnCachedContent(resource);
446
447 if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
448 {
449 if (gzip)
450 {
451 response.setHeader(HttpHeaders.CONTENT_ENCODING,"gzip");
452 String mt=_servletContext.getMimeType(pathInContext);
453 if (mt!=null)
454 response.setContentType(mt);
455 }
456 sendData(request,response,included.booleanValue(),resource,content,reqRanges,byteRangeRules);
457 }
458 }
459 }
460 else
461 {
462 String welcome=null;
463
464 if (!endsWithSlash || (pathInContext.length()==1 && request.getAttribute("org.eclipse.jetty.server.nullPathInfo")!=null))
465 {
466 StringBuffer buf=request.getRequestURL();
467 synchronized(buf)
468 {
469 int param=buf.lastIndexOf(";");
470 if (param<0)
471 buf.append('/');
472 else
473 buf.insert(param,'/');
474 String q=request.getQueryString();
475 if (q!=null&&q.length()!=0)
476 {
477 buf.append('?');
478 buf.append(q);
479 }
480 response.setContentLength(0);
481 response.sendRedirect(response.encodeRedirectURL(buf.toString()));
482 }
483 }
484
485 else if (null!=(welcome=getWelcomeFile(resource)))
486 {
487 String ipath=URIUtil.addPaths(pathInContext,welcome);
488 if (_redirectWelcome)
489 {
490
491 response.setContentLength(0);
492 String q=request.getQueryString();
493 if (q!=null&&q.length()!=0)
494 response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths( _servletContext.getContextPath(),ipath)+"?"+q));
495 else
496 response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths( _servletContext.getContextPath(),ipath)));
497 }
498 else
499 {
500
501 RequestDispatcher dispatcher=request.getRequestDispatcher(ipath);
502 if (dispatcher!=null)
503 {
504 if (included.booleanValue())
505 dispatcher.include(request,response);
506 else
507 {
508 request.setAttribute("org.eclipse.jetty.server.welcome",ipath);
509 dispatcher.forward(request,response);
510 }
511 }
512 }
513 }
514 else
515 {
516 content=new UnCachedContent(resource);
517 if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
518 sendDirectory(request,response,resource,pathInContext.length()>1);
519 }
520 }
521 }
522 catch(IllegalArgumentException e)
523 {
524 Log.warn(Log.EXCEPTION,e);
525 if(!response.isCommitted())
526 response.sendError(500, e.getMessage());
527 }
528 finally
529 {
530 if (content!=null)
531 content.release();
532 else if (resource!=null)
533 resource.release();
534 }
535
536 }
537
538
539 private boolean hasDefinedRange(Enumeration reqRanges)
540 {
541 return (reqRanges!=null && reqRanges.hasMoreElements());
542 }
543
544
545 @Override
546 protected void doPost(HttpServletRequest request, HttpServletResponse response)
547 throws ServletException, IOException
548 {
549 doGet(request,response);
550 }
551
552
553
554
555
556 @Override
557 protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
558 {
559 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
560 }
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575 private String getWelcomeFile(Resource resource) throws MalformedURLException, IOException
576 {
577 if (!resource.isDirectory() || _welcomes==null)
578 return null;
579
580 for (int i=0;i<_welcomes.length;i++)
581 {
582 Resource welcome=resource.addPath(_welcomes[i]);
583 if (welcome.exists())
584 return _welcomes[i];
585 }
586
587 if (_welcomeServlets)
588 {
589 ServletHandler servletHandler = (ServletHandler)_contextHandler.getChildHandlerByClass(ServletHandler.class);
590 for (int i=0;i<_welcomes.length;i++)
591 {
592 if (servletHandler.matchesPath(_welcomes[i]))
593 return _welcomes[i];
594 }
595 }
596
597 return null;
598 }
599
600
601
602
603 protected boolean passConditionalHeaders(HttpServletRequest request,HttpServletResponse response, Resource resource, HttpContent content)
604 throws IOException
605 {
606 try
607 {
608 if (!request.getMethod().equals(HttpMethods.HEAD) )
609 {
610 String ifms=request.getHeader(HttpHeaders.IF_MODIFIED_SINCE);
611 if (ifms!=null)
612 {
613 if (content!=null)
614 {
615 Buffer mdlm=content.getLastModified();
616 if (mdlm!=null)
617 {
618 if (ifms.equals(mdlm.toString()))
619 {
620 response.reset();
621 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
622 response.flushBuffer();
623 return false;
624 }
625 }
626 }
627
628 long ifmsl=request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
629 if (ifmsl!=-1)
630 {
631 if (resource.lastModified()/1000 <= ifmsl/1000)
632 {
633 response.reset();
634 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
635 response.flushBuffer();
636 return false;
637 }
638 }
639 }
640
641
642 long date=request.getDateHeader(HttpHeaders.IF_UNMODIFIED_SINCE);
643
644 if (date!=-1)
645 {
646 if (resource.lastModified()/1000 > date/1000)
647 {
648 response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
649 return false;
650 }
651 }
652
653 }
654 }
655 catch(IllegalArgumentException iae)
656 {
657 if(!response.isCommitted())
658 response.sendError(400, iae.getMessage());
659 throw iae;
660 }
661 return true;
662 }
663
664
665
666 protected void sendDirectory(HttpServletRequest request,
667 HttpServletResponse response,
668 Resource resource,
669 boolean parent)
670 throws IOException
671 {
672 if (!_dirAllowed)
673 {
674 response.sendError(HttpServletResponse.SC_FORBIDDEN);
675 return;
676 }
677
678 byte[] data=null;
679 String base = URIUtil.addPaths(request.getRequestURI(),URIUtil.SLASH);
680 String dir = resource.getListHTML(base,parent);
681 if (dir==null)
682 {
683 response.sendError(HttpServletResponse.SC_FORBIDDEN,
684 "No directory");
685 return;
686 }
687
688 data=dir.getBytes("UTF-8");
689 response.setContentType("text/html; charset=UTF-8");
690 response.setContentLength(data.length);
691 response.getOutputStream().write(data);
692 }
693
694
695 protected void sendData(HttpServletRequest request,
696 HttpServletResponse response,
697 boolean include,
698 Resource resource,
699 HttpContent content,
700 Enumeration reqRanges,
701 boolean byteRangeRules)
702 throws IOException
703 {
704 long content_length=resource.length();
705
706
707 OutputStream out =null;
708 try{out = response.getOutputStream();}
709 catch(IllegalStateException e) {out = new WriterOutputStream(response.getWriter());}
710
711 if ( reqRanges == null || !reqRanges.hasMoreElements())
712 {
713
714 if (include)
715 {
716 resource.writeTo(out,0,content_length);
717 }
718 else
719 {
720
721 if (out instanceof HttpConnection.Output)
722 {
723 if (response instanceof Response)
724 {
725 writeOptionHeaders(((Response)response).getHttpFields());
726 ((HttpConnection.Output)out).sendContent(content);
727 }
728 else if (content.getBuffer()!=null)
729 {
730 writeHeaders(response,content,content_length);
731 ((HttpConnection.Output)out).sendContent(content.getBuffer());
732 }
733 else
734 {
735 writeHeaders(response,content,content_length);
736 resource.writeTo(out,0,content_length);
737 }
738 }
739 else
740 {
741
742 writeHeaders(response,content,content_length);
743 resource.writeTo(out,0,content_length);
744 }
745 }
746 }
747 else
748 {
749
750 List ranges =InclusiveByteRange.satisfiableRanges(reqRanges,byteRangeRules,content_length);
751
752
753 if (ranges==null || ranges.size()==0)
754 {
755 writeHeaders(response, content, content_length);
756 response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
757 response.setHeader(HttpHeaders.CONTENT_RANGE,
758 InclusiveByteRange.to416HeaderRangeString(content_length));
759 resource.writeTo(out,0,content_length);
760 return;
761 }
762
763
764
765 if ( ranges.size()== 1)
766 {
767 InclusiveByteRange singleSatisfiableRange =
768 (InclusiveByteRange)ranges.get(0);
769 long singleLength = singleSatisfiableRange.getSize(content_length);
770 writeHeaders(response,content,singleLength );
771 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
772 response.setHeader(HttpHeaders.CONTENT_RANGE,
773 singleSatisfiableRange.toHeaderRangeString(content_length));
774 resource.writeTo(out,singleSatisfiableRange.getFirst(content_length),singleLength);
775 return;
776 }
777
778
779
780
781 if (!byteRangeRules)
782 {
783 writeHeaders(response,content,content_length);
784 response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
785 response.setHeader(HttpHeaders.CONTENT_RANGE,InclusiveByteRange.to416HeaderRangeString(content_length));
786 resource.writeTo(out,0,content_length);
787 return;
788 }
789
790
791
792
793
794 writeHeaders(response,content,-1);
795 String mimetype=content.getContentType().toString();
796 MultiPartOutputStream multi = new MultiPartOutputStream(out);
797 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
798
799
800
801
802 String ctp;
803 if (request.getHeader(HttpHeaders.REQUEST_RANGE)!=null)
804 ctp = "multipart/x-byteranges; boundary=";
805 else
806 ctp = "multipart/byteranges; boundary=";
807 response.setContentType(ctp+multi.getBoundary());
808
809 InputStream in=resource.getInputStream();
810 long pos=0;
811
812 for (int i=0;i<ranges.size();i++)
813 {
814 InclusiveByteRange ibr = (InclusiveByteRange) ranges.get(i);
815 String header=HttpHeaders.CONTENT_RANGE+": "+
816 ibr.toHeaderRangeString(content_length);
817 multi.startPart(mimetype,new String[]{header});
818
819 long start=ibr.getFirst(content_length);
820 long size=ibr.getSize(content_length);
821 if (in!=null)
822 {
823
824 if (start<pos)
825 {
826 in.close();
827 in=resource.getInputStream();
828 pos=0;
829 }
830 if (pos<start)
831 {
832 in.skip(start-pos);
833 pos=start;
834 }
835 IO.copy(in,multi,size);
836 pos+=size;
837 }
838 else
839
840 (resource).writeTo(multi,start,size);
841
842 }
843 if (in!=null)
844 in.close();
845 multi.close();
846 }
847 return;
848 }
849
850
851 protected void writeHeaders(HttpServletResponse response,HttpContent content,long count)
852 throws IOException
853 {
854 if (content.getContentType()!=null && response.getContentType()==null)
855 response.setContentType(content.getContentType().toString());
856
857 if (response instanceof Response)
858 {
859 Response r=(Response)response;
860 HttpFields fields = r.getHttpFields();
861
862 if (content.getLastModified()!=null)
863 fields.put(HttpHeaders.LAST_MODIFIED_BUFFER,content.getLastModified(),content.getResource().lastModified());
864 else if (content.getResource()!=null)
865 {
866 long lml=content.getResource().lastModified();
867 if (lml!=-1)
868 fields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER,lml);
869 }
870
871 if (count != -1)
872 r.setLongContentLength(count);
873
874 writeOptionHeaders(fields);
875 }
876 else
877 {
878 long lml=content.getResource().lastModified();
879 if (lml>=0)
880 response.setDateHeader(HttpHeaders.LAST_MODIFIED,lml);
881
882 if (count != -1)
883 {
884 if (count<Integer.MAX_VALUE)
885 response.setContentLength((int)count);
886 else
887 response.setHeader(HttpHeaders.CONTENT_LENGTH,TypeUtil.toString(count));
888 }
889
890 writeOptionHeaders(response);
891 }
892 }
893
894
895 protected void writeOptionHeaders(HttpFields fields) throws IOException
896 {
897 if (_acceptRanges)
898 fields.put(HttpHeaders.ACCEPT_RANGES_BUFFER,HttpHeaderValues.BYTES_BUFFER);
899
900 if (_cacheControl!=null)
901 fields.put(HttpHeaders.CACHE_CONTROL_BUFFER,_cacheControl);
902 }
903
904
905 protected void writeOptionHeaders(HttpServletResponse response) throws IOException
906 {
907 if (_acceptRanges)
908 response.setHeader(HttpHeaders.ACCEPT_RANGES,"bytes");
909
910 if (_cacheControl!=null)
911 response.setHeader(HttpHeaders.CACHE_CONTROL,_cacheControl.toString());
912 }
913
914
915
916
917
918 @Override
919 public void destroy()
920 {
921 try
922 {
923 if (_nioCache!=null)
924 _nioCache.stop();
925 if (_bioCache!=null)
926 _bioCache.stop();
927 }
928 catch(Exception e)
929 {
930 Log.warn(Log.EXCEPTION,e);
931 }
932 finally
933 {
934 super.destroy();
935 }
936 }
937
938
939
940
941 private class UnCachedContent implements HttpContent
942 {
943 Resource _resource;
944
945 UnCachedContent(Resource resource)
946 {
947 _resource=resource;
948 }
949
950
951 public Buffer getContentType()
952 {
953 return _mimeTypes.getMimeByExtension(_resource.toString());
954 }
955
956
957 public Buffer getLastModified()
958 {
959 return null;
960 }
961
962
963 public Buffer getBuffer()
964 {
965 return null;
966 }
967
968
969 public long getContentLength()
970 {
971 return _resource.length();
972 }
973
974
975 public InputStream getInputStream() throws IOException
976 {
977 return _resource.getInputStream();
978 }
979
980
981 public Resource getResource()
982 {
983 return _resource;
984 }
985
986
987 public void release()
988 {
989 _resource.release();
990 _resource=null;
991 }
992
993 }
994 }