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