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