KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > http > handler > ResourceHandler


1 // ========================================================================
2
// $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $
3
// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.http.handler;
17
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.io.OutputStream JavaDoc;
21 import java.util.Enumeration JavaDoc;
22 import java.util.List JavaDoc;
23
24 import org.apache.commons.logging.Log;
25 import org.mortbay.log.LogFactory;
26 import org.mortbay.http.HttpException;
27 import org.mortbay.http.HttpFields;
28 import org.mortbay.http.HttpRequest;
29 import org.mortbay.http.HttpResponse;
30 import org.mortbay.http.InclusiveByteRange;
31 import org.mortbay.http.MultiPartResponse;
32 import org.mortbay.http.ResourceCache;
33 import org.mortbay.util.CachedResource;
34 import org.mortbay.util.IO;
35 import org.mortbay.util.LogSupport;
36 import org.mortbay.util.Resource;
37 import org.mortbay.util.StringMap;
38 import org.mortbay.util.TypeUtil;
39 import org.mortbay.util.URI;
40
41 /* ------------------------------------------------------------ */
42 /** Handler to serve files and resources.
43  * Serves files from a given resource URL base and implements
44  * the GET, HEAD, DELETE, OPTIONS, PUT, MOVE methods and the
45  * IfModifiedSince and IfUnmodifiedSince header fields.
46  * A simple memory cache is also provided to reduce file I/O.
47  * HTTP/1.1 ranges are supported.
48  *
49  * @version $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $
50  * @author Nuno Preguiça
51  * @author Greg Wilkins
52  */

