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.util.Iterator;
023:
024: import net.homeip.donaldm.httpdbase4j.Httpd.LogLevel;
025:
026: import com.sun.net.httpserver.HttpExchange;
027: import com.sun.net.httpserver.HttpHandler;
028:
029: import de.schlichtherle.io.File;
030:
031: /**
032: * An abstraction of a handler for archive or classpath based HTTP requests.
033: * @author Donald Munro
034: */
035: public class ArchiveRequestHandler extends RequestHandler implements
036: HttpHandler
037: //==========================================================================
038: {
039: /**
040: * The base directory within the archive containing the web content.
041: */
042: protected File m_homeDir = null;
043:
044: /**
045: * A directory on the file system that can be used for creating dynamic
046: * content
047: */
048: protected java.io.File m_localHomeDir = null;
049:
050: /**
051: * Create a ArchiveRequestHandler.
052: * @param httpd - The Httpd instance
053: * @param homeDir The base directory within the compressed file containing
054: * the web resources. Must be an instance of a TrueZip File ie
055: * de.schlichtherle.io.File
056: * @param localHomeDir - A directory on the file system that can be used for creating
057: * dynamic content. If null then the alternate home in JatHttpd is used and if that is
058: * null then a directory is created in the temporary directory.
059: * @param isVerbose
060: */
061: public ArchiveRequestHandler(ArchiveHttpd httpd, File homeDir,
062: java.io.File localHomeDir, boolean isVerbose)
063: //---------------------------------------------------------------------------
064: {
065: super (httpd, isVerbose);
066: m_homeDir = homeDir;
067: if (localHomeDir == null)
068: localHomeDir = httpd.getAltFileSystemHome();
069: if (localHomeDir == null) {
070: _createLocalFileHome();
071: localHomeDir = m_localHomeDir;
072: }
073: if (!localHomeDir.exists())
074: localHomeDir.mkdirs();
075: if ((localHomeDir.exists()) && (localHomeDir.canWrite()))
076: m_localHomeDir = localHomeDir;
077: else
078: _createLocalFileHome();
079: }
080:
081: public java.io.File getAltFileSystemHome() {
082: return m_localHomeDir;
083: }
084:
085: private void _createLocalFileHome()
086: //---------------------------------
087: {
088: java.io.File tmpDir = new java.io.File(System
089: .getProperty("java.io.tmpdir"));
090:
091: if ((tmpDir.exists()) && (tmpDir.canWrite())) {
092: tmpDir = new File(tmpDir, "HttpdBase4J");
093: tmpDir.mkdirs();
094: if ((!tmpDir.exists()) || (!tmpDir.canWrite())) {
095: tmpDir = new File(System.getProperty("java.io.tmpdir"));
096: m_localHomeDir = new java.io.File(tmpDir,
097: "HttpdBase4J-AltDocs");
098: } else
099: m_localHomeDir = new java.io.File(tmpDir,
100: "AlternateDocs");
101: m_localHomeDir.mkdirs();
102: if (!m_localHomeDir.exists())
103: m_localHomeDir = tmpDir;
104: if (!m_localHomeDir.canWrite())
105: m_localHomeDir = tmpDir;
106: } else
107: m_localHomeDir = null;
108: }
109:
110: @Override
111: public void handle(HttpExchange ex)
112: //--------------------------------
113: {
114: m_ex = ex;
115: //System.out.println(this.toString());
116: Request request = null;
117: FileRequest altRequest = null;
118: try {
119: if (isCombinedRequest(ex.getRequestURI().getPath()))
120: request = new ArchiveCombinedRequest(m_httpd, ex,
121: m_homeDir);
122: else
123: request = new ArchiveRequest(m_httpd, ex, m_homeDir);
124: } catch (Exception e) {
125: Httpd.Log(LogLevel.ERROR, "Creating request for "
126: + ex.getRequestURI().toASCIIString(), e);
127: return;
128: }
129: try {
130: if (m_verbose)
131: Httpd.Log(Httpd.LogLevel.INFO, "Received "
132: + request.getMethodString() + " "
133: + request.getPath() + " request from "
134: + ex.getRemoteAddress().toString(), null);
135: if ((request.isGETorHEAD()) && (request.isDirectory())) {
136: ArchiveRequest req = null;
137: for (Iterator<String> i = m_httpd.m_defaultFiles
138: .iterator(); i.hasNext();) {
139: String defaultName = i.next();
140: req = new ArchiveRequest((ArchiveRequest) request,
141: defaultName);
142: if (req.exists())
143: break;
144: req = null;
145: }
146: if (req != null)
147: request = req;
148: else {
149: browseDirCheck(ex, request);
150: return;
151: }
152: }
153:
154: HttpResponse r = new HttpResponse(ex);
155: boolean isProcessAsGet = false;
156: long id = Httpd.getNextSequence();
157:
158: if (request.getMethod() == Request.HTTP_METHOD.POST) {
159: Postable postHandler = request.getPostHandler();
160: if (postHandler == null)
161: postHandler = m_httpd;
162: Object o = postHandler.onHandlePost(id, ex, request, r,
163: m_localHomeDir);
164: if ((o != null) && (o instanceof HttpResponse)) {
165: r = (HttpResponse) o;
166: r.send();
167: return;
168: }
169:
170: java.io.File f;
171: if ((o == null) || (o instanceof File)
172: || (o instanceof java.io.File)) {
173: if ((o == null) || (m_localHomeDir == null)) {
174: String html = "<head><title>POST Error</title></head><body>"
175: + "<p>Service unavailable for POST "
176: + request.getPath()
177: + "</p><hr>"
178: + "</body></html>";
179: r.setStatus(503);
180: r.setMimeType(Http.MIME_HTML);
181: r.setBody(html);
182: r.send();
183: if (m_verbose)
184: Httpd.Log(Httpd.LogLevel.INFO,
185: "No POST handler for "
186: + request.getPath()
187: + " request from "
188: + ex.getRemoteAddress()
189: .toString(), null);
190: return;
191: } else {
192: f = (java.io.File) o;
193: request = new FileRequest(request,
194: m_localHomeDir, f);
195: isProcessAsGet = true;
196: }
197: if (m_verbose)
198: Httpd.Log(Httpd.LogLevel.INFO,
199: "POST handler for "
200: + request.getPath()
201: + " request from "
202: + ex.getRemoteAddress()
203: .toString()
204: + " generated "
205: + request.getAbsolutePath(),
206: null);
207: } else // if ( (o == null) || (o instanceof File) )
208: {
209: Httpd.Log(LogLevel.ERROR, "Invalid return type "
210: + o.getClass().getName()
211: + " from onHandlePost "
212: + ex.getRequestURI().toASCIIString(), null);
213: HttpResponse.internalError(ex, request.getURI(), ex
214: .getRequestHeaders());
215: }
216: }
217:
218: if ((request.isGETorHEAD()) || (isProcessAsGet)) {
219: HttpHandleable handler = request.getHandler();
220: if (request.isDirectory()) {
221: String dirHtml = handler.onListDirectory(request);
222: if (dirHtml == null) {
223: r = HttpResponse.accessDenied(ex, request
224: .getURI(), ex.getRequestHeaders());
225: r.send();
226: return;
227: }
228: r.setMimeType(Http.MIME_HTML);
229: r.setBody(dirHtml);
230: r.send();
231: return;
232: }
233:
234: String etag = null;
235: if (handler.onIsCacheable(id, ex, request)) {
236: etag = request.getETag(false);
237: if (request.checkClientCache()) {
238: r.setStatus(304);
239: r.send();
240: return;
241: }
242: }
243:
244: if (!handler.onPreServe(id, ex, request)) {
245: HttpResponse.notFound(ex, request.getURI(),
246: ex.getRequestHeaders()).send();
247: return;
248: }
249:
250: if (!request.exists()) {
251: if ((altRequest == null)
252: && (m_localHomeDir != null))
253: altRequest = new FileRequest(request,
254: m_localHomeDir, null);
255: if ((altRequest != null) && (altRequest.exists())) {
256: request = altRequest;
257: etag = request.getETag(true);
258: } else {
259: if (m_verbose)
260: Httpd.Log(Httpd.LogLevel.INFO, "Request "
261: + request.getURI().toASCIIString()
262: + " not found", null);
263: Request newRequest = handler.onFileNotFound(id,
264: ex, request);
265: if ((newRequest == null)
266: || (!newRequest.exists())) {
267: HttpResponse.notFound(
268: ex,
269: (newRequest == null) ? request
270: .getURI() : newRequest
271: .getURI(),
272: ex.getRequestHeaders()).send();
273: return;
274: }
275: request = newRequest;
276: if (request.isCacheable())
277: etag = request.getETag(true);
278: }
279: }
280:
281: sendResult(request, r, id, etag, ex);
282: return;
283: }
284: } catch (Exception e) {
285: Httpd
286: .Log(Httpd.LogLevel.ERROR,
287: "Error handling request", e);
288: } finally {
289: if (ex != null)
290: try {
291: ex.close();
292: } catch (Exception e) {
293: }
294: }
295: }
296:
297: @Override
298: public String toString()
299: //----------------------
300: {
301: return super .toString()
302: + Httpd.EOL
303: + "Base Directory: "
304: + ((m_homeDir == null) ? "Unknown" : m_homeDir)
305: + Httpd.EOL
306: + "File System Directory: "
307: + ((m_localHomeDir == null) ? "Unknown"
308: : m_localHomeDir.getAbsolutePath());
309: }
310: }
|