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