Mercurial > hg > digilib-old
diff pdf/src/main/java/digilib/servlet/PDFCache.java @ 903:7779b37d1d05
refactored into maven modules per servlet type.
can build servlet-api 2.3 and 3.0 via profile now!
author | robcast |
---|---|
date | Tue, 26 Apr 2011 20:24:31 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pdf/src/main/java/digilib/servlet/PDFCache.java Tue Apr 26 20:24:31 2011 +0200 @@ -0,0 +1,327 @@ +package digilib.servlet; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.concurrent.Future; + +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 org.apache.log4j.Logger; + +import digilib.image.DocuImage; +import digilib.pdf.PDFFileWorker; +import digilib.util.DigilibJobCenter; + +/** + * A class for handling user requests for pdf documents made from digilib images. + * + * If a document does not already exist, it will be enqueued for generation; if it does exist, it is sent + * to the user. + * + * @author cmielack + * + */ + +@SuppressWarnings("serial") +public class PDFCache extends HttpServlet { + + public static String version = "0.3a"; + + /** logger for accounting requests */ + protected static Logger accountlog = Logger.getLogger("account.pdf.request"); + + /** gengeral logger for this class */ + protected static Logger logger = Logger.getLogger("digilib.pdfcache"); + + /** logger for authentication related */ + protected static Logger authlog = Logger.getLogger("digilib.pdf.auth"); + + private DigilibConfiguration dlConfig = null; + + public static String instanceKey = "digilib.servlet.PDFCache"; + + private DigilibJobCenter<File> pdfJobCenter = null; + + private DigilibJobCenter<DocuImage> pdfImageJobCenter = null; + + private File cache_directory = new File("cache"); + + private File temp_directory = new File("pdf_temp"); + + private static String JSP_WIP = "/pdf/wip.jsp"; + + private static String JSP_ERROR = "/pdf/error.jsp"; + + /** document status. + * DONE: document exists in cache + * WIP: document is "work in progress" + * NONEXISTENT: document does not exist in cache and is not in progress + * ERROR: an error occurred while processing the request + */ + public static enum PDFStatus {DONE, WIP, NONEXISTENT, ERROR}; + + + public void init(ServletConfig config) throws ServletException { + super.init(config); + + System.out.println("***** Digital Image Library Image PDF-Cache Servlet (version " + + version + ") *****"); + // say hello in the log file + logger.info("***** Digital Image Library Image PDF-Cache Servlet (version " + + version + ") *****"); + + ServletContext context = getServletContext(); + dlConfig = (DigilibConfiguration) context.getAttribute("digilib.servlet.configuration"); + if (dlConfig == null) { + // no Configuration + throw new ServletException("No Configuration!"); + } + + String temp_fn = dlConfig.getAsString("pdf-temp-dir"); + temp_directory = new File(temp_fn); + if (!temp_directory.exists()) { + // try to create + temp_directory.mkdirs(); + } else { + // rid the temporary directory of possible incomplete document files + emptyDirectory(temp_directory); + } + if (!temp_directory.isDirectory()) { + throw new ServletException("Configuration error: problem with pdf-temp-dir="+temp_fn); + } + + String cache_fn = dlConfig.getAsString("pdf-cache-dir"); + cache_directory = new File(cache_fn); + if (!cache_directory.exists()) { + // try to create + cache_directory.mkdirs(); + } + if (!cache_directory.isDirectory()) { + throw new ServletException("Configuration error: problem with pdf-cache-dir="+cache_fn); + } + + pdfJobCenter = (DigilibJobCenter<File>) dlConfig.getValue("servlet.worker.pdfexecutor"); + pdfImageJobCenter = (DigilibJobCenter<DocuImage>) dlConfig.getValue("servlet.worker.pdfimageexecutor"); + + // register this instance globally + context.setAttribute(instanceKey, this); + + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { + accountlog.info("GET from " + request.getRemoteAddr()); + this.processRequest(request, response); + } + + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { + accountlog.info("POST from " + request.getRemoteAddr()); + this.processRequest(request, response); + } + + /** + * clean up any broken and unfinished files from the temporary directory. + */ + public void emptyDirectory(File dir){ + File[] temp_files = dir.listFiles(); + for (File f: temp_files){ + f.delete(); + } + } + + + public void processRequest(HttpServletRequest request, + HttpServletResponse response) throws ServletException { + + if (dlConfig == null) { + logger.error("ERROR: No Configuration!"); + throw new ServletException("NO VALID digilib CONFIGURATION!"); + } + + String docid = ""; + try { + // evaluate request ( make a PDFJobDeclaration , get the DocumentId) + PDFRequest pdfji = new PDFRequest(request, dlConfig); + + docid = pdfji.getDocumentId(); + + // if some invalid data has been entered ... + if(!pdfji.checkValidity()) { + notifyUser(PDFStatus.ERROR, docid, request, response); + return; + } + + PDFStatus status = getStatus(docid); + + if (status == PDFStatus.NONEXISTENT) { + // not there -- start creation + try { + createNewPdfDocument(pdfji, docid); + notifyUser(status, docid, request, response); + return; + } catch (FileNotFoundException e) { + // error in pdf creation + logger.error(e.getMessage()); + notifyUser(PDFStatus.ERROR, docid, request, response); + return; + } + } else if (status == PDFStatus.DONE) { + // pdf created -- send it + try { + ServletOps.sendFile(getCacheFile(docid), "application/pdf", getDownloadFilename(pdfji), response, logger); + return; + } catch (Exception e) { + // sending didn't work + logger.error(e.getMessage()); + return; + } + } else { + // should be work in progress + notifyUser(status, docid, request, response); + return; + } + } catch (Exception e) { + // error in pdf creation + logger.error(e.getMessage()); + notifyUser(PDFStatus.ERROR, docid, request, response); + return; + } + } + + /** + * depending on the documents status, redirect the user to the appropriate + * waiting or download page. + * + * @param status + * @param documentid + * @param request + * @param response + */ + public void notifyUser(PDFStatus status, String documentid, + HttpServletRequest request, HttpServletResponse response) { + + String jsp = null; + + if (status == PDFStatus.NONEXISTENT) { + // tell the user that the document has to be created before he/she + // can download it + logger.debug("PDFCache: " + documentid + " has STATUS_NONEXISTENT."); + jsp = JSP_WIP; + } else if (status == PDFStatus.WIP) { + logger.debug("PDFCache: " + documentid + " has STATUS_WIP."); + jsp = JSP_WIP; + + // TODO: estimate remaining work time + // TODO: tell the user he/she has to wait + } else if (status == PDFStatus.DONE) { + logger.debug("PDFCache: " + documentid + " has STATUS_DONE."); + } else { + logger.debug("PDFCache: " + documentid + " has STATUS_ERROR."); + jsp = JSP_ERROR; + } + + try { + // forward to the relevant jsp + ServletContext context = getServletContext(); + RequestDispatcher dispatch = context.getRequestDispatcher(jsp); + dispatch.forward(request, response); + } catch (ServletException e) { + logger.debug(e.getMessage()); + e.printStackTrace(); + } catch (IOException e) { + logger.debug(e.getMessage()); + e.printStackTrace(); + } + + } + + + /** check the status of the document corresponding to the documentid */ + public PDFStatus getStatus(String documentid){ + // looks into the cache and temp directory in order to find out the status of the document + File cached = getCacheFile(documentid); + File wip = getTempFile(documentid); + if(cached.exists()){ + return PDFStatus.DONE; + } else if (wip.exists()){ + return PDFStatus.WIP; + } else { + return PDFStatus.NONEXISTENT; + } + } + + /** + * create new thread for pdf generation. + * + * @param pdfji + * @param filename + * @return + * @throws FileNotFoundException + */ + public Future<File> createNewPdfDocument(PDFRequest pdfji, String filename) throws FileNotFoundException{ + // start new worker + File tempf = this.getTempFile(filename); + File finalf = this.getCacheFile(filename); + PDFFileWorker job = new PDFFileWorker(dlConfig, tempf, finalf, pdfji, pdfImageJobCenter); + // start job + Future<File> jobTicket = pdfJobCenter.submit(job); + return jobTicket; + } + + + /** + * generate the filename the user is going to receive the pdf as + * + * @param pdfji + * @return + */ + public String getDownloadFilename(PDFRequest pdfji){ + // filename example: digilib_example_pgs1-3.pdf + String filename; + filename = "digilib_"; + filename += pdfji.getAsString("fn"); + filename += "_pgs" + pdfji.getAsString("pgs"); + filename += ".pdf"; + + return filename; + } + + public File getCacheDirectory(){ + return cache_directory; + } + + public File getTempDirectory(){ + return temp_directory; + } + + /** + * returns a File object based on filename in the temp directory. + * @param filename + * @return + */ + public File getTempFile(String filename) { + return new File(temp_directory, filename); + } + + /** + * returns a File object based on filename in the cache directory. + * @param filename + * @return + */ + public File getCacheFile(String filename) { + return new File(cache_directory, filename); + } +}