Package fitnesse.responders.files

Source Code of fitnesse.responders.files.FileResponder

// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package fitnesse.responders.files;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.text.ParseException;
import java.util.Date;

import fitnesse.util.Clock;
import util.StreamReader;
import fitnesse.FitNesseContext;
import fitnesse.Responder;
import fitnesse.http.InputStreamResponse;
import fitnesse.http.Request;
import fitnesse.http.Response;
import fitnesse.http.SimpleResponse;
import fitnesse.responders.ErrorResponder;
import fitnesse.responders.NotFoundResponder;

public class FileResponder implements Responder {
  // 1000-trick: remove milliseconds.
  private final static Date LAST_MODIFIED_FOR_RESOURCES = new Date((System.currentTimeMillis() / 1000) * 1000 );

  private static final int RESOURCE_SIZE_LIMIT = 262144;
  private static final FileNameMap fileNameMap = URLConnection.getFileNameMap();
  final public String resource;
  final public File requestedFile;
  public Date lastModifiedDate;

  public static Responder makeResponder(Request request, String rootPath) throws IOException {
    String resource = request.getResource();

    try {
      resource = URLDecoder.decode(resource, "UTF-8");
    } catch (UnsupportedEncodingException e) {
      return new ErrorResponder(e);
    }

    File requestedFile = new File(rootPath, resource);

    if (!isInFilesDirectory(new File(rootPath), requestedFile)) {
      return new ErrorResponder("Invalid path: " + resource);
    } else if (requestedFile.isDirectory())
      return new DirectoryResponder(resource, requestedFile);
    else
      return new FileResponder(resource, requestedFile);
  }

  public FileResponder(String resource, File requestedFile) {
    this.resource = resource;
    this.requestedFile = requestedFile;
  }

  public Response makeResponse(FitNesseContext context, Request request) throws IOException {
    if (requestedFile.exists()) {
      return makeFileResponse(request);
    } else if (canLoadFromClasspath()) {
      return makeClasspathResponse(context, request);
    } else {
      return new NotFoundResponder().makeResponse(context, request);
    }
  }
 

  private boolean canLoadFromClasspath() {
    return resource.startsWith("files/fitnesse/");
  }

  private Response makeClasspathResponse(FitNesseContext context, Request request) throws IOException {

    determineLastModifiedInfo(LAST_MODIFIED_FOR_RESOURCES);

    if (isNotModified(request))
      return createNotModifiedResponse();

    String classpathResource = "/fitnesse/resources/" + resource.substring("files/fitnesse/".length());
   
    InputStream input = getClass().getResourceAsStream(classpathResource);
    if (input == null) {
      return new NotFoundResponder().makeResponse(context, request);
    }
    StreamReader reader = new StreamReader(input);
    // Set a hard limit on the amount of data that can be read:
    byte[] content = reader.readBytes(RESOURCE_SIZE_LIMIT);
    SimpleResponse response = new SimpleResponse();
    response.setContent(content);
    setContentType(classpathResource, response);
    lastModifiedDate = LAST_MODIFIED_FOR_RESOURCES;
    response.setLastModifiedHeader(lastModifiedDate);

    return response;
  }

  private Response makeFileResponse(Request request) throws FileNotFoundException {
    InputStreamResponse response = new InputStreamResponse();
    determineLastModifiedInfo(new Date(requestedFile.lastModified()));

    if (isNotModified(request))
      return createNotModifiedResponse();
    else {
      response.setBody(requestedFile);
      setContentType(requestedFile.getName(), response);
      response.setLastModifiedHeader(lastModifiedDate);
    }
    return response;
  }

  private boolean isNotModified(Request request) {
    if (request.hasHeader("If-Modified-Since")) {
      String queryDateString = (String) request.getHeader("If-Modified-Since");
      try {
        Date queryDate = Response.makeStandardHttpDateFormat().parse(queryDateString);
        if (!queryDate.before(lastModifiedDate))
          return true;
      }
      catch (ParseException e) {
        //Some browsers use local date formats that we can't parse.
        //So just ignore this exception if we can't parse the date.
      }
    }
    return false;
  }

  private Response createNotModifiedResponse() {
    Response response = new SimpleResponse();
    response.notModified(lastModifiedDate, Clock.currentDate());
    return response;
  }

  private void determineLastModifiedInfo(Date lastModified) {
    // remove milliseconds
    lastModifiedDate = new Date((lastModified.getTime() / 1000) * 1000);
  }

  private void setContentType(String filename, Response response) {
    String contentType = getContentType(filename);
    response.setContentType(contentType);
  }

  public static String getContentType(String filename) {
    String contentType = fileNameMap.getContentTypeFor(filename);
    if (contentType == null) {
      if (filename.endsWith(".css")) {
        contentType = "text/css";
      } else if (filename.endsWith(".js")) {
        contentType = "text/javascript";
      } else if (filename.endsWith(".jar")) {
        contentType = "application/x-java-archive";
      } else if ((filename.endsWith(".jpg")) || (filename.endsWith(".jpeg"))) {
          contentType = "image/jpeg";
      } else if (filename.endsWith(".png")) {
          contentType = "image/png";
      } else if (filename.endsWith(".gif")) {
          contentType = "image/gif";
      } else {
        contentType = "text/plain";
      }
    }
    return contentType;
  }

  public static boolean isInFilesDirectory(File rootPath, File file) throws IOException {
    return isInSubDirectory(new File(rootPath, "files").getCanonicalFile(),
            file.getCanonicalFile());
  }

  private static boolean isInSubDirectory(File dir, File file) {
    return file != null && (file.equals(dir) || isInSubDirectory(dir, file.getParentFile()));
  }
}
TOP

Related Classes of fitnesse.responders.files.FileResponder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.