001: // ========================================================================
002: // Copyright 1999-2005 Mort Bay Consulting Pty. Ltd.
003: // ------------------------------------------------------------------------
004: // Licensed under the Apache License, Version 2.0 (the "License");
005: // you may not use this file except in compliance with the License.
006: // You may obtain a copy of the License at
007: // http://www.apache.org/licenses/LICENSE-2.0
008: // Unless required by applicable law or agreed to in writing, software
009: // distributed under the License is distributed on an "AS IS" BASIS,
010: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: // See the License for the specific language governing permissions and
012: // limitations under the License.
013: // ========================================================================
014:
015: package org.mortbay.jetty.handler;
016:
017: import java.io.IOException;
018: import java.io.OutputStream;
019: import java.net.MalformedURLException;
020:
021: import javax.servlet.ServletException;
022: import javax.servlet.http.HttpServletRequest;
023: import javax.servlet.http.HttpServletResponse;
024:
025: import org.mortbay.io.Buffer;
026: import org.mortbay.io.WriterOutputStream;
027: import org.mortbay.jetty.HttpConnection;
028: import org.mortbay.jetty.HttpHeaders;
029: import org.mortbay.jetty.HttpMethods;
030: import org.mortbay.jetty.MimeTypes;
031: import org.mortbay.jetty.Request;
032: import org.mortbay.log.Log;
033: import org.mortbay.resource.Resource;
034: import org.mortbay.util.TypeUtil;
035: import org.mortbay.util.URIUtil;
036:
037: /* ------------------------------------------------------------ */
038: /** Resource Handler.
039: *
040: * This handle will serve static content and handle If-Modified-Since headers.
041: * No caching is done.
042: * Requests that cannot be handled are let pass (Eg no 404's)
043: *
044: * @author Greg Wilkins (gregw)
045: * @org.apache.xbean.XBean
046: */
047: public class ResourceHandler extends AbstractHandler {
048: Resource _baseResource;
049: String[] _welcomeFiles = { "index.html" };
050: MimeTypes _mimeTypes = new MimeTypes();
051:
052: public ResourceHandler() {
053: }
054:
055: /* ------------------------------------------------------------ */
056: /**
057: * @return Returns the resourceBase.
058: */
059: public Resource getBaseResource() {
060: if (_baseResource == null)
061: return null;
062: return _baseResource;
063: }
064:
065: /* ------------------------------------------------------------ */
066: /**
067: * @return Returns the base resource as a string.
068: */
069: public String getResourceBase() {
070: if (_baseResource == null)
071: return null;
072: return _baseResource.toString();
073: }
074:
075: /* ------------------------------------------------------------ */
076: /**
077: * @param base The resourceBase to set.
078: */
079: public void setBaseResource(Resource base) {
080: _baseResource = base;
081: }
082:
083: /* ------------------------------------------------------------ */
084: /**
085: * @param resourceBase The base resource as a string.
086: */
087: public void setResourceBase(String resourceBase) {
088: try {
089: setBaseResource(Resource.newResource(resourceBase));
090: } catch (Exception e) {
091: Log.warn(e);
092: throw new IllegalArgumentException(resourceBase);
093: }
094: }
095:
096: /* ------------------------------------------------------------ */
097: /*
098: */
099: public Resource getResource(String path)
100: throws MalformedURLException {
101: if (path == null || !path.startsWith("/"))
102: throw new MalformedURLException(path);
103:
104: if (_baseResource == null)
105: return null;
106:
107: try {
108: path = URIUtil.canonicalPath(path);
109: Resource resource = _baseResource.addPath(path);
110: return resource;
111: } catch (Exception e) {
112: Log.ignore(e);
113: }
114:
115: return null;
116: }
117:
118: /* ------------------------------------------------------------ */
119: protected Resource getResource(HttpServletRequest request)
120: throws MalformedURLException {
121: String path_info = request.getPathInfo();
122: if (path_info == null)
123: return null;
124: return getResource(path_info);
125: }
126:
127: /* ------------------------------------------------------------ */
128: public String[] getWelcomeFiles() {
129: return _welcomeFiles;
130: }
131:
132: /* ------------------------------------------------------------ */
133: public void setWelcomeFiles(String[] welcomeFiles) {
134: _welcomeFiles = welcomeFiles;
135: }
136:
137: /* ------------------------------------------------------------ */
138: protected Resource getWelcome(Resource directory)
139: throws MalformedURLException, IOException {
140: for (int i = 0; i < _welcomeFiles.length; i++) {
141: Resource welcome = directory.addPath(_welcomeFiles[i]);
142: if (welcome.exists() && !welcome.isDirectory())
143: return welcome;
144: }
145:
146: return null;
147: }
148:
149: /* ------------------------------------------------------------ */
150: /*
151: * @see org.mortbay.jetty.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
152: */
153: public void handle(String target, HttpServletRequest request,
154: HttpServletResponse response, int dispatch)
155: throws IOException, ServletException {
156: Request base_request = request instanceof Request ? (Request) request
157: : HttpConnection.getCurrentConnection().getRequest();
158: if (base_request.isHandled()
159: || !request.getMethod().equals(HttpMethods.GET))
160: return;
161:
162: Resource resource = getResource(request);
163:
164: if (resource == null || !resource.exists())
165: return;
166:
167: // We are going to server something
168: base_request.setHandled(true);
169:
170: if (resource.isDirectory()) {
171: if (!request.getPathInfo().endsWith("/")) {
172: response.sendRedirect(request.getRequestURI() + "/");
173: return;
174: }
175: resource = getWelcome(resource);
176:
177: if (resource == null || !resource.exists()
178: || resource.isDirectory()) {
179: response.sendError(HttpServletResponse.SC_FORBIDDEN);
180: return;
181: }
182: }
183:
184: // set some headers
185: long last_modified = resource.lastModified();
186: if (last_modified > 0) {
187: long if_modified = request
188: .getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
189: if (if_modified > 0
190: && last_modified / 1000 <= if_modified / 1000) {
191: response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
192: return;
193: }
194: response.setDateHeader(HttpHeaders.LAST_MODIFIED,
195: last_modified);
196: }
197:
198: Buffer mime = _mimeTypes.getMimeByExtension(request
199: .getPathInfo());
200: if (mime != null)
201: response.setContentType(mime.toString());
202:
203: long length = resource.length();
204: if (length > 0)
205: response.setHeader(HttpHeaders.CONTENT_LENGTH, TypeUtil
206: .toString(length));
207:
208: // Send the content
209: OutputStream out = null;
210: try {
211: out = response.getOutputStream();
212: } catch (IllegalStateException e) {
213: out = new WriterOutputStream(response.getWriter());
214: }
215:
216: // See if a short direct method can be used?
217: if (out instanceof HttpConnection.Output) {
218: // TODO file mapped buffers
219: ((HttpConnection.Output) out).sendContent(resource
220: .getInputStream());
221: } else {
222: // Write content normally
223: resource.writeTo(out, 0, length);
224: }
225: }
226:
227: }
|