001: /*
002: HttpdBase4J: An embeddable Java web server framework that supports HTTP, HTTPS,
003: templated content and serving content from inside a jar or archive.
004: Copyright (C) 2007 Donald Munro
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; either
009: version 2.1 of the License, or (at your option) any later version.
010:
011: This library is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public
017: License along with this library; if not,see http://www.gnu.org/licenses/lgpl.txt
018: */
019:
020: package net.homeip.donaldm.httpdbase4j;
021:
022: import java.io.File;
023: import java.util.Iterator;
024:
025: import net.homeip.donaldm.httpdbase4j.Httpd.LogLevel;
026:
027: import com.sun.net.httpserver.HttpExchange;
028: import com.sun.net.httpserver.HttpHandler;
029:
030: /**
031: * An abstraction of a handler for local filesystem based HTTP requests.
032: * @author Donald Munro
033: */
034: public class FileRequestHandler extends RequestHandler implements
035: HttpHandler
036: //===========================================================================
037: {
038: /**
039: * The home directory within the file system for this request.
040: */
041: protected File m_homeDir = null;
042:
043: /**
044: * Create a FileRequestHandler.
045: * @param httpd - The Httpd instance
046: * @param homeDir - The home directory within the file system for this request.
047: * @param isVerbose - Logging verbosity
048: */
049: public FileRequestHandler(Httpd httpd, File homeDir,
050: boolean isVerbose)
051: //-----------------------------------------------------------------
052: {
053: super (httpd, isVerbose);
054: m_homeDir = homeDir;
055: }
056:
057: /**
058: * @inheritDoc
059: */
060: @Override
061: public void handle(HttpExchange ex)
062: //--------------------------------
063: {
064: m_ex = ex;
065: Request request = null;
066: try {
067: if (isCombinedRequest(ex.getRequestURI().getPath()))
068: request = new FileCombinedRequest(m_httpd, ex,
069: m_homeDir);
070: else
071: request = new FileRequest(m_httpd, ex, m_homeDir);
072: } catch (Exception e) {
073: Httpd.Log(LogLevel.ERROR, "Creating request for "
074: + ex.getRequestURI().toASCIIString(), e);
075: return;
076: }
077: try {
078: if (m_verbose)
079: Httpd.Log(Httpd.LogLevel.INFO, "Received "
080: + request.getMethodString() + " "
081: + request.getPath() + " request from "
082: + ex.getRemoteAddress().toString(), null);
083:
084: if ((request.isGETorHEAD()) && (request.isDirectory())) {
085: FileRequest req = null;
086: for (Iterator<String> i = m_httpd.m_defaultFiles
087: .iterator(); i.hasNext();) {
088: String defaultName = i.next();
089: req = new FileRequest((FileRequest) request,
090: defaultName);
091: if (req.exists())
092: break;
093: req = null;
094: }
095: if (req != null)
096: request = req;
097: else {
098: browseDirCheck(ex, request);
099: return;
100: }
101: }
102:
103: HttpResponse r = new HttpResponse(ex);
104: boolean isProcessAsGet = false;
105: long id = Httpd.getNextSequence();
106:
107: if (request.getMethod() == Request.HTTP_METHOD.POST) {
108: Postable postHandler = request.getPostHandler();
109: if (postHandler == null)
110: postHandler = m_httpd;
111: Object o = postHandler.onHandlePost(id, ex, request, r,
112: m_homeDir);
113: if ((o != null) && (o instanceof HttpResponse)) {
114: r = (HttpResponse) o;
115: r.send();
116: return;
117: }
118:
119: File f;
120: if ((o == null) || (o instanceof File)) {
121: if (o == null) {
122: String html = "<head><title>POST Error</title></head><body>"
123: + "<p>Service unavailable for POST "
124: + request.getPath()
125: + "</p><hr>"
126: + "</body></html>";
127: r.setStatus(503);
128: r.setMimeType(Http.MIME_HTML);
129: r.setBody(html);
130: r.send();
131: if (m_verbose)
132: Httpd.Log(Httpd.LogLevel.INFO,
133: "No POST handler for "
134: + request.getPath()
135: + " request from "
136: + ex.getRemoteAddress()
137: .toString(), null);
138: return;
139: } else {
140: f = (File) o;
141: request = new FileRequest(request, m_homeDir, f);
142: isProcessAsGet = true;
143: }
144: if (m_verbose)
145: Httpd.Log(Httpd.LogLevel.INFO,
146: "POST handler for "
147: + request.getPath()
148: + " request from "
149: + ex.getRemoteAddress()
150: .toString()
151: + " generated "
152: + request.getAbsolutePath(),
153: null);
154: } else // if ( (o == null) || (o instanceof File) )
155: {
156: Httpd.Log(LogLevel.ERROR, "Invalid return type "
157: + o.getClass().getName()
158: + " from onHandlePost "
159: + ex.getRequestURI().toASCIIString(), null);
160: HttpResponse.internalError(ex, request.getURI(), ex
161: .getRequestHeaders());
162: }
163: }
164:
165: if ((request.isGETorHEAD()) || (isProcessAsGet)) {
166: HttpHandleable handler = request.getHandler();
167: if (request.isDirectory()) {
168: String dirHtml = handler.onListDirectory(request);
169: if (dirHtml == null) {
170: r = HttpResponse.accessDenied(ex, request
171: .getURI(), ex.getRequestHeaders());
172: r.send();
173: return;
174: }
175: r.setMimeType(Http.MIME_HTML);
176: r.setBody(dirHtml);
177: r.send();
178: return;
179: }
180:
181: String etag = null;
182: if (handler.onIsCacheable(id, ex, request)) {
183: etag = request.getETag(false);
184: if (request.checkClientCache()) {
185: r.setStatus(304);
186: r.send();
187: return;
188: }
189: }
190:
191: if (!handler.onPreServe(id, ex, request)) {
192: HttpResponse.notFound(ex, request.getURI(),
193: ex.getRequestHeaders()).send();
194: return;
195: }
196:
197: if (!request.exists()) {
198: if (m_verbose)
199: Httpd.Log(Httpd.LogLevel.INFO, "Request "
200: + request.getURI().toASCIIString()
201: + " not found", null);
202: Request newRequest = handler.onFileNotFound(id, ex,
203: request);
204: if ((newRequest == null) || (!newRequest.exists())) {
205: HttpResponse.notFound(
206: ex,
207: (newRequest == null) ? request.getURI()
208: : newRequest.getURI(),
209: ex.getRequestHeaders()).send();
210: return;
211: }
212: request = newRequest;
213: etag = request.getETag(true);
214: }
215:
216: if (!request.isReadable()) {
217: HttpResponse.accessDenied(ex, request.getURI(),
218: ex.getRequestHeaders()).send();
219: return;
220: }
221:
222: sendResult(request, r, id, etag, ex);
223: return;
224: }
225: } catch (Exception e) {
226: Httpd
227: .Log(Httpd.LogLevel.ERROR,
228: "Error handling request", e);
229: } finally {
230: if (ex != null)
231: try {
232: ex.close();
233: } catch (Exception e) {
234: }
235: }
236: }
237:
238: /**
239: * @inheritDoc
240: */
241: @Override
242: public String toString()
243: //----------------------
244: {
245: return super .toString() + Httpd.EOL + "Base Directory: "
246: + ((m_homeDir == null) ? "Unknown" : m_homeDir);
247: }
248: }
|