53 public class ResourceHandler extends AbstractHttpHandler
54 {
55     private static Log log = LogFactory.getLog(ResourceHandler.class);
56
57     /* ----------------------------------------------------------------- */
58     private boolean _acceptRanges=true;
59     private boolean _redirectWelcomeFiles ;
60     private String JavaDoc[] _methods=null;
61     private String JavaDoc _allowed;
62     private boolean _dirAllowed=true;
63     private int _minGzipLength =-1;
64     private StringMap _methodMap = new StringMap();
65     {
66         setAllowedMethods(new String JavaDoc[]
67             {
68                 HttpRequest.__GET,
69                 HttpRequest.__POST,
70                 HttpRequest.__HEAD,
71                 HttpRequest.__OPTIONS,
72                 HttpRequest.__TRACE
73             });
74     }
75
76     /* ----------------------------------------------------------------- */
77     /** Construct a ResourceHandler.
78      */

79     public ResourceHandler()
80     {}
81
82  
83     /* ----------------------------------------------------------------- */
84     public synchronized void start()
85         throws Exception JavaDoc
86     {
87         super.start();
88     }
89  
90     /* ----------------------------------------------------------------- */
91     public void stop()
92         throws InterruptedException JavaDoc
93     {
94         super.stop();
95     }
96
97     /* ------------------------------------------------------------ */
98     public String JavaDoc[] getAllowedMethods()
99     {
100         return _methods;
101     }
102
103     /* ------------------------------------------------------------ */
104     public void setAllowedMethods(String JavaDoc[] methods)
105     {
106         StringBuffer JavaDoc b = new StringBuffer JavaDoc();
107         _methods=methods;
108         _methodMap.clear();
109         for (int i=0;i<methods.length;i++)
110         {
111             _methodMap.put(methods[i],methods[i]);
112             if (i>0)
113                 b.append(',');
114             b.append(methods[i]);
115         }
116         _allowed=b.toString();
117     }
118
119     /* ------------------------------------------------------------ */
120     public boolean isMethodAllowed(String JavaDoc method)
121     {
122         return _methodMap.get(method)!=null;
123     }
124
125     /* ------------------------------------------------------------ */
126     public String JavaDoc getAllowedString()
127     {
128         return _allowed;
129     }
130     
131     /* ------------------------------------------------------------ */
132     public boolean isDirAllowed()
133     {
134         return _dirAllowed;
135     }
136     
137     /* ------------------------------------------------------------ */
138     public void setDirAllowed(boolean dirAllowed)
139     {
140         _dirAllowed = dirAllowed;
141     }
142     
143     /* ------------------------------------------------------------ */
144     public boolean isAcceptRanges()
145     {
146         return _acceptRanges;
147     }
148     
149     /* ------------------------------------------------------------ */
150     /**
151      * @return True if welcome files are redirected to. False if forward is used.
152      */

153     public boolean getRedirectWelcome()
154     {
155         return _redirectWelcomeFiles;
156     }
157     
158     /* ------------------------------------------------------------ */
159     /**
160      * @param redirectWelcome True if welcome files are redirected to. False
161      * if forward is used.
162      */

163     public void setRedirectWelcome(boolean redirectWelcome)
164     {
165         _redirectWelcomeFiles = redirectWelcome;
166     }
167     
168     /* ------------------------------------------------------------ */
169     /** Set if the handler accepts range requests.
170      * Default is false;
171      * @param ar True if the handler should accept ranges
172      */

173     public void setAcceptRanges(boolean ar)
174     {
175         _acceptRanges=ar;
176     }
177     
178     /* ------------------------------------------------------------ */
179     /** Get minimum content length for GZIP encoding.
180      * @return Minimum length of content for gzip encoding or -1 if disabled.
181      */

182     public int getMinGzipLength()
183     {
184         return _minGzipLength;
185     }
186     
187     /* ------------------------------------------------------------ */
188     /** Set minimum content length for GZIP encoding.
189      * @param minGzipLength If set to a positive integer, then static content
190      * larger than this will be served as gzip content encoded
191      * if a matching resource is found ending with ".gz"
192      */

193     public void setMinGzipLength(int minGzipLength)
194     {
195         _minGzipLength = minGzipLength;
196     }
197
198     
199     /* ------------------------------------------------------------ */
200     /** get Resource to serve.
201      * Map a path to a resource. The default implementation calls
202      * HttpContext.getResource but derived handers may provide
203      * their own mapping.
204      * @param pathInContext The path to find a resource for.
205      * @return The resource to serve.
206      */

207     protected Resource getResource(String JavaDoc pathInContext)
208         throws IOException JavaDoc
209     {
210         return getHttpContext().getResource(pathInContext);
211     }
212     
213     /* ------------------------------------------------------------ */
214     public void handle(String JavaDoc pathInContext,
215                        String JavaDoc pathParams,
216                        HttpRequest request,
217                        HttpResponse response)
218         throws HttpException, IOException JavaDoc
219     {
220         Resource resource = getResource(pathInContext);
221         if (resource==null)
222             return;
223
224         // Is the method allowed?
225
if (!isMethodAllowed(request.getMethod()))
226         {
227             if(log.isDebugEnabled())log.debug("Method not allowed: "+request.getMethod());
228             if (resource.exists())
229             {
230                 setAllowHeader(response);
231                 response.sendError(HttpResponse.__405_Method_Not_Allowed);
232             }
233             return;
234         }
235
236         // Handle the request
237
try
238         {
239             if(log.isDebugEnabled())log.debug("PATH="+pathInContext+" RESOURCE="+resource);
240             
241             // check filename
242
String JavaDoc method=request.getMethod();
243             if (method.equals(HttpRequest.__GET) ||
244                 method.equals(HttpRequest.__POST) ||
245                 method.equals(HttpRequest.__HEAD))
246                 handleGet(request, response, pathInContext, pathParams, resource);
247             else if (method.equals(HttpRequest.__PUT))
248                 handlePut(request, response, pathInContext, resource);
249             else if (method.equals(HttpRequest.__DELETE))
250                 handleDelete(request, response, pathInContext, resource);
251             else if (method.equals(HttpRequest.__OPTIONS))
252                 handleOptions(response, pathInContext);
253             else if (method.equals(HttpRequest.__MOVE))
254                 handleMove(request, response, pathInContext, resource);
255             else if (method.equals(HttpRequest.__TRACE))
256                 handleTrace(request, response);
257             else
258             {
259                 if(log.isDebugEnabled())log.debug("Unknown action:"+method);
260                 // anything else...
261
try{
262                     if (resource.exists())
263                         response.sendError(HttpResponse.__501_Not_Implemented);
264                 }
265                 catch(Exception JavaDoc e) {LogSupport.ignore(log,e);}
266             }
267         }
268         catch(IllegalArgumentException JavaDoc e)
269         {
270             LogSupport.ignore(log,e);
271         }
272         finally
273         {
274             if (resource!=null && !(resource instanceof CachedResource))
275                 resource.release();
276         }
277     }
278
279     /* ------------------------------------------------------------------- */
280     public void handleGet(HttpRequest request,
281                           HttpResponse response,
282                           String JavaDoc pathInContext,
283                           String JavaDoc pathParams,
284                           Resource resource)
285         throws IOException JavaDoc
286     {
287         if(log.isDebugEnabled())log.debug("Looking for "+resource);
288         
289         if (resource!=null && resource.exists())
290         {
291             // check if directory
292
if (resource.isDirectory())
293             {
294                 if (!pathInContext.endsWith("/") && !pathInContext.equals("/"))
295                 {
296                     log.debug("Redirect to directory/");
297                     
298                     String JavaDoc q=request.getQuery();
299                     StringBuffer JavaDoc buf=request.getRequestURL();
300                     if (q!=null&&q.length()!=0)
301                     {
302                         buf.append('?');
303                         buf.append(q);
304                     }
305                     response.setField(HttpFields.__Location, URI.addPaths(buf.toString(),"/"));
306                     response.setStatus(302);
307                     request.setHandled(true);
308                     return;
309                 }
310   
311                 // See if index file exists
312
String JavaDoc welcome=getHttpContext().getWelcomeFile(resource);
313                 if (welcome!=null)
314                 {
315                     // Forward to the index
316
String JavaDoc ipath=URI.addPaths(pathInContext,welcome);
317                     if (_redirectWelcomeFiles)
318                     {
319                         // Redirect to the index
320
ipath=URI.addPaths(getHttpContext().getContextPath(),ipath);
321                         response.setContentLength(0);
322                         response.sendRedirect(ipath);
323                     }
324                     else
325                     {
326                         URI uri=request.getURI();
327                         uri.setPath(URI.addPaths(uri.getPath(),welcome));
328                         getHttpContext().handle(ipath,pathParams,request,response);
329                     }
330                     return;
331                 }
332
333                 // Check modified dates
334
if (!passConditionalHeaders(request,response,resource))
335                     return;
336                 // If we got here, no forward to index took place
337
sendDirectory(request,response,resource,pathInContext.length()>1);
338             }
339             // check if it is a file
340
else if (resource.exists())
341             {
342                 // Check modified dates
343
if (!passConditionalHeaders(request,response,resource))
344                     return;
345                 sendData(request,response,pathInContext,resource,true);
346             }
347             else
348                 // don't know what it is
349
log.warn("Unknown file type");
350         }
351     }
352
353  
354     /* ------------------------------------------------------------ */
355     /* Check modification date headers.
356      */

357     private boolean passConditionalHeaders(HttpRequest request,
358                                            HttpResponse response,
359                                            Resource resource)
360         throws IOException JavaDoc
361     {
362         if (!request.getMethod().equals(HttpRequest.__HEAD))
363         {
364             // If we have meta data for the file
365
// Try a direct match for most common requests. Avoids
366
// parsing the date.
367
ResourceCache.ResourceMetaData metaData =
368                 (ResourceCache.ResourceMetaData)resource.getAssociate();
369             if (metaData!=null)
370             {
371                 String JavaDoc ifms=request.getField(HttpFields.__IfModifiedSince);
372                 String JavaDoc mdlm=metaData.getLastModified();
373                 if (ifms!=null && mdlm!=null && ifms.equals(mdlm))
374                 {
375                     response.setStatus(HttpResponse.__304_Not_Modified);
376                     request.setHandled(true);
377                     return false;
378                 }
379             }
380
381             
382             long date=0;
383             // Parse the if[un]modified dates and compare to resource
384

385             if ((date=request.getDateField(HttpFields.__IfUnmodifiedSince))>0)
386             {
387                 if (resource.lastModified()/1000 > date/1000)
388                 {
389                     response.sendError(HttpResponse.__412_Precondition_Failed);
390                     return false;
391                 }
392             }
393             
394             if ((date=request.getDateField(HttpFields.__IfModifiedSince))>0)
395             {
396                 
397                 if (resource.lastModified()/1000 <= date/1000)
398                 {
399                     response.setStatus(HttpResponse.__304_Not_Modified);
400                     request.setHandled(true);
401                     return false;
402                 }
403             }
404    
405         }
406         return true;
407     }
408  
409  
410     /* ------------------------------------------------------------ */
411     void handlePut(HttpRequest request,
412                    HttpResponse response,
413                    String JavaDoc pathInContext,
414                    Resource resource)
415         throws IOException JavaDoc
416     {
417         if(log.isDebugEnabled())log.debug("PUT "+pathInContext+" in "+resource);
418
419         boolean exists=resource!=null && resource.exists();
420         if (exists &&
421             !passConditionalHeaders(request,response,resource))
422             return;
423         
424         if (pathInContext.endsWith("/"))
425         {
426             if (!exists)
427             {
428                 if (!resource.getFile().mkdirs())
429                     response.sendError(HttpResponse.__403_Forbidden, "Directories could not be created");
430                 else
431                 {
432                     request.setHandled(true);
433                     response.setStatus(HttpResponse.__201_Created);
434                     response.commit();
435                 }
436             }
437             else
438             {
439                 request.setHandled(true);
440                 response.setStatus(HttpResponse.__200_OK);
441                 response.commit();
442             }
443         }
444         else
445         {
446             try
447             {
448                 int toRead = request.getContentLength();
449                 InputStream JavaDoc in = request.getInputStream();
450                 OutputStream JavaDoc out = resource.getOutputStream();
451                 if (toRead>=0)
452                     IO.copy(in,out,toRead);
453                 else
454                     IO.copy(in,out);
455                 out.close();
456                 request.setHandled(true);
457                 response.setStatus(exists
458                                    ?HttpResponse.__200_OK
459                                    :HttpResponse.__201_Created);
460                 response.commit();
461             }
462             catch (Exception JavaDoc ex)
463             {
464                 log.warn(LogSupport.EXCEPTION,ex);
465                 response.sendError(HttpResponse.__403_Forbidden,
466                                    ex.getMessage());
467             }
468         }
469     }
470
471     /* ------------------------------------------------------------ */
472     void handleDelete(HttpRequest request,
473                       HttpResponse response,
474                       String JavaDoc pathInContext,
475                       Resource resource)
476         throws IOException JavaDoc
477     {
478         if(log.isDebugEnabled())log.debug("DELETE "+pathInContext+" from "+resource);
479  
480         if (!resource.exists() ||
481             !passConditionalHeaders(request,response,resource))
482             return;
483  
484         try
485         {
486             // delete the file
487
if (resource.delete())
488                 response.setStatus(HttpResponse.__204_No_Content);
489             else
490                 response.sendError(HttpResponse.__403_Forbidden);
491
492             // Send response
493
request.setHandled(true);
494         }
495         catch (SecurityException JavaDoc sex)
496         {
497             log.warn(LogSupport.EXCEPTION,sex);
498             response.sendError(HttpResponse.__403_Forbidden, sex.getMessage());
499         }
500     }
501
502  
503     /* ------------------------------------------------------------ */
504     void handleMove(HttpRequest request,
505                     HttpResponse response,
506                     String JavaDoc pathInContext,
507                     Resource resource)
508         throws IOException JavaDoc
509     {
510         if (!resource.exists() || !passConditionalHeaders(request,response,resource))
511             return;
512
513  
514         String JavaDoc newPath = URI.canonicalPath(request.getField("New-uri"));
515         if (newPath==null)
516         {
517             response.sendError(HttpResponse.__405_Method_Not_Allowed,
518                                "Bad new uri");
519             return;
520         }
521
522         String JavaDoc contextPath = getHttpContext().getContextPath();
523         if (contextPath!=null && !newPath.startsWith(contextPath))
524         {
525             response.sendError(HttpResponse.__405_Method_Not_Allowed,
526                                "Not in context");
527             return;
528         }
529         
530
531         // Find path
532
try
533         {
534             // TODO - Check this
535
String JavaDoc newInfo=newPath;
536             if (contextPath!=null)
537                 newInfo=newInfo.substring(contextPath.length());
538             Resource newFile = getHttpContext().getBaseResource().addPath(newInfo);
539      
540             if(log.isDebugEnabled())log.debug("Moving "+resource+" to "+newFile);
541             resource.renameTo(newFile);
542     
543             response.setStatus(HttpResponse.__204_No_Content);
544             request.setHandled(true);
545         }
546         catch (Exception JavaDoc ex)
547         {
548             log.warn(LogSupport.EXCEPTION,ex);
549             setAllowHeader(response);
550             response.sendError(HttpResponse.__405_Method_Not_Allowed,
551                                "Error:"+ex);
552             return;
553         }
554     }
555  
556     /* ------------------------------------------------------------ */
557     void handleOptions(HttpResponse response, String JavaDoc pathInContext)
558         throws IOException JavaDoc
559     {
560         if ("*".equals(pathInContext))
561             return;
562         setAllowHeader(response);
563         response.commit();
564     }
565  
566     /* ------------------------------------------------------------ */
567     void setAllowHeader(HttpResponse response)
568     {
569         response.setField(HttpFields.__Allow, getAllowedString());
570     }
571     
572     /* ------------------------------------------------------------ */
573     public void writeHeaders(HttpResponse response,Resource resource, long count)
574         throws IOException JavaDoc
575     {
576         ResourceCache.ResourceMetaData metaData =
577             (ResourceCache.ResourceMetaData)resource.getAssociate();
578
579         response.setContentType(metaData.getMimeType());
580         if (count != -1)
581         {
582             if (count==resource.length())
583                 response.setField(HttpFields.__ContentLength,metaData.getLength());
584             else
585                 response.setContentLength((int)count);
586         }
587
588         response.setField(HttpFields.__LastModified,metaData.getLastModified());
589         
590         if (_acceptRanges && response.getHttpRequest().getDotVersion()>0)
591             response.setField(HttpFields.__AcceptRanges,"bytes");
592     }
593
594     /* ------------------------------------------------------------ */
595     public void sendData(HttpRequest request,
596                          HttpResponse response,
597                          String JavaDoc pathInContext,
598                          Resource resource,
599                          boolean writeHeaders)
600         throws IOException JavaDoc
601     {
602         long resLength=resource.length();
603         
604         // see if there are any range headers
605
Enumeration JavaDoc reqRanges =
606             request.getDotVersion()>0
607             ?request.getFieldValues(HttpFields.__Range)
608             :null;
609         
610         if (!writeHeaders || reqRanges == null || !reqRanges.hasMoreElements())
611         {
612             // look for a gziped content.
613
Resource data=resource;
614             if (_minGzipLength>0)
615             {
616                 String JavaDoc accept=request.getField(HttpFields.__AcceptEncoding);
617                 if (accept!=null && resLength>_minGzipLength &&
618                     !pathInContext.endsWith(".gz"))
619                 {
620                     Resource gz = getHttpContext().getResource(pathInContext+".gz");
621                     if (gz.exists() && accept.indexOf("gzip")>=0)
622                     {
623                         if(log.isDebugEnabled())log.debug("gzip="+gz);
624                         response.setField(HttpFields.__ContentEncoding,"gzip");
625                         data=gz;
626                         resLength=data.length();
627                     }
628                 }
629             }
630             writeHeaders(response,resource,resLength);
631             
632             request.setHandled(true);
633             OutputStream JavaDoc out = response.getOutputStream();
634             data.writeTo(out,0,resLength);
635             return;
636         }
637             
638         // Parse the satisfiable ranges
639
List JavaDoc ranges =InclusiveByteRange.satisfiableRanges(reqRanges,resLength);
640         if(log.isDebugEnabled())log.debug("ranges: " + reqRanges + " == " + ranges);
641         
642         // if there are no satisfiable ranges, send 416 response
643
if (ranges==null || ranges.size()==0)
644         {
645             log.debug("no satisfiable ranges");
646             writeHeaders(response, resource, resLength);
647             response.setStatus(HttpResponse.__416_Requested_Range_Not_Satisfiable);
648             response.setReason((String JavaDoc)HttpResponse.__statusMsg
649                                .get(TypeUtil.newInteger(HttpResponse.__416_Requested_Range_Not_Satisfiable)));
650
651             response.setField(HttpFields.__ContentRange,
652                               InclusiveByteRange.to416HeaderRangeString(resLength));
653             
654             OutputStream JavaDoc out = response.getOutputStream();
655             resource.writeTo(out,0,resLength);
656             request.setHandled(true);
657             return;
658         }
659
660         
661         // if there is only a single valid range (must be satisfiable
662
// since were here now), send that range with a 216 response
663
if ( ranges.size()== 1)
664         {
665             InclusiveByteRange singleSatisfiableRange =
666                 (InclusiveByteRange)ranges.get(0);
667             if(log.isDebugEnabled())log.debug("single satisfiable range: " + singleSatisfiableRange);
668             long singleLength = singleSatisfiableRange.getSize(resLength);
669             writeHeaders(response,resource,singleLength);
670             response.setStatus(HttpResponse.__206_Partial_Content);
671             response.setReason((String JavaDoc)HttpResponse.__statusMsg
672                                .get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
673             response.setField(HttpFields.__ContentRange,
674                               singleSatisfiableRange.toHeaderRangeString(resLength));
675             OutputStream JavaDoc out = response.getOutputStream();
676             resource.writeTo(out,
677                              singleSatisfiableRange.getFirst(resLength),
678                              singleLength);
679             request.setHandled(true);
680             return;
681         }
682
683         
684         // multiple non-overlapping valid ranges cause a multipart
685
// 216 response which does not require an overall
686
// content-length header
687
//
688
ResourceCache.ResourceMetaData metaData =
689             (ResourceCache.ResourceMetaData)resource.getAssociate();
690         String JavaDoc encoding = metaData.getMimeType();
691         MultiPartResponse multi = new MultiPartResponse(response);
692         response.setStatus(HttpResponse.__206_Partial_Content);
693         response.setReason((String JavaDoc)HttpResponse.__statusMsg
694                            .get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
695
696     // If the request has a "Request-Range" header then we need to
697
// send an old style multipart/x-byteranges Content-Type. This
698
// keeps Netscape and acrobat happy. This is what Apache does.
699
String JavaDoc ctp;
700     if (request.containsField(HttpFields.__RequestRange))
701         ctp = "multipart/x-byteranges; boundary=";
702     else
703         ctp = "multipart/byteranges; boundary=";
704     response.setContentType(ctp+multi.getBoundary());
705
706         InputStream JavaDoc in=(resource instanceof CachedResource)
707             ?null:resource.getInputStream();
708         OutputStream JavaDoc out = response.getOutputStream();
709         long pos=0;
710             
711         for (int i=0;i<ranges.size();i++)
712         {
713             InclusiveByteRange ibr = (InclusiveByteRange) ranges.get(i);
714             String JavaDoc header=HttpFields.__ContentRange+": "+
715                 ibr.toHeaderRangeString(resLength);
716             if(log.isDebugEnabled())log.debug("multi range: "+encoding+" "+header);
717             multi.startPart(encoding,new String JavaDoc[]{header});
718
719             long start=ibr.getFirst(resLength);
720             long size=ibr.getSize(resLength);
721             if (in!=null)
722             {
723                 // Handle non cached resource
724
if (start<pos)
725                 {
726                     in.close();
727                     in=resource.getInputStream();
728                     pos=0;
729                 }
730                 if (pos<start)
731                 {
732                     in.skip(start-pos);
733                     pos=start;
734                 }
735                 IO.copy(in,out,size);
736                 pos+=size;
737             }
738             else
739                 // Handle cached resource
740
resource.writeTo(out,start,size);
741             
742         }
743         if (in!=null)
744             in.close();
745         multi.close();
746
747         request.setHandled(true);
748
749         return;
750     }
751
752
753     /* ------------------------------------------------------------------- */
754     void sendDirectory(HttpRequest request,
755                        HttpResponse response,
756                        Resource resource,
757                        boolean parent)
758         throws IOException JavaDoc
759     {
760         if (!_dirAllowed)
761         {
762             response.sendError(HttpResponse.__403_Forbidden);
763             return;
764         }
765         
766         request.setHandled(true);
767         
768         if(log.isDebugEnabled())log.debug("sendDirectory: "+resource);
769         byte[] data=null;
770         if (resource instanceof CachedResource)
771             data=((CachedResource)resource).getCachedData();
772         
773         if (data==null)
774         {
775             String JavaDoc base = URI.addPaths(request.getPath(),"/");
776             String JavaDoc dir = resource.getListHTML(URI.encodePath(base),parent);
777             if (dir==null)
778             {
779                 response.sendError(HttpResponse.__403_Forbidden,
780                                    "No directory");
781                 return;
782             }
783             data=dir.getBytes("UTF8");
784             if (resource instanceof CachedResource)
785                 ((CachedResource)resource).setCachedData(data);
786         }
787         
788         response.setContentType("text/html; charset=UTF8");
789         response.setContentLength(data.length);
790         
791         if (request.getMethod().equals(HttpRequest.__HEAD))
792         {
793             response.commit();
794             return;
795         }
796         
797         response.getOutputStream().write(data,0,data.length);
798         response.commit();
799     }
800 }
801
802
803
804
Popular Tags