changeset 1180:5abbf21fdf9f

changed DigilibConfiguration to work with inheritance. DigilibServletConfiguration takes the role of Initialiser. DocuImage gets a static factory.
author robcast
date Thu, 04 Apr 2013 18:43:13 +0200
parents d4990c1463e3
children f5e16d31cccb
files common/src/main/java/digilib/conf/DigilibConfiguration.java common/src/main/java/digilib/image/DocuImageFactory.java common/src/main/java/digilib/image/ImageWorker.java common/src/main/java/digilib/io/ImageFile.java pdf/pom.xml pdf/src/main/java/digilib/conf/PDFRequest.java pdf/src/main/java/digilib/conf/PDFServletConfiguration.java pdf/src/main/java/digilib/pdf/PDFFileWorker.java pdf/src/main/java/digilib/pdf/PDFStreamWorker.java pdf/src/main/java/digilib/pdf/PDFTitlePage.java pdf/src/main/java/digilib/servlet/PDFCache.java pdf/src/main/java/digilib/servlet/PDFRequest.java servlet/src/main/java/digilib/conf/DigilibServletConfiguration.java servlet2/src/main/java/digilib/servlet/Initialiser.java servlet2/src/main/java/digilib/servlet/Scaler.java servlet3/src/main/java/digilib/conf/DigilibServlet3Configuration.java servlet3/src/main/java/digilib/servlet/Initialiser.java text/src/main/java/digilib/servlet/Texter.java webapp/src/main/webapp/WEB-INF/web-2.3.xml webapp/src/main/webapp/WEB-INF/web-3.0.xml webapp/src/main/webapp/server/dlConfig.jsp
diffstat 21 files changed, 622 insertions(+), 789 deletions(-) [+]
line wrap: on
line diff
--- a/common/src/main/java/digilib/conf/DigilibConfiguration.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/common/src/main/java/digilib/conf/DigilibConfiguration.java	Thu Apr 04 18:43:13 2013 +0200
@@ -25,64 +25,36 @@
  * Author: Robert Casties (robcast@berlios.de)
  */
 
-import java.io.IOException;
+import javax.imageio.ImageIO;
 
 import org.apache.log4j.BasicConfigurator;
 import org.apache.log4j.Logger;
 
 import digilib.image.DocuImage;
