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 private boolean hasDefinedRange(Enumeration reqRanges)
539 {
540 return (reqRanges!=null && reqRanges.hasMoreElements());
541 }
542
543
544 @Override
545 protected void doPost(HttpServletRequest request, HttpServletResponse response)
546 throws ServletException, IOException
547 {
548 doGet(request,response);
549 }
550
551
552
553
554
555 @Override
556 protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
557 {
558 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
559 }
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574 private String getWelcomeFile(Resource resource) throws MalformedURLException, IOException
575 {
576 if (!resource.isDirectory() || _welcomes==null)
577 return null;
578
579 for (int i=0;i<_welcomes.length;i++)
580 {
581 Resource welcome=resource.addPath(_welcomes[i]);
582 if (welcome.exists())
583 return _welcomes[i];
584 }
585
586 if (_welcomeServlets)
587 {
588 ServletHandler servletHandler = (ServletHandler)_contextHandler.getChildHandlerByClass(ServletHandler.class);
589 for (int i=0;i<_welcomes.length;i++)
590 {
591 if (servletHandler.matchesPath(_welcomes[i]))
592 return _welcomes[i];
593 }
594 }
595
596 return null;
597 }
598
599
600
601
602 protected boolean passConditionalHeaders(HttpServletRequest request,HttpServletResponse response, Resource resource, HttpContent content)
603 throws IOException
604 {
605 try
606 {
607 if (!request.getMethod().equals(HttpMethods.HEAD) )
608 {
609 String ifms=request.getHeader(HttpHeaders.IF_MODIFIED_SINCE);
610 if (ifms!=null)
611 {
612 if (content!=null)
613 {
614 Buffer mdlm=content.getLastModified();
615 if (mdlm!=null)
616 {
617 if (ifms.equals(mdlm.toString()))
618 {
619 response.reset();
620 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
621 response.flushBuffer();
622 return false;
623 }
624 }
625 }
626
627 long ifmsl=request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
628 if (ifmsl!=-1)
629 {
630 if (resource.lastModified()/1000 <= ifmsl/1000)
631 {
632 response.reset();
633 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
634 response.flushBuffer();
635 return false;
636 }
637 }
638 }
639
640
641 long date=request.getDateHeader(HttpHeaders.IF_UNMODIFIED_SINCE);
642
643 if (date!=-1)
644 {
645 if (resource.lastModified()/1000 > date/1000)
646 {
647 response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
648 return false;
649 }
650 }
651
652 }
653 }
654 catch(IllegalArgumentException iae)
655 {
656 if(!response.isCommitted())
657 response.sendError(400, iae.getMessage());
658 throw iae;
659 }
660 return true;
661 }
662
663
664
665 protected void sendDirectory(HttpServletRequest request,
666 HttpServletResponse response,
667 Resource resource,
668 boolean parent)
669 throws IOException
670 {
671 if (!_dirAllowed)
672 {
673 response.sendError(HttpServletResponse.SC_FORBIDDEN);
674 return;
675 }
676
677 byte[] data=null;
678 String base = URIUtil.addPaths(request.getRequestURI(),URIUtil.SLASH);
679 String dir = resource.getListHTML(base,parent);
680 if (dir==null)
681 {
682 response.sendError(HttpServletResponse.SC_FORBIDDEN,
683 "No directory");
684 return;
685 }
686
687 data=dir.getBytes("UTF-8");
688 response.setContentType("text/html; charset=UTF-8");
689 response.setContentLength(data.length);
690 response.getOutputStream().write(data);
691 }
692
693
694 protected void sendData(HttpServletRequest request,
695 HttpServletResponse response,
696 boolean include,
697 Resource resource,
698 HttpContent content,
699 Enumeration reqRanges,
700 boolean byteRangeRules)
701 throws IOException
702 {
703 long content_length=resource.length();
704
705
706 OutputStream out =null;
707 try{out = response.getOutputStream();}
708 catch(IllegalStateException e) {out = new WriterOutputStream(response.getWriter());}
709
710 if ( reqRanges == null || !reqRanges.hasMoreElements())
711 {
712
713 if (include)
714 {
715 resource.writeTo(out,0,content_length);
716 }
717 else
718 {
719
720 if (out instanceof HttpConnection.Output)
721 {
722 if (response instanceof Response)
723 {
724 writeOptionHeaders(((Response)response).getHttpFields());
725 ((HttpConnection.Output)out).sendContent(content);
726 }
727 else if (content.getBuffer()!=null)
728 {
729 writeHeaders(response,content,content_length);
730 ((HttpConnection.Output)out).sendContent(content.getBuffer());
731 }
732 else
733 {
734 writeHeaders(response,content,content_length);
735 resource.writeTo(out,0,content_length);
736 }
737 }
738 else
739 {
740
741 writeHeaders(response,content,content_length);
742 resource.writeTo(out,0,content_length);
743 }
744 }
745 }
746 else
747 {
748
749 List ranges =InclusiveByteRange.satisfiableRanges(reqRanges,byteRangeRules,content_length);
750
751
752 if (ranges==null || ranges.size()==0)
753 {
754 writeHeaders(response, content, content_length);
755 response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
756 response.setHeader(HttpHeaders.CONTENT_RANGE,
757 InclusiveByteRange.to416HeaderRangeString(content_length));
758 resource.writeTo(out,0,content_length);
759 return;
760 }
761
762
763
764 if ( ranges.size()== 1)
765 {
766 InclusiveByteRange singleSatisfiableRange =
767 (InclusiveByteRange)ranges.get(0);
768 long singleLength = singleSatisfiableRange.getSize(content_length);
769 writeHeaders(response,content,singleLength );
770 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
771 response.setHeader(HttpHeaders.CONTENT_RANGE,
772 singleSatisfiableRange.toHeaderRangeString(content_length));
773 resource.writeTo(out,singleSatisfiableRange.getFirst(content_length),singleLength);
774 return;
775 }
776
777
778
779
780 if (!byteRangeRules)
781 {
782 writeHeaders(response,content,content_length);
783 response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
784 response.setHeader(HttpHeaders.CONTENT_RANGE,InclusiveByteRange.to416HeaderRangeString(content_length));
785 resource.writeTo(out,0,content_length);
786 return;
787 }
788
789
790
791
792
793 writeHeaders(response,content,-1);
794 String mimetype=content.getContentType().toString();
795 MultiPartOutputStream multi = new MultiPartOutputStream(out);
796 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
797
798
799
800
801 String ctp;
802 if (request.getHeader(HttpHeaders.REQUEST_RANGE)!=null)
803 ctp = "multipart/x-byteranges; boundary=";
804 else
805 ctp = "multipart/byteranges; boundary=";
806 response.setContentType(ctp+multi.getBoundary());
807
808 InputStream in=resource.getInputStream();
809 long pos=0;
810
811 for (int i=0;i<ranges.size();i++)
812 {
813 InclusiveByteRange ibr = (InclusiveByteRange) ranges.get(i);
814 String header=HttpHeaders.CONTENT_RANGE+": "+
815 ibr.toHeaderRangeString(content_length);
816 multi.startPart(mimetype,new String[]{header});
817
818 long start=ibr.getFirst(content_length);
819 long size=ibr.getSize(content_length);
820 if (in!=null)
821 {
822
823 if (start<pos)
824 {
825 in.close();
826 in=resource.getInputStream();
827 pos=0;
828 }
829 if (pos<start)
830 {
831 in.skip(start-pos);
832 pos=start;
833 }
834 IO.copy(in,multi,size);
835 pos+=size;
836 }
837 else
838
839 (resource).writeTo(multi,start,size);
840
841 }
842 if (in!=null)
843 in.close();
844 multi.close();
845 }
846 return;
847 }
848
849
850 protected void writeHeaders(HttpServletResponse response,HttpContent content,long count)
851 throws IOException
852 {
853 if (content.getContentType()!=null && response.getContentType()==null)
854 response.setContentType(content.getContentType().toString());
855
856 if (response instanceof Response)
857 {
858 Response r=(Response)response;
859 HttpFields fields = r.getHttpFields();
860
861 if (content.getLastModified()!=null)
862 fields.put(HttpHeaders.LAST_MODIFIED_BUFFER,content.getLastModified(),content.getResource().lastModified());
863 else if (content.getResource()!=null)
864 {
865 long lml=content.getResource().lastModified();
866 if (lml!=-1)
867 fields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER,lml);
868 }
869
870 if (count != -1)
871 r.setLongContentLength(count);
872
873 writeOptionHeaders(fields);
874 }
875 else
876 {
877 long lml=content.getResource().lastModified();
878 if (lml>=0)
879 response.setDateHeader(HttpHeaders.LAST_MODIFIED,lml);
880
881 if (count != -1)
882 {
883 if (count<Integer.MAX_VALUE)
884 response.setContentLength((int)count);
885 else
886 response.setHeader(HttpHeaders.CONTENT_LENGTH,TypeUtil.toString(count));
887 }
888
889 writeOptionHeaders(response);
890 }
891 }
892
893
894 protected void writeOptionHeaders(HttpFields fields) throws IOException
895 {
896 if (_acceptRanges)
897 fields.put(HttpHeaders.ACCEPT_RANGES_BUFFER,HttpHeaderValues.BYTES_BUFFER);
898
899 if (_cacheControl!=null)
900 fields.put(HttpHeaders.CACHE_CONTROL_BUFFER,_cacheControl);
901 }
902
903
904 protected void writeOptionHeaders(HttpServletResponse response) throws IOException
905 {
906 if (_acceptRanges)
907 response.setHeader(HttpHeaders.ACCEPT_RANGES,"bytes");
908
909 if (_cacheControl!=null)
910 response.setHeader(HttpHeaders.CACHE_CONTROL,_cacheControl.toString());
911 }
912
913
914
915
916
917 @Override
918 public void destroy()
919 {
920 try
921 {
922 if (_nioCache!=null)
923 _nioCache.stop();
924 if (_bioCache!=null)
925 _bioCache.stop();
926 }
927 catch(Exception e)
928 {
929 Log.warn(Log.EXCEPTION,e);
930 }
931 finally
932 {
933 super.destroy();
934 }
935 }
936
937
938
939
940 private class UnCachedContent implements HttpContent
941 {
942 Resource _resource;
943
944 UnCachedContent(Resource resource)
945 {
946 _resource=resource;
947 }
948
949
950 public Buffer getContentType()
951 {
952 return _mimeTypes.getMimeByExtension(_resource.toString());
953 }
954
955
956 public Buffer getLastModified()
957 {
958 return null;
959 }
960
961
962 public Buffer getBuffer()
963 {
964 return null;
965 }
966
967
968 public long getContentLength()
969 {
970 return _resource.length();
971 }
972
973
974 public InputStream getInputStream() throws IOException
975 {
976 return _resource.getInputStream();
977 }
978
979
980 public Resource getResource()
981 {
982 return _resource;
983 }
984
985
986 public void release()
987 {
988 _resource.release();
989 _resource=null;
990 }
991
992 }
993 }