Mercurial > hg > digilib-old
changeset 503:fdb824bd57ab digilibPDF
first functional version of PDFCache after restructuring the code
author | cmielack |
---|---|
date | Mon, 02 Mar 2009 17:11:26 +0100 |
parents | 157d4c7d2343 |
children | a370e72f2179 |
files | servlet/src/digilib/servlet/DigilibImageWorker.java servlet/src/digilib/servlet/DigilibPDFWorker.java servlet/src/digilib/servlet/DigilibWorker.java servlet/src/digilib/servlet/ImageJobInformation.java servlet/src/digilib/servlet/OldDigilibPDFWorker.java servlet/src/digilib/servlet/PDFCache.java servlet/src/digilib/servlet/PDFJobDeclaration.java servlet/src/digilib/servlet/PDFJobInformation.java servlet/src/digilib/servlet/PDFMaker.java servlet/src/digilib/servlet/RequestHandler.java servlet/src/digilib/servlet/Scaler.java |
diffstat | 11 files changed, 1037 insertions(+), 1259 deletions(-) [+] |
line wrap: on
line diff
--- a/servlet/src/digilib/servlet/DigilibImageWorker.java Mon Feb 23 16:03:06 2009 +0100 +++ b/servlet/src/digilib/servlet/DigilibImageWorker.java Mon Mar 02 17:11:26 2009 +0100 @@ -94,62 +94,44 @@ int forceType; - /** - * @param dlConfig - * @param response - * @param mimeType - * @param scaleQual - * @param dlRequest - * @param paramROT - * @param paramCONT - * @param paramBRGT - * @param paramRGBM - * @param paramRGBA - * @param fileToLoad - * @param areaXoff - * @param outerUserImgArea - * @param innerUserImgArea - * @param minSubsample - * @param wholeRotArea - * @param forceType - */ - public DigilibImageWorker(DigilibConfiguration dlConfig, - OutputStream outstream, String mimeType, int scaleQual, - //DigilibRequest dlRequest, - //ImageJobInformation ijd, - float paramROT, float paramCONT, - float paramBRGT, float[] paramRGBM, float[] paramRGBA, - ImageFile fileToLoad, float scaleXY, Rectangle2D outerUserImgArea, - Rectangle2D innerUserImgArea, float minSubsample, - boolean wholeRotArea, int forceType, boolean hmir, boolean vmir) { + + public DigilibImageWorker(DigilibConfiguration dlConfig, OutputStream outstream, ImageJobInformation jobinfo) { super(); + this.dlConfig = dlConfig; this.outstream = outstream; - this.mimeType = mimeType; - this.scaleQual = scaleQual; - //this.dlRequest = dlRequest; - //this.ijd = ijd; - this.paramROT = paramROT; - this.paramCONT = paramCONT; - this.paramBRGT = paramBRGT; - this.paramRGBM = paramRGBM; - this.paramRGBA = paramRGBA; - this.fileToLoad = fileToLoad; - this.scaleXY = scaleXY; - this.outerUserImgArea = outerUserImgArea; - this.innerUserImgArea = innerUserImgArea; - this.minSubsample = minSubsample; - this.wholeRotArea = wholeRotArea; - this.forceType = forceType; - this.hmir = hmir; - this.vmir = vmir; + this.mimeType = jobinfo.get_mimeType(); + this.scaleQual = jobinfo.get_scaleQual(); + this.paramROT = jobinfo.getAsFloat("rot"); + this.paramCONT = jobinfo.getAsFloat("cont"); + this.paramBRGT = jobinfo.getAsFloat("brgt"); + this.paramRGBM = jobinfo.get_paramRGBM(); + this.paramRGBA = jobinfo.get_paramRGBA(); + try { + this.fileToLoad = jobinfo.get_fileToLoad(); + this.scaleXY = jobinfo.get_scaleXY(); + this.outerUserImgArea = jobinfo.get_outerUserImgArea(); + this.innerUserImgArea = jobinfo.get_innerUserImgArea(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ImageOpException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + this.minSubsample = dlConfig.getAsFloat("subsample-minimum"); + this.wholeRotArea = jobinfo.get_wholeRotArea(); + this.forceType = jobinfo.get_forceType(); + this.hmir = jobinfo.get_hmir(); + this.vmir = jobinfo.get_vmir(); } /* * do the work */ public DocuImage render() throws FileOpException, IOException, ImageOpException { - ; + logger.debug("image worker " + this.getName() + " working"); startTime = System.currentTimeMillis();
--- a/servlet/src/digilib/servlet/DigilibPDFWorker.java Mon Feb 23 16:03:06 2009 +0100 +++ b/servlet/src/digilib/servlet/DigilibPDFWorker.java Mon Mar 02 17:11:26 2009 +0100 @@ -24,8 +24,13 @@ import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; import javax.servlet.http.HttpServletResponse; @@ -34,6 +39,7 @@ import com.lowagie.text.DocumentException; import com.lowagie.text.Image; import com.lowagie.text.PageSize; +import com.lowagie.text.pdf.PdfWriter; import digilib.image.DocuImage; import digilib.image.DocuImageImpl; @@ -45,183 +51,185 @@ import digilib.io.ImageFile; /** - * worker for image operations. + * worker for pdf operations. * - * @author casties + * @author cmielack * */ -public class DigilibPDFWorker extends DigilibImageWorker { - - private DigilibConfiguration dlConfig; - - - long startTime; - - String mimeType; - - int scaleQual; - - DigilibRequest dlRequest; - - float paramROT; - - float paramCONT; - - float paramBRGT; - - float[] paramRGBM; - - float[] paramRGBA; - - ImageFile fileToLoad; +public class DigilibPDFWorker extends DigilibWorker { - float areaXoff; - - float areaYoff; - - float areaWidth; - - float areaHeight; - - float scaleXY; - - Rectangle2D outerUserImgArea; + private DigilibConfiguration dlConfig = null; - Rectangle2D innerUserImgArea; - - float minSubsample; - - boolean wholeRotArea; - - int forceType; - - Document doc; - - - //public ImageLoaderDocuImage render();// throws Exception; - + private Document doc = null; - /** - * @param dlConfig - * @param response - * @param mimeType - * @param scaleQual - * @param dlRequest - * @param paramROT - * @param paramCONT - * @param paramBRGT - * @param paramRGBM - * @param paramRGBA - * @param fileToLoad - * @param areaXoff - * @param outerUserImgArea - * @param innerUserImgArea - * @param minSubsample - * @param wholeRotArea - * @param forceType - */ - public DigilibPDFWorker(DigilibConfiguration dlConfig, - BufferedOutputStream outstream, String mimeType, int scaleQual, - DigilibRequest dlRequest, float paramCONT, - float paramBRGT, float[] paramRGBM, float[] paramRGBA, - ImageFile fileToLoad, float scaleXY, Rectangle2D outerUserImgArea, - Rectangle2D innerUserImgArea, float minSubsample, - boolean wholeRotArea, int forceType, Document doc) { - super(dlConfig, - outstream, mimeType, scaleQual, - dlRequest, 0.0f , paramCONT, - paramBRGT, paramRGBM,paramRGBA, - fileToLoad, scaleXY, outerUserImgArea, - innerUserImgArea,minSubsample, - wholeRotArea, forceType); - + private String filename = null; + + private PDFJobInformation job_info = null; + + public DigilibPDFWorker(DigilibConfiguration dlConfig, PDFJobInformation pdfji, String filename) { + super(); + // TODO dlConfig this.dlConfig = dlConfig; - this.outstream = outstream; - this.mimeType = mimeType; - this.scaleQual = scaleQual; - this.dlRequest = dlRequest; - //this.paramROT = paramROT; - this.paramCONT = paramCONT; - this.paramBRGT = paramBRGT; - this.paramRGBM = paramRGBM; - this.paramRGBA = paramRGBA; - this.fileToLoad = fileToLoad; - this.scaleXY = scaleXY; - this.outerUserImgArea = outerUserImgArea; - this.innerUserImgArea = innerUserImgArea; - this.minSubsample = minSubsample; - this.wholeRotArea = wholeRotArea; - this.forceType = forceType; - this.doc = doc; + this.job_info = pdfji; + this.filename = filename; } public void run() { - //logger.debug((++waitingThreads) + " waiting threads"); - ImageLoaderDocuImage img = null; + // create document object + doc = new Document(PageSize.A4, 0,0,0,0); + PdfWriter docwriter = null; + File output_file = new File(PDFCache.cache_directory + filename); + FileOutputStream fos; + try { - sem.acquire(); - //waitingThreads--; - } catch (InterruptedException e) { - error = e; - //waitingThreads--; - // should we reinterrupt? + fos = new FileOutputStream(output_file); + } catch (FileNotFoundException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); return; } - //logger.debug((++runningThreads) + " running threads"); + + + long start_time = System.currentTimeMillis(); + + try { - /* - * do rendering under the semaphore - */ - img = (ImageLoaderDocuImage) super.render(); - } catch (Throwable e) { + docwriter = PdfWriter.getInstance(doc, fos); + + setPDFProperties(); + + doc.open(); + + logger.debug("- doc.open()ed ("+(System.currentTimeMillis()-start_time) + "ms)"); + start_time = System.currentTimeMillis(); + + + Integer[] pgs = get_pgs(); + + for(Integer p: pgs){ + addImage(p); + } + + + + } + catch(Exception e) { + logger.error(e.getMessage()); error = e; - logger.error(e); - } finally { - // runningThreads--; - sem.release(); + return; + } + + finally { + if (doc!=null){ + doc.close(); + logger.debug("- doc.close() ("+(System.currentTimeMillis()-start_time) + "ms)"); + } + if (docwriter!=null){ + docwriter.close(); + } } - /* - * write the result without semaphore - */ - if (!hasError()) { - try{ - write(img); - } catch (Throwable e) { - error = e; - logger.error(e); + + + + try { + fos.flush(); + } catch (IOException e) { + e.printStackTrace(); + error = e; + } + finally{ + if(fos!=null){ + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } } } } - public void write(ImageLoaderDocuImage img) throws FileOpException, IOException { - /* write the resulting image */ + public void setPDFProperties(){ + // TODO get proper Information from dlConfig + doc.addAuthor(this.getClass().getName()); + doc.addCreationDate(); + doc.addKeywords("digilib"); + doc.addTitle("digilib PDF"); + doc.addCreator(this.getClass().getName()); + } + + public Integer[] get_pgs(){ + String pages = job_info.getAsString("pgs"); + ArrayList<Integer> pgs = new ArrayList<Integer>(); + Integer[] out = null; + + String intervals[] = pages.split(","); + + + // convert the page-interval-strings into a list containing every single page + for(String interval: intervals){ + if(interval.indexOf("-") > -1){ + String nums[] = interval.split("-"); + + for(int i=Integer.valueOf(nums[0]); i <= Integer.valueOf(nums[1]); i++){ + pgs.add(i); + } + } + else{ + pgs.add(Integer.valueOf(interval)); + } + } + out = new Integer[pgs.size()]; - + pgs.toArray(out); + return out; + } + + public void addImage(int pn) { + // create ImageJobInformation + ImageJobInformation iji = job_info.getImageJobInformation(); + iji.setValue("pn", pn); + // create image worker + DigilibImageWorker image_worker = new DigilibImageWorker(dlConfig, null, iji); try { - long timing = System.currentTimeMillis(); + ImageLoaderDocuImage img = (ImageLoaderDocuImage) image_worker.render(); + Image theimg = Image.getInstance(img.getImage(),null); - theimg.scaleToFit(PageSize.A4.getWidth(),PageSize.A4.getHeight()); + float docW = PageSize.A4.getWidth() - 2*PageSize.A4.getBorder(); + float docH= PageSize.A4.getHeight()- 2*PageSize.A4.getBorder(); + - logger.debug(" --- loading and scaling took "+(-timing+System.currentTimeMillis())+"ms"); - - timing = System.currentTimeMillis(); + theimg.scaleToFit(docW,docH); + doc.add(theimg); - logger.debug(" --- adding took "+(-timing+System.currentTimeMillis())+"ms"); - + + } catch (FileOpException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ImageOpException e) { + e.printStackTrace(); } catch (BadElementException e) { e.printStackTrace(); - logger.debug("------DigilibPDFWorker write BadElementException"); - } catch (DocumentException e) { e.printStackTrace(); - logger.debug("------DigilibPDFWorker write DocumentException"); + } + } + - } + + + + // unnecessary + @Override + public DocuImage render() throws Exception { + return null; + } + + @Override + public void write(DocuImage img) throws Exception { - logger.info("pdf worker " + this.getName() + " done in " - + (System.currentTimeMillis() - startTime)); - } + } \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/servlet/DigilibWorker.java Mon Mar 02 17:11:26 2009 +0100 @@ -0,0 +1,195 @@ +/* DigilibWorker.java -- image operation worker + * + * Digital Image Library servlet components + * + * Copyright (C) 2004 Robert Casties (robcast@mail.berlios.de) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * Please read license.txt for the full details. A copy of the GPL may be found + * at http://www.gnu.org/copyleft/lgpl.html + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + * + * Created on 18.10.2004 + */ +package digilib.servlet; + +import java.util.concurrent.Semaphore; + +import org.apache.log4j.Logger; + +import digilib.image.DocuImage; + +/** + * image operation worker. + * + * @author casties + */ +public abstract class DigilibWorker { + + protected static Logger logger = Logger.getLogger(DigilibWorker.class); + + private static int maxRunningThreads = 0; + + private static int runningThreads = 0; + + private static int waitingThreads = 0; + + private static int maxWaitingThreads = 0; + + public static Semaphore sem = new Semaphore(2, true); + + protected Throwable error; + + /** + * @param job + */ + public DigilibWorker() { + super(); + error = null; + } + + public abstract DocuImage render() throws Exception; + + public abstract void write(DocuImage img) throws Exception; + + /** + * Do the work. + */ + public void run() { + logger.debug((++waitingThreads) + " waiting threads"); + DocuImage img = null; + try { + sem.acquire(); + waitingThreads--; + } catch (InterruptedException e) { + error = e; + waitingThreads--; + // should we reinterrupt? + return; + } + logger.debug((++runningThreads) + " running threads"); + try { + /* + * do rendering under the semaphore + */ + img = render(); + } catch (Throwable e) { + error = e; + logger.error(e); + } finally { + runningThreads--; + sem.release(); + } + /* + * write the result without semaphore + */ + if (!hasError()) { + try{ + write(img); + } catch (Throwable e) { + error = e; + logger.error(e); + } + } + } + + /** + * Returns the name of this thread. + * + * @return + */ + public String getName() { + return Thread.currentThread().getName(); + } + + /** Returns if the worker could run (i.e. is not overloaded). + * + * @return + */ + public static boolean canRun() { + return ((DigilibWorker.maxWaitingThreads == 0) || (DigilibWorker.getNumWaiting() <= DigilibWorker.maxWaitingThreads)); + } + + /** + * returns if an error occurred. + * + * @return + */ + public boolean hasError() { + return (error != null); + } + + /** + * @return Returns the error. + */ + public Throwable getError() { + return error; + } + + /** + * @return Returns the semaphore. + */ + public static Semaphore getSemaphore() { + return sem; + } + + /** + * @param sem + * The semaphore to set. + */ + public static void setSemaphore(Semaphore sem) { + DigilibWorker.sem = sem; + } + + public static void setSemaphore(int maxrun, boolean fair) { + sem = new Semaphore(maxrun, fair); + maxRunningThreads = maxrun; + } + + /** + * The number of currently running threads (approximate). + * + * @return + */ + public static int getNumRunning() { + return (maxRunningThreads - sem.availablePermits()); + } + + /** + * The number of currently waiting threads (approximate). + * + * @return + */ + public static int getNumWaiting() { + return sem.getQueueLength(); + } + + /** + * @return Returns the maxWaitingThreads. + */ + public static int getMaxWaitingThreads() { + return maxWaitingThreads; + } + + /** + * @param maxWaitingThreads The maxWaitingThreads to set. + */ + public static void setMaxWaitingThreads(int maxWaitingThreads) { + DigilibWorker.maxWaitingThreads = maxWaitingThreads; + } + + public static int getMaxRunningThreads() { + return maxRunningThreads; + } + + public static void setMaxRunningThreads(int maxRunningThreads) { + DigilibWorker.maxRunningThreads = maxRunningThreads; + } +}
--- a/servlet/src/digilib/servlet/ImageJobInformation.java Mon Feb 23 16:03:06 2009 +0100 +++ b/servlet/src/digilib/servlet/ImageJobInformation.java Mon Mar 02 17:11:26 2009 +0100 @@ -51,7 +51,7 @@ Boolean imageSendable = null; // Integer paramDW = null; // Integer paramDH - public ImageJobInformation() { + public ImageJobInformation(DigilibConfiguration dlcfg) { super(30); // url of the page/document (second part) @@ -126,11 +126,13 @@ // marks newParameter("mk", "", null, 'c'); */ + dlConfig = dlcfg; } - public void setConfig(DigilibConfiguration dlcfg){ - dlConfig = dlcfg; - } + + /*public void setPageNumber(int pn){ + put("pn",pn); + }*/ public void setWithRequest(HttpServletRequest request) { for (String param : parameter_list){ @@ -148,7 +150,7 @@ return parameter_list; } - + public boolean hasOption(String param, String opt) { String s = getAsString(param); if (s != null) { @@ -464,7 +466,6 @@ public ImageSize get_imgSize() throws IOException, ImageOpException{ - logger.debug("get_imgSize()"); ImageSize imgSize = get_fileToLoad().getSize(); return imgSize;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/servlet/OldDigilibPDFWorker.java Mon Mar 02 17:11:26 2009 +0100 @@ -0,0 +1,205 @@ +/* DigilibImageWorker.java -- worker for image operations + * + * Digital Image Library servlet components + * + * Copyright (C) 2004 Robert Casties (robcast@mail.berlios.de) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * Please read license.txt for the full details. A copy of the GPL may be found + * at http://www.gnu.org/copyleft/lgpl.html + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + * + * Created on 19.10.2004 + */ + +package digilib.servlet; + +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.http.HttpServletResponse; + +import com.lowagie.text.BadElementException; +import com.lowagie.text.Document; +import com.lowagie.text.DocumentException; +import com.lowagie.text.Image; +import com.lowagie.text.PageSize; + +import digilib.image.DocuImage; +import digilib.image.DocuImageImpl; +import digilib.image.ImageLoaderDocuImage; +import digilib.image.ImageOpException; +import digilib.image.ImageOps; +import digilib.servlet.DigilibImageWorker; +import digilib.io.FileOpException; +import digilib.io.ImageFile; + +/** + * worker for image operations. + * + * @author casties + * + */ +public class OldDigilibPDFWorker extends DigilibImageWorker { + + private DigilibConfiguration dlConfig; + + + long startTime; + + String mimeType; + + int scaleQual; + + DigilibRequest dlRequest; + + float paramROT; + + float paramCONT; + + float paramBRGT; + + float[] paramRGBM; + + float[] paramRGBA; + + ImageFile fileToLoad; + + float areaXoff; + + float areaYoff; + + float areaWidth; + + float areaHeight; + + float scaleXY; + + Rectangle2D outerUserImgArea; + + Rectangle2D innerUserImgArea; + + float minSubsample; + + boolean wholeRotArea; + + int forceType; + + Document doc; + + + + public OldDigilibPDFWorker(DigilibConfiguration dlConfig, + BufferedOutputStream outstream, String mimeType, int scaleQual, + DigilibRequest dlRequest, float paramCONT, + float paramBRGT, float[] paramRGBM, float[] paramRGBA, + ImageFile fileToLoad, float scaleXY, Rectangle2D outerUserImgArea, + Rectangle2D innerUserImgArea, float minSubsample, + boolean wholeRotArea, int forceType, Document doc) { + super(dlConfig, + outstream, mimeType, scaleQual, + //dlRequest, + 0.0f , paramCONT, + paramBRGT, paramRGBM,paramRGBA, + fileToLoad, scaleXY, outerUserImgArea, + innerUserImgArea,minSubsample, + wholeRotArea, forceType, false, false); + + this.dlConfig = dlConfig; + this.outstream = outstream; + this.mimeType = mimeType; + this.scaleQual = scaleQual; + this.dlRequest = dlRequest; + //this.paramROT = paramROT; + this.paramCONT = paramCONT; + this.paramBRGT = paramBRGT; + this.paramRGBM = paramRGBM; + this.paramRGBA = paramRGBA; + this.fileToLoad = fileToLoad; + this.scaleXY = scaleXY; + this.outerUserImgArea = outerUserImgArea; + this.innerUserImgArea = innerUserImgArea; + this.minSubsample = minSubsample; + this.wholeRotArea = wholeRotArea; + this.forceType = forceType; + this.doc = doc; + } + + public void run() { + //logger.debug((++waitingThreads) + " waiting threads"); + ImageLoaderDocuImage img = null; + try { + sem.acquire(); + //waitingThreads--; + } catch (InterruptedException e) { + error = e; + //waitingThreads--; + // should we reinterrupt? + return; + } + //logger.debug((++runningThreads) + " running threads"); + try { + /* + * do rendering under the semaphore + */ + img = (ImageLoaderDocuImage) super.render(); + } catch (Throwable e) { + error = e; + logger.error(e); + } finally { + // runningThreads--; + sem.release(); + } + /* + * write the result without semaphore + */ + if (!hasError()) { + try{ + write(img); + } catch (Throwable e) { + error = e; + logger.error(e); + } + } + } + + public void write(ImageLoaderDocuImage img) throws FileOpException, IOException { + /* write the resulting image */ + + + try { + long timing = System.currentTimeMillis(); + Image theimg = Image.getInstance(img.getImage(),null); + + theimg.scaleToFit(PageSize.A4.getWidth(),PageSize.A4.getHeight()); + + logger.debug(" --- loading and scaling took "+(-timing+System.currentTimeMillis())+"ms"); + + timing = System.currentTimeMillis(); + + doc.add(theimg); + logger.debug(" --- adding took "+(-timing+System.currentTimeMillis())+"ms"); + + } catch (BadElementException e) { + e.printStackTrace(); + logger.error("DigilibPDFWorker write BadElementException"); + } catch (DocumentException e) { + e.printStackTrace(); + logger.error("DigilibPDFWorker write DocumentException"); + } + + logger.info("pdf worker " + this.getName() + " done in " + + (System.currentTimeMillis() - startTime)); + + } +} \ No newline at end of file
--- a/servlet/src/digilib/servlet/PDFCache.java Mon Feb 23 16:03:06 2009 +0100 +++ b/servlet/src/digilib/servlet/PDFCache.java Mon Mar 02 17:11:26 2009 +0100 @@ -1,12 +1,29 @@ package digilib.servlet; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; +import java.util.HashMap; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class PDFCache extends RequestHandler { + private DigilibConfiguration dlConfig = null; + + public static String cache_directory = "cache/"; // TODO set using dlConfig + + public static String cache_hash_id = "digilib.servlet.PDFCache"; + + HashMap<String,Integer> cache_hash = null; + public static Integer STATUS_DONE = 0; // document exists in cache @@ -15,7 +32,67 @@ public static Integer STATUS_NONEXISTENT = 2; // document does not exist in cache and is not in progress public static Integer STATUS_ERROR = 3; // an error occurred while processing the request + + public static String version = "0.2"; + + // TODO functionality for the pre-generation of complete books/chapters using default values + // TODO use DLConfig for default values + // TODO use JSPs for automatically refreshing waiting-pages and download-pages + // TODO register the PDFCache instance globally and implement getters for cache_dir + + + public void init(ServletConfig config) throws ServletException{ + + super.init(config); + + + + logger.info("initialized PDFCache v."+version); + + // create and register hashtable + ServletContext context = config.getServletContext(); + + dlConfig = (DigilibConfiguration) context.getAttribute("digilib.servlet.configuration"); + + if (dlConfig == null) { + // no Configuration + throw new ServletException("No Configuration!"); + } + + context.setAttribute(cache_hash_id, new HashMap<String,Integer>()); + + cache_hash = (HashMap<String,Integer>) context.getAttribute(cache_hash_id); + if (cache_hash==null){ + cache_hash = new HashMap<String,Integer>(); + context.setAttribute(cache_hash_id, cache_hash); + } + + // scan the directory + scanCacheDirectory(); + + } + + + public void scanCacheDirectory(){ + // search the cache-directory for existing files and fill them into the Hashtable as STATUS_DONE + + ServletContext context = this.getServletContext(); + HashMap<String,Integer> cache_hash = (HashMap<String,Integer>) context.getAttribute(cache_hash_id); + + File cache_dir = new File(cache_directory); + String[] cached_files = cache_dir.list(); + + + for (String file: cached_files){ + String docid = file.substring(0,file.length()-4); + logger.debug("docid = "+docid); + if (file.endsWith(".pdf") && !cache_hash.containsKey(docid)){ + logger.debug("PDFCache reads in "+file); + cache_hash.put(file, STATUS_DONE); + } + } + } @@ -24,37 +101,133 @@ HttpServletResponse response) { // evaluate request ( make a PDFJobDeclaration , get the DocumentId) + PDFJobInformation pdfji = new PDFJobInformation(dlConfig); + pdfji.setWithRequest(request); - // check, which state the requested document is in (ready, work in progress, non existent) + + String docid = pdfji.getDocumentId(); + + + int status = getStatus(docid); + + - // if necessary, initialize document generation (and notify the user) - - // send the document + if(status == STATUS_NONEXISTENT){ + createNewPdfDocument(pdfji, docid); + informUser(status, docid, response); + } + else if (status == STATUS_DONE){ + try { + sendFile(docid, downloadFilename(pdfji), response); + } catch (IOException e) { + e.printStackTrace(); + logger.error(e.getMessage()); + } + } + else { + informUser(status, docid, response); + } } - @Override - public void sendFile(InputStream is, HttpServletResponse response, String filename) { + + public void informUser(int status, String documentid, HttpServletResponse response){ + // depending on the documents status, redirect the user to an appropriate waiting- or download-site + // TODO - } + if(status == STATUS_NONEXISTENT){ + // tell the user that the document has to be created before he/she can download it + logger.debug("PDFCache: "+documentid+" has STATUS_NONEXISTENT."); + } + else if(status == STATUS_WIP){ + logger.debug("PDFCache: "+documentid+" has STATUS_WIP."); - public String getDocumentId(PDFJobDeclaration jobdeclaration){ - // generate an unambiguous ID from the request (this is used for filenames etc) - String id; + // estimate remaining work time + // tell the user he/she has to wait + } + else if(status == STATUS_DONE){ + logger.debug("PDFCache: "+documentid+" has STATUS_DONE."); - String fn = jobdeclaration.getAsString("fn"); - String dh = jobdeclaration.getAsString("dh"); - String pgs = jobdeclaration.getAsString("pgs"); - - id = "fn=" + fn + "&dh=" + dh + "&pgs=" + pgs + ".pdf"; + // do nothing or refresh + } + else { + logger.debug("PDFCache: "+documentid+" has STATUS_ERROR."); - return id; + // status == STATUS_ERROR + // an error must have occured; show error page + } + } /** check the status of the document corresponding to the documentid */ public Integer getStatus(String documentid){ - + // rescan directory? might be useful if more than one instance uses the same cache directory ; Problem: wip-files occur in the list + if(cache_hash.containsKey(documentid)) + return cache_hash.get(documentid); + else + return STATUS_NONEXISTENT; + } + + + public void createNewPdfDocument(PDFJobInformation pdfji, String filename){ + // start new worker + PDFMaker pdf_maker = new PDFMaker(dlConfig, cache_hash, pdfji,filename); + new Thread(pdf_maker, "PDFMaker").start(); + } + + + public String downloadFilename(PDFJobInformation pdfji){ + String filename; + filename = "digilib_"; + filename += pdfji.getImageJobInformation().getAsString("fn"); + filename += "_pgs" + pdfji.getAsString("pgs"); + filename += ".pdf"; - return 0; + return filename; + } + + /** + * sends a document to the user + * + * @param cachefile The filename of the document in cache. + * @param filename The filename used for downloading. + * @param response + * @throws IOException + */ + public void sendFile(String cachefile, String filename, HttpServletResponse response) throws IOException{ + File cached_file = null; + FileInputStream fis = null; + ServletOutputStream sos = null; + BufferedInputStream bis = null; + + try { + cached_file = new File(cache_directory + cachefile); + fis = new FileInputStream(cached_file); + sos = response.getOutputStream(); + bis = new BufferedInputStream(fis); + + int bytes = 0; + + response.setContentType("application/pdf"); + response.addHeader("Content-Disposition", "attachment; filename="+filename); + response.setContentLength( (int) cached_file.length()); + + while ((bytes = bis.read()) != -1){ + sos.write(bytes); + } + } + catch(Exception e){ + logger.error(e.getMessage()); + } + finally{ + // close all streams + if (fis != null) + fis.close(); + if (bis != null) + bis.close(); + if (sos != null) + sos.close(); + } + } }
--- a/servlet/src/digilib/servlet/PDFJobDeclaration.java Mon Feb 23 16:03:06 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -package digilib.servlet; - -import javax.servlet.http.HttpServletRequest; - - -/** - * A container class for storing a set of instructional parameters - * used for content generating classes like MakePDF. - * - * - * @author cmielack - * - */ - - - -public class PDFJobDeclaration extends ParameterMap { - - String[] parameter_list = {"fn","pgs","dw","dh"};/*, - "wx", "wy", "ww", "wh", "ws", - "mo", "rot", "cont", "brgt", "rgbm", "rbgm", - "ddpi", "ddpix", "ddpiy", "scale"};*/ - - public PDFJobDeclaration() { - super(30); - - // url of the page/document (second part) - newParameter("fn", "", null, 's'); - // page number - newParameter("pgs", "", null, 's'); - // width of client in pixels - newParameter("dw", new Integer(0), null, 's'); - // height of client in pixels - newParameter("dh", new Integer(0), null, 's'); - // left edge of image (float from 0 to 1) -/* newParameter("wx", new Float(0), null, 's'); - // top edge in image (float from 0 to 1) - newParameter("wy", new Float(0), null, 's'); - // width of image (float from 0 to 1) - newParameter("ww", new Float(1), null, 's'); - // height of image (float from 0 to 1) - newParameter("wh", new Float(1), null, 's'); - // scale factor - newParameter("ws", new Float(1), null, 's'); - // special options like 'fit' for gifs - newParameter("mo", "", null, 's'); - // rotation angle (degree) - newParameter("rot", new Float(0), null, 's'); - // contrast enhancement factor - newParameter("cont", new Float(0), null, 's'); - // brightness enhancement factor - newParameter("brgt", new Float(0), null, 's'); - // color multiplicative factors - newParameter("rgbm", "0/0/0", null, 's'); - // color additive factors - newParameter("rgba", "0/0/0", null, 's'); - // display dpi resolution (total) - newParameter("ddpi", new Float(0), null, 's'); - // display dpi X resolution - newParameter("ddpix", new Float(0), null, 's'); - // display dpi Y resolution - newParameter("ddpiy", new Float(0), null, 's'); - // scale factor for mo=ascale - newParameter("scale", new Float(1), null, 's'); -*/ - /* - * Parameters of type 'i' are not exchanged between client and server, - * but are for the servlets or JSPs internal use. - */ - -/* // url of the page/document (first part, may be empty) - newParameter("request.path", "", null, 'i'); - // base URL (from http:// to below /servlet) - newParameter("base.url", null, null, 'i'); - // DocuImage instance for this request -*/ - /* - * Parameters of type 'c' are for the clients use - */ - -/* // "real" filename - newParameter("img.fn", "", null, 'c'); - // image dpi x - newParameter("img.dpix", new Integer(0), null, 'c'); - // image dpi y - newParameter("img.dpiy", new Integer(0), null, 'c'); - // hires image size x - newParameter("img.pix_x", new Integer(0), null, 'c'); - // hires image size y - newParameter("img.pix_y", new Integer(0), null, 'c'); - // total number of pages - newParameter("pt", new Integer(0), null, 'c'); - // display level of digilib (0 = just image, 1 = one HTML page - // 2 = in frameset, 3 = XUL-'frameset' - // 4 = XUL-Sidebar ) - newParameter("lv", new Integer(2), null, 'c'); - // marks - newParameter("mk", "", null, 'c'); -*/ - - } - - public void setWithRequest(HttpServletRequest request) { - for (String param : parameter_list){ - if (request.getParameterMap().containsKey(param)){ - put(param, request.getAttribute(param)); - } - } - } - - -} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/servlet/PDFJobInformation.java Mon Mar 02 17:11:26 2009 +0100 @@ -0,0 +1,179 @@ +package digilib.servlet; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; + + +/** + * A container class for storing a set of instructional parameters + * used for content generating classes like MakePDF. + * + * + * @author cmielack + * + */ + + + +public class PDFJobInformation extends ParameterMap { + + String[] parameter_list = {"pgs"};//{"fn","pgs","dw","dh"}; + /*, + "wx", "wy", "ww", "wh", "ws", + "mo", "rot", "cont", "brgt", "rgbm", "rbgm", + "ddpi", "ddpix", "ddpiy", "scale"};*/ + + + ImageJobInformation image_info = null; + DigilibConfiguration dlConfig = null; + + public PDFJobInformation(DigilibConfiguration dlcfg) { + super(30); + + // url of the page/document (second part) +// newParameter("fn", "", null, 's'); + // page number + newParameter("pgs", "", null, 's'); + // width of client in pixels +// newParameter("dw", new Integer(0), null, 's'); + // height of client in pixels +// newParameter("dh", new Integer(0), null, 's'); + // left edge of image (float from 0 to 1) +/* newParameter("wx", new Float(0), null, 's'); + // top edge in image (float from 0 to 1) + newParameter("wy", new Float(0), null, 's'); + // width of image (float from 0 to 1) + newParameter("ww", new Float(1), null, 's'); + // height of image (float from 0 to 1) + newParameter("wh", new Float(1), null, 's'); + // scale factor + newParameter("ws", new Float(1), null, 's'); + // special options like 'fit' for gifs + newParameter("mo", "", null, 's'); + // rotation angle (degree) + newParameter("rot", new Float(0), null, 's'); + // contrast enhancement factor + newParameter("cont", new Float(0), null, 's'); + // brightness enhancement factor + newParameter("brgt", new Float(0), null, 's'); + // color multiplicative factors + newParameter("rgbm", "0/0/0", null, 's'); + // color additive factors + newParameter("rgba", "0/0/0", null, 's'); + // display dpi resolution (total) + newParameter("ddpi", new Float(0), null, 's'); + // display dpi X resolution + newParameter("ddpix", new Float(0), null, 's'); + // display dpi Y resolution + newParameter("ddpiy", new Float(0), null, 's'); + // scale factor for mo=ascale + newParameter("scale", new Float(1), null, 's'); +*/ + /* + * Parameters of type 'i' are not exchanged between client and server, + * but are for the servlets or JSPs internal use. + */ + +/* // url of the page/document (first part, may be empty) + newParameter("request.path", "", null, 'i'); + // base URL (from http:// to below /servlet) + newParameter("base.url", null, null, 'i'); + // DocuImage instance for this request +*/ + /* + * Parameters of type 'c' are for the clients use + */ + +/* // "real" filename + newParameter("img.fn", "", null, 'c'); + // image dpi x + newParameter("img.dpix", new Integer(0), null, 'c'); + // image dpi y + newParameter("img.dpiy", new Integer(0), null, 'c'); + // hires image size x + newParameter("img.pix_x", new Integer(0), null, 'c'); + // hires image size y + newParameter("img.pix_y", new Integer(0), null, 'c'); + // total number of pages + newParameter("pt", new Integer(0), null, 'c'); + // display level of digilib (0 = just image, 1 = one HTML page + // 2 = in frameset, 3 = XUL-'frameset' + // 4 = XUL-Sidebar ) + newParameter("lv", new Integer(2), null, 'c'); + // marks + newParameter("mk", "", null, 'c'); +*/ + dlConfig = dlcfg; + + } + + public void setWithRequest(HttpServletRequest request) { + image_info = new ImageJobInformation(dlConfig); + image_info.setWithRequest(request); + + for (String param : parameter_list){ + if (request.getParameterMap().containsKey(param)){ + setValueFromString(param, request.getParameter(param)); + } + } + } + + public String getDocumentId(){ + String id; + + // TODO use complete request information for id generation + + if(this.image_info!=null){ + String fn = image_info.getAsString("fn"); + String dh = image_info.getAsString("dh"); + String pgs = getAsString("pgs"); + + id = "fn=" + fn + "&dh=" + dh + "&pgs=" + pgs + ".pdf"; + } + else { + id = null; + } + + return id; + } + + public ImageJobInformation getImageJobInformation(){ + ImageJobInformation new_image_info = (ImageJobInformation) image_info.clone(); + return new_image_info; + } + + public Integer[] getPageNrs() throws Exception{ + ArrayList<Integer> pgs=new ArrayList<Integer>(); + Integer[] numarray = null; + + String intervals[] = getAsString("pgs").split(","); + + // convert the page-interval-strings into a list containing every single page + for(String interval: intervals){ + if(interval.indexOf("-") > 1){ + String nums[] = interval.split("-"); + +// if(nums.length!=2){ +// throw new Exception("Malformed pageset expression: "+getAsString("pgs")); +// } + + for(int i=Integer.valueOf(nums[0]); i <= Integer.valueOf(nums[1]); i++){ + pgs.add(i); + } + } + else if (interval.indexOf("-") < 0){ + pgs.add(Integer.valueOf(interval)); + } +// else{ +// throw new Exception("Malformed pageset expression: "+getAsString("pgs")); +// } + } + + pgs.toArray(numarray); + return numarray; + } + +} \ No newline at end of file
--- a/servlet/src/digilib/servlet/PDFMaker.java Mon Feb 23 16:03:06 2009 +0100 +++ b/servlet/src/digilib/servlet/PDFMaker.java Mon Mar 02 17:11:26 2009 +0100 @@ -1,931 +1,60 @@ -/* - * MakePDF - * - * Digital Image Library servlet components - * - * Copyright (C) 200-2004 Robert Casties (robcast@mail.berlios.de) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * Please read license.txt for the full details. A copy of the GPL may be found - * at http://www.gnu.org/copyleft/lgpl.html - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - package digilib.servlet; -import java.awt.geom.AffineTransform; -import java.awt.geom.NoninvertibleTransformException; -import java.awt.geom.Rectangle2D; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.List; +import java.util.HashMap; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.log4j.Logger; - -import com.lowagie.text.*; -import com.lowagie.text.pdf.PdfWriter; - -import digilib.auth.AuthOpException; -import digilib.auth.AuthOps; -import digilib.image.ImageOpException; -import digilib.image.ImageOps; -import digilib.image.ImageSize; -import digilib.io.DocuDirCache; -import digilib.io.DocuDirectory; -import digilib.io.DocuDirent; -import digilib.io.FileOpException; -import digilib.io.FileOps; -import digilib.io.ImageFile; -import digilib.io.ImageFileset; +public class PDFMaker extends HttpServlet implements Runnable { -/** - * generates pdf-files from a digilib images. - * This is a very quick and dirty but functional version and will - * (hopefully soon) be replaced by a parallelized and more sophisticated one. - * - * @author cmielack - */ - -public class PDFMaker extends HttpServlet implements Runnable{ - - private static final long serialVersionUID = -325080527268912852L; - - /** digilib servlet version (for all components) */ - public static final String dlVersion = "1.7.0b"; - - /** logger for accounting requests */ - private static Logger accountlog = Logger.getLogger("account.request"); - - /** gengeral logger for this class */ - private static Logger logger = Logger.getLogger("digilib.servlet"); - - /** logger for authentication related */ - private static Logger authlog = Logger.getLogger("digilib.auth"); - - /** general error code */ - public static final int ERROR_UNKNOWN = 0; + private PDFJobInformation job_info = null; + private String filename = null; + private HashMap cache_hash = null; + private DigilibConfiguration dlConfig = null; + - /** error code for authentication error */ - public static final int ERROR_AUTH = 1; - - /** error code for file operation error */ - public static final int ERROR_FILE = 2; - - /** error code for image operation error */ - public static final int ERROR_IMAGE = 3; - - /** DocuDirCache instance */ - DocuDirCache dirCache; - - /** authentication error image file */ - File denyImgFile; - - /** image error image file */ - File errorImgFile; - - /** not found error image file */ - File notfoundImgFile; +/** public void init(ServletConfig config){ + ServletContext context = config.getServletContext(); + cache_hash = (HashMap<String,Integer>) context.getAttribute(PDFCache.cache_hash_id); + }*/ - /** subsampling before scaling */ - float minSubsample = 2f; - - /** send files as is? */ - boolean sendFileAllowed = true; - - /** default scaling quality */ - int defaultQuality = 1; - - /** DigilibConfiguration instance */ - DigilibConfiguration dlConfig; + + public PDFMaker(DigilibConfiguration dlConfig, HashMap cache_hash, PDFJobInformation pdfji, String filename){ + this.cache_hash = cache_hash; + this.job_info = pdfji; + this.filename = filename; + this.dlConfig = dlConfig; + } + - /** use authorization database */ - boolean useAuthorization = true; - - /** AuthOps instance */ - AuthOps authOp; - - HttpServletRequest mpdf_request = null; - HttpServletResponse mpdf_response = null; - String mpdf_filename = ""; - - String default_filename = "digilib_pages.pdf"; - // EXPRIMENTAL - /** try to enlarge cropping area for "oblique" angles */ - boolean wholeRotArea = false; + public void run() { - /** - * Initialisation on first run. - * - * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) - */ - public void init(ServletConfig config) throws ServletException { - super.init(config); - - System.out - .println("***** Digital Image Library Image MakePDF Servlet (version " - + dlVersion + ") *****"); - // say hello in the log file - logger - .info("***** Digital Image Library Image MakePDF Servlet (version " - + dlVersion + ") *****"); + if (! DigilibWorker.canRun()) { + // logger.error("Servlet overloaded!"); + cache_hash.put(filename, PDFCache.STATUS_ERROR); + return; + } - // get our ServletContext - ServletContext context = config.getServletContext(); - // see if there is a Configuration instance - dlConfig = (DigilibConfiguration) context - .getAttribute("digilib.servlet.configuration"); - if (dlConfig == null) { - // no Configuration - throw new ServletException("No Configuration!"); + cache_hash.put(filename, PDFCache.STATUS_WIP); + + // create PDFWorker + DigilibPDFWorker pdf_worker = new DigilibPDFWorker(dlConfig, job_info, filename); + + // run PDFWorker + pdf_worker.run(); + + if(pdf_worker.hasError()){ + cache_hash.put(filename, PDFCache.STATUS_ERROR); + return; } - // set our AuthOps - useAuthorization = dlConfig.getAsBoolean("use-authorization"); - authOp = (AuthOps) dlConfig.getValue("servlet.auth.op"); - - // DocuDirCache instance - dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); - denyImgFile = ServletOps.getFile((File) dlConfig.getValue("denied-image"), config); - errorImgFile = ServletOps.getFile((File) dlConfig.getValue("error-image"), config); - notfoundImgFile = ServletOps.getFile((File) dlConfig.getValue("notfound-image"), config); - sendFileAllowed = dlConfig.getAsBoolean("sendfile-allowed"); - minSubsample = dlConfig.getAsFloat("subsample-minimum"); - defaultQuality = dlConfig.getAsInt("default-quality"); - - - context.setAttribute("digilib.servlet.MakePDF", this); // register this instance globally, so PDFCache can access it + cache_hash.put(filename, PDFCache.STATUS_DONE); } - public void doCreate(HttpServletRequest request, HttpServletResponse response, String filename) - throws ServletException, IOException { - - accountlog.info("GET from " + request.getRemoteAddr()); - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); - - - mpdf_request = request; - mpdf_response = response; - mpdf_filename = filename; - - } -/* public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - accountlog.info("GET from " + request.getRemoteAddr()); - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); - // do the processing - processRequest(request, response,default_filename); - }*/ - -/* public void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - accountlog.info("POST from " + request.getRemoteAddr()); - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); - // do the processing - processRequest(request, response,default_filename); - }*/ - - /* - * (non-Javadoc) - * - * @see javax.servlet.http.HttpServlet#getLastModified(javax.servlet.http.HttpServletRequest) - */ - - protected long getLastModified(HttpServletRequest request) { - accountlog.debug("GetLastModified from " + request.getRemoteAddr() - + " for " + request.getQueryString()); - long mtime = -1; - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // find the requested file - DocuDirent f = findFile(dlReq); - if (f != null) { - DocuDirectory dd = (DocuDirectory) f.getParent(); - mtime = dd.getDirMTime() / 1000 * 1000; - } - return mtime; - } - - void createPDFfile(HttpServletRequest request, HttpServletResponse response, String filename) - throws javax.servlet.ServletException, java.io.IOException { - - Hashtable<String,Integer> cache_hash = (Hashtable<String,Integer>) this.getServletContext().getAttribute("digilib.servlet.PDFCache"); - BufferedOutputStream pdfOutStream = null; - FileOutputStream fos = null; - - String file_only = filename.split("/")[filename.split("/").length-1]; - - try { - - cache_hash.put(file_only, 2); // register the file as 'pending' - - // TODO check, if file can be created without overwriting another file etc. - - fos = new FileOutputStream(filename); - - pdfOutStream = generatePDFcontent(request, response, this.getServletContext(), fos); - - fos.flush(); - - cache_hash.put(file_only, 1); // register the file as 'done' - - } - catch (DocumentException de){ - // inform the user about what went wrong - response.setContentType("text/html"); - PrintWriter writer = response.getWriter(); - writer.println(this.getClass().getName() + " caught an exception: " - + de.getClass().getName() + "<br/> <pre>"); - de.printStackTrace(writer); - writer.println("</pre>"); - } - - finally { - if (pdfOutStream != null){ - pdfOutStream.close(); - } - if (fos!=null){ - fos.close(); - } - } - } - - - - - void addImageToPDF(HttpServletRequest request, HttpServletResponse response, int pn, Document doc) - throws ServletException { - /** until now, this is taken from the Scaler-method processRequest and modified ...*/ - - - if (dlConfig == null) { - throw new ServletException("ERROR: No Configuration!"); - } - - accountlog.debug("request: " + request.getQueryString()); - logger.debug("request: " + request.getQueryString()); - - // output mime-type - String mimeType = "image/png"; - - /* preset request parameters */ - - // scale the image file to fit window size i.e. respect dw,dh - boolean scaleToFit = true; - // scale the image by a fixed factor only - boolean absoluteScale = false; - // use low resolution images only - boolean loresOnly = false; - // use hires images only - boolean hiresOnly = false; - // send the image always as a specific type (e.g. JPEG or PNG) - int forceType = ImageOps.TYPE_AUTO; - // interpolation to use for scaling - int scaleQual = defaultQuality; - // send html error message (or image file) - boolean errorMsgHtml = false; - // original (hires) image resolution - float origResX = 0; - float origResY = 0; - - /* request parameters */ - - DigilibRequest dlRequest = (DigilibRequest) request - .getAttribute("digilib.servlet.request"); - - dlRequest.setValue("pn", pn); - //dlRequest.setValue("mo", "osize"); - //dlRequest.setValue("ddpix",72); - //dlRequest.setValue("ddpix",72); - - // destination image width - int paramDW = dlRequest.getAsInt("dw"); - // destination image height - int paramDH = dlRequest.getAsInt("dh"); - // relative area x_offset (0..1) - float paramWX = dlRequest.getAsFloat("wx"); - // relative area y_offset - float paramWY = dlRequest.getAsFloat("wy"); - // relative area width (0..1) - float paramWW = dlRequest.getAsFloat("ww"); - // relative area height - float paramWH = dlRequest.getAsFloat("wh"); - // scale factor (additional to dw/width, dh/height) - float paramWS = dlRequest.getAsFloat("ws"); - // rotation angle - float paramROT = dlRequest.getAsFloat("rot"); - // contrast enhancement - float paramCONT = dlRequest.getAsFloat("cont"); - // brightness enhancement - float paramBRGT = dlRequest.getAsFloat("brgt"); - // color modification - float[] paramRGBM = null; - Parameter p = dlRequest.get("rgbm"); - if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) { - paramRGBM = p.parseAsFloatArray("/"); - } - float[] paramRGBA = null; - p = dlRequest.get("rgba"); - if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) { - paramRGBA = p.parseAsFloatArray("/"); - } - // destination resolution (DPI) - float paramDDPIX = dlRequest.getAsFloat("ddpix"); - float paramDDPIY = dlRequest.getAsFloat("ddpiy"); - if ((paramDDPIX == 0) || (paramDDPIY == 0)) { - // if X or Y resolution isn't set, use DDPI - paramDDPIX = dlRequest.getAsFloat("ddpi"); - paramDDPIY = paramDDPIX; - } - // absolute scale factor for mo=ascale (and mo=osize) - float paramSCALE = dlRequest.getAsFloat("scale"); - - /* - * operation mode: "fit": always fit to page, "clip": send original - * resolution cropped, "file": send whole file (if allowed) - */ - if (dlRequest.hasOption("mo", "clip")) { - scaleToFit = false; - absoluteScale = false; - hiresOnly = true; - } else if (dlRequest.hasOption("mo", "fit")) { - scaleToFit = true; - absoluteScale = false; - hiresOnly = false; - } else if (dlRequest.hasOption("mo", "osize")) { - scaleToFit = false; - absoluteScale = true; - hiresOnly = true; - } else if (dlRequest.hasOption("mo", "ascale")) { - scaleToFit = false; - absoluteScale = true; - hiresOnly = false; - } - - // operation mode: "lores": try to use scaled image, "hires": use - // unscaled image - // "autores": try best fitting resolution - if (dlRequest.hasOption("mo", "lores")) { - loresOnly = true; - hiresOnly = false; - } else if (dlRequest.hasOption("mo", "hires")) { - loresOnly = false; - hiresOnly = true; - } else if (dlRequest.hasOption("mo", "autores")) { - loresOnly = false; - hiresOnly = false; - } - // operation mode: "errtxt": error message in html, "errimg": error - // image - if (dlRequest.hasOption("mo", "errtxt")) { - errorMsgHtml = true; - } else if (dlRequest.hasOption("mo", "errimg")) { - errorMsgHtml = false; - } - // operation mode: "q0" - "q2": interpolation quality - if (dlRequest.hasOption("mo", "q0")) { - scaleQual = 0; - } else if (dlRequest.hasOption("mo", "q1")) { - scaleQual = 1; - } else if (dlRequest.hasOption("mo", "q2")) { - scaleQual = 2; - } - // operation mode: "jpg": always use JPEG - if (dlRequest.hasOption("mo", "jpg")) { - forceType = ImageOps.TYPE_JPEG; - } - // operation mode: "png": always use PNG - if (dlRequest.hasOption("mo", "png")) { - forceType = ImageOps.TYPE_PNG; - } - - // check with the maximum allowed size (if set) - int maxImgSize = dlConfig.getAsInt("max-image-size"); - if (maxImgSize > 0) { - paramDW = (paramDW * paramWS > maxImgSize) ? (int) (maxImgSize / paramWS) - : paramDW; - paramDH = (paramDH * paramWS > maxImgSize) ? (int) (maxImgSize / paramWS) - : paramDH; - } - - // "big" try for all file/image actions - try { - - // ImageFileset of the image to load - ImageFileset fileset = null; - - /* find the file to load/send */ - - // get PathInfo - String loadPathName = dlRequest.getFilePath(); - - /* check permissions */ - if (useAuthorization) { - // get a list of required roles (empty if no restrictions) - List rolesRequired = authOp.rolesForPath(loadPathName, request); - if (rolesRequired != null) { - authlog.debug("Role required: " + rolesRequired); - authlog.debug("User: " + request.getRemoteUser()); - // is the current request/user authorized? - if (!authOp.isRoleAuthorized(rolesRequired, request)) { - // send deny answer and abort - throw new AuthOpException(); - } - } - } - - // find the file - fileset = (ImageFileset) findFile(dlRequest); - if (fileset == null) { - throw new FileOpException("File " + loadPathName + "(" - + dlRequest.getAsInt("pn") + ") not found."); - } - - /* for absolute scale and original size we need the hires size */ - ImageSize hiresSize = null; - if (absoluteScale) { - ImageFile hiresFile = fileset.getBiggest(); - if (!hiresFile.isChecked()) { - ImageOps.checkFile(hiresFile); - } - hiresSize = hiresFile.getSize(); - - /* prepare resolution and scale factor for original size */ - if (dlRequest.hasOption("mo", "osize")) { - // get original resolution from metadata - fileset.checkMeta(); - origResX = fileset.getResX(); - origResY = fileset.getResY(); - if ((origResX == 0) || (origResY == 0)) { - throw new ImageOpException("Missing image DPI information!"); - } - - if ((paramDDPIX == 0) || (paramDDPIY == 0)) { - throw new ImageOpException( - "Missing display DPI information!"); - } - // calculate absolute scale factor - float sx = paramDDPIX / origResX; - float sy = paramDDPIY / origResY; - // currently only same scale :-( - paramSCALE = (sx + sy)/2f; - } - - } - - - /* calculate expected source image size */ - ImageSize expectedSourceSize = new ImageSize(); - if (scaleToFit) { - // scale to fit -- calculate minimum source size - float scale = (1 / Math.min(paramWW, paramWH)) * paramWS; - expectedSourceSize.setSize((int) (paramDW * scale), - (int) (paramDH * scale)); - } else if (absoluteScale && dlRequest.hasOption("mo", "ascale")) { - // absolute scale -- apply scale to hires size - expectedSourceSize = hiresSize.getScaled(paramSCALE); - } else { - // clip to fit -- source = destination size - expectedSourceSize.setSize((int) (paramDW * paramWS), - (int) (paramDH * paramWS)); - } - - ImageFile fileToLoad; - /* select a resolution */ - if (hiresOnly) { - // get first element (= highest resolution) - fileToLoad = fileset.getBiggest(); - } else if (loresOnly) { - // enforced lores uses next smaller resolution - fileToLoad = fileset.getNextSmaller(expectedSourceSize); - if (fileToLoad == null) { - // this is the smallest we have - fileToLoad = fileset.getSmallest(); - } - } else { - // autores: use next higher resolution - fileToLoad = fileset.getNextBigger(expectedSourceSize); - if (fileToLoad == null) { - // this is the highest we have - fileToLoad = fileset.getBiggest(); - } - } - logger.info("Planning to load: " + fileToLoad.getFile()); - - /* - * send the image if its mo=(raw)file - */ - if (dlRequest.hasOption("mo", "file") - || dlRequest.hasOption("mo", "rawfile")) { - if (sendFileAllowed) { - String mt = null; - if (dlRequest.hasOption("mo", "rawfile")) { - mt = "application/octet-stream"; - } - logger.debug("Sending RAW File as is."); - ServletOps.sendFile(fileToLoad.getFile(), mt, response); - return; - } - } - - // check the source image - if (!fileToLoad.isChecked()) { - ImageOps.checkFile(fileToLoad); - } - // get the source image type - mimeType = fileToLoad.getMimetype(); - // get the source image size - ImageSize imgSize = fileToLoad.getSize(); - - // decide if the image can be sent as is - boolean mimetypeSendable = mimeType.equals("image/jpeg") - || mimeType.equals("image/png") - || mimeType.equals("image/gif"); - boolean imagoOptions = dlRequest.hasOption("mo", "hmir") - || dlRequest.hasOption("mo", "vmir") || (paramROT != 0) - || (paramRGBM != null) || (paramRGBA != null) - || (paramCONT != 0) || (paramBRGT != 0); - boolean imageSendable = mimetypeSendable && !imagoOptions; - - /* - * if not autoRes and image smaller than requested size then send as - * is. if autoRes and image has requested size then send as is. if - * not autoScale and not scaleToFit nor cropToFit then send as is - * (mo=file) - */ -/* if (imageSendable - && ((loresOnly && fileToLoad.getSize().isSmallerThan( - expectedSourceSize)) || (!(loresOnly || hiresOnly) && fileToLoad - .getSize().fitsIn(expectedSourceSize)))) { - - logger.debug("Sending File as is."); - - ServletOps.sendFile(fileToLoad.getFile(), null, response); - - logger.info("Done in " - + (System.currentTimeMillis() - startTime) + "ms"); - return; - } -*/ - - - /* - * stop here if we're overloaded... - * - * 503 Service Unavailable - * The server is currently unable to - * handle the request due to a temporary overloading or maintenance - * of the server. The implication is that this is a temporary - * condition which will be alleviated after some delay. If known, - * the length of the delay MAY be indicated in a Retry-After header. - * If no Retry-After is given, the client SHOULD handle the response - * as it would for a 500 response. Note: The existence of the 503 - * status code does not imply that a server must use it when - * becoming overloaded. Some servers may wish to simply refuse the - * connection. - * (RFC2616 HTTP1.1) - */ - if (! DigilibWorker.canRun()) { - logger.error("Servlet overloaded!"); - response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - return; - } - - // set missing dw or dh from aspect ratio - float imgAspect = fileToLoad.getAspect(); - if (paramDW == 0) { - paramDW = (int) Math.round(paramDH * imgAspect); - } else if (paramDH == 0) { - paramDH = (int) Math.round(paramDW / imgAspect); - } - - /* crop and scale the image */ - - logger.debug("IMG: " + imgSize.getWidth() + "x" - + imgSize.getHeight()); - - // coordinates and scaling - float areaWidth; - float areaHeight; - float scaleX; - float scaleY; - float scaleXY; - - // coordinates using Java2D - // image size in pixels - Rectangle2D imgBounds = new Rectangle2D.Float(0, 0, imgSize - .getWidth(), imgSize.getHeight()); - // user window area in [0,1] coordinates - Rectangle2D relUserArea = new Rectangle2D.Float(paramWX, paramWY, - paramWW, paramWH); - // transform from relative [0,1] to image coordinates. - AffineTransform imgTrafo = AffineTransform.getScaleInstance(imgSize - .getWidth(), imgSize.getHeight()); - // transform user coordinate area to image coordinate area - Rectangle2D userImgArea = imgTrafo.createTransformedShape( - relUserArea).getBounds2D(); - - // calculate scaling factors based on inner user area - if (scaleToFit) { - areaWidth = (float) userImgArea.getWidth(); - areaHeight = (float) userImgArea.getHeight(); - scaleX = paramDW / areaWidth * paramWS; - scaleY = paramDH / areaHeight * paramWS; - scaleXY = (scaleX > scaleY) ? scaleY : scaleX; - } else if (absoluteScale) { - scaleXY = paramSCALE; - // we need to correct the factor if we use a pre-scaled image - if (imgSize.getWidth() != hiresSize.getWidth()) { - scaleXY *= (float)hiresSize.getWidth() / (float)imgSize.getWidth(); - } - scaleX = scaleXY; - scaleY = scaleXY; - areaWidth = paramDW / scaleXY * paramWS; - areaHeight = paramDH / scaleXY * paramWS; - // reset user area size - userImgArea.setRect(userImgArea.getX(), userImgArea.getY(), - areaWidth, areaHeight); - } else { - // crop to fit - areaWidth = paramDW * paramWS; - areaHeight = paramDH * paramWS; - // reset user area size - userImgArea.setRect(userImgArea.getX(), userImgArea.getY(), - areaWidth, areaHeight); - scaleX = 1f; - scaleY = 1f; - scaleXY = 1f; - } - - // enlarge image area for rotations to cover additional pixels - Rectangle2D outerUserImgArea = userImgArea; - Rectangle2D innerUserImgArea = userImgArea; - if (wholeRotArea) { - if (paramROT != 0) { - try { - // rotate user area coordinates around center of user - // area - AffineTransform rotTrafo = AffineTransform - .getRotateInstance(Math.toRadians(paramROT), - userImgArea.getCenterX(), userImgArea - .getCenterY()); - // get bounds from rotated end position - innerUserImgArea = rotTrafo.createTransformedShape( - userImgArea).getBounds2D(); - // get bounds from back-rotated bounds - outerUserImgArea = rotTrafo.createInverse() - .createTransformedShape(innerUserImgArea) - .getBounds2D(); - } catch (NoninvertibleTransformException e1) { - // this shouldn't happen anyway - logger.error(e1); - } - } - } - - logger.debug("Scale " + scaleXY + "(" + scaleX + "," + scaleY - + ") on " + outerUserImgArea); - - // clip area at the image border - outerUserImgArea = outerUserImgArea.createIntersection(imgBounds); - - // check image parameters sanity - if ((outerUserImgArea.getWidth() < 1) - || (outerUserImgArea.getHeight() < 1) - || (scaleXY * outerUserImgArea.getWidth() < 2) - || (scaleXY * outerUserImgArea.getHeight() < 2)) { - logger.error("ERROR: invalid scale parameter set!"); - throw new ImageOpException("Invalid scale parameter set!"); - } - - /* - * submit the image worker job - */ - - DigilibPDFWorker job = new DigilibPDFWorker(dlConfig, response, - mimeType, scaleQual, dlRequest, paramCONT, - paramBRGT, paramRGBM, paramRGBA, fileToLoad, scaleXY, - outerUserImgArea, innerUserImgArea, minSubsample, - wholeRotArea, forceType, doc); - - job.run(); - if (job.hasError()) { - throw new ImageOpException(job.getError().toString()); - } - - /* error handling */ - - } // end of "big" try - catch (IOException e) { - logger.error("ERROR: File IO Error: " + e); - digilibError(errorMsgHtml, ERROR_FILE, - "ERROR: File IO Error: " + e, response); - } catch (AuthOpException e) { - logger.error("ERROR: Authorization error: " + e); - digilibError(errorMsgHtml, ERROR_AUTH, - "ERROR: Authorization error: " + e, response); - } catch (ImageOpException e) { - logger.error("ERROR: Image Error: " + e); - digilibError(errorMsgHtml, ERROR_IMAGE, - "ERROR: Image Operation Error: " + e, response); - } catch (RuntimeException e) { - // JAI likes to throw RuntimeExceptions ;-( - logger.error("ERROR: Other Image Error: " + e); - digilibError(errorMsgHtml, ERROR_IMAGE, - "ERROR: Other Image Operation Error: " + e, response); - } - } - - /** - * Returns the DocuDirent corresponding to the DigilibRequest. - * - * @param dlRequest - * @return - */ - public DocuDirent findFile(DigilibRequest dlRequest) { - // find the file(set) - DocuDirent f = dirCache.getFile(dlRequest.getFilePath(), dlRequest - .getAsInt("pn"), FileOps.CLASS_IMAGE); - return f; - } - - /** - * Sends an error to the client as text or image. - * - * @param asHTML - * @param type - * @param msg - * @param response - */ - public void digilibError(boolean asHTML, int type, String msg, - HttpServletResponse response) { - try { - File img = null; - if (type == ERROR_AUTH) { - if (msg == null) { - msg = "ERROR: Unauthorized access!"; - } - img = denyImgFile; - } else if (type == ERROR_FILE) { - if (msg == null) { - msg = "ERROR: Image file not found!"; - } - img = notfoundImgFile; - } else { - if (msg == null) { - msg = "ERROR: Other image error!"; - } - img = this.errorImgFile; - } - if (asHTML && (img != null)) { - ServletOps.htmlMessage(msg, response); - } else { - ServletOps.sendFile(img, null, response); - } - } catch (IOException e) { - logger.error("Error sending error!", e); - } - - } - - /** - * @return the dlVersion - */ - public static String getVersion() { - return dlVersion; - } - - - protected BufferedOutputStream generatePDFcontent(HttpServletRequest request, HttpServletResponse response, - ServletContext servletcontext, OutputStream out) - throws DocumentException { - - /** This method sets up a document and calls the addImage method to add all the images */ - Document doc = new Document(PageSize.A4,0,0,0,0); - BufferedOutputStream outstream = new BufferedOutputStream(out); - - PdfWriter docwriter = null; - - - try{ - - docwriter = PdfWriter.getInstance(doc, outstream); - - - doc.addAuthor(this.getClass().getName()); - doc.addCreationDate(); - doc.addKeywords("digilib"); - doc.addTitle("digilib PDF"); - doc.addCreator(this.getClass().getName()); - - doc.open(); - - - // get width and height from the request -/* float docW = PageSize.A4.getWidth() - 2*PageSize.A4.getBorder(); - float docH= PageSize.A4.getHeight()- 2*PageSize.A4.getBorder(); -*/ - - // evaluate the pgs parameter (which pages go into the pdf) - String pages = request.getParameter("pgs"); - ArrayList<Integer> pgs=new ArrayList<Integer>(); // a list of the requested page numbers - String intervals[] = pages.split(","); - - // convert the page-interval-strings into a list containing every single page - for(String interval: intervals){ - if(interval.indexOf("-") > -1){ - String nums[] = interval.split("-"); - - for(int i=Integer.valueOf(nums[0]); i <= Integer.valueOf(nums[1]); i++){ - pgs.add(i); - } - } - else{ - pgs.add(Integer.valueOf(interval)); - } - } - - - - - // add all the images/pages to the pdf - for(int i=0; i<pgs.size(); i++){ - int pn=pgs.get(i); - this.addImageToPDF(request, response, pn, doc); - } - - - - } - catch (Exception de) { - logger.debug(de.getMessage()); - } - finally{ - if (doc!=null){ - doc.close(); - } - if (docwriter!=null){ - docwriter.close(); - } - } - return outstream; - } - - - public void run() { - if(mpdf_request!=null && mpdf_response!=null && mpdf_filename!=""){ - try { - createPDFfile(mpdf_request, mpdf_response, mpdf_filename); - } catch (ServletException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } -} \ No newline at end of file +}
--- a/servlet/src/digilib/servlet/RequestHandler.java Mon Feb 23 16:03:06 2009 +0100 +++ b/servlet/src/digilib/servlet/RequestHandler.java Mon Mar 02 17:11:26 2009 +0100 @@ -2,6 +2,7 @@ import java.io.InputStream; +import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -23,9 +24,9 @@ protected static Logger authlog = Logger.getLogger("digilib.auth"); - public void init(){ + public void init(ServletConfig config) throws ServletException{ try { - super.init(); + super.init(config); } catch (ServletException e) { e.printStackTrace(); logger.error(e.getMessage());
--- a/servlet/src/digilib/servlet/Scaler.java Mon Feb 23 16:03:06 2009 +0100 +++ b/servlet/src/digilib/servlet/Scaler.java Mon Mar 02 17:11:26 2009 +0100 @@ -21,6 +21,7 @@ import digilib.auth.AuthOps; import digilib.image.ImageOpException; import digilib.io.DocuDirCache; +import digilib.io.DocuDirectory; import digilib.io.DocuDirent; import digilib.io.FileOpException; import digilib.io.FileOps; @@ -78,8 +79,41 @@ /** try to enlarge cropping area for "oblique" angles */ boolean wholeRotArea = false; + + protected long getLastModified(HttpServletRequest request) { + accountlog.debug("GetLastModified from " + request.getRemoteAddr() + + " for " + request.getQueryString()); + long mtime = -1; + // create new request with defaults + DigilibRequest dlReq = new DigilibRequest(); + // set with request parameters + dlReq.setWithRequest(request); + // find the requested file + DocuDirent f = findFile(dlReq); + if (f != null) { + DocuDirectory dd = (DocuDirectory) f.getParent(); + mtime = dd.getDirMTime() / 1000 * 1000; + } + return mtime; + } + /** + * Returns the DocuDirent corresponding to the DigilibRequest. + * + * @param dlRequest + * @return + */ + public DocuDirent findFile(DigilibRequest dlRequest) { + // find the file(set) + DocuDirent f = dirCache.getFile(dlRequest.getFilePath(), dlRequest + .getAsInt("pn"), FileOps.CLASS_IMAGE); + return f; + } + + + /** * Initialisation on first run. + * @throws ServletException * * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) */ @@ -134,9 +168,8 @@ // define the job information - ImageJobInformation jobdeclaration = new ImageJobInformation(); + ImageJobInformation jobdeclaration = new ImageJobInformation(dlConfig); jobdeclaration.setWithRequest(request); - jobdeclaration.setConfig(dlConfig); ImageFile fileToLoad = null; try { @@ -238,27 +271,11 @@ } - job = new DigilibImageWorker(dlConfig, - outputstream , - jobdeclaration.get_mimeType(), - jobdeclaration.get_scaleQual(), - jobdeclaration.getAsFloat("rot"), - jobdeclaration.getAsFloat("cont"), - jobdeclaration.getAsFloat("brgt"), - jobdeclaration.get_paramRGBM(), - jobdeclaration.get_paramRGBA(), - jobdeclaration.get_fileToLoad(), - jobdeclaration.get_scaleXY(), - jobdeclaration.get_outerUserImgArea(), - jobdeclaration.get_innerUserImgArea(), - minSubsample, - jobdeclaration.get_wholeRotArea(), - jobdeclaration.get_forceType(), - jobdeclaration.get_hmir(), - jobdeclaration.get_vmir()); + job = new DigilibImageWorker(dlConfig, outputstream , jobdeclaration); job.run(); + if (job.hasError()) { throw new ImageOpException(job.getError().toString()); }