-import digilib.image.DocuImageImpl;
-import digilib.io.ImageInput;
+import digilib.image.DocuImageFactory;
 import digilib.util.ParameterMap;
 
 /**
- * Class to hold the digilib servlet configuration parameters. The parameters
- * can be read from the digilib-config file and be passed to other servlets or
- * beans. <br>
- * errorImgFileName: image file to send in case of error. <br>
- * denyImgFileName: image file to send if access is denied. <br>
- * baseDirs: array of base directories in order of preference (prescaled
- * versions first). <br>
- * useAuth: use authentication information. <br>
- * authConfPath: authentication configuration file. <br>
- * ... <br>
- * 
+ * Class to hold the digilib servlet configuration parameters.
  * @author casties
  * 
  */
 public class DigilibConfiguration extends ParameterMap {
 
-    /** DocuImage class instance */
-    protected static Class<DocuImageImpl> docuImageClass = null;
-
     /** Log4J logger */
-    protected Logger logger = Logger.getLogger("digilib.config");
+    protected static Logger logger = Logger.getLogger(DigilibConfiguration.class);
 
     /**
      * Default constructor defines all parameters and their default values.
-     * 
      */
     public DigilibConfiguration() {
         super(20);
-        // we start with a default logger config
-        BasicConfigurator.configure();
-        initParams();
-    }
-
-    /**
-     * Definition of parameters and default values.
-     * 
-     */
-    @SuppressWarnings("unchecked")
-    protected void initParams() {
         /*
          * Definition of parameters and default values. System parameters that
          * are not read from config file have a type 's'.
          */
         // digilib version
-        newParameter("digilib.version", "2.1.3", null, 's');
-        // DocuImage class instance
-        newParameter("servlet.docuimage.class", digilib.image.ImageLoaderDocuImage.class, null, 's');
+        newParameter("digilib.version", "2.2.0", null, 's');
         // sending image files as-is allowed
         newParameter("sendfile-allowed", Boolean.TRUE, null, 'f');
         // Type of DocuImage instance
@@ -90,7 +62,7 @@
         // degree of subsampling on image load
         newParameter("subsample-minimum", new Float(2f), null, 'f');
         // default scaling quality
-        newParameter("default-quality", new Integer(1), null, 'f');
+        newParameter("default-quality", new Integer(2), null, 'f');
         // maximum destination image size (0 means no limit)
         newParameter("max-image-size", new Integer(0), null, 'f');
         // allow image toolkit to use disk cache
@@ -98,55 +70,33 @@
         // default type of error message (image, text, code)
         newParameter("default-errmsg-type", "image", null, 'f');
 
-        // initialise static DocuImage class instance
-        try {
-            DigilibConfiguration.docuImageClass = (Class<DocuImageImpl>) Class.forName(getAsString("docuimage-class"));
-        } catch (ClassNotFoundException e) {
-            logger.error("Unable to set docuImageClass!");
-        }
-    }
-
-    /**
-     * Creates a new DocuImage instance.
-     * 
-     * The type of DocuImage is specified by docuimage-class.
-     * 
-     * @return DocuImage
-     */
-    public static DocuImage getDocuImageInstance() {
-        DocuImageImpl di = null;
-        try {
-            di = docuImageClass.newInstance();
-        } catch (Exception e) {
-        }
-        return di;
     }
 
     /**
-     * Check image size and type and store in ImageFile imgf
+     * Configure digilib.
      * 
-     * @param imgf
-     * @return
-     * @throws IOException
+     * Sets up Factories and Singletons using the configuration. 
      */
-    public static ImageInput identifyDocuImage(ImageInput imgf) throws IOException {
-        // use fresh DocuImage instance
-        DocuImage di = getDocuImageInstance();
-        return di.identify(imgf);
+    @SuppressWarnings("unchecked")
+    public void configure() {
+        // we start log4j with a default logger config TODO: is this the right place?
+        BasicConfigurator.configure();
+        /*
+         * initialise static DocuImage class instance
+         */
+        try {
+            Class<DocuImage> docuImageClass = (Class<DocuImage>) Class.forName(getAsString("docuimage-class"));
+            DocuImageFactory.setDocuImageClass(docuImageClass);
+            // DocuImage class instance
+            newParameter("servlet.docuimage.class", docuImageClass, null, 's');
+            newParameter("servlet.docuimage.version", DocuImageFactory.getInstance().getVersion(), null, 's');
+        } catch (ClassNotFoundException e) {
+            logger.error("Error setting DocuImage class!");
+        }
+        // disk cache for image toolkit
+        boolean dc = getAsBoolean("img-diskcache-allowed");
+        // TODO: methods for all toolkits?
+        ImageIO.setUseCache(dc);
     }
 
-    /**
-     * @return Returns the docuImageClass.
-     */
-    public static Class<DocuImageImpl> getDocuImageClass() {
-        return docuImageClass;
-    }
-
-    /**
-     * @param docuImageClass
-     *            The docuImageClass to set.
-     */
-    public static void setDocuImageClass(Class<DocuImageImpl> dic) {
-        docuImageClass = dic;
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/digilib/image/DocuImageFactory.java	Thu Apr 04 18:43:13 2013 +0200
@@ -0,0 +1,66 @@
+package digilib.image;
+
+/*
+ * #%L
+ * digilib-common
+ * %%
+ * Copyright (C) 2013 MPIWG Berlin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Lesser Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Lesser Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/lgpl-3.0.html>.
+ * #L%
+ * Author: Robert Casties (robcast@berlios.de)
+ */
+
+import org.apache.log4j.Logger;
+
+
+/**
+ * Static factory for DocuImages.
+ * 
+ * @author casties
+ * 
+ */
+public class DocuImageFactory {
+    /** Log4J logger */
+    protected static Logger logger = Logger.getLogger(DocuImageFactory.class);
+
+    /** AuthOps implementation class */
+    protected static Class<DocuImage> docuImageClass;
+
+    /**
+     * Creates a new DocuImage instance.
+     * 
+     * The type of DocuImage is specified by docuimage-class.
+     * 
+     * @return DocuImage
+     */
+    public static DocuImage getInstance() {
+        DocuImage di = null;
+        try {
+            di = docuImageClass.newInstance();
+        } catch (Exception e) {
+            logger.error("Unable to create DocuImage instance!", e);
+        }
+        return di;
+    }
+
+    /** set the DocuImage implementation class.
+     * @param clazz
+     */
+    public static void setDocuImageClass(Class<DocuImage> clazz) {
+        DocuImageFactory.docuImageClass = clazz;
+    }
+
+}
--- a/common/src/main/java/digilib/image/ImageWorker.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/common/src/main/java/digilib/image/ImageWorker.java	Thu Apr 04 18:43:13 2013 +0200
@@ -69,7 +69,7 @@
 
         DocuImage docuImage = jobinfo.getDocuImage();
         if (docuImage == null) {
-            docuImage = DigilibConfiguration.getDocuImageInstance();
+            docuImage = DocuImageFactory.getInstance();
             if (docuImage == null) {
                 throw new ImageOpException("Unable to load DocuImage class!");
             }
--- a/common/src/main/java/digilib/io/ImageFile.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/common/src/main/java/digilib/io/ImageFile.java	Thu Apr 04 18:43:13 2013 +0200
@@ -34,7 +34,8 @@
 import javax.imageio.stream.FileImageInputStream;
 import javax.imageio.stream.ImageInputStream;
 
-import digilib.conf.DigilibConfiguration;
+import digilib.image.DocuImage;
+import digilib.image.DocuImageFactory;
 import digilib.util.ImageSize;
 
 /**
@@ -82,7 +83,8 @@
 	    if (pixelSize == null) {
 	        try {
 	            // use the configured toolkit to identify the image
-                DigilibConfiguration.identifyDocuImage(this);
+                DocuImage di = DocuImageFactory.getInstance();
+                di.identify(this);
             } catch (IOException e) {
                 // nothing much to do...
             }
--- a/pdf/pom.xml	Thu Apr 04 12:43:43 2013 +0200
+++ b/pdf/pom.xml	Thu Apr 04 18:43:13 2013 +0200
@@ -34,6 +34,7 @@
 		<dependency>
 			<groupId>org.jdom</groupId>
 			<artifactId>jdom</artifactId>
+			<version>1.1.3</version>
 		</dependency>
 	</dependencies>
 	<profiles>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pdf/src/main/java/digilib/conf/PDFRequest.java	Thu Apr 04 18:43:13 2013 +0200
@@ -0,0 +1,176 @@
+package digilib.conf;
+
+/*
+ * #%L
+ * A container class for storing a set of instruction parameters 
+ * used for content generator classes like MakePDF.  
+ * %%
+ * Copyright (C) 2009 - 2013 MPIWG Berlin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Lesser Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Lesser Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/lgpl-3.0.html>.
+ * #L%
+ * Authors: Christopher Mielack,
+ *          Robert Casties (robcast@berlios.de)
+ */
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.log4j.Logger;
+
+import digilib.conf.DigilibConfiguration;
+import digilib.image.ImageJobDescription;
+import digilib.io.DocuDirectory;
+import digilib.io.FileOpException;
+import digilib.io.FileOps.FileClass;
+import digilib.util.NumRange;
+import digilib.util.OptionsSet;
+import digilib.util.ParameterMap;
+
+
+/** 
+ * A container class for storing a set of instruction parameters 
+ * used for content generator classes like MakePDF.  
+ * 
+ * 
+ * @author cmielack, casties
+ *
+ */
+public class PDFRequest extends ParameterMap {
+
+	DigilibConfiguration dlConfig = null;
+	NumRange pages = null;
+	/** general logger for this class */
+	protected static Logger logger = Logger.getLogger("digilib.servlet");
+
+	
+	/**
+	 * Initialize the PDFJobInformation
+	 * 
+	 * @param dlcfg			
+	 * 						The DigilibConfiguration. 
+	 */
+	public PDFRequest(DigilibConfiguration dlcfg) {
+		super(30);
+		dlConfig = dlcfg;
+	}
+
+	/**
+	 * Initialize the PDFJobInformation with a request.
+	 * 
+	 * @param dlcfg		The DigilibConfiguration. 		
+	 * @param request
+	 * @throws FileOpException 
+	 */
+	public PDFRequest(HttpServletRequest request, DigilibConfiguration dlcfg) throws FileOpException {
+		super(30);
+		dlConfig = dlcfg;
+		this.setWithRequest(request);
+	}
+
+	
+	protected void initParams() {
+		// page numbers
+		newParameter("pgs", "", null, 's');
+		// url of the page/document (second part)
+		newParameter("fn", "", null, 's');
+		// width of client in pixels
+		newParameter("dw", new Integer(0), null, 's');
+		// height of client in pixels
+		newParameter("dh", new Integer(500), null, 's');
+	}
+	
+	/* (non-Javadoc)
+     * @see digilib.servlet.ParameterMap#initOptions()
+     */
+    @Override
+    protected void initOptions() {
+        options = (OptionsSet) getValue("mo");
+    }
+
+    /**
+	 * Read the request object.
+	 * 
+	 * @param request
+	 * @throws FileOpException 
+	 */
+	public void setWithRequest(HttpServletRequest request) throws FileOpException {
+	    // read matching request parameters for the parameters in this map 
+		for (String k : params.keySet()) {
+			if (request.getParameterMap().containsKey(k)) {
+				setValueFromString(k, request.getParameter(k));
+			}
+		}
+		// process parameters
+		pages = new NumRange(getAsString("pgs"));
+        ImageJobDescription ij = ImageJobDescription.getInstance(this, dlConfig);
+        DocuDirectory dir = ij.getFileDirectory();
+        int dirsize = dir.size(FileClass.IMAGE);
+        pages.setMaxnum(dirsize);
+	}
+	
+	
+	/**
+	 * Generate a filename for the pdf to be created.
+	 * 
+	 * @return
+	 */
+	public String getDocumentId(){
+		String fn = getAsString("fn");
+		String dh = getAsString("dh");
+		String dw = getAsString("dw");
+		String pgs = getAsString("pgs");
+			
+		String id = "fn=" + fn + "&dw=" + dw + "&dh=" + dh + "&pgs=" + pgs + ".pdf";
+		// make safe to use as filename by urlencoding
+		try {
+			id = URLEncoder.encode(id, "UTF-8");
+		} catch (UnsupportedEncodingException e) {
+			// this shouldn't happen
+		}
+		return id;
+	}
+
+	
+	public ImageJobDescription getImageJobInformation(){
+		return ImageJobDescription.getInstance(this, dlConfig);
+	}
+	
+	
+	public NumRange getPages() {
+	    return pages;
+	}
+	
+	
+	/**
+	 * Check parameters for validity.
+	 * Returns true if no errors are found.
+	 * 
+	 * @return
+	 */
+	public boolean checkValidity(){
+	    if (pages != null) {
+	        return true;
+	    }
+	    return false;
+	} 
+	
+	public DigilibConfiguration getDlConfig(){
+		return dlConfig;
+	}
+	
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pdf/src/main/java/digilib/conf/PDFServletConfiguration.java	Thu Apr 04 18:43:13 2013 +0200
@@ -0,0 +1,140 @@
+package digilib.conf;
+
+import java.io.OutputStream;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+
+import digilib.image.DocuImage;
+import digilib.util.DigilibJobCenter;
+
+/*
+ * #%L
+ * DigilibConfiguration -- Holding all parameters for digilib servlet.
+ * 
+ * Digital Image Library servlet components
+ * 
+ * %%
+ * Copyright (C) 2001 - 2013 MPIWG Berlin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Lesser Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Lesser Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/lgpl-3.0.html>.
+ * #L%
+ * Author: Robert Casties (robcast@berlios.de)
+ */
+
+
+/**
+ * Class to hold the digilib servlet configuration parameters. The parameters
+ * can be read from the digilib-config file and be passed to other servlets or
+ * beans. <br>
+ * errorImgFileName: image file to send in case of error. <br>
+ * denyImgFileName: image file to send if access is denied. <br>
+ * baseDirs: array of base directories in order of preference (prescaled
+ * versions first). <br>
+ * useAuth: use authentication information. <br>
+ * authConfPath: authentication configuration file. <br>
+ * ... <br>
+ * 
+ * @author casties
+ * 
+ */
+public class PDFServletConfiguration extends DigilibServletConfiguration {
+
+    private DigilibJobCenter<OutputStream> pdfExecutor;
+    private DigilibJobCenter<DocuImage> pdfImageExecutor;
+
+    public String getVersion() {
+        return "2.2.0 pdf";
+    }
+
+    /**
+     * Constructs PDFServletConfiguration and defines all parameters and their default values.
+     */
+    public PDFServletConfiguration() {
+        super();
+        /*
+         * Definition of additional parameters and default values. System parameters that
+         * are not read from config file have a type 's'.
+         */
+
+        // Executor for PDF operations
+        newParameter("servlet.worker.pdfexecutor", null, null, 's');
+        // Executor for PDF-image operations
+        newParameter("servlet.worker.pdfimageexecutor", null, null, 's');
+
+        /*
+         * parameters that can be read from config file have a type 'f'
+         */
+
+        // number of pdf-generation threads
+        newParameter("pdf-worker-threads", new Integer(1), null, 'f');
+        // max number of waiting pdf-generation threads
+        newParameter("pdf-max-waiting-threads", new Integer(20), null, 'f');
+        // number of pdf-image generation threads
+        newParameter("pdf-image-worker-threads", new Integer(1), null, 'f');
+        // max number of waiting pdf-image generation threads
+        newParameter("pdf-image-max-waiting-threads", new Integer(10), null, 'f');
+        // PDF generation temp directory
+        newParameter("pdf-temp-dir", "pdf_temp", null, 'f');
+        // PDF generation cache directory
+        newParameter("pdf-cache-dir", "pdf_cache", null, 'f');
+    }
+
+    /* (non-Javadoc)
+     * @see digilib.conf.DigilibServletConfiguration#configure(javax.servlet.ServletContext)
+     */
+    @Override
+    public void configure(ServletContext context) {
+        super.configure(context);
+        PDFServletConfiguration dlConfig = this;
+        // PDF worker threads
+        int pnt = dlConfig.getAsInt("pdf-worker-threads");
+        int pmt = dlConfig.getAsInt("pdf-max-waiting-threads");
+        pdfExecutor = new DigilibJobCenter<OutputStream>(pnt, pmt, false, "servlet.worker.pdfexecutor");
+        dlConfig.setValue("servlet.worker.pdfexecutor", pdfExecutor);
+        // PDF image worker threads
+        int pint = dlConfig.getAsInt("pdf-image-worker-threads");
+        int pimt = dlConfig.getAsInt("pdf-image-max-waiting-threads");
+        pdfImageExecutor = new DigilibJobCenter<DocuImage>(pint, pimt, false, "servlet.worker.pdfimageexecutor");
+        dlConfig.setValue("servlet.worker.pdfimageexecutor", pdfImageExecutor);
+    }
+
+    /* (non-Javadoc)
+     * @see digilib.conf.DigilibServletConfiguration#contextDestroyed(javax.servlet.ServletContextEvent)
+     */
+    @Override
+    public void contextDestroyed(ServletContextEvent sce) {
+        super.contextDestroyed(sce);
+        if (pdfExecutor != null) {
+            // shut down pdf thread pool
+            List<Runnable> rj = pdfExecutor.shutdownNow();
+            int nrj = rj.size();
+            if (nrj > 0) {
+                logger.error("Still running threads when shutting down PDF job queue: " + nrj);
+            }
+        }
+        if (pdfImageExecutor != null) {
+            // shut down pdf image thread pool
+            List<Runnable> rj = pdfImageExecutor.shutdownNow();
+            int nrj = rj.size();
+            if (nrj > 0) {
+                logger.error("Still running threads when shutting down PDF-image job queue: " + nrj);
+            }
+        }
+    }
+
+
+}
--- a/pdf/src/main/java/digilib/pdf/PDFFileWorker.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/pdf/src/main/java/digilib/pdf/PDFFileWorker.java	Thu Apr 04 18:43:13 2013 +0200
@@ -31,8 +31,8 @@
 import java.util.concurrent.Callable;
 
 import digilib.image.DocuImage;
-import digilib.servlet.DigilibConfiguration;
-import digilib.servlet.PDFRequest;
+import digilib.conf.DigilibConfiguration;
+import digilib.conf.PDFRequest;
 import digilib.util.DigilibJobCenter;
 
 /**
--- a/pdf/src/main/java/digilib/pdf/PDFStreamWorker.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/pdf/src/main/java/digilib/pdf/PDFStreamWorker.java	Thu Apr 04 18:43:13 2013 +0200
@@ -41,8 +41,8 @@
 import digilib.image.DocuImage;
 import digilib.image.ImageJobDescription;
 import digilib.image.ImageWorker;
-import digilib.servlet.DigilibConfiguration;
-import digilib.servlet.PDFRequest;
+import digilib.conf.DigilibConfiguration;
+import digilib.conf.PDFRequest;
 import digilib.util.DigilibJobCenter;
 import digilib.util.NumRange;
 
--- a/pdf/src/main/java/digilib/pdf/PDFTitlePage.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/pdf/src/main/java/digilib/pdf/PDFTitlePage.java	Thu Apr 04 18:43:13 2013 +0200
@@ -39,9 +39,9 @@
 import com.itextpdf.text.Image;
 import com.itextpdf.text.Paragraph;
 
+import digilib.conf.PDFRequest;
 import digilib.io.FileOpException;
 import digilib.servlet.PDFCache;
-import digilib.servlet.PDFRequest;
 
 /** A class for the generation of title pages for the generated pdf documents.
  * 
--- a/pdf/src/main/java/digilib/servlet/PDFCache.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/pdf/src/main/java/digilib/servlet/PDFCache.java	Thu Apr 04 18:43:13 2013 +0200
@@ -39,6 +39,8 @@
 
 import org.apache.log4j.Logger;
 
+import digilib.conf.DigilibConfiguration;
+import digilib.conf.PDFRequest;
 import digilib.image.DocuImage;
 import digilib.pdf.PDFFileWorker;
 import digilib.util.DigilibJobCenter;
@@ -56,7 +58,7 @@
 @SuppressWarnings("serial")
 public class PDFCache extends HttpServlet {
 
-    public static String version = "0.3a";
+    public static String version = "2.2.0";
 
     /** logger for accounting requests */
     protected static Logger accountlog = Logger.getLogger("account.pdf.request");
@@ -92,7 +94,8 @@
 	public static enum PDFStatus {DONE, WIP, NONEXISTENT, ERROR};
 
 	
-	public void init(ServletConfig config) throws ServletException {
+	@SuppressWarnings("unchecked")
+    public void init(ServletConfig config) throws ServletException {
 		super.init(config);
 		
         System.out.println("***** Digital Image Library Image PDF-Cache Servlet (version "
--- a/pdf/src/main/java/digilib/servlet/PDFRequest.java	Thu Apr 04 12:43:43 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * A container class for storing a set of instruction parameters 
- * used for content generator classes like MakePDF.  
- * %%
- * Copyright (C) 2009 - 2013 MPIWG Berlin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Lesser Public License for more details.
- * 
- * You should have received a copy of the GNU General Lesser Public 
- * License along with this program.  If not, see
- * <http://www.gnu.org/licenses/lgpl-3.0.html>.
- * #L%
- * Authors: Christopher Mielack,
- *          Robert Casties (robcast@berlios.de)
- */
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.log4j.Logger;
-
-import digilib.image.ImageJobDescription;
-import digilib.io.DocuDirectory;
-import digilib.io.FileOpException;
-import digilib.io.FileOps.FileClass;
-import digilib.util.NumRange;
-import digilib.util.OptionsSet;
-import digilib.util.ParameterMap;
-
-
-/** 
- * A container class for storing a set of instruction parameters 
- * used for content generator classes like MakePDF.  
- * 
- * 
- * @author cmielack, casties
- *
- */
-public class PDFRequest extends ParameterMap {
-
-	DigilibConfiguration dlConfig = null;
-	NumRange pages = null;
-	/** general logger for this class */
-	protected static Logger logger = Logger.getLogger("digilib.servlet");
-
-	
-	/**
-	 * Initialize the PDFJobInformation
-	 * 
-	 * @param dlcfg			
-	 * 						The DigilibConfiguration. 
-	 */
-	public PDFRequest(DigilibConfiguration dlcfg) {
-		super(30);
-		dlConfig = dlcfg;
-	}
-
-	/**
-	 * Initialize the PDFJobInformation with a request.
-	 * 
-	 * @param dlcfg		The DigilibConfiguration. 		
-	 * @param request
-	 * @throws FileOpException 
-	 */
-	public PDFRequest(HttpServletRequest request, DigilibConfiguration dlcfg) throws FileOpException {
-		super(30);
-		dlConfig = dlcfg;
-		this.setWithRequest(request);
-	}
-
-	
-	protected void initParams() {
-		// page numbers
-		newParameter("pgs", "", null, 's');
-		// url of the page/document (second part)
-		newParameter("fn", "", null, 's');
-		// width of client in pixels
-		newParameter("dw", new Integer(0), null, 's');
-		// height of client in pixels
-		newParameter("dh", new Integer(500), null, 's');
-	}
-	
-	/* (non-Javadoc)
-     * @see digilib.servlet.ParameterMap#initOptions()
-     */
-    @Override
-    protected void initOptions() {
-        options = (OptionsSet) getValue("mo");
-    }
-
-    /**
-	 * Read the request object.
-	 * 
-	 * @param request
-	 * @throws FileOpException 
-	 */
-	public void setWithRequest(HttpServletRequest request) throws FileOpException {
-	    // read matching request parameters for the parameters in this map 
-		for (String k : params.keySet()) {
-			if (request.getParameterMap().containsKey(k)) {
-				setValueFromString(k, request.getParameter(k));
-			}
-		}
-		// process parameters
-		pages = new NumRange(getAsString("pgs"));
-        ImageJobDescription ij = ImageJobDescription.getInstance(this, dlConfig);
-        DocuDirectory dir = ij.getFileDirectory();
-        int dirsize = dir.size(FileClass.IMAGE);
-        pages.setMaxnum(dirsize);
-	}
-	
-	
-	/**
-	 * Generate a filename for the pdf to be created.
-	 * 
-	 * @return
-	 */
-	public String getDocumentId(){
-		String fn = getAsString("fn");
-		String dh = getAsString("dh");
-		String dw = getAsString("dw");
-		String pgs = getAsString("pgs");
-			
-		String id = "fn=" + fn + "&dw=" + dw + "&dh=" + dh + "&pgs=" + pgs + ".pdf";
-		// make safe to use as filename by urlencoding
-		try {
-			id = URLEncoder.encode(id, "UTF-8");
-		} catch (UnsupportedEncodingException e) {
-			// this shouldn't happen
-		}
-		return id;
-	}
-
-	
-	public ImageJobDescription getImageJobInformation(){
-		return ImageJobDescription.getInstance(this, dlConfig);
-	}
-	
-	
-	public NumRange getPages() {
-	    return pages;
-	}
-	
-	
-	/**
-	 * Check parameters for validity.
-	 * Returns true if no errors are found.
-	 * 
-	 * @return
-	 */
-	public boolean checkValidity(){
-	    if (pages != null) {
-	        return true;
-	    }
-	    return false;
-	} 
-	
-	public DigilibConfiguration getDlConfig(){
-		return dlConfig;
-	}
-	
-}
\ No newline at end of file
--- a/servlet/src/main/java/digilib/conf/DigilibServletConfiguration.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/servlet/src/main/java/digilib/conf/DigilibServletConfiguration.java	Thu Apr 04 18:43:13 2013 +0200
@@ -27,20 +27,30 @@
  */
 
 import java.io.File;
+import java.io.IOException;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.log4j.xml.DOMConfigurator;
+import org.xml.sax.SAXException;
 
 import digilib.auth.AuthOps;
 import digilib.auth.AuthOpsFactory;
-import digilib.image.DocuImageImpl;
+import digilib.image.DocuImage;
+import digilib.io.AliasingDocuDirCache;
+import digilib.io.DocuDirCache;
 import digilib.io.FileOps;
+import digilib.io.FileOps.FileClass;
 import digilib.meta.DirMeta;
 import digilib.meta.FileMeta;
 import digilib.meta.MetaFactory;
 import digilib.servlet.ServletOps;
+import digilib.util.DigilibJobCenter;
 import digilib.util.Parameter;
 import digilib.util.XMLListLoader;
 
@@ -59,21 +69,23 @@
  * @author casties
  * 
  */
-public class DigilibServletConfiguration extends DigilibConfiguration {
+public class DigilibServletConfiguration extends DigilibConfiguration implements ServletContextListener {
 
     /** time the webapp (i.e. this class) was loaded */
     public final Long webappStartTime = System.currentTimeMillis();
 
-    /** counter for HttpRequests (mostly for debugging) */
-    public AtomicInteger webappRequestCnt = new AtomicInteger(0);
+    private DigilibJobCenter<DocuImage> imageExecutor;
 
-    /** counter for open HttpRequests (mostly for debugging) */
-    public AtomicInteger openRequestCnt = new AtomicInteger(0);
-
+    public String getVersion() {
+        return "2.2.0 srv";
+    }
+    
     /**
-     * Definition of parameters and default values.
+     * Constructs DigilibServletConfiguration and defines all parameters and their default values.
      */
-    protected void initParams() {
+    public DigilibServletConfiguration() {
+        super();
+
         /*
          * Definition of parameters and default values. System parameters that
          * are not read from config file have a type 's'.
@@ -83,18 +95,8 @@
         newParameter("servlet.config.file", null, null, 's');
         // DocuDirCache instance
         newParameter("servlet.dir.cache", null, null, 's');
-        // DocuImage class instance
-        newParameter("servlet.docuimage.class", digilib.image.ImageLoaderDocuImage.class, null, 's');
-        // DocuImage version
-        newParameter("servlet.docuimage.version", "?", null, 's');
-        // AuthOps instance for authentication
-        newParameter("servlet.auth.op", null, null, 's');
         // Executor for image operations
         newParameter("servlet.worker.imageexecutor", null, null, 's');
-        // Executor for PDF operations
-        newParameter("servlet.worker.pdfexecutor", null, null, 's');
-        // Executor for PDF-image operations
-        newParameter("servlet.worker.pdfimageexecutor", null, null, 's');
 
         /*
          * parameters that can be read from config file have a type 'f'
@@ -113,73 +115,34 @@
         newParameter("use-authorization", Boolean.FALSE, null, 'f');
         // authentication configuration file
         newParameter("auth-file", new File("digilib-auth.xml"), null, 'f');
-        // sending image files as-is allowed
-        newParameter("sendfile-allowed", Boolean.TRUE, null, 'f');
-        // Type of DocuImage instance
-        newParameter("docuimage-class", "digilib.image.ImageLoaderDocuImage", null, 'f');
         // part of URL used to indicate authorized access
         newParameter("auth-url-path", "authenticated/", null, 'f');
-        // degree of subsampling on image load
-        newParameter("subsample-minimum", new Float(2f), null, 'f');
-        // default scaling quality
-        newParameter("default-quality", new Integer(2), null, 'f');
         // use mapping file to translate paths
         newParameter("use-mapping", Boolean.FALSE, null, 'f');
         // mapping file location
         newParameter("mapping-file", new File("digilib-map.xml"), null, 'f');
         // log4j config file location
         newParameter("log-config-file", new File("log4j-config.xml"), null, 'f');
-        // maximum destination image size (0 means no limit)
-        newParameter("max-image-size", new Integer(0), null, 'f');
         // number of working threads
-        newParameter("worker-threads", new Integer(1), null, 'f');
+        newParameter("worker-threads", new Integer(2), null, 'f');
         // max number of waiting threads
         newParameter("max-waiting-threads", new Integer(20), null, 'f');
-        // timeout for worker threads (ms)
-        newParameter("worker-timeout", new Integer(60000), null, 'f');
-        // allow image toolkit to use disk cache
-        newParameter("img-diskcache-allowed", Boolean.TRUE, null, 'f');
-        // default type of error message (image, text, code)
-        newParameter("default-errmsg-type", "image", null, 'f');
         // FileMeta implementation
         newParameter("filemeta-class", "digilib.meta.IndexMetaFileMeta", null, 'f');
         // DirMeta implementation
         newParameter("dirmeta-class", "digilib.meta.IndexMetaDirMeta", null, 'f');
         // AuthOps implementation
         newParameter("authops-class", "digilib.auth.PathServletAuthOps", null, 'f');
-        
-        // TODO: move pdf-stuff to its own config
-        // number of pdf-generation threads
-        newParameter("pdf-worker-threads", new Integer(1), null, 'f');
-        // max number of waiting pdf-generation threads
-        newParameter("pdf-max-waiting-threads", new Integer(20), null, 'f');
-        // number of pdf-image generation threads
-        newParameter("pdf-image-worker-threads", new Integer(1), null, 'f');
-        // max number of waiting pdf-image generation threads
-        newParameter("pdf-image-max-waiting-threads", new Integer(10), null, 'f');
-        // PDF generation temp directory
-        newParameter("pdf-temp-dir", "pdf_temp", null, 'f');
-        // PDF generation cache directory
-        newParameter("pdf-cache-dir", "pdf_cache", null, 'f');
-    }
 
-    /**
-     * Constructor taking a ServletConfig. Reads the config file location from
-     * an init parameter and loads the config file. Calls
-     * <code>readConfig()</code>.
-     * 
-     * @see readConfig()
-     */
-    public DigilibServletConfiguration(ServletContext c) throws Exception {
-        readConfig(c);
     }
 
     /**
      * read parameter list from the XML file in init parameter "config-file" or
      * file digilib-config.xml
+     * @throws IOException 
+     * @throws SAXException 
      */
-    @SuppressWarnings("unchecked")
-    public void readConfig(ServletContext c) throws Exception {
+    public void readConfig(ServletContext c) throws SAXException, IOException  {
 
         /*
          * Get config file name. The file name is first looked for as an init
@@ -249,21 +212,126 @@
                 dirs[j] = ServletOps.getFile(dirs[j], c);
             }
         }
-        // initialise static DocuImage class instance
-        DigilibServletConfiguration.docuImageClass = (Class<DocuImageImpl>) Class.forName(getAsString("docuimage-class"));
-        setValue("servlet.docuimage.class", DigilibServletConfiguration.docuImageClass);
-        setValue("servlet.docuimage.version", getDocuImageInstance().getVersion());
-        // initialise MetaFactory
-        Class<FileMeta> fileMetaClass = (Class<FileMeta>) Class.forName(getAsString("filemeta-class"));
-        newParameter("servlet.filemeta.class", fileMetaClass, null, 's');
-        MetaFactory.setFileMetaClass(fileMetaClass);
-        Class<DirMeta> dirMetaClass = (Class<DirMeta>) Class.forName(getAsString("dirmeta-class"));
-        newParameter("servlet.dirmeta.class", dirMetaClass, null, 's');
-        MetaFactory.setDirMetaClass(dirMetaClass);
-        // initialise AuthOpsFactory
-        Class<AuthOps> authOpsClass = (Class<AuthOps>) Class.forName(getAsString("authops-class"));
-        newParameter("servlet.authops.class", authOpsClass, null, 's');
-        AuthOpsFactory.setAuthOpsClass(authOpsClass);
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see digilib.conf.DigilibConfiguration#configure()
+     */
+    @SuppressWarnings("unchecked")
+    public void configure(ServletContext context) {
+        super.configure();
+        /*
+         * configure factories
+         */
+        try {
+            // initialise MetaFactory
+            Class<FileMeta> fileMetaClass = (Class<FileMeta>) Class.forName(getAsString("filemeta-class"));
+            newParameter("servlet.filemeta.class", fileMetaClass, null, 's');
+            MetaFactory.setFileMetaClass(fileMetaClass);
+            Class<DirMeta> dirMetaClass = (Class<DirMeta>) Class.forName(getAsString("dirmeta-class"));
+            newParameter("servlet.dirmeta.class", dirMetaClass, null, 's');
+            MetaFactory.setDirMetaClass(dirMetaClass);
+        } catch (ClassNotFoundException e) {
+            logger.error("Error setting Metadata classes!");
+        }
+        try {
+            // initialise AuthOpsFactory
+            Class<AuthOps> authOpsClass = (Class<AuthOps>) Class.forName(getAsString("authops-class"));
+            newParameter("servlet.authops.class", authOpsClass, null, 's');
+            AuthOpsFactory.setAuthOpsClass(authOpsClass);
+        } catch (ClassNotFoundException e) {
+            logger.error("Error setting AuthOps class!");
+        }
+        /*
+         * configure singletons
+         */
+        // set up the logger
+        File logConf = ServletOps.getConfigFile((File) this.getValue("log-config-file"), context);
+        if (logConf.canRead()) {
+            DOMConfigurator.configure(logConf.getAbsolutePath());
+            this.setValue("log-config-file", logConf);
+        }
+        // say hello in the log file
+        logger.info("***** Digital Image Library Configuration (version " + getVersion() + ") *****");
+        try {
+            // directory cache
+            String[] bd = (String[]) this.getValue("basedir-list");
+            FileClass[] fcs = { FileClass.IMAGE, FileClass.TEXT };
+            DocuDirCache dirCache;
+            if (this.getAsBoolean("use-mapping")) {
+                // with mapping file
+                File mapConf = ServletOps.getConfigFile((File) this.getValue("mapping-file"), context);
+                dirCache = new AliasingDocuDirCache(bd, fcs, mapConf, this);
+                this.setValue("mapping-file", mapConf);
+            } else {
+                // without mapping
+                dirCache = new DocuDirCache(bd, fcs, this);
+            }
+            this.setValue("servlet.dir.cache", dirCache);
+            // useAuthentication
+            if (this.getAsBoolean("use-authorization")) {
+                AuthOps authOp = AuthOpsFactory.getAuthOpsInstance();
+                // get config file
+                File authConf = ServletOps.getConfigFile((File) this.getValue("auth-file"), context);
+                if (authConf != null) {
+                    authOp.setConfig(authConf);
+                }
+                this.setValue("servlet.auth.op", authOp);
+                this.setValue("auth-file", authConf);
+            }
+            // digilib worker threads
+            int nt = this.getAsInt("worker-threads");
+            int mt = this.getAsInt("max-waiting-threads");
+            imageExecutor = new DigilibJobCenter<DocuImage>(nt, mt, false, "servlet.worker.imageexecutor");
+            this.setValue("servlet.worker.imageexecutor", imageExecutor);
+            /*
+             * set as the servlets main config
+             */
+            context.setAttribute("digilib.servlet.configuration", this);
+        } catch (Exception e) {
+            logger.error("Error configuring digilib servlet:", e);
+        }
+    }
+
+    /**
+     * Initialisation on first run.
+     */
+    public void contextInitialized(ServletContextEvent cte) {
+        ServletContext context = cte.getServletContext();
+        context.log("***** Digital Image Library Configuration (version " + getVersion() + ") *****");
+
+        // see if there is a Configuration instance
+        DigilibServletConfiguration dlConfig = (DigilibServletConfiguration) context.getAttribute("digilib.servlet.configuration");
+        if (dlConfig == null) {
+            try {
+                readConfig(context);
+                configure(context);
+            } catch (Exception e) {
+                logger.error("Error reading digilib servlet configuration:", e);
+            }
+        } else {
+            // say hello in the log file
+            logger.warn("DigilibServletConfiguration already configured!");
+        }
+    }
+
+    /**
+     * clean up local resources
+     * 
+     */
+    public void contextDestroyed(ServletContextEvent arg0) {
+        logger.info("DigilibServletConfiguration shutting down.");
+        if (imageExecutor != null) {
+            // shut down image thread pool
+            List<Runnable> rj = imageExecutor.shutdownNow();
+            int nrj = rj.size();
+            if (nrj > 0) {
+                logger.error("Still running threads when shutting down image job queue: " + nrj);
+            }
+        }
     }
 
 }
--- a/servlet2/src/main/java/digilib/servlet/Initialiser.java	Thu Apr 04 12:43:43 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * 
- * Initialiser.java -- initalisation servlet for setup tasks
- * 
- * Digital Image Library servlet components
- * 
- * %%
- * Copyright (C) 2004 - 2013 MPIWG Berlin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Lesser Public License for more details.
- * 
- * You should have received a copy of the GNU General Lesser Public 
- * License along with this program.  If not, see
- * <http://www.gnu.org/licenses/lgpl-3.0.html>.
- * #L%
- * Author: Robert Casties (robcast@berlios.de)
- * 
- * Created on 18.10.2004
- */
-
-import java.io.File;
-import java.io.OutputStream;
-import java.util.List;
-
-import javax.imageio.ImageIO;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.xml.DOMConfigurator;
-
-import digilib.auth.AuthOps;
-import digilib.auth.AuthOpsFactory;
-import digilib.conf.DigilibServletConfiguration;
-import digilib.image.DocuImage;
-import digilib.io.AliasingDocuDirCache;
-import digilib.io.DocuDirCache;
-import digilib.io.FileOps.FileClass;
-import digilib.util.DigilibJobCenter;
-
-/**
- * Singleton initalisation listener for setup tasks and resources.
- * 
- * @author casties
- * 
- */
-public class Initialiser implements ServletContextListener {
-
-    /** servlet version */
-    public static final String version = "0.3";
-
-    /** general logger for this class */
-    private static Logger logger = Logger.getLogger("digilib.init");
-
-    /** DocuDirCache instance */
-    DocuDirCache dirCache;
-
-    /** DigilibConfiguration instance */
-    DigilibServletConfiguration dlConfig;
-
-    /**
-     * Executor for digilib image jobs (AsyncServletWorker doesn't return
-     * anything)
-     */
-    DigilibJobCenter<DocuImage> imageEx;
-
-    /** Executor for PDF jobs */
-    DigilibJobCenter<OutputStream> pdfEx;
-
-    /** Executor for PDF image jobs */
-    DigilibJobCenter<DocuImage> pdfImageEx;
-
-    /**
-     * Initialisation on first run.
-     */
-    public void contextInitialized(ServletContextEvent cte) {
-        ServletContext context = cte.getServletContext();
-        context.log("***** Digital Image Library Initialiser (version " + version + ") *****");
-        System.out.println("***** Digital Image Library Initialiser (version " + version + ") *****");
-
-        // see if there is a Configuration instance
-        dlConfig = (DigilibServletConfiguration) context.getAttribute("digilib.servlet.configuration");
-        if (dlConfig == null) {
-            // create new Configuration
-            try {
-                dlConfig = new DigilibServletConfiguration(context);
-                // add servlet version
-                dlConfig.newParameter("servlet.version", Scaler.getVersion(), null, 's');
-
-                /*
-                 * further initialization
-                 */
-
-                // set up the logger
-                File logConf = ServletOps.getConfigFile((File) dlConfig.getValue("log-config-file"), context);
-                DOMConfigurator.configure(logConf.getAbsolutePath());
-                dlConfig.setValue("log-config-file", logConf);
-                // say hello in the log file
-                logger.info("***** Digital Image Library Initialiser (version " + version + ") *****");
-                // directory cache
-                String[] bd = (String[]) dlConfig.getValue("basedir-list");
-                FileClass[] fcs = { FileClass.IMAGE, FileClass.TEXT };
-                if (dlConfig.getAsBoolean("use-mapping")) {
-                    // with mapping file
-                    File mapConf = ServletOps.getConfigFile((File) dlConfig.getValue("mapping-file"), context);
-                    dirCache = new AliasingDocuDirCache(bd, fcs, mapConf, dlConfig);
-                    dlConfig.setValue("mapping-file", mapConf);
-                } else {
-                    // without mapping
-                    dirCache = new DocuDirCache(bd, fcs, dlConfig);
-                }
-                dlConfig.setValue("servlet.dir.cache", dirCache);
-                // useAuthentication
-                if (dlConfig.getAsBoolean("use-authorization")) {
-                    AuthOps authOp = AuthOpsFactory.getAuthOpsInstance();
-                    // get config file
-                    File authConf = ServletOps.getConfigFile((File) dlConfig.getValue("auth-file"), context);
-                    if (authConf != null) {
-                        authOp.setConfig(authConf);
-                    }
-                    dlConfig.setValue("servlet.auth.op", authOp);
-                    dlConfig.setValue("auth-file", authConf);
-                }
-                // DocuImage class
-                DocuImage di = DigilibServletConfiguration.getDocuImageInstance();
-                dlConfig.setValue("servlet.docuimage.class", di.getClass().getName());
-                // disk cache for image toolkit
-                boolean dc = dlConfig.getAsBoolean("img-diskcache-allowed");
-                // TODO: methods for all toolkits?
-                ImageIO.setUseCache(dc);
-                // digilib worker threads
-                int nt = dlConfig.getAsInt("worker-threads");
-                int mt = dlConfig.getAsInt("max-waiting-threads");
-                imageEx = new DigilibJobCenter<DocuImage>(nt, mt, false, "servlet.worker.imageexecutor");
-                dlConfig.setValue("servlet.worker.imageexecutor", imageEx);
-                // PDF worker threads
-                int pnt = dlConfig.getAsInt("pdf-worker-threads");
-                int pmt = dlConfig.getAsInt("pdf-max-waiting-threads");
-                pdfEx = new DigilibJobCenter<OutputStream>(pnt, pmt, false, "servlet.worker.pdfexecutor");
-                dlConfig.setValue("servlet.worker.pdfexecutor", pdfEx);
-                // PDF image worker threads
-                int pint = dlConfig.getAsInt("pdf-image-worker-threads");
-                int pimt = dlConfig.getAsInt("pdf-image-max-waiting-threads");
-                pdfImageEx = new DigilibJobCenter<DocuImage>(pint, pimt, false, "servlet.worker.pdfimageexecutor");
-                dlConfig.setValue("servlet.worker.pdfimageexecutor", pdfImageEx);
-                // set as the servlets main config
-                context.setAttribute("digilib.servlet.configuration", dlConfig);
-
-            } catch (Exception e) {
-                logger.error("Error in initialisation: ", e);
-            }
-        } else {
-            // say hello in the log file
-            logger.info("***** Digital Image Library Initialiser (version " + version + ") *****");
-            logger.warn("Already initialised!");
-        }
-    }
-
-    /**
-     * clean up local resources
-     * 
-     */
-    public void contextDestroyed(ServletContextEvent arg0) {
-        logger.info("Initialiser shutting down.");
-        if (dirCache != null) {
-            // shut down dirCache?
-            dirCache = null;
-        }
-        if (imageEx != null) {
-            // shut down image thread pool
-            List<Runnable> rj = imageEx.shutdownNow();
-            int nrj = rj.size();
-            if (nrj > 0) {
-                logger.error("Still running threads when shutting down image job queue: " + nrj);
-            }
-        }
-        if (pdfEx != null) {
-            // shut down pdf thread pool
-            List<Runnable> rj = pdfEx.shutdownNow();
-            int nrj = rj.size();
-            if (nrj > 0) {
-                logger.error("Still running threads when shutting down PDF job queue: " + nrj);
-            }
-        }
-        if (pdfImageEx != null) {
-            // shut down pdf image thread pool
-            List<Runnable> rj = pdfImageEx.shutdownNow();
-            int nrj = rj.size();
-            if (nrj > 0) {
-                logger.error("Still running threads when shutting down PDF-image job queue: " + nrj);
-            }
-        }
-    }
-
-}
--- a/servlet2/src/main/java/digilib/servlet/Scaler.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/servlet2/src/main/java/digilib/servlet/Scaler.java	Thu Apr 04 18:43:13 2013 +0200
@@ -132,6 +132,8 @@
             // no Configuration
             throw new ServletException("No Configuration!");
         }
+        // add servlet version
+        dlConfig.newParameter("servlet.version", Scaler.getVersion(), null, 's');
         // log DocuImage version
         logger.info("Scaler uses " + dlConfig.getValue("servlet.docuimage.version"));
         // set our AuthOps
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet3/src/main/java/digilib/conf/DigilibServlet3Configuration.java	Thu Apr 04 18:43:13 2013 +0200
@@ -0,0 +1,41 @@
+package digilib.conf;
+
+import javax.servlet.ServletContext;
+import javax.servlet.annotation.WebListener;
+
+import digilib.servlet.AsyncServletWorker;
+
+/**
+ * @author casties
+ *
+ */
+@WebListener
+public class DigilibServlet3Configuration extends DigilibServletConfiguration {
+
+    public String getVersion() {
+        return "2.2.0 srv3";
+    }
+
+    /**
+     * Constructs DigilibServletConfiguration and defines all parameters and their default values.
+     */
+    public DigilibServlet3Configuration() {
+        super();
+        
+        // timeout for worker threads (ms)
+        newParameter("worker-timeout", new Integer(60000), null, 'f');
+    }
+
+    /* (non-Javadoc)
+     * @see digilib.conf.DigilibServletConfiguration#configure(javax.servlet.ServletContext)
+     */
+    @Override
+    public void configure(ServletContext context) {
+        super.configure(context);
+        
+        // digilib worker timeout
+        long to = getAsInt("worker-timeout");
+        AsyncServletWorker.setTimeout(to);
+    }
+
+}
--- a/servlet3/src/main/java/digilib/servlet/Initialiser.java	Thu Apr 04 12:43:43 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * Initialiser.java -- initalisation servlet for setup tasks
- * 
- * Digital Image Library servlet components
- * 
- * %%
- * Copyright (C) 2004 - 2013 MPIWG Berlin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Lesser Public License for more details.
- * 
- * You should have received a copy of the GNU General Lesser Public 
- * License along with this program.  If not, see
- * <http://www.gnu.org/licenses/lgpl-3.0.html>.
- * #L%
- * Author: Robert Casties (robcast@berlios.de)
- * Created on 18.10.2004
- */
-
-import java.io.File;
-import java.io.OutputStream;
-import java.util.List;
-
-import javax.imageio.ImageIO;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletRequestEvent;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.annotation.WebListener;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.xml.DOMConfigurator;
-
-import digilib.auth.AuthOps;
-import digilib.auth.AuthOpsFactory;
-import digilib.conf.DigilibConfiguration;
-import digilib.conf.DigilibServletConfiguration;
-import digilib.image.DocuImage;
-import digilib.io.AliasingDocuDirCache;
-import digilib.io.DocuDirCache;
-import digilib.io.FileOps.FileClass;
-import digilib.util.DigilibJobCenter;
-
-/**
- * Singleton initialisation listener for setup tasks and resources.
- * 
- * @author casties
- * 
- */
-@WebListener
-public class Initialiser implements ServletContextListener, ServletRequestListener {
-
-    /** servlet version */
-    public static final String version = "0.4";
-
-    /** gengeral logger for this class */
-    private static Logger logger = Logger.getLogger("digilib.init");
-
-    /** DocuDirCache instance */
-    DocuDirCache dirCache;
-
-    /** DigilibConfiguration instance */
-    DigilibServletConfiguration dlConfig;
-
-    /**
-     * Executor for digilib image jobs (AsyncServletWorker doesn't return
-     * anything)
-     */
-    DigilibJobCenter<DocuImage> imageEx;
-
-    /** Executor for PDF jobs */
-    DigilibJobCenter<OutputStream> pdfEx;
-
-    /** Executor for PDF image jobs */
-    DigilibJobCenter<DocuImage> pdfImageEx;
-
-    /**
-     * Initialisation on first run.
-     */
-    public void contextInitialized(ServletContextEvent cte) {
-        ServletContext context = cte.getServletContext();
-
-        System.out.println("***** Digital Image Library Initialiser (version " + version + ") *****");
-
-        // see if there is a Configuration instance
-        dlConfig = (DigilibServletConfiguration) context.getAttribute("digilib.servlet.configuration");
-        if (dlConfig == null) {
-            // create new Configuration
-            try {
-                dlConfig = new DigilibServletConfiguration(context);
-                // add servlet version
-                dlConfig.newParameter("servlet.version", Scaler.getVersion(), null, 's');
-
-                /*
-                 * further initialization
-                 */
-
-                // set up the logger
-                File logConf = ServletOps.getConfigFile((File) dlConfig.getValue("log-config-file"), context);
-                if (logConf.canRead()) {
-                    DOMConfigurator.configure(logConf.getAbsolutePath());
-                    dlConfig.setValue("log-config-file", logConf);
-                }
-                // say hello in the log file
-                logger.info("***** Digital Image Library Initialiser (version " + version + ") *****");
-                // directory cache
-                String[] bd = (String[]) dlConfig.getValue("basedir-list");
-                FileClass[] fcs = { FileClass.IMAGE, FileClass.TEXT };
-                if (dlConfig.getAsBoolean("use-mapping")) {
-                    // with mapping file
-                    File mapConf = ServletOps.getConfigFile((File) dlConfig.getValue("mapping-file"), context);
-                    dirCache = new AliasingDocuDirCache(bd, fcs, mapConf, dlConfig);
-                    dlConfig.setValue("mapping-file", mapConf);
-                } else {
-                    // without mapping
-                    dirCache = new DocuDirCache(bd, fcs, dlConfig);
-                }
-                dlConfig.setValue("servlet.dir.cache", dirCache);
-                // useAuthentication
-                if (dlConfig.getAsBoolean("use-authorization")) {
-                    AuthOps authOp = AuthOpsFactory.getAuthOpsInstance();
-                    // get config file
-                    File authConf = ServletOps.getConfigFile((File) dlConfig.getValue("auth-file"), context);
-                    if (authConf != null) {
-                        authOp.setConfig(authConf);
-                    }
-                    dlConfig.setValue("servlet.auth.op", authOp);
-                    dlConfig.setValue("auth-file", authConf);
-                }
-                // DocuImage class
-                DocuImage di = DigilibConfiguration.getDocuImageInstance();
-                dlConfig.setValue("servlet.docuimage.class", di.getClass().getName());
-                // disk cache for image toolkit
-                boolean dc = dlConfig.getAsBoolean("img-diskcache-allowed");
-                // TODO: methods for all toolkits?
-                ImageIO.setUseCache(dc);
-                // digilib worker threads
-                int nt = dlConfig.getAsInt("worker-threads");
-                int mt = dlConfig.getAsInt("max-waiting-threads");
-                imageEx = new DigilibJobCenter<DocuImage>(nt, mt, false, "servlet.worker.imageexecutor");
-                dlConfig.setValue("servlet.worker.imageexecutor", imageEx);
-                // digilib worker timeout
-                long to = dlConfig.getAsInt("worker-timeout");
-                AsyncServletWorker.setTimeout(to);
-                // PDF worker threads
-                int pnt = dlConfig.getAsInt("pdf-worker-threads");
-                int pmt = dlConfig.getAsInt("pdf-max-waiting-threads");
-                pdfEx = new DigilibJobCenter<OutputStream>(pnt, pmt, false, "servlet.worker.pdfexecutor");
-                dlConfig.setValue("servlet.worker.pdfexecutor", pdfEx);
-                // PDF image worker threads
-                int pint = dlConfig.getAsInt("pdf-image-worker-threads");
-                int pimt = dlConfig.getAsInt("pdf-image-max-waiting-threads");
-                pdfImageEx = new DigilibJobCenter<DocuImage>(pint, pimt, false, "servlet.worker.pdfimageexecutor");
-                dlConfig.setValue("servlet.worker.pdfimageexecutor", pdfImageEx);
-                // set as the servlets main config
-                context.setAttribute("digilib.servlet.configuration", dlConfig);
-
-            } catch (Exception e) {
-                logger.error("Error in initialisation: ", e);
-            }
-        } else {
-            // say hello in the log file
-            logger.info("***** Digital Image Library Initialiser (version " + version + ") *****");
-            logger.warn("Already initialised!");
-        }
-    }
-
-    /**
-     * clean up local resources
-     * 
-     */
-    public void contextDestroyed(ServletContextEvent arg0) {
-        logger.info("Initialiser shutting down.");
-        if (dirCache != null) {
-            // shut down dirCache?
-            dirCache = null;
-        }
-        if (imageEx != null) {
-            // shut down image thread pool
-            List<Runnable> rj = imageEx.shutdownNow();
-            int nrj = rj.size();
-            if (nrj > 0) {
-                logger.error("Still running threads when shutting down image job queue: " + nrj);
-            }
-        }
-        if (pdfEx != null) {
-            // shut down pdf thread pool
-            List<Runnable> rj = pdfEx.shutdownNow();
-            int nrj = rj.size();
-            if (nrj > 0) {
-                logger.error("Still running threads when shutting down PDF job queue: " + nrj);
-            }
-        }
-        if (pdfImageEx != null) {
-            // shut down pdf image thread pool
-            List<Runnable> rj = pdfImageEx.shutdownNow();
-            int nrj = rj.size();
-            if (nrj > 0) {
-                logger.error("Still running threads when shutting down PDF-image job queue: " + nrj);
-            }
-        }
-    }
-
-    @Override
-    public void requestDestroyed(ServletRequestEvent arg0) {
-        int i = dlConfig.openRequestCnt.decrementAndGet();
-        logger.debug("ServletRequest destroyed. (cnt=" + i + ")");
-    }
-
-    @Override
-    public void requestInitialized(ServletRequestEvent arg0) {
-        dlConfig.webappRequestCnt.incrementAndGet();
-        int i = dlConfig.openRequestCnt.incrementAndGet();
-        logger.debug("ServletRequest created. (cnt=" + i + ")");
-    }
-
-}
--- a/text/src/main/java/digilib/servlet/Texter.java	Thu Apr 04 12:43:43 2013 +0200
+++ b/text/src/main/java/digilib/servlet/Texter.java	Thu Apr 04 18:43:13 2013 +0200
@@ -39,6 +39,8 @@
 import org.apache.log4j.Logger;
 
 import digilib.auth.AuthOps;
+import digilib.conf.DigilibServletConfiguration;
+import digilib.conf.DigilibServletRequest;
 import digilib.image.ImageOpException;
 import digilib.io.DocuDirCache;
 import digilib.io.FileOps;
@@ -57,7 +59,7 @@
     private static final long serialVersionUID = 6678666342141409867L;
 
     /** Servlet version */
-	public static String tlVersion = "0.1b3";
+	public static String tlVersion = "2.2.0";
 
 	/** DigilibConfiguration instance */
 	DigilibServletConfiguration dlConfig = null;
--- a/webapp/src/main/webapp/WEB-INF/web-2.3.xml	Thu Apr 04 12:43:43 2013 +0200
+++ b/webapp/src/main/webapp/WEB-INF/web-2.3.xml	Thu Apr 04 18:43:13 2013 +0200
@@ -12,7 +12,7 @@
   <!-- The Intialisation Listener -->
   <listener>
         <listener-class>
-            digilib.servlet.Initialiser
+            digilib.conf.DigilibServletConfig
         </listener-class>
   </listener>
   <!-- The Scaler servlet -->
--- a/webapp/src/main/webapp/WEB-INF/web-3.0.xml	Thu Apr 04 12:43:43 2013 +0200
+++ b/webapp/src/main/webapp/WEB-INF/web-3.0.xml	Thu Apr 04 18:43:13 2013 +0200
@@ -15,7 +15,7 @@
   <!-- The Intialisation Listener (also configured by annotation) -->
   <listener>
         <listener-class>
-            digilib.servlet.Initialiser
+            digilib.conf.DigilibServlet3Configuration
         </listener-class>
   </listener>
   <!-- The Scaler servlet (also configured by annotation) -->
--- a/webapp/src/main/webapp/server/dlConfig.jsp	Thu Apr 04 12:43:43 2013 +0200
+++ b/webapp/src/main/webapp/server/dlConfig.jsp	Thu Apr 04 18:43:13 2013 +0200
@@ -25,6 +25,7 @@
           digilib.conf.DigilibServletConfiguration,
           digilib.conf.DigilibServletRequest,
           digilib.io.DocuDirCache,
+          digilib.image.DocuImageFactory,
           java.io.File"%>
 <%!
 // authentication stuff - robert
@@ -130,16 +131,7 @@
 
 <table>
   <tr>
-    <td>currently open requests</td><td><b><%= dlConfig.openRequestCnt.get() %></b></td>
-    <td>(including this)</td>
-  </tr>
-  <tr>
-    <td>total requests</td><td><b><%= dlConfig.webappRequestCnt.get() %></b></td>
-    <td></td>
-  </tr>
-  <tr>
     <td>total runtime </td><td><b><%= (System.currentTimeMillis() - dlConfig.webappStartTime)/1000 %></b></td>
-    <td>s (<%= dlConfig.webappRequestCnt.get() / (float)((System.currentTimeMillis() - dlConfig.webappStartTime)/1000) %> req/s)</td>
   </tr>
 </table>
 
@@ -202,7 +194,7 @@
 <p>Supported image types</p>
 <ul>
 <% 
-  java.util.Iterator dlfs = dlConfig.getDocuImageInstance().getSupportedFormats();
+  java.util.Iterator dlfs = DocuImageFactory.getInstance().getSupportedFormats();
   for (Object f = dlfs.next(); dlfs.hasNext(); f = dlfs.next()) {
 %>
   <li><%= (String)f %></li>