/*
* Copyright (C) 2014 Stefano Fornari.
* All Rights Reserved. No use, copying or distribution of this
* work may be made except in accordance with a valid license
* agreement from Stefano Fornari. This notice must be
* included on all copies, modifications and derivatives of this
* work.
*
* STEFANO FORNARI MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. STEFANO FORNARI SHALL NOT BE LIABLE FOR ANY
* DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*/
package ste.web.http.handlers;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Locale;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.util.EntityUtils;
import ste.web.http.MimeUtils;
public class FileHandler implements HttpRequestHandler {
protected final String docRoot;
protected final String webContext;
/**
* Creates a new FileHandler that reads files located under docRoot, which
* is taken as parent of the URI.
*
* @param docRoot the root directory for files - NOT NULL
* @param webContext the base uri for content uris - NOT BLANK
*
* @throws IllegalArgumentException if any of the parameter has an illegal
* value
*/
public FileHandler(final String docRoot, final String webContext) {
if (docRoot == null) {
throw new IllegalArgumentException("docRoot cannot be null");
}
this.docRoot = docRoot;
this.webContext = webContext;
}
public FileHandler(final String docRoot) {
this(docRoot, null);
}
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
checkHttpMethod(request);
String target = request.getRequestLine().getUri();
if (StringUtils.isNotBlank(webContext) && target.startsWith(webContext)) {
target = target.substring(webContext.length());
}
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] entityContent = EntityUtils.toByteArray(entity);
}
URI uri = null;
try {
uri = new URI(target);
} catch (URISyntaxException x) {
throw new HttpException("malformed URL '" + target + "'");
}
final File file = new File(this.docRoot, uri.getPath());
if (!file.exists()) {
response.setStatusCode(HttpStatus.SC_NOT_FOUND);
StringEntity entity = new StringEntity(
"<html><body><h1>File " + file.getPath() +
" not found</h1></body></html>",
ContentType.TEXT_HTML);
response.setEntity(entity);
} else if (!file.canRead() || file.isDirectory()) {
response.setStatusCode(HttpStatus.SC_FORBIDDEN);
StringEntity entity = new StringEntity(
"<html><body><h1>Access denied</h1></body></html>",
ContentType.TEXT_HTML);
response.setEntity(entity);
} else {
response.setStatusCode(HttpStatus.SC_OK);
String mimeType = MimeUtils.getInstance().getMimeType(file);
ContentType type = MimeUtils.MIME_UNKNOWN.equals(mimeType)
? ContentType.APPLICATION_OCTET_STREAM
: ContentType.create(mimeType)
;
FileEntity body = new FileEntity(file, type);
response.setEntity(body);
}
}
// --------------------------------------------------------- private methods
private void checkHttpMethod(final HttpRequest request) throws MethodNotSupportedException {
String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
throw new MethodNotSupportedException(method + " method not supported");
}
}
}