001: /*
002: * FileComponent.java February 2001
003: *
004: * Copyright (C) 2001, Niall Gallagher <niallg@users.sf.net>
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General
016: * Public License along with this library; if not, write to the
017: * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
018: * Boston, MA 02111-1307 USA
019: */
020:
021: package simple.http.serve;
022:
023: import simple.http.Response;
024: import simple.http.Request;
025:
026: /**
027: * The <code>FileComponent</code> provides an implementation of the
028: * <code>Component</code> that can be used to acquire generic files.
029: * The <code>FileComponent</code> is an <code>IndexedComponent</code>.
030: * This means that all the meta information on the file is acquired
031: * once the resource is instantiated.
032: * <p>
033: * This <code>Component</code> implementation delegates to the
034: * provided context to acquire the contents of the file. This means
035: * that all caching can be provided by the context, and thus it can
036: * be shared amongst other interested objects. The performance of
037: * this object is largely dependant on the context implementation.
038: *
039: * @author Niall Gallagher
040: *
041: * @see simple.http.serve.CacheContext
042: */
043: final class FileComponent extends ContentComponent {
044:
045: /**
046: * The files meta information is taken from the path that is
047: * specified. The <code>IndexedComponent</code> constructor will
048: * provide the meta information for the specified resource.
049: * This delegates to the provided <code>Context</code> object
050: * to acquire the content for the resource. This allows the
051: * context to determine the caching policy for all files.
052: *
053: * @param target this is the HTTP request URI for this resource
054: * @param context the root context of this file resource
055: */
056: public FileComponent(Context context, String target) {
057: super (context, target);
058: }
059:
060: /**
061: * This method handles the HTTP request and response. When a
062: * HTTP request is generated it is given to this method. This
063: * will then either respond with the appropriate error message
064: * or process the request.
065: * <p>
066: * If the file requested does not exist then this will use the
067: * <code>Component.handle(Request,Response,int)</code> to
068: * generate the appropriate response.
069: * <p>
070: * If the method used is HEAD then this will write only the
071: * headers and will subsequently close the pipeline. However
072: * this will not handle POST, OPTIONS, TRACE, DELETE or PUT
073: * requests and will generate a "501 Not Implemented" message
074: * if attempted, see RFC 2616 sec 5.1.1.
075: *
076: * @param req the <code>Request</code> to be processed
077: * @param resp the <code>Response</code> to be processed
078: *
079: * @exception Exception throw if theres an I/O error
080: */
081: protected void process(Request req, Response resp) throws Exception {
082: if (req.getDate("If-Modified-Since") < getLastModified()) {
083: resp.setDate("Date", System.currentTimeMillis());
084: resp.setDate("Last-Modified", getLastModified());
085: resp.set("Content-Type", getContentType());
086: resp.setContentLength(getLength());
087:
088: if (req.getMethod().equals("HEAD")) {
089: resp.commit();
090: } else if (req.getMethod().equals("GET")) {
091: write(resp.getOutputStream());
092: resp.getOutputStream().close();
093: } else {
094: handle(req, resp, 501);
095: }
096: } else {
097: handle(req, resp, 304);
098: }
099: }
100: }
|