package org.jblooming.http;
import org.jblooming.utilities.file.FileUtilities;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExternalFolderServlet extends HttpServlet {
File fsroot;
File httproot;
String httpRootPrefix;
boolean processJsp;
boolean allowCache;
public void init(ServletConfig servletConfig) throws ServletException {
try {
httpRootPrefix = servletConfig.getInitParameter("http-work-folder");
if (httpRootPrefix == null || httpRootPrefix.trim().length() == 0)
httpRootPrefix = "work";
httpRootPrefix = '/' + httpRootPrefix.trim();
String fsRootName = servletConfig.getInitParameter("external-folders-root");
if (fsRootName == null)
throw new ServletException("You must specify a filesystem folder ( 'external-folders-root' parameter ) ");
fsroot = new File(fsRootName).getCanonicalFile();
httproot = new File(servletConfig.getServletContext().getRealPath(httpRootPrefix)).getCanonicalFile();
if ("true".equalsIgnoreCase(servletConfig.getInitParameter("create-roots"))) {
fsroot.mkdirs();
httproot.mkdirs();
}
processJsp = "true".equalsIgnoreCase(servletConfig.getInitParameter("compile-jsp"));
if (processJsp) {
ServletContext servletContext = servletConfig.getServletContext();
int major = servletContext.getMajorVersion();
int minor = servletContext.getMinorVersion();
if (major < 2 || (major == 2 && minor < 3)) {
throw new ServletException(getClass().getName() + " needs servlets 2.3 or newer, current vesion is " + major + '.' + minor);
}
}
allowCache = "true".equalsIgnoreCase(servletConfig.getInitParameter("allow-cache"));
if (!fsroot.exists() ||
!fsroot.isDirectory() ||
!httproot.exists() ||
!httproot.isDirectory())
throw new ServletException("Cannot find repository");
} catch (IOException e) {
throw new ServletException(e);
}
}
protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
perform(httpServletRequest, httpServletResponse);
}
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
perform(httpServletRequest, httpServletResponse);
}
private void perform(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
String resource;
boolean resourceIsIncluded = false;
resource = (String) httpServletRequest.getAttribute("javax.servlet.include.request_uri");
if (resource == null)
resource = (String) httpServletRequest.getAttribute("javax.servlet.forward.request_uri");
else
resourceIsIncluded = true;
if (resource == null)
resource = httpServletRequest.getRequestURI();
else
resourceIsIncluded = true;
resource = java.net.URLDecoder.decode(resource);
String fsresource = resource.replace('/', File.separatorChar);
String httpresource = httpRootPrefix + resource;
File fsfile = new File(fsroot, fsresource);
if (!fsfile.exists() || !fsfile.isFile()) {
httpServletResponse.sendError(404, "Department " + resource + " not found on this server");
return;
}
if (processJsp && resource.toUpperCase().endsWith(".JSP")) {
File httpfile = new File(httproot, fsresource);
manageDuplication(fsfile, httpfile);
RequestDispatcher requestDispatcher = httpServletRequest.getRequestDispatcher(httpresource);
if (resourceIsIncluded)
requestDispatcher.include(httpServletRequest, httpServletResponse);
else
requestDispatcher.forward(httpServletRequest, httpServletResponse);
} else {
ZipServe.serve(fsfile, httpServletRequest, httpServletResponse, allowCache, resourceIsIncluded);
}
}
private void manageDuplication(File fsfile, File httpfile) throws IOException {
if (isDuplicationNeeded(httpfile, fsfile)) {
duplicate(httpfile, fsfile);
}
}
private synchronized void duplicate(File httpfile, File fsfile) throws IOException {
if (isDuplicationNeeded(httpfile, fsfile)) {
httpfile.getParentFile().mkdirs();
FileInputStream source = new FileInputStream(fsfile);
FileOutputStream dest = new FileOutputStream(httpfile);
FileUtilities.copy(source, dest);
}
}
private boolean isDuplicationNeeded(File httpfile, File fsfile) {
boolean duplicate = !httpfile.exists();
if (!duplicate) {
long fsdate = fsfile.lastModified();
long httpdate = httpfile.lastModified();
duplicate = fsdate >= httpdate;
}
return duplicate;
}
}