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