changeset 1169:888cdaf022fe

shuffling classes around: moved last servlet dependencies from common to new servlet module. moved common code from servlet2 and servlet3 to servlet. moved DigilibConfiguration and DigilibRequest to digilib.conf package (needs changes in JSPs).
author robcast
date Wed, 27 Mar 2013 17:23:44 +0100
parents 6c5eb1896cc0
children cf8ecc67200e
files .hgignore common/pom.xml common/src/main/java/digilib/auth/AuthOps.java common/src/main/java/digilib/auth/AuthOpsImpl.java common/src/main/java/digilib/auth/XMLAuthOps.java common/src/main/java/digilib/conf/DigilibConfiguration.java common/src/main/java/digilib/conf/DigilibRequest.java common/src/main/java/digilib/image/ImageJobDescription.java common/src/main/java/digilib/image/ImageWorker.java common/src/main/java/digilib/io/AliasingDocuDirCache.java common/src/main/java/digilib/io/DocuDirCache.java common/src/main/java/digilib/io/ImageFile.java common/src/main/java/digilib/servlet/DigilibConfiguration.java common/src/main/java/digilib/servlet/DigilibRequest.java pom.xml servlet/pom.xml servlet/src/main/java/digilib/auth/ServletAuthOps.java servlet/src/main/java/digilib/auth/XMLAuthOps.java servlet/src/main/java/digilib/conf/DigilibServletConfiguration.java servlet/src/main/java/digilib/conf/DigilibServletRequest.java servlet/src/main/java/digilib/servlet/DocumentBean.java servlet/src/main/java/digilib/servlet/ServletOps.java servlet2/pom.xml servlet2/src/main/java/digilib/servlet/DigilibServletConfiguration.java servlet2/src/main/java/digilib/servlet/DigilibServletRequest.java servlet2/src/main/java/digilib/servlet/DocumentBean.java servlet2/src/main/java/digilib/servlet/Initialiser.java servlet2/src/main/java/digilib/servlet/Scaler.java servlet2/src/main/java/digilib/servlet/ScalerNoThread.java servlet2/src/main/java/digilib/servlet/ServletOps.java servlet3/pom.xml servlet3/src/main/java/digilib/servlet/AsyncServletWorker.java servlet3/src/main/java/digilib/servlet/DigilibServletConfiguration.java servlet3/src/main/java/digilib/servlet/DigilibServletRequest.java servlet3/src/main/java/digilib/servlet/DocumentBean.java servlet3/src/main/java/digilib/servlet/Initialiser.java servlet3/src/main/java/digilib/servlet/Scaler.java servlet3/src/main/java/digilib/servlet/ServletOps.java webapp/src/main/webapp/ImgInfo-json.jsp webapp/src/main/webapp/WEB-INF/web-additional.xml webapp/src/main/webapp/api/ImgInfo-json.jsp webapp/src/main/webapp/api/dirInfo-xml.jsp webapp/src/main/webapp/api/dlContext-xml.jsp webapp/src/main/webapp/api/dlInfo-json.jsp webapp/src/main/webapp/api/dlInfo-xml.jsp webapp/src/main/webapp/dirInfo-xml.jsp webapp/src/main/webapp/dlContext-xml.jsp webapp/src/main/webapp/dlInfo-json.jsp webapp/src/main/webapp/dlInfo-xml.jsp webapp/src/main/webapp/greyskin/diginew.jsp webapp/src/main/webapp/oldskin/dcMain.jsp webapp/src/main/webapp/oldskin/digicat.jsp webapp/src/main/webapp/oldskin/digilib.jsp webapp/src/main/webapp/oldskin/digimage.jsp webapp/src/main/webapp/oldskin/digimage_img_inc.jsp webapp/src/main/webapp/oldskin/digimage_tbl_inc.jsp webapp/src/main/webapp/server/dlConfig.jsp webapp/src/main/webapp/server/dlRequest.jsp
diffstat 58 files changed, 2452 insertions(+), 3901 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Mar 27 13:02:27 2013 +0100
+++ b/.hgignore	Wed Mar 27 17:23:44 2013 +0100
@@ -103,4 +103,12 @@
 syntax: regexp
 ^target$
 syntax: regexp
-^webapp/bin$
\ No newline at end of file
+^webapp/bin$
+syntax: regexp
+^servlet/target$
+syntax: regexp
+^servlet/\.settings$
+syntax: regexp
+^servlet/\.classpath$
+syntax: regexp
+^servlet/\.project$
\ No newline at end of file
--- a/common/pom.xml	Wed Mar 27 13:02:27 2013 +0100
+++ b/common/pom.xml	Wed Mar 27 17:23:44 2013 +0100
@@ -54,12 +54,5 @@
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>
-    <dependency>
-    	<groupId>javax.servlet</groupId>
-    	<artifactId>servlet-api</artifactId>
-    	<version>2.3</version>
-    	<type>jar</type>
-    	<scope>provided</scope>
-    </dependency>
   </dependencies>
 </project>
--- a/common/src/main/java/digilib/auth/AuthOps.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/common/src/main/java/digilib/auth/AuthOps.java	Wed Mar 27 17:23:44 2013 +0100
@@ -28,26 +28,13 @@
 
 import java.util.List;
 
-import javax.servlet.http.HttpServletRequest;
-
-import digilib.servlet.DigilibRequest;
+import digilib.conf.DigilibRequest;
 
 /** Class of operations requiring authentication. */
 public interface AuthOps {
 
 	/** Test if the request must be authorized to access the filepath.
 	 *
-	 * Information about the user is taken from the ServletRequest.
-	 * @param filepath filepath to be accessed.
-	 * @param request ServletRequest with user information.
-	 * @throws AuthOpException Exception thrown on error.
-	 * @return true if the user request must be authorized.
-	 */
-	public boolean isAuthRequired(String filepath, HttpServletRequest request)
-		throws AuthOpException;
-
-	/** Test if the request must be authorized to access the filepath.
-	 *
 	 * Information about the user is taken from the DigilibRequest.
 	 * @param request DigilibRequest with user information.
 	 * @throws AuthOpException Exception thrown on error.
@@ -58,16 +45,6 @@
 
 	/** Test if the request is allowed to access filepath.
 	 * 
-	 * @param filepath filepath to be acessed.
-	 * @param request Request with user information.
-	 * @throws AuthOpException Exception thrown on error.
-	 * @return true if the request is allowed.
-	 */
-	public boolean isAuthorized(String filepath, HttpServletRequest request)
-		throws AuthOpException;
-
-	/** Test if the request is allowed to access filepath.
-	 * 
 	 * @param request Request with user information.
 	 * @throws AuthOpException Exception thrown on error.
 	 * @return true if the request is allowed.
@@ -82,21 +59,6 @@
 	 *
 	 * The location information of the request is also considered.
 	 *
-	 * @param filepath filepath to be accessed.
-	 * @param request ServletRequest with address information.
-	 * @throws AuthOpException Exception thrown on error.
-	 * @return List of Strings with role names.
-	 */
-	public List<String> rolesForPath(String filepath, HttpServletRequest request)
-		throws AuthOpException;
-
-	/** Authorization roles needed for request.
-	 *
-	 * Returns the list of authorization roles that are needed to access the
-	 * specified path. No list means the path is free.
-	 *
-	 * The location information of the request is also considered.
-	 *
 	 * @param request DigilibRequest with address information.
 	 * @throws AuthOpException Exception thrown on error.
 	 * @return List of Strings with role names.
@@ -109,13 +71,6 @@
 	 * @param request ServletRequest with address information.
 	 * @return true if the user information in the request authorizes one of the roles.
 	 */
-	public boolean isRoleAuthorized(List<String> roles, HttpServletRequest request);
-
-	/** Test request authorization against a list of roles.
-	 * @param roles List of Strings with role names.
-	 * @param request ServletRequest with address information.
-	 * @return true if the user information in the request authorizes one of the roles.
-	 */
 	public boolean isRoleAuthorized(List<String> roles, DigilibRequest request);
 
 }
--- a/common/src/main/java/digilib/auth/AuthOpsImpl.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-package digilib.auth;
-
-/*
- * #%L
- *  AuthOps -- Authentication class implementation
- *
- *  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)
- */
-
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.log4j.Logger;
-
-import digilib.servlet.DigilibRequest;
-
-/**
- * Basic implementation of AuthOps interface.
- * 
- * Provides basic implementations. Only rolesForPath needs to be implemented by
- * specific implementations.
- */
-public abstract class AuthOpsImpl implements AuthOps {
-
-    /** general logger for this class */
-    protected Logger logger = Logger.getLogger(this.getClass());
-
-    /** Default constructor. */
-    public AuthOpsImpl() {
-        try {
-            init();
-        } catch (AuthOpException e) {
-        }
-    }
-
-    /**
-     * Test if the request is allowed to access filepath.
-     * 
-     * @param filepath
-     *            filepath to be acessed.
-     * @param request
-     *            Request with user information.
-     * @throws AuthOpException
-     *             Exception thrown on error.
-     * @return true if the request is allowed.
-     */
-    public boolean isAuthRequired(String filepath, HttpServletRequest request) throws AuthOpException {
-        // check permissions
-        List<String> rolesRequired = rolesForPath(filepath, request);
-        return (rolesRequired != null);
-    }
-
-    /**
-     * @see digilib.auth.AuthOps#isAuthRequired(digilib.servlet.DigilibRequest)
-     */
-    public boolean isAuthRequired(DigilibRequest request) throws AuthOpException {
-        // check permissions
-        List<String> rolesRequired = rolesForPath(request);
-        return (rolesRequired != null);
-    }
-
-    /**
-     * Return authorization roles needed for request.
-     * 
-     * Returns a list of authorization roles that would be allowed to access the
-     * specified path. The location information of the request is considered
-     * also.
-     * 
-     * @param filepath
-     *            filepath to be accessed.
-     * @param request
-     *            ServletRequest with address information.
-     * @throws AuthOpException
-     *             Exception thrown on error.
-     * @return List of Strings with role names.
-     */
-    public boolean isAuthorized(String filepath, HttpServletRequest request) throws AuthOpException {
-        List<String> rolesAllowed = rolesForPath(filepath, request);
-        return isRoleAuthorized(rolesAllowed, request);
-    }
-
-    /**
-     * @see digilib.auth.AuthOps#isAuthorized(digilib.servlet.DigilibRequest)
-     */
-    public boolean isAuthorized(DigilibRequest request) throws AuthOpException {
-        List<String> rolesAllowed = rolesForPath(request);
-        return isRoleAuthorized(rolesAllowed, request);
-    }
-
-    /**
-     * Test request authorization against a list of roles.
-     * 
-     * @param roles
-     *            List of Strings with role names.
-     * @param request
-     *            ServletRequest with address information.
-     * @return true if the user information in the request authorizes one of the
-     *         roles.
-     */
-    public boolean isRoleAuthorized(List<String> roles, HttpServletRequest request) {
-        for (String s : roles) {
-            logger.debug("Testing role: " + s);
-            if (request.isUserInRole(s)) {
-                logger.debug("Role Authorized");
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @see digilib.auth.AuthOps#isRoleAuthorized(java.util.List,
-     *      digilib.servlet.DigilibRequest)
-     */
-    public boolean isRoleAuthorized(List<String> roles, DigilibRequest request) {
-        for (String s : roles) {
-            logger.debug("Testing role: " + s);
-            if (request.getServletRequest().isUserInRole(s)) {
-                logger.debug("Role Authorized");
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public abstract void init() throws AuthOpException;
-
-    public abstract List<String> rolesForPath(String filepath, HttpServletRequest request) throws AuthOpException;
-
-    /**
-     * @see digilib.auth.AuthOps#rolesForPath(digilib.servlet.DigilibRequest)
-     */
-    public List<String> rolesForPath(DigilibRequest request) throws AuthOpException {
-        return rolesForPath(request.getFilePath(), request.getServletRequest());
-    }
-
-}
--- a/common/src/main/java/digilib/auth/XMLAuthOps.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-package digilib.auth;
-
-/*
- * #%L
- * XMLAuthOps -- Authentication class implementation using XML files
- * 
- * 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)
- */
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
-import digilib.util.HashTree;
-import digilib.util.XMLListLoader;
-
-/** Implementation of AuthOps using XML files.
- *
- * The configuration file is read by an XMLListLoader into HashTree objects for 
- * authentication paths and IP numbers.
- */
-public class XMLAuthOps extends AuthOpsImpl {
-
-	private File configFile;
-	private HashTree authPaths;
-	private HashTree authIPs;
-
-	/** Constructor taking an XML config file.
-	 *
-	 * @param u utils object
-	 * @param confFile Configuration file.
-	 * @throws AuthOpException Exception thrown on error.
-	 */
-	public XMLAuthOps(File confFile) throws AuthOpException {
-		configFile = confFile;
-		init();
-	}
-
-	/** Set configuration file.
-	 *
-	 * @param confFile XML config file.
-	 * @throws AuthOpException Exception thrown on error.
-	 */
-	public void setConfig(File confFile) throws AuthOpException {
-		configFile = confFile;
-		init();
-	}
-
-	/** Initialize.
-	 *
-	 * Read configuration files and setup authentication arrays.
-	 *
-	 * @throws AuthOpException Exception thrown on error.
-	 */
-	public void init() throws AuthOpException {
-		logger.debug("xmlauthops.init (" + configFile + ")");
-		Map<String, String> pathList = null;
-		Map<String, String> ipList = null;
-		try {
-			// load authPaths
-			XMLListLoader pathLoader =
-				new XMLListLoader("digilib-paths", "path", "name", "role");
-			pathList = pathLoader.loadUri(configFile.toURI());
-			// load authIPs
-			XMLListLoader ipLoader =
-				new XMLListLoader("digilib-addresses", "address", "ip", "role");
-			ipList = ipLoader.loadUri(configFile.toURI());
-		} catch (Exception e) {
-			throw new AuthOpException(
-				"ERROR loading authorization config file: " + e);
-		}
-		if ((pathList == null) || (ipList == null)) {
-			throw new AuthOpException("ERROR unable to load authorization config file!");
-		}
-		// setup path tree
-		authPaths = new HashTree(pathList, "/", ",");
-		// setup ip tree
-		authIPs = new HashTree(ipList, ".", ",");
-	}
-
-	/** Return authorization roles needed for request.
-	 *
-	 * Returns the list of authorization roles that are needed to access the
-	 * specified path. No list means the path is free.
-	 *
-	 * The location information of the request is also considered.
-	 *
-	 * @param filepath filepath to be accessed.
-	 * @param request ServletRequest with address information.
-	 * @throws AuthOpException Exception thrown on error.
-	 * @return List of Strings with role names.
-	 */
-	public List<String> rolesForPath(String filepath, HttpServletRequest request)
-		throws digilib.auth.AuthOpException {
-		logger.debug("rolesForPath ("
-				+ filepath
-				+ ") by ["
-				+ request.getRemoteAddr()
-				+ "]");
-
-		// check if the requests address provides a role
-		List<String> provided = authIPs.match(request.getRemoteAddr());
-		if ((provided != null) && (provided.contains("ALL"))) {
-			// ALL switches off checking;
-			return null;
-		}
-		// which roles are required?
-		List<String> required = authPaths.match(filepath);
-		// do any provided roles match?
-		if ((provided != null) && (required != null)) {
-			for (int i = 0; i < provided.size(); i++) {
-				if (required.contains(provided.get(i))) {
-					// satisfied
-					return null;
-				}
-			}
-		}
-		return required;
-	}
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/digilib/conf/DigilibConfiguration.java	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,153 @@
+package digilib.conf;
+
+/*
+ * #%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)
+ */
+
+import java.io.IOException;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Logger;
+
+import digilib.image.DocuImage;
+import digilib.image.DocuImageImpl;
+import digilib.io.ImageInput;
+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>
+ * 
+ * @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");
+
+    /**
+     * 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 servlet version
+        newParameter("digilib.version", "2.0b1", null, 's');
+        // DocuImage class instance
+        newParameter("servlet.docuimage.class",
+                digilib.image.ImageLoaderDocuImage.class, null, 's');
+        // 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');
+        // 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');
+        // maximum destination image size (0 means no limit)
+        newParameter("max-image-size", new Integer(0), 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');
+
+        // 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
+     * 
+     * @param imgf
+     * @return
+     * @throws IOException
+     */
+    public static ImageInput identifyDocuImage(ImageInput imgf)
+            throws IOException {
+        // use fresh DocuImage instance
+        DocuImage di = getDocuImageInstance();
+        return di.identify(imgf);
+    }
+
+    /**
+     * @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/conf/DigilibRequest.java	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,308 @@
+package digilib.conf;
+
+/*
+ * #%L
+ * DigilibRequest.java
+ *
+ * lightweight class carrying all parameters for a request to digilib
+ * %%
+ * Copyright (C) 2002 - 2013 MPIWG Berlin, WTWG Uni Bern
+ *                           
+ * %%
+ * 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: Robert Casties (robcast@berlios.de),
+ *          Christian Luginbuehl
+ *          
+ * Created on 27. August 2002
+ */
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.StringTokenizer;
+
+import digilib.image.DocuImage;
+import digilib.io.FileOps;
+import digilib.util.OptionsSet;
+import digilib.util.Parameter;
+import digilib.util.ParameterMap;
+
+/**
+ * Class holding the parameters of a digilib user request. The parameters are
+ * mostly named like the servlet parameters: <br>
+ * request_path: url of the page/document. <br>
+ * fn: url of the page/document. <br>
+ * pn: page number. <br>
+ * dw: width of result window in pixels. <br>
+ * dh: height of result window in pixels. <br>
+ * wx: left edge of image area (float from 0 to 1). <br>
+ * wy: top edge of image area (float from 0 to 1). <br>
+ * ww: width of image area(float from 0 to 1). <br>
+ * wh: height of image area(float from 0 to 1). <br>
+ * ws: scale factor. <br>
+ * mo: special options like 'fit' for gifs. <br>
+ * mk: list of marks. <br>
+ * pt: total number of pages (generated by sevlet). <br>
+ * baseURL: base URL (from http:// to below /servlet). <br>
+ * ...et alii
+ * 
+ * @author casties
+ * 
+ */
+public class DigilibRequest extends ParameterMap {
+
+	protected DocuImage image; // internal DocuImage instance for this request
+
+	public DigilibRequest() {
+		super(30);
+	}
+
+	/** set up parameters.
+	 * 
+	 */
+	protected void initParams() {
+		/*
+		 * Definition of parameters and default values. Parameter of type 's'
+		 * are for the servlet.
+		 */
+
+		// url of the page/document (second part)
+		newParameter("fn", "", null, 's');
+		// page number
+		newParameter("pn", new Integer(1), 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", this.options, 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');
+		// color conversion operation
+		newParameter("colop", "", 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
+		newParameter("docu.image", image, null, 'i');
+		image = null;
+		/*
+		 * 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');
+	}
+
+    /* (non-Javadoc)
+     * @see digilib.servlet.ParameterMap#initOptions()
+     */
+    @Override
+    protected void initOptions() {
+        options = (OptionsSet) getValue("mo");
+    }
+
+	/**
+	 * Return the request parameters as a String in the parameter form
+	 * 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not included.
+	 * 
+	 * @return String of request parameters in parameter form.
+	 */
+	public String getAsString() {
+		return getAsString(0);
+	}
+
+	/**
+	 * Return the request parameters of a given type type as a String in the
+	 * parameter form 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not
+	 * included.
+	 * 
+	 * @return String of request parameters in parameter form.
+	 */
+	public String getAsString(int type) {
+		StringBuffer s = new StringBuffer(50);
+		// go through all values
+		for (Parameter p: params.values()) {
+			if ((type > 0) && (p.getType() != type)) {
+				// skip the wrong types
+				continue;
+			}
+			String name = p.getName();
+			/*
+			 * handling special cases
+			 */
+			// request_path adds to fn
+			if (name.equals("fn")) {
+				s.append("&fn=" + getAsString("request.path")
+						+ getAsString("fn"));
+				continue;
+			}
+			/*
+			 * the rest is sent with its name
+			 */
+			// parameters that are not set or internal are not sent
+			if ((!p.hasValue()) || (p.getType() == 'i')) {
+				continue;
+			}
+			s.append("&" + name + "=" + p.getAsString());
+		}
+		// kill first "&"
+		s.deleteCharAt(0);
+		return s.toString();
+	}
+
+	/**
+	 * Set request parameters from query string. Uses the separator string qs to
+	 * get 'fn=foo' style parameters.
+	 * 
+	 * @param qs
+	 *            query string
+	 * @param sep
+	 *            parameter-separator string
+	 */
+	public void setWithParamString(String qs, String sep) {
+		// go through all request parameters
+		String[] qa = qs.split(sep);
+		for (int i = 0; i < qa.length; i++) {
+			// split names and values on "="
+			String[] nv = qa[i].split("=");
+			try {
+				String name = URLDecoder.decode(nv[0], "UTF-8");
+				String val = URLDecoder.decode(nv[1], "UTF-8");
+				// is this a known parameter?
+				if (params.containsKey(name)) {
+					Parameter p = (Parameter) this.get(name);
+					// internal parameters are not set
+					if (p.getType() == 'i') {
+						continue;
+					}
+					p.setValueFromString(val);
+					continue;
+				}
+				// unknown parameters are just added with type 'r'
+				newParameter(name, null, val, 'r');
+			} catch (UnsupportedEncodingException e) {
+				// this shouldn't happen anyway
+				e.printStackTrace();
+			}
+		}
+	}
+
+	/**
+	 * Test if option string <code>opt</code> is set. Checks if the substring
+	 * <code>opt</code> is contained in the options string <code>param</code>.
+	 * Deprecated! use hasOption(String opt) for "mo"-options.
+	 * 
+	 * @param opt
+	 *            Option string to be tested.
+	 * @return boolean
+	 */
+	public boolean hasOption(String param, String opt) {
+		String s = getAsString(param);
+		if (s != null) {
+			StringTokenizer i = new StringTokenizer(s, ",");
+			while (i.hasMoreTokens()) {
+				if (i.nextToken().equals(opt)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * The image file path to be accessed.
+	 * 
+	 * The mage file path is assembled from the servlets RequestPath and
+	 * Parameter fn and normalized.
+	 * 
+	 * @return String the effective filepath.
+	 */
+	public String getFilePath() {
+		String s = getAsString("request.path");
+		s += getAsString("fn");
+		return FileOps.normalName(s);
+	}
+
+	/**
+	 * Returns the image.
+	 * 
+	 * @return DocuImage
+	 */
+	public DocuImage getImage() {
+		return image;
+	}
+
+	/**
+	 * Sets the image.
+	 * 
+	 * @param image
+	 *            The image to set
+	 */
+	public void setImage(DocuImage image) {
+		this.image = image;
+		setValue("docu.image", image);
+	}
+
+}
--- a/common/src/main/java/digilib/image/ImageJobDescription.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/common/src/main/java/digilib/image/ImageJobDescription.java	Wed Mar 27 17:23:44 2013 +0100
@@ -31,6 +31,7 @@
 
 import org.apache.log4j.Logger;
 
+import digilib.conf.DigilibConfiguration;
 import digilib.image.DocuImage.ColorOp;
 import digilib.io.DocuDirCache;
 import digilib.io.DocuDirectory;
@@ -39,7 +40,6 @@
 import digilib.io.FileOps.FileClass;
 import digilib.io.ImageInput;
 import digilib.io.ImageSet;
-import digilib.servlet.DigilibConfiguration;
 import digilib.util.ImageSize;
 import digilib.util.OptionsSet;
 import digilib.util.Parameter;
--- a/common/src/main/java/digilib/image/ImageWorker.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/common/src/main/java/digilib/image/ImageWorker.java	Wed Mar 27 17:23:44 2013 +0100
@@ -29,8 +29,8 @@
 
 import org.apache.log4j.Logger;
 
+import digilib.conf.DigilibConfiguration;
 import digilib.io.FileOpException;
-import digilib.servlet.DigilibConfiguration;
 
 /**
  * Worker that renders an image.
--- a/common/src/main/java/digilib/io/AliasingDocuDirCache.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/common/src/main/java/digilib/io/AliasingDocuDirCache.java	Wed Mar 27 17:23:44 2013 +0100
@@ -32,8 +32,8 @@
 import java.util.Map;
 import java.util.Map.Entry;
 
+import digilib.conf.DigilibConfiguration;
 import digilib.io.FileOps.FileClass;
-import digilib.servlet.DigilibConfiguration;
 import digilib.util.XMLListLoader;
 
 /**
--- a/common/src/main/java/digilib/io/DocuDirCache.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/common/src/main/java/digilib/io/DocuDirCache.java	Wed Mar 27 17:23:44 2013 +0100
@@ -36,8 +36,8 @@
 
 import org.apache.log4j.Logger;
 
+import digilib.conf.DigilibConfiguration;
 import digilib.io.FileOps.FileClass;
-import digilib.servlet.DigilibConfiguration;
 
 /**
  * @author casties
--- a/common/src/main/java/digilib/io/ImageFile.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/common/src/main/java/digilib/io/ImageFile.java	Wed Mar 27 17:23:44 2013 +0100
@@ -34,7 +34,7 @@
 import javax.imageio.stream.FileImageInputStream;
 import javax.imageio.stream.ImageInputStream;
 
-import digilib.servlet.DigilibConfiguration;
+import digilib.conf.DigilibConfiguration;
 import digilib.util.ImageSize;
 
 /**
--- a/common/src/main/java/digilib/servlet/DigilibConfiguration.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%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)
- */
-
-import java.io.IOException;
-
-import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.Logger;
-
-import digilib.image.DocuImage;
-import digilib.image.DocuImageImpl;
-import digilib.io.ImageInput;
-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>
- * 
- * @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");
-
-    /**
-     * 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 servlet version
-        newParameter("digilib.version", "2.0b1", null, 's');
-        // DocuImage class instance
-        newParameter("servlet.docuimage.class",
-                digilib.image.ImageLoaderDocuImage.class, null, 's');
-        // 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');
-        // 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');
-        // maximum destination image size (0 means no limit)
-        newParameter("max-image-size", new Integer(0), 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');
-
-        // 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
-     * 
-     * @param imgf
-     * @return
-     * @throws IOException
-     */
-    public static ImageInput identifyDocuImage(ImageInput imgf)
-            throws IOException {
-        // use fresh DocuImage instance
-        DocuImage di = getDocuImageInstance();
-        return di.identify(imgf);
-    }
-
-    /**
-     * @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;
-    }
-}
--- a/common/src/main/java/digilib/servlet/DigilibRequest.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * DigilibRequest.java
- *
- * lightweight class carrying all parameters for a request to digilib
- * %%
- * Copyright (C) 2002 - 2013 MPIWG Berlin, WTWG Uni Bern
- *                           
- * %%
- * 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: Robert Casties (robcast@berlios.de),
- *          Christian Luginbuehl
- *          
- * Created on 27. August 2002
- */
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.StringTokenizer;
-
-import javax.servlet.http.HttpServletRequest;
-
-import digilib.image.DocuImage;
-import digilib.io.FileOps;
-import digilib.util.OptionsSet;
-import digilib.util.Parameter;
-import digilib.util.ParameterMap;
-
-/**
- * Class holding the parameters of a digilib user request. The parameters are
- * mostly named like the servlet parameters: <br>
- * request_path: url of the page/document. <br>
- * fn: url of the page/document. <br>
- * pn: page number. <br>
- * dw: width of result window in pixels. <br>
- * dh: height of result window in pixels. <br>
- * wx: left edge of image area (float from 0 to 1). <br>
- * wy: top edge of image area (float from 0 to 1). <br>
- * ww: width of image area(float from 0 to 1). <br>
- * wh: height of image area(float from 0 to 1). <br>
- * ws: scale factor. <br>
- * mo: special options like 'fit' for gifs. <br>
- * mk: list of marks. <br>
- * pt: total number of pages (generated by sevlet). <br>
- * baseURL: base URL (from http:// to below /servlet). <br>
- * ...et alii
- * 
- * @author casties
- * 
- */
-public class DigilibRequest extends ParameterMap {
-
-	protected DocuImage image; // internal DocuImage instance for this request
-
-	public DigilibRequest() {
-		super(30);
-	}
-
-	/** set up parameters.
-	 * 
-	 */
-	protected void initParams() {
-		/*
-		 * Definition of parameters and default values. Parameter of type 's'
-		 * are for the servlet.
-		 */
-
-		// url of the page/document (second part)
-		newParameter("fn", "", null, 's');
-		// page number
-		newParameter("pn", new Integer(1), 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", this.options, 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');
-		// color conversion operation
-		newParameter("colop", "", 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
-		newParameter("docu.image", image, null, 'i');
-		image = null;
-		/*
-		 * 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');
-	}
-
-    /* (non-Javadoc)
-     * @see digilib.servlet.ParameterMap#initOptions()
-     */
-    @Override
-    protected void initOptions() {
-        options = (OptionsSet) getValue("mo");
-    }
-
-	/**
-	 * Return the request parameters as a String in the parameter form
-	 * 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not included.
-	 * 
-	 * @return String of request parameters in parameter form.
-	 */
-	public String getAsString() {
-		return getAsString(0);
-	}
-
-	/**
-	 * Return the request parameters of a given type type as a String in the
-	 * parameter form 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not
-	 * included.
-	 * 
-	 * @return String of request parameters in parameter form.
-	 */
-	public String getAsString(int type) {
-		StringBuffer s = new StringBuffer(50);
-		// go through all values
-		for (Parameter p: params.values()) {
-			if ((type > 0) && (p.getType() != type)) {
-				// skip the wrong types
-				continue;
-			}
-			String name = p.getName();
-			/*
-			 * handling special cases
-			 */
-			// request_path adds to fn
-			if (name.equals("fn")) {
-				s.append("&fn=" + getAsString("request.path")
-						+ getAsString("fn"));
-				continue;
-			}
-			/*
-			 * the rest is sent with its name
-			 */
-			// parameters that are not set or internal are not sent
-			if ((!p.hasValue()) || (p.getType() == 'i')) {
-				continue;
-			}
-			s.append("&" + name + "=" + p.getAsString());
-		}
-		// kill first "&"
-		s.deleteCharAt(0);
-		return s.toString();
-	}
-
-	/**
-	 * Set request parameters from query string. Uses the separator string qs to
-	 * get 'fn=foo' style parameters.
-	 * 
-	 * @param qs
-	 *            query string
-	 * @param sep
-	 *            parameter-separator string
-	 */
-	public void setWithParamString(String qs, String sep) {
-		// go through all request parameters
-		String[] qa = qs.split(sep);
-		for (int i = 0; i < qa.length; i++) {
-			// split names and values on "="
-			String[] nv = qa[i].split("=");
-			try {
-				String name = URLDecoder.decode(nv[0], "UTF-8");
-				String val = URLDecoder.decode(nv[1], "UTF-8");
-				// is this a known parameter?
-				if (params.containsKey(name)) {
-					Parameter p = (Parameter) this.get(name);
-					// internal parameters are not set
-					if (p.getType() == 'i') {
-						continue;
-					}
-					p.setValueFromString(val);
-					continue;
-				}
-				// unknown parameters are just added with type 'r'
-				newParameter(name, null, val, 'r');
-			} catch (UnsupportedEncodingException e) {
-				// this shouldn't happen anyway
-				e.printStackTrace();
-			}
-		}
-	}
-
-	/**
-	 * Test if option string <code>opt</code> is set. Checks if the substring
-	 * <code>opt</code> is contained in the options string <code>param</code>.
-	 * Deprecated! use hasOption(String opt) for "mo"-options.
-	 * 
-	 * @param opt
-	 *            Option string to be tested.
-	 * @return boolean
-	 */
-	public boolean hasOption(String param, String opt) {
-		String s = getAsString(param);
-		if (s != null) {
-			StringTokenizer i = new StringTokenizer(s, ",");
-			while (i.hasMoreTokens()) {
-				if (i.nextToken().equals(opt)) {
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * The image file path to be accessed.
-	 * 
-	 * The mage file path is assembled from the servlets RequestPath and
-	 * Parameter fn and normalized.
-	 * 
-	 * @return String the effective filepath.
-	 */
-	public String getFilePath() {
-		String s = getAsString("request.path");
-		s += getAsString("fn");
-		return FileOps.normalName(s);
-	}
-
-	/**
-	 * Returns the image.
-	 * 
-	 * @return DocuImage
-	 */
-	public DocuImage getImage() {
-		return image;
-	}
-
-	/**
-	 * Sets the image.
-	 * 
-	 * @param image
-	 *            The image to set
-	 */
-	public void setImage(DocuImage image) {
-		this.image = image;
-		setValue("docu.image", image);
-	}
-
-    public HttpServletRequest getServletRequest() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-}
--- a/pom.xml	Wed Mar 27 13:02:27 2013 +0100
+++ b/pom.xml	Wed Mar 27 17:23:44 2013 +0100
@@ -176,6 +176,11 @@
 			</dependency>
 			<dependency>
 				<groupId>digilib</groupId>
+				<artifactId>digilib-servlet</artifactId>
+				<version>2.1-SNAPSHOT</version>
+			</dependency>
+			<dependency>
+				<groupId>digilib</groupId>
 				<artifactId>digilib-servlet2</artifactId>
 				<version>2.1-SNAPSHOT</version>
 			</dependency>
@@ -200,6 +205,7 @@
 	<!-- default modules -->
 	<modules>
 		<module>common</module>
+		<module>servlet</module>
 		<module>servlet2</module>
 		<module>servlet3</module>
 		<module>webapp</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/pom.xml	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>digilib</groupId>
+    <artifactId>digilib</artifactId>
+    <version>2.1-SNAPSHOT</version>
+  </parent>
+  <artifactId>digilib-servlet</artifactId>
+  <name>digilib-servlet</name>
+  <url>http://digilib.berlios.de</url>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  <description>The Digital Image Library - common Servlet code</description>
+  <dependencies>
+  	<dependency>
+  		<groupId>digilib</groupId>
+  		<artifactId>digilib-common</artifactId>
+  	</dependency>
+  	<dependency>
+  		<groupId>javax.servlet</groupId>
+  		<artifactId>servlet-api</artifactId>
+  		<version>2.3</version>
+  		<type>jar</type>
+  		<scope>provided</scope>
+  	</dependency>
+  </dependencies>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/main/java/digilib/auth/ServletAuthOps.java	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,158 @@
+package digilib.auth;
+
+/*
+ * #%L
+ *  AuthOps -- Authentication class implementation
+ *
+ *  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)
+ */
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.log4j.Logger;
+
+import digilib.conf.DigilibRequest;
+import digilib.conf.DigilibServletRequest;
+
+/**
+ * Basic implementation of AuthOps interface.
+ * 
+ * Provides basic implementations. Only rolesForPath needs to be implemented by
+ * specific implementations.
+ */
+public abstract class ServletAuthOps implements AuthOps {
+
+    /** general logger for this class */
+    protected Logger logger = Logger.getLogger(this.getClass());
+
+    /** Default constructor. */
+    public ServletAuthOps() {
+        try {
+            init();
+        } catch (AuthOpException e) {
+        }
+    }
+
+    /**
+     * Test if the request is allowed to access filepath.
+     * 
+     * @param filepath
+     *            filepath to be acessed.
+     * @param request
+     *            Request with user information.
+     * @throws AuthOpException
+     *             Exception thrown on error.
+     * @return true if the request is allowed.
+     */
+    public boolean isAuthRequired(String filepath, HttpServletRequest request) throws AuthOpException {
+        // check permissions
+        List<String> rolesRequired = rolesForPath(filepath, request);
+        return (rolesRequired != null);
+    }
+
+    /**
+     * @see digilib.auth.AuthOps#isAuthRequired(digilib.conf.DigilibRequest)
+     */
+    public boolean isAuthRequired(DigilibRequest request) throws AuthOpException {
+        // check permissions
+        List<String> rolesRequired = rolesForPath(request);
+        return (rolesRequired != null);
+    }
+
+    /**
+     * Return authorization roles needed for request.
+     * 
+     * Returns a list of authorization roles that would be allowed to access the
+     * specified path. The location information of the request is considered
+     * also.
+     * 
+     * @param filepath
+     *            filepath to be accessed.
+     * @param request
+     *            ServletRequest with address information.
+     * @throws AuthOpException
+     *             Exception thrown on error.
+     * @return List of Strings with role names.
+     */
+    public boolean isAuthorized(String filepath, HttpServletRequest request) throws AuthOpException {
+        List<String> rolesAllowed = rolesForPath(filepath, request);
+        return isRoleAuthorized(rolesAllowed, request);
+    }
+
+    /**
+     * @see digilib.auth.AuthOps#isAuthorized(digilib.conf.DigilibRequest)
+     */
+    public boolean isAuthorized(DigilibRequest request) throws AuthOpException {
+        List<String> rolesAllowed = rolesForPath(request);
+        return isRoleAuthorized(rolesAllowed, request);
+    }
+
+    /**
+     * Test request authorization against a list of roles.
+     * 
+     * @param roles
+     *            List of Strings with role names.
+     * @param request
+     *            ServletRequest with address information.
+     * @return true if the user information in the request authorizes one of the
+     *         roles.
+     */
+    public boolean isRoleAuthorized(List<String> roles, HttpServletRequest request) {
+        for (String s : roles) {
+            logger.debug("Testing role: " + s);
+            if (request.isUserInRole(s)) {
+                logger.debug("Role Authorized");
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see digilib.auth.AuthOps#isRoleAuthorized(java.util.List,
+     *      digilib.conf.DigilibRequest)
+     */
+    public boolean isRoleAuthorized(List<String> roles, DigilibRequest request) {
+        for (String s : roles) {
+            logger.debug("Testing role: " + s);
+            if (((DigilibServletRequest) request).getServletRequest().isUserInRole(s)) {
+                logger.debug("Role Authorized");
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public abstract void init() throws AuthOpException;
+
+    public abstract List<String> rolesForPath(String filepath, HttpServletRequest request) throws AuthOpException;
+
+    /**
+     * @see digilib.auth.AuthOps#rolesForPath(digilib.conf.DigilibRequest)
+     */
+    public List<String> rolesForPath(DigilibRequest request) throws AuthOpException {
+        return rolesForPath(request.getFilePath(), ((DigilibServletRequest) request).getServletRequest());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/main/java/digilib/auth/XMLAuthOps.java	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,142 @@
+package digilib.auth;
+
+/*
+ * #%L
+ * XMLAuthOps -- Authentication class implementation using XML files
+ * 
+ * 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)
+ */
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import digilib.util.HashTree;
+import digilib.util.XMLListLoader;
+
+/** Implementation of AuthOps using XML files.
+ *
+ * The configuration file is read by an XMLListLoader into HashTree objects for 
+ * authentication paths and IP numbers.
+ */
+public class XMLAuthOps extends ServletAuthOps {
+
+	private File configFile;
+	private HashTree authPaths;
+	private HashTree authIPs;
+
+	/** Constructor taking an XML config file.
+	 *
+	 * @param u utils object
+	 * @param confFile Configuration file.
+	 * @throws AuthOpException Exception thrown on error.
+	 */
+	public XMLAuthOps(File confFile) throws AuthOpException {
+		configFile = confFile;
+		init();
+	}
+
+	/** Set configuration file.
+	 *
+	 * @param confFile XML config file.
+	 * @throws AuthOpException Exception thrown on error.
+	 */
+	public void setConfig(File confFile) throws AuthOpException {
+		configFile = confFile;
+		init();
+	}
+
+	/** Initialize.
+	 *
+	 * Read configuration files and setup authentication arrays.
+	 *
+	 * @throws AuthOpException Exception thrown on error.
+	 */
+	public void init() throws AuthOpException {
+		logger.debug("xmlauthops.init (" + configFile + ")");
+		Map<String, String> pathList = null;
+		Map<String, String> ipList = null;
+		try {
+			// load authPaths
+			XMLListLoader pathLoader =
+				new XMLListLoader("digilib-paths", "path", "name", "role");
+			pathList = pathLoader.loadUri(configFile.toURI());
+			// load authIPs
+			XMLListLoader ipLoader =
+				new XMLListLoader("digilib-addresses", "address", "ip", "role");
+			ipList = ipLoader.loadUri(configFile.toURI());
+		} catch (Exception e) {
+			throw new AuthOpException(
+				"ERROR loading authorization config file: " + e);
+		}
+		if ((pathList == null) || (ipList == null)) {
+			throw new AuthOpException("ERROR unable to load authorization config file!");
+		}
+		// setup path tree
+		authPaths = new HashTree(pathList, "/", ",");
+		// setup ip tree
+		authIPs = new HashTree(ipList, ".", ",");
+	}
+
+	/** Return authorization roles needed for request.
+	 *
+	 * Returns the list of authorization roles that are needed to access the
+	 * specified path. No list means the path is free.
+	 *
+	 * The location information of the request is also considered.
+	 *
+	 * @param filepath filepath to be accessed.
+	 * @param request ServletRequest with address information.
+	 * @throws AuthOpException Exception thrown on error.
+	 * @return List of Strings with role names.
+	 */
+	public List<String> rolesForPath(String filepath, HttpServletRequest request)
+		throws digilib.auth.AuthOpException {
+		logger.debug("rolesForPath ("
+				+ filepath
+				+ ") by ["
+				+ request.getRemoteAddr()
+				+ "]");
+
+		// check if the requests address provides a role
+		List<String> provided = authIPs.match(request.getRemoteAddr());
+		if ((provided != null) && (provided.contains("ALL"))) {
+			// ALL switches off checking;
+			return null;
+		}
+		// which roles are required?
+		List<String> required = authPaths.match(filepath);
+		// do any provided roles match?
+		if ((provided != null) && (required != null)) {
+			for (int i = 0; i < provided.size(); i++) {
+				if (required.contains(provided.get(i))) {
+					// satisfied
+					return null;
+				}
+			}
+		}
+		return required;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/main/java/digilib/conf/DigilibServletConfiguration.java	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,244 @@
+package digilib.conf;
+
+/*
+ * #%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)
+ */
+
+import java.io.File;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.ServletContext;
+
+import digilib.image.DocuImageImpl;
+import digilib.io.FileOps;
+import digilib.servlet.ServletOps;
+import digilib.util.Parameter;
+import digilib.util.XMLListLoader;
+
+/**
+ * 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 DigilibServletConfiguration extends DigilibConfiguration {
+
+    /** 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);
+
+    /** counter for open HttpRequests (mostly for debugging) */
+    public AtomicInteger openRequestCnt = new AtomicInteger(0);
+
+    /**
+     * Definition of parameters and default values.
+     */
+    protected void initParams() {
+        /*
+         * Definition of parameters and default values. System parameters that
+         * are not read from config file have a type 's'.
+         */
+
+        // configuration file location
+        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'
+         */
+
+        // image file to send in case of error
+        newParameter("error-image", new File("img/digilib-error.png"), null, 'f');
+        // image file to send if access is denied
+        newParameter("denied-image", new File("img/digilib-denied.png"), null, 'f');
+        // image file to send if image file not found
+        newParameter("notfound-image", new File("img/digilib-notfound.png"), null, 'f');
+        // base directories in order of preference (prescaled versions last)
+        String[] bd = { "sample-images" };
+        newParameter("basedir-list", bd, null, 'f');
+        // use authentication information
+        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');
+        // 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');
+        // 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');
+        // 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');
+    }
+
+    /**
+     * 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
+     */
+    @SuppressWarnings("unchecked")
+    public void readConfig(ServletContext c) throws Exception {
+
+        /*
+         * Get config file name. The file name is first looked for as an init
+         * parameter, then in a fixed location in the webapp.
+         */
+        if (c == null) {
+            // no config no file...
+            return;
+        }
+        String fn = c.getInitParameter("config-file");
+        if (fn == null) {
+            logger.debug("readConfig: no param config-file");
+            fn = ServletOps.getConfigFile("digilib-config.xml", c);
+        }
+        File f = new File(fn);
+        if (f.canRead()) {
+            // setup config file list reader
+            XMLListLoader lilo = new XMLListLoader("digilib-config", "parameter", "name", "value");
+            // read config file into HashMap
+            Map<String, String> confTable = lilo.loadUri(f.toURI());
+
+            // set config file path parameter
+            setValue("servlet.config.file", f.getCanonicalPath());
+
+            /*
+             * read parameters
+             */
+
+            for (Entry<String, String> confEntry : confTable.entrySet()) {
+                Parameter p = get(confEntry.getKey());
+                if (p != null) {
+                    if (p.getType() == 's') {
+                        // type 's' Parameters are not overwritten.
+                        continue;
+                    }
+                    if (!p.setValueFromString(confEntry.getValue())) {
+                        /*
+                         * automatic conversion failed -- try special cases
+                         */
+
+                        // basedir-list
+                        if (confEntry.getKey().equals("basedir-list")) {
+                            // split list into directories
+                            String[] dirs = FileOps.pathToArray(confEntry.getValue());
+                            for (int j = 0; j < dirs.length; j++) {
+                                // make relative directory paths be inside the
+                                // webapp
+                                dirs[j] = ServletOps.getFile(dirs[j], c);
+                            }
+                            if (dirs != null) {
+                                p.setValue(dirs);
+                            }
+                        }
+                    }
+                } else {
+                    // parameter unknown -- just add
+                    newParameter(confEntry.getKey(), null, confEntry.getValue(), 'f');
+                }
+            }
+        } else {
+            logger.warn("No digilib config file! Using defaults!");
+            // update basedir-list
+            String[] dirs = (String[]) this.getValue("basedir-list");
+            for (int j = 0; j < dirs.length; j++) {
+                // make relative directory paths be inside the
+                // webapp
+                dirs[j] = ServletOps.getFile(dirs[j], c);
+            }
+        }
+        // initialise static DocuImage class instance
+        DigilibServletConfiguration.docuImageClass = (Class<DocuImageImpl>) Class.forName(getAsString("docuimage-class"));
+        setValue("servlet.docuimage.version", getDocuImageInstance().getVersion());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/main/java/digilib/conf/DigilibServletRequest.java	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,541 @@
+package digilib.conf;
+
+/*
+ * #%L
+ * DigilibRequest.java
+ *
+ * lightweight class carrying all parameters for a request to digilib
+ * %%
+ * Copyright (C) 2001 - 2013 MPIWG Berlin, WTWG Uni Bern
+ *                           
+ * %%
+ * 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),
+ *         Christian Luginbuehl
+ */
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+
+import digilib.conf.DigilibRequest;
+import digilib.image.DocuImage;
+import digilib.io.FileOps;
+import digilib.util.OptionsSet;
+import digilib.util.Parameter;
+
+/**
+ * Class holding the parameters of a digilib user request. The parameters are
+ * mostly named like the servlet parameters: <br>
+ * request_path: url of the page/document. <br>
+ * fn: url of the page/document. <br>
+ * pn: page number. <br>
+ * dw: width of result window in pixels. <br>
+ * dh: height of result window in pixels. <br>
+ * wx: left edge of image area (float from 0 to 1). <br>
+ * wy: top edge of image area (float from 0 to 1). <br>
+ * ww: width of image area(float from 0 to 1). <br>
+ * wh: height of image area(float from 0 to 1). <br>
+ * ws: scale factor. <br>
+ * mo: special options like 'fit' for gifs. <br>
+ * mk: list of marks. <br>
+ * pt: total number of pages (generated by sevlet). <br>
+ * baseURL: base URL (from http:// to below /servlet). <br>
+ * ...et alii
+ * 
+ * @author casties
+ * 
+ */
+public class DigilibServletRequest extends DigilibRequest {
+
+    protected DocuImage image; // internal DocuImage instance for this request
+
+    protected HttpServletRequest servletRequest; // internal ServletRequest
+
+    /**
+     * Creates a new instance of DigilibRequest with parameters from a
+     * ServletRequest. All undefined parameters are set to default values.
+     * 
+     * @param request
+     */
+    public DigilibServletRequest(HttpServletRequest request) {
+        setWithRequest(request);
+        initOptions();
+    }
+
+    /**
+     * set up parameters.
+     * 
+     */
+    protected void initParams() {
+        /*
+         * Definition of parameters and default values. Parameter of type 's'
+         * are for the servlet.
+         */
+
+        // url of the page/document (second part)
+        newParameter("fn", "", null, 's');
+        // page number
+        newParameter("pn", new Integer(1), 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", this.options, 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');
+        // color conversion operation
+        newParameter("colop", "", 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
+        newParameter("docu.image", image, null, 'i');
+        image = null;
+        // HttpServletRequest for this request
+        newParameter("servlet.request", servletRequest, null, 'i');
+        servletRequest = null;
+
+        /*
+         * 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');
+        // marks
+        newParameter("mk", "", null, 'c');
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see digilib.servlet.ParameterMap#initOptions()
+     */
+    @Override
+    protected void initOptions() {
+        options = (OptionsSet) getValue("mo");
+    }
+
+    /**
+     * Populate the request object with data from a ServletRequest.
+     * 
+     * 
+     * @param request
+     */
+    public void setWithRequest(HttpServletRequest request) {
+        servletRequest = request;
+        // decide if it's old-style or new-style
+        String qs = ((HttpServletRequest) request).getQueryString();
+        if (qs != null) {
+            if (qs.indexOf("&amp;") > -1) {
+                // &amp; separator
+                setWithParamString(qs, "&amp;");
+            } else if (qs.indexOf(";") > -1) {
+                // ; separator
+                setWithParamString(qs, ";");
+            } else if (qs.indexOf('=') > -1) {
+                // standard '&' parameters
+                setWithParamRequest(request);
+            } else {
+                setWithOldString(qs);
+            }
+        }
+        setValue("servlet.request", request);
+        // add path from request
+        setValue("request.path", ((HttpServletRequest) request).getPathInfo());
+        // set the baseURL
+        setBaseURL((HttpServletRequest) request);
+    }
+
+    /**
+     * Populate a request from a string in the old "++++" parameter form.
+     * 
+     * @param queryString
+     *            String with paramters in the old "+++" form.
+     */
+    public void setWithOldString(String queryString) {
+        if (queryString == null) {
+            return;
+        }
+        // enable the passing of delimiter to get empty parameters
+        StringTokenizer query = new StringTokenizer(queryString, "+", true);
+        String token;
+        // first parameter FN
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("fn", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+        // second parameter PN
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("pn", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+        // third parameter WS
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("ws", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+        // fourth parameter MO
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("mo", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+        // fifth parameter MK
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("mk", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+        // sixth parameter WX
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("wx", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+        // seventh parameter WY
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("wy", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+        // eigth parameter WW
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("ww", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+        // ninth parameter WH
+        if (query.hasMoreTokens()) {
+            token = query.nextToken();
+            if (!token.equals("+")) {
+                setValueFromString("wh", token);
+                if (query.hasMoreTokens()) {
+                    query.nextToken();
+                }
+            }
+        }
+    }
+
+    /**
+     * Return the request parameters as a String in the parameter form
+     * 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not included.
+     * 
+     * @return String of request parameters in parameter form.
+     */
+    public String getAsString() {
+        return getAsString(0);
+    }
+
+    /**
+     * Return the request parameters of a given type type as a String in the
+     * parameter form 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not
+     * included.
+     * 
+     * @return String of request parameters in parameter form.
+     */
+    public String getAsString(int type) {
+        StringBuffer s = new StringBuffer(50);
+        // go through all values
+        for (Parameter p : params.values()) {
+            if ((type > 0) && (p.getType() != type)) {
+                // skip the wrong types
+                continue;
+            }
+            String name = p.getName();
+            /*
+             * handling special cases
+             */
+            // request_path adds to fn
+            if (name.equals("fn")) {
+                s.append("&fn=" + getAsString("request.path") + getAsString("fn"));
+                continue;
+            }
+            /*
+             * the rest is sent with its name
+             */
+            // parameters that are not set or internal are not sent
+            if ((!p.hasValue()) || (p.getType() == 'i')) {
+                continue;
+            }
+            s.append("&" + name + "=" + p.getAsString());
+        }
+        // kill first "&"
+        s.deleteCharAt(0);
+        return s.toString();
+    }
+
+    /**
+     * Returns request parameters in old '++++' form.
+     * 
+     * @return String with parameters in old '++++' form.
+     */
+    public String getAsOldString() {
+        StringBuffer s = new StringBuffer(50);
+        s.append(getAsString("request.path"));
+        s.append(getAsString("fn"));
+        s.append("+" + getAsString("pn"));
+        s.append("+" + getAsString("ws"));
+        s.append("+" + getAsString("mo"));
+        s.append("+" + getAsString("mk"));
+        s.append("+" + getAsString("wx"));
+        s.append("+" + getAsString("wy"));
+        s.append("+" + getAsString("ww"));
+        s.append("+" + getAsString("wh"));
+        return s.toString();
+    }
+
+    /**
+     * Set request parameters from javax.servlet.ServletRequest. Uses the
+     * Requests getParameter methods for 'fn=foo' style parameters.
+     * 
+     * @param request
+     *            ServletRequest to get parameters from.
+     */
+    // @SuppressWarnings("unchecked") // ServletRequest.getParameterNames()
+    // returns naked Enumeration
+    public void setWithParamRequest(ServletRequest request) {
+        setValue("servlet.request", request);
+        // go through all request parameters
+        for (@SuppressWarnings("unchecked")
+        Enumeration<String> i = request.getParameterNames(); i.hasMoreElements();) {
+            String name = (String) i.nextElement();
+            // is this a known parameter?
+            if (params.containsKey(name)) {
+                Parameter p = (Parameter) this.get(name);
+                // internal parameters are not set
+                if (p.getType() == 'i') {
+                    continue;
+                }
+                p.setValueFromString(request.getParameter(name));
+                continue;
+            }
+            // unknown parameters are just added with type 'r'
+            newParameter(name, null, request.getParameter(name), 'r');
+        }
+        // add path from request
+        setValue("request.path", ((HttpServletRequest) request).getPathInfo());
+    }
+
+    /**
+     * Set request parameters from query string. Uses the separator string qs to
+     * get 'fn=foo' style parameters.
+     * 
+     * @param qs
+     *            query string
+     * @param sep
+     *            parameter-separator string
+     */
+    public void setWithParamString(String qs, String sep) {
+        // go through all request parameters
+        String[] qa = qs.split(sep);
+        for (int i = 0; i < qa.length; i++) {
+            // split names and values on "="
+            String[] nv = qa[i].split("=");
+            try {
+                String name = URLDecoder.decode(nv[0], "UTF-8");
+                String val = URLDecoder.decode(nv[1], "UTF-8");
+                // is this a known parameter?
+                if (params.containsKey(name)) {
+                    Parameter p = (Parameter) this.get(name);
+                    // internal parameters are not set
+                    if (p.getType() == 'i') {
+                        continue;
+                    }
+                    p.setValueFromString(val);
+                    continue;
+                }
+                // unknown parameters are just added with type 'r'
+                newParameter(name, null, val, 'r');
+            } catch (UnsupportedEncodingException e) {
+                // this shouldn't happen anyway
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Test if option string <code>opt</code> is set. Checks if the substring
+     * <code>opt</code> is contained in the options string <code>param</code>.
+     * Deprecated! use hasOption(String opt) for "mo"-options.
+     * 
+     * @param opt
+     *            Option string to be tested.
+     * @return boolean
+     */
+    public boolean hasOption(String param, String opt) {
+        String s = getAsString(param);
+        if (s != null) {
+            StringTokenizer i = new StringTokenizer(s, ",");
+            while (i.hasMoreTokens()) {
+                if (i.nextToken().equals(opt)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * The image file path to be accessed.
+     * 
+     * The mage file path is assembled from the servlets RequestPath and
+     * Parameter fn and normalized.
+     * 
+     * @return String the effective filepath.
+     */
+    public String getFilePath() {
+        String s = getAsString("request.path");
+        s += getAsString("fn");
+        return FileOps.normalName(s);
+    }
+
+    /* Property getter and setter */
+
+    /**
+     * Set the requests base URL parameter from a
+     * javax.sevlet.http.HttpServletRequest.
+     * 
+     * @param request
+     *            HttpServletRequest to set the base URL.
+     */
+    public void setBaseURL(javax.servlet.http.HttpServletRequest request) {
+        String baseURL = null;
+        // calculate base URL string from request until webapp
+        String s = request.getRequestURL().toString();
+        // get name of webapp 
+        String wn = request.getContextPath();
+        int eop = s.lastIndexOf(wn);
+        if (eop > 0) {
+            baseURL = s.substring(0, eop + wn.length());
+        } else {
+            // fall back
+            baseURL = "http://" + request.getServerName() + "/digitallibrary";
+        }
+        setValue("base.url", baseURL);
+    }
+
+    /**
+     * Returns the image.
+     * 
+     * @return DocuImage
+     */
+    public DocuImage getImage() {
+        return image;
+    }
+
+    /**
+     * Sets the image.
+     * 
+     * @param image
+     *            The image to set
+     */
+    public void setImage(DocuImage image) {
+        this.image = image;
+        setValue("docu.image", image);
+    }
+
+    /**
+     * @return
+     */
+    public HttpServletRequest getServletRequest() {
+        return servletRequest;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/main/java/digilib/servlet/DocumentBean.java	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,331 @@
+package digilib.servlet;
+
+/*
+ * #%L
+ * 
+ * DocumentBean -- Access control bean for JSP
+ *
+ * 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)
+ */
+
+import java.util.List;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+
+import digilib.auth.AuthOpException;
+import digilib.auth.AuthOps;
+import digilib.conf.DigilibServletConfiguration;
+import digilib.conf.DigilibServletRequest;
+import digilib.io.DocuDirCache;
+import digilib.io.DocuDirectory;
+import digilib.io.FileOps.FileClass;
+import digilib.io.ImageInput;
+import digilib.io.ImageSet;
+import digilib.util.ImageSize;
+
+public class DocumentBean {
+
+	// general logger
+	private static Logger logger = Logger.getLogger("digilib.docubean");
+
+	// AuthOps object to check authorization
+	private AuthOps authOp;
+
+	// use authorization database
+	private boolean useAuthentication = true;
+
+	// path to add for authenticated access
+	private String authURLPath = "";
+
+	// DocuDirCache
+	private DocuDirCache dirCache = null;
+
+	// DigilibConfiguration object
+	private DigilibServletConfiguration dlConfig;
+
+	// DigilibRequest object
+	private DigilibServletRequest dlRequest = null;
+
+	/**
+	 * Constructor for DocumentBean.
+	 */
+	public DocumentBean() {
+        logger.debug("new DocumentBean");
+	}
+
+	public DocumentBean(ServletConfig conf) {
+        logger.debug("new DocumentBean");
+		try {
+			setConfig(conf);
+		} catch (Exception e) {
+			logger.fatal("ERROR: Unable to read config: ", e);
+		}
+	}
+
+	public void setConfig(ServletConfig conf) throws ServletException {
+		logger.debug("setConfig");
+		// get our ServletContext
+		ServletContext context = conf.getServletContext();
+		// see if there is a Configuration instance
+		dlConfig = (DigilibServletConfiguration) context
+				.getAttribute("digilib.servlet.configuration");
+		if (dlConfig == null) {
+			// create new Configuration
+			throw new ServletException("ERROR: No configuration!");
+		}
+
+		// get cache
+		dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
+
+		/*
+		 * authentication
+		 */
+		useAuthentication = dlConfig.getAsBoolean("use-authorization");
+		authOp = (AuthOps) dlConfig.getValue("servlet.auth.op");
+		authURLPath = dlConfig.getAsString("auth-url-path");
+		if (useAuthentication && (authOp == null)) {
+			throw new ServletException(
+					"ERROR: use-authorization configured but no AuthOp!");
+		}
+	}
+
+	/**
+	 * check if the request must be authorized to access filepath
+	 */
+	public boolean isAuthRequired(DigilibServletRequest request)
+			throws AuthOpException {
+		logger.debug("isAuthRequired");
+		return useAuthentication ? authOp.isAuthRequired(request) : false;
+	}
+
+	/**
+	 * check if the request is allowed to access filepath
+	 */
+	public boolean isAuthorized(DigilibServletRequest request) throws AuthOpException {
+		logger.debug("isAuthorized");
+		return useAuthentication ? authOp.isAuthorized(request) : true;
+	}
+
+	/**
+	 * return a list of authorization roles needed for request to access the
+	 * specified path
+	 */
+	public List<String> rolesForPath(DigilibServletRequest request) throws AuthOpException {
+		logger.debug("rolesForPath");
+		return useAuthentication ? authOp.rolesForPath(request) : null;
+	}
+
+	/**
+	 * check request authorization against a list of roles
+	 */
+	public boolean isRoleAuthorized(List<String> roles, DigilibServletRequest request) {
+		logger.debug("isRoleAuthorized");
+		return useAuthentication ? authOp.isRoleAuthorized(roles, request)
+				: true;
+	}
+
+	/**
+	 * check for authenticated access and redirect if necessary
+	 */
+	public boolean doAuthentication(HttpServletResponse response)
+			throws Exception {
+        logger.debug("doAuthenication-Method");
+		return doAuthentication(dlRequest, response);
+	}
+
+	/**
+	 * check for authenticated access and redirect if necessary
+	 */
+	public boolean doAuthentication(DigilibServletRequest request,
+			HttpServletResponse response) throws Exception {
+		logger.debug("doAuthentication");
+		if (!useAuthentication) {
+			// shortcut if no authentication
+			return true;
+		}
+		// quick fix: add auth-url-path to base.url
+        if (isAuthRequired(request)) {
+            String baseUrl = request.getAsString("base.url");
+            if (!baseUrl.endsWith(authURLPath)) {
+                request.setValue("base.url", baseUrl + "/" + authURLPath);
+            }
+        }
+		// check if we are already authenticated
+		if (((HttpServletRequest) request.getServletRequest()).getRemoteUser() == null) {
+			logger.debug("unauthenticated so far");
+			// if not maybe we must?
+			if (isAuthRequired(request)) {
+				logger.debug("auth required, redirect");
+				// we are not yet authenticated -> redirect
+				response.sendRedirect(request.getAsString("base.url")
+						+ ((HttpServletRequest) request.getServletRequest())
+								.getServletPath()
+						+ "?"
+						+ ((HttpServletRequest) request.getServletRequest())
+								.getQueryString());
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * Sets the current DigilibRequest. Also completes information in the request.
+	 * 
+	 * @param dlRequest
+	 *            The dlRequest to set.
+	 */
+	public void setRequest(DigilibServletRequest dlRequest) throws Exception {
+		this.dlRequest = dlRequest;
+		if (dirCache == null) {
+			return;
+		}
+		String fn = dlRequest.getFilePath();
+		// get information about the file
+		ImageSet fileset = (ImageSet) dirCache.getFile(fn, dlRequest
+				.getAsInt("pn"), FileClass.IMAGE);
+		if (fileset == null) {
+			return;
+		}
+		// add file name
+		dlRequest.setValue("img.fn", fileset);
+		// add dpi
+		dlRequest.setValue("img.dpix", new Double(fileset.getResX()));
+		dlRequest.setValue("img.dpiy", new Double(fileset.getResY()));
+		// get number of pages in directory
+		DocuDirectory dd = dirCache.getDirectory(fn);
+		if (dd != null) {
+			// add pt
+			dlRequest.setValue("pt", dd.size());
+		}
+		// get original pixel size
+		ImageInput origfile = fileset.getBiggest();
+		// check image for size (TODO: just if mo=hires?)
+		ImageSize pixsize = origfile.getSize();
+		if (pixsize != null) {
+			// add pixel size
+			dlRequest.setValue("img.pix_x", new Integer(pixsize.getWidth()));
+			dlRequest.setValue("img.pix_y", new Integer(pixsize.getHeight()));
+		}
+	}
+
+	/**
+	 * get the first page number in the directory (not yet functional)
+	 */
+	public int getFirstPage(DigilibServletRequest request) {
+		logger.debug("getFirstPage");
+		return 1;
+	}
+
+	/**
+	 * get the number of pages/files in the directory
+	 */
+	public int getNumPages() throws Exception {
+		return getNumPages(dlRequest);
+	}
+
+    /**
+     * get the number of image pages/files in the directory
+     */
+    public int getNumPages(DigilibServletRequest request) throws Exception {
+        return getNumPages(request, FileClass.IMAGE);
+    }
+
+	/**
+	 * get the number of pages/files of type fc in the directory
+	 */
+	public int getNumPages(DigilibServletRequest request, FileClass fc) throws Exception {
+		logger.debug("getNumPages");
+		DocuDirectory dd = (dirCache != null) ? dirCache.getDirectory(request
+				.getFilePath()) : null;
+		if (dd != null) {
+			return dd.size(fc);
+		}
+		return 0;
+	}
+
+	/**
+	 * Returns the dlConfig.
+	 * 
+	 * @return DigilibConfiguration
+	 */
+	public DigilibServletConfiguration getDlConfig() {
+		return dlConfig;
+	}
+
+	/**
+	 * returns if the zoom area in the request can be moved
+	 * 
+	 * @return
+	 */
+	public boolean canMoveRight() {
+		float ww = dlRequest.getAsFloat("ww");
+		float wx = dlRequest.getAsFloat("wx");
+		return (ww + wx < 1.0);
+	}
+
+	/**
+	 * returns if the zoom area in the request can be moved
+	 * 
+	 * @return
+	 */
+	public boolean canMoveLeft() {
+		float ww = dlRequest.getAsFloat("ww");
+		float wx = dlRequest.getAsFloat("wx");
+		return ((ww < 1.0) && (wx > 0));
+	}
+
+	/**
+	 * returns if the zoom area in the request can be moved
+	 * 
+	 * @return
+	 */
+	public boolean canMoveUp() {
+		float wh = dlRequest.getAsFloat("wh");
+		float wy = dlRequest.getAsFloat("wy");
+		return ((wh < 1.0) && (wy > 0));
+	}
+
+	/**
+	 * returns if the zoom area in the request can be moved
+	 * 
+	 * @return
+	 */
+	public boolean canMoveDown() {
+		float wh = dlRequest.getAsFloat("wh");
+		float wy = dlRequest.getAsFloat("wy");
+		return (wh + wy < 1.0);
+	}
+
+	/**
+	 * @return Returns the dlRequest.
+	 */
+	public DigilibServletRequest getRequest() {
+		return dlRequest;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/main/java/digilib/servlet/ServletOps.java	Wed Mar 27 17:23:44 2013 +0100
@@ -0,0 +1,362 @@
+package digilib.servlet;
+
+/*
+ * #%L
+ * ServletOps -- Servlet utility class
+ * 
+ * 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)
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+
+import digilib.image.DocuImage;
+import digilib.image.ImageOpException;
+import digilib.io.FileOps;
+
+public class ServletOps {
+
+    private static Logger logger = Logger.getLogger("servlet.op");
+
+    /**
+     * convert a string with a list of pathnames into an array of strings using
+     * the system's path separator string
+     */
+    public static String[] getPathArray(String paths) {
+        // split list into directories
+        StringTokenizer dirs = new StringTokenizer(paths,
+                java.io.File.pathSeparator);
+        int n = dirs.countTokens();
+        if (n < 1) {
+            return null;
+        }
+        // add directories into array
+        String[] pathArray = new String[n];
+        for (int i = 0; i < n; i++) {
+            pathArray[i] = dirs.nextToken();
+        }
+        return pathArray;
+    }
+
+    /**
+     * get a real File for a web app File.
+     * 
+     * If the File is not absolute the path is appended to the base directory of
+     * the web-app.
+     * 
+     * @param file
+     * @param sc
+     * @return
+     */
+    public static File getFile(File f, ServletContext sc) {
+        // is the filename absolute?
+        if (!f.isAbsolute()) {
+            // relative path -> use getRealPath to resolve in WEB-INF
+            String fn = sc.getRealPath(f.getPath());
+            if (fn == null) {
+                // TODO: use getResourceAsStream?
+                return null;
+            }
+            f = new File(fn);
+        }
+        return f;
+    }
+
+    /**
+     * get a real file name for a web app file pathname.
+     * 
+     * If filename starts with "/" its treated as absolute else the path is
+     * appended to the base directory of the web-app.
+     * 
+     * @param filename
+     * @param sc
+     * @return
+     */
+    public static String getFile(String filename, ServletContext sc) {
+        File f = new File(filename);
+        // is the filename absolute?
+        if (!f.isAbsolute()) {
+            // relative path -> use getRealPath to resolve in WEB-INF
+            filename = sc.getRealPath(filename);
+        }
+        return filename;
+    }
+
+    /**
+     * get a real File for a config File.
+     * 
+     * If the File is not absolute the path is appended to the WEB-INF directory
+     * of the web-app.
+     * 
+     * @param file
+     * @param sc
+     * @return
+     */
+    public static File getConfigFile(File f, ServletContext sc) {
+        String fn = f.getPath();
+        // is the filename absolute?
+        if (f.isAbsolute()) {
+            // does it exist?
+            if (f.canRead()) {
+                // fine
+                return f;
+            } else {
+                // try just the filename as relative
+                fn = f.getName();
+            }
+        }
+        // relative path -> use getRealPath to resolve in WEB-INF
+        String newfn = sc.getRealPath("WEB-INF/" + fn);
+        if (fn == null) {
+            // TODO: use getResourceAsStream?
+            return null;
+        }
+        f = new File(newfn);
+        return f;
+    }
+
+    /**
+     * get a real file name for a config file pathname.
+     * 
+     * If filename starts with "/" its treated as absolute else the path is
+     * appended to the WEB-INF directory of the web-app.
+     * 
+     * @param filename
+     * @param sc
+     * @return
+     */
+    public static String getConfigFile(String filename, ServletContext sc) {
+        File f = new File(filename);
+        // is the filename absolute?
+        if (!f.isAbsolute()) {
+            // relative path -> use getRealPath to resolve in WEB-INF
+            filename = sc.getRealPath("WEB-INF/" + filename);
+        }
+        return filename;
+    }
+
+    /**
+     * print a servlet response
+     */
+    public static void htmlMessage(String msg, HttpServletResponse response)
+            throws IOException {
+        htmlMessage("Scaler", msg, response);
+    }
+
+    /**
+     * print a servlet response
+     */
+    public static void htmlMessage(String title, String msg,
+            HttpServletResponse response) throws IOException {
+        response.setContentType("text/html; charset=iso-8859-1");
+        PrintWriter out = response.getWriter();
+        out.println("<html>");
+        out.println("<head><title>" + title + "</title></head>");
+        out.println("<body>");
+        out.println("<p>" + msg + "</p>");
+        out.println("</body></html>");
+    }
+
+    /**
+     * Transfers an image file as-is with the mime type mt.
+     * 
+     * The local file is copied to the <code>OutputStream</code> of the
+     * <code>ServletResponse</code>. If mt is null then the mime-type is
+     * auto-detected with mimeForFile.
+     * 
+     * @param f
+     *            Image file to be sent.
+     * @param mt
+     *            mime-type of the file.
+     * @param name
+     *            name of the download file (for application/x)
+     * @param res
+     *            ServletResponse where the image file will be sent.
+     * @throws ImageOpException
+     * @throws ServletException
+     *             Exception on sending data.
+     * @throws IOException
+     */
+    public static void sendFile(File f, String mt, String name,
+            HttpServletResponse response) throws ImageOpException, IOException {
+        // use default logger
+        ServletOps.sendFile(f, mt, name, response, ServletOps.logger);
+    }
+
+    /**
+     * Transfers an image file as-is with the mime type mt.
+     * 
+     * The local file is copied to the <code>OutputStream</code> of the
+     * <code>ServletResponse</code>. If mt is null then the mime-type is
+     * auto-detected with mimeForFile.
+     * @param f
+     *            Image file to be sent.
+     * @param mt
+     *            mime-type of the file.
+     * @param name 
+     *            name of the download file (for application/x)
+     * @param res
+     *            ServletResponse where the image file will be sent.
+     * @param logger
+     *            Logger to use
+     * @throws ImageOpException
+     * @throws ServletException Exception on sending data.
+     * @throws IOException 
+     */
+    public static void sendFile(File f, String mt, String name, HttpServletResponse response, Logger logger)
+            throws ImageOpException, IOException {
+        logger.debug("sendRawFile(" + mt + ", " + f + ")");
+    	if (response == null) {
+    		logger.error("No response!");
+    		return;
+    	}
+        if (mt == null) {
+            // auto-detect mime-type
+            mt = FileOps.mimeForFile(f);
+            if (mt == null) {
+                throw new ImageOpException("Unknown file type.");
+            }
+        }
+        response.setContentType(mt);
+        // open file
+        if (mt.startsWith("application")) {
+            if (name == null) {
+                // no download name -- use filename
+                name = f.getName();
+            }
+            response.addHeader("Content-Disposition", "attachment; filename=\""+name+"\"");
+        }
+        FileInputStream inFile = null;
+        try {
+            inFile = new FileInputStream(f);
+            OutputStream outStream = response.getOutputStream();
+            // TODO: should we set content length? 
+            // see http://www.prozesse-und-systeme.de/servletFlush.html
+            response.setContentLength( (int) f.length());
+            byte dataBuffer[] = new byte[4096];
+            int len;
+            while ((len = inFile.read(dataBuffer)) != -1) {
+                // copy out file
+                outStream.write(dataBuffer, 0, len);
+            }
+        } finally {
+            try {
+                if (inFile != null) {
+                    inFile.close();
+                }
+            } catch (IOException e) {
+                // nothing to do
+            }
+        }
+    }
+
+    /**
+     * Write image img to ServletResponse response.
+     * 
+     * @param img
+     * @param mimeType
+     * @param response
+     * @throws ImageOpException
+     * @throws ServletException Exception on sending data.
+     */
+    public static void sendImage(DocuImage img, String mimeType,
+            HttpServletResponse response) throws ImageOpException,
+            ServletException {
+        ServletOps.sendImage(img, mimeType, response, ServletOps.logger);
+    }
+
+    /**
+     * Write image img to ServletResponse response.
+     * 
+     * @param img
+     * @param mimeType
+     * @param response
+     * @param logger
+     * @throws ImageOpException
+     * @throws ServletException Exception on sending data.
+     */
+    public static void sendImage(DocuImage img, String mimeType,
+            HttpServletResponse response, Logger logger) throws ImageOpException,
+            ServletException {
+    	if (response == null) {
+    		logger.error("No response!");
+    		return;
+    	}
+        //logger.debug("sending to response: ("+ headersToString(response) + ") committed=" + response.isCommitted());
+        logger.debug("sending to response. committed=" + response.isCommitted());
+        // TODO: should we erase or replace old last-modified header?
+        try {
+            OutputStream outstream = response.getOutputStream();
+            // setup output -- if mime type is set use that otherwise
+            // if source is JPG then dest will be JPG else it's PNG
+            if (mimeType == null) {
+                mimeType = img.getMimetype();
+                if (mimeType == null) {
+                    // still no mime-type
+                    logger.warn("sendImage without mime-type! using image/jpeg.");
+                    mimeType = "image/jpeg";
+                }
+            }
+            if ((mimeType.equals("image/jpeg") || mimeType.equals("image/jp2") || 
+                    mimeType.equals("image/fpx"))) {
+                mimeType = "image/jpeg";
+            } else {
+                mimeType = "image/png";
+            }
+            // write the image
+            response.setContentType(mimeType);
+            img.writeImage(mimeType, outstream);
+        } catch (IOException e) {
+            throw new ServletException("Error sending image:", e);
+        }
+        // TODO: should we: finally { img.dispose(); }
+    }
+
+    /** Returns text representation of headers for debuggging purposes.
+     * @param req
+     * @return
+     */
+    public static String headersToString(HttpServletRequest req) {
+        String s = "";
+        @SuppressWarnings("unchecked")
+        Enumeration<String> hns = req.getHeaderNames();
+        while (hns.hasMoreElements()) {
+            String hn = hns.nextElement();
+            s += hn + "=" + req.getHeader(hn) + "; ";
+        }
+        return s;
+    }
+    
+    
+}
--- a/servlet2/pom.xml	Wed Mar 27 13:02:27 2013 +0100
+++ b/servlet2/pom.xml	Wed Mar 27 17:23:44 2013 +0100
@@ -16,17 +16,15 @@
   </properties>
   <dependencies>
   	<dependency>
-  		<groupId>digilib</groupId>
-  		<artifactId>digilib-common</artifactId>
-  		<type>jar</type>
-  		<scope>compile</scope>
-  	</dependency>
-  	<dependency>
   		<groupId>javax.servlet</groupId>
   		<artifactId>servlet-api</artifactId>
   		<version>2.3</version>
   		<type>jar</type>
   		<scope>provided</scope>
   	</dependency>
+  	<dependency>
+  		<groupId>digilib</groupId>
+  		<artifactId>digilib-servlet</artifactId>
+  	</dependency>
   </dependencies>
 </project>
--- a/servlet2/src/main/java/digilib/servlet/DigilibServletConfiguration.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%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)
- */
-
-import java.io.File;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.servlet.ServletContext;
-
-import digilib.image.DocuImageImpl;
-import digilib.io.FileOps;
-import digilib.util.Parameter;
-import digilib.util.XMLListLoader;
-
-/**
- * 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 DigilibServletConfiguration extends DigilibConfiguration {
-
-    /** 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);
-
-    /** counter for open HttpRequests (mostly for debugging) */
-    public AtomicInteger openRequestCnt = new AtomicInteger(0);
-
-    /**
-     * Definition of parameters and default values.
-     */
-    protected void initParams() {
-        /*
-         * Definition of parameters and default values. System parameters that
-         * are not read from config file have a type 's'.
-         */
-
-        // digilib servlet version
-        newParameter("servlet.version", digilib.servlet.Scaler.getVersion(), null, 's');
-        // configuration file location
-        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'
-         */
-
-        // image file to send in case of error
-        newParameter("error-image", new File("img/digilib-error.png"), null, 'f');
-        // image file to send if access is denied
-        newParameter("denied-image", new File("img/digilib-denied.png"), null, 'f');
-        // image file to send if image file not found
-        newParameter("notfound-image", new File("img/digilib-notfound.png"), null, 'f');
-        // base directories in order of preference (prescaled versions last)
-        String[] bd = { "sample-images" };
-        newParameter("basedir-list", bd, null, 'f');
-        // use authentication information
-        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');
-        // 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');
-        // 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');
-        // 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');
-    }
-
-    /**
-     * 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
-     */
-    @SuppressWarnings("unchecked")
-    public void readConfig(ServletContext c) throws Exception {
-
-        /*
-         * Get config file name. The file name is first looked for as an init
-         * parameter, then in a fixed location in the webapp.
-         */
-        if (c == null) {
-            // no config no file...
-            return;
-        }
-        String fn = c.getInitParameter("config-file");
-        if (fn == null) {
-            logger.debug("readConfig: no param config-file");
-            fn = ServletOps.getConfigFile("digilib-config.xml", c);
-        }
-        File f = new File(fn);
-        if (f.canRead()) {
-            // setup config file list reader
-            XMLListLoader lilo = new XMLListLoader("digilib-config", "parameter", "name", "value");
-            // read config file into HashMap
-            Map<String, String> confTable = lilo.loadUri(f.toURI());
-
-            // set config file path parameter
-            setValue("servlet.config.file", f.getCanonicalPath());
-
-            /*
-             * read parameters
-             */
-
-            for (Entry<String, String> confEntry : confTable.entrySet()) {
-                Parameter p = get(confEntry.getKey());
-                if (p != null) {
-                    if (p.getType() == 's') {
-                        // type 's' Parameters are not overwritten.
-                        continue;
-                    }
-                    if (!p.setValueFromString(confEntry.getValue())) {
-                        /*
-                         * automatic conversion failed -- try special cases
-                         */
-
-                        // basedir-list
-                        if (confEntry.getKey().equals("basedir-list")) {
-                            // split list into directories
-                            String[] dirs = FileOps.pathToArray(confEntry.getValue());
-                            for (int j = 0; j < dirs.length; j++) {
-                                // make relative directory paths be inside the
-                                // webapp
-                                dirs[j] = ServletOps.getFile(dirs[j], c);
-                            }
-                            if (dirs != null) {
-                                p.setValue(dirs);
-                            }
-                        }
-                    }
-                } else {
-                    // parameter unknown -- just add
-                    newParameter(confEntry.getKey(), null, confEntry.getValue(), 'f');
-                }
-            }
-        } else {
-            logger.warn("No digilib config file! Using defaults!");
-            // update basedir-list
-            String[] dirs = (String[]) this.getValue("basedir-list");
-            for (int j = 0; j < dirs.length; j++) {
-                // make relative directory paths be inside the
-                // webapp
-                dirs[j] = ServletOps.getFile(dirs[j], c);
-            }
-        }
-        // initialise static DocuImage class instance
-        DigilibServletConfiguration.docuImageClass = (Class<DocuImageImpl>) Class.forName(getAsString("docuimage-class"));
-        setValue("servlet.docuimage.version", getDocuImageInstance().getVersion());
-    }
-
-}
--- a/servlet2/src/main/java/digilib/servlet/DigilibServletRequest.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,540 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * DigilibRequest.java
- *
- * lightweight class carrying all parameters for a request to digilib
- * %%
- * Copyright (C) 2001 - 2013 MPIWG Berlin, WTWG Uni Bern
- *                           
- * %%
- * 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),
- *         Christian Luginbuehl
- */
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-
-import digilib.image.DocuImage;
-import digilib.io.FileOps;
-import digilib.util.OptionsSet;
-import digilib.util.Parameter;
-
-/**
- * Class holding the parameters of a digilib user request. The parameters are
- * mostly named like the servlet parameters: <br>
- * request_path: url of the page/document. <br>
- * fn: url of the page/document. <br>
- * pn: page number. <br>
- * dw: width of result window in pixels. <br>
- * dh: height of result window in pixels. <br>
- * wx: left edge of image area (float from 0 to 1). <br>
- * wy: top edge of image area (float from 0 to 1). <br>
- * ww: width of image area(float from 0 to 1). <br>
- * wh: height of image area(float from 0 to 1). <br>
- * ws: scale factor. <br>
- * mo: special options like 'fit' for gifs. <br>
- * mk: list of marks. <br>
- * pt: total number of pages (generated by sevlet). <br>
- * baseURL: base URL (from http:// to below /servlet). <br>
- * ...et alii
- * 
- * @author casties
- * 
- */
-public class DigilibServletRequest extends DigilibRequest {
-
-    protected DocuImage image; // internal DocuImage instance for this request
-
-    protected HttpServletRequest servletRequest; // internal ServletRequest
-
-    /**
-     * Creates a new instance of DigilibRequest with parameters from a
-     * ServletRequest. All undefined parameters are set to default values.
-     * 
-     * @param request
-     */
-    public DigilibServletRequest(HttpServletRequest request) {
-        setWithRequest(request);
-        initOptions();
-    }
-
-    /**
-     * set up parameters.
-     * 
-     */
-    protected void initParams() {
-        /*
-         * Definition of parameters and default values. Parameter of type 's'
-         * are for the servlet.
-         */
-
-        // url of the page/document (second part)
-        newParameter("fn", "", null, 's');
-        // page number
-        newParameter("pn", new Integer(1), 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", this.options, 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');
-        // color conversion operation
-        newParameter("colop", "", 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
-        newParameter("docu.image", image, null, 'i');
-        image = null;
-        // HttpServletRequest for this request
-        newParameter("servlet.request", servletRequest, null, 'i');
-        servletRequest = null;
-
-        /*
-         * 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');
-        // marks
-        newParameter("mk", "", null, 'c');
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see digilib.servlet.ParameterMap#initOptions()
-     */
-    @Override
-    protected void initOptions() {
-        options = (OptionsSet) getValue("mo");
-    }
-
-    /**
-     * Populate the request object with data from a ServletRequest.
-     * 
-     * 
-     * @param request
-     */
-    public void setWithRequest(HttpServletRequest request) {
-        servletRequest = request;
-        // decide if it's old-style or new-style
-        String qs = ((HttpServletRequest) request).getQueryString();
-        if (qs != null) {
-            if (qs.indexOf("&amp;") > -1) {
-                // &amp; separator
-                setWithParamString(qs, "&amp;");
-            } else if (qs.indexOf(";") > -1) {
-                // ; separator
-                setWithParamString(qs, ";");
-            } else if (qs.indexOf('=') > -1) {
-                // standard '&' parameters
-                setWithParamRequest(request);
-            } else {
-                setWithOldString(qs);
-            }
-        }
-        setValue("servlet.request", request);
-        // add path from request
-        setValue("request.path", ((HttpServletRequest) request).getPathInfo());
-        // set the baseURL
-        setBaseURL((HttpServletRequest) request);
-    }
-
-    /**
-     * Populate a request from a string in the old "++++" parameter form.
-     * 
-     * @param queryString
-     *            String with paramters in the old "+++" form.
-     */
-    public void setWithOldString(String queryString) {
-        if (queryString == null) {
-            return;
-        }
-        // enable the passing of delimiter to get empty parameters
-        StringTokenizer query = new StringTokenizer(queryString, "+", true);
-        String token;
-        // first parameter FN
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("fn", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // second parameter PN
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("pn", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // third parameter WS
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("ws", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // fourth parameter MO
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("mo", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // fifth parameter MK
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("mk", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // sixth parameter WX
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("wx", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // seventh parameter WY
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("wy", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // eigth parameter WW
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("ww", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // ninth parameter WH
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("wh", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-    }
-
-    /**
-     * Return the request parameters as a String in the parameter form
-     * 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not included.
-     * 
-     * @return String of request parameters in parameter form.
-     */
-    public String getAsString() {
-        return getAsString(0);
-    }
-
-    /**
-     * Return the request parameters of a given type type as a String in the
-     * parameter form 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not
-     * included.
-     * 
-     * @return String of request parameters in parameter form.
-     */
-    public String getAsString(int type) {
-        StringBuffer s = new StringBuffer(50);
-        // go through all values
-        for (Parameter p : params.values()) {
-            if ((type > 0) && (p.getType() != type)) {
-                // skip the wrong types
-                continue;
-            }
-            String name = p.getName();
-            /*
-             * handling special cases
-             */
-            // request_path adds to fn
-            if (name.equals("fn")) {
-                s.append("&fn=" + getAsString("request.path") + getAsString("fn"));
-                continue;
-            }
-            /*
-             * the rest is sent with its name
-             */
-            // parameters that are not set or internal are not sent
-            if ((!p.hasValue()) || (p.getType() == 'i')) {
-                continue;
-            }
-            s.append("&" + name + "=" + p.getAsString());
-        }
-        // kill first "&"
-        s.deleteCharAt(0);
-        return s.toString();
-    }
-
-    /**
-     * Returns request parameters in old '++++' form.
-     * 
-     * @return String with parameters in old '++++' form.
-     */
-    public String getAsOldString() {
-        StringBuffer s = new StringBuffer(50);
-        s.append(getAsString("request.path"));
-        s.append(getAsString("fn"));
-        s.append("+" + getAsString("pn"));
-        s.append("+" + getAsString("ws"));
-        s.append("+" + getAsString("mo"));
-        s.append("+" + getAsString("mk"));
-        s.append("+" + getAsString("wx"));
-        s.append("+" + getAsString("wy"));
-        s.append("+" + getAsString("ww"));
-        s.append("+" + getAsString("wh"));
-        return s.toString();
-    }
-
-    /**
-     * Set request parameters from javax.servlet.ServletRequest. Uses the
-     * Requests getParameter methods for 'fn=foo' style parameters.
-     * 
-     * @param request
-     *            ServletRequest to get parameters from.
-     */
-    // @SuppressWarnings("unchecked") // ServletRequest.getParameterNames()
-    // returns naked Enumeration
-    public void setWithParamRequest(ServletRequest request) {
-        setValue("servlet.request", request);
-        // go through all request parameters
-        for (@SuppressWarnings("unchecked")
-        Enumeration<String> i = request.getParameterNames(); i.hasMoreElements();) {
-            String name = (String) i.nextElement();
-            // is this a known parameter?
-            if (params.containsKey(name)) {
-                Parameter p = (Parameter) this.get(name);
-                // internal parameters are not set
-                if (p.getType() == 'i') {
-                    continue;
-                }
-                p.setValueFromString(request.getParameter(name));
-                continue;
-            }
-            // unknown parameters are just added with type 'r'
-            newParameter(name, null, request.getParameter(name), 'r');
-        }
-        // add path from request
-        setValue("request.path", ((HttpServletRequest) request).getPathInfo());
-    }
-
-    /**
-     * Set request parameters from query string. Uses the separator string qs to
-     * get 'fn=foo' style parameters.
-     * 
-     * @param qs
-     *            query string
-     * @param sep
-     *            parameter-separator string
-     */
-    public void setWithParamString(String qs, String sep) {
-        // go through all request parameters
-        String[] qa = qs.split(sep);
-        for (int i = 0; i < qa.length; i++) {
-            // split names and values on "="
-            String[] nv = qa[i].split("=");
-            try {
-                String name = URLDecoder.decode(nv[0], "UTF-8");
-                String val = URLDecoder.decode(nv[1], "UTF-8");
-                // is this a known parameter?
-                if (params.containsKey(name)) {
-                    Parameter p = (Parameter) this.get(name);
-                    // internal parameters are not set
-                    if (p.getType() == 'i') {
-                        continue;
-                    }
-                    p.setValueFromString(val);
-                    continue;
-                }
-                // unknown parameters are just added with type 'r'
-                newParameter(name, null, val, 'r');
-            } catch (UnsupportedEncodingException e) {
-                // this shouldn't happen anyway
-                e.printStackTrace();
-            }
-        }
-    }
-
-    /**
-     * Test if option string <code>opt</code> is set. Checks if the substring
-     * <code>opt</code> is contained in the options string <code>param</code>.
-     * Deprecated! use hasOption(String opt) for "mo"-options.
-     * 
-     * @param opt
-     *            Option string to be tested.
-     * @return boolean
-     */
-    public boolean hasOption(String param, String opt) {
-        String s = getAsString(param);
-        if (s != null) {
-            StringTokenizer i = new StringTokenizer(s, ",");
-            while (i.hasMoreTokens()) {
-                if (i.nextToken().equals(opt)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * The image file path to be accessed.
-     * 
-     * The mage file path is assembled from the servlets RequestPath and
-     * Parameter fn and normalized.
-     * 
-     * @return String the effective filepath.
-     */
-    public String getFilePath() {
-        String s = getAsString("request.path");
-        s += getAsString("fn");
-        return FileOps.normalName(s);
-    }
-
-    /* Property getter and setter */
-
-    /**
-     * Set the requests base URL parameter from a
-     * javax.sevlet.http.HttpServletRequest.
-     * 
-     * @param request
-     *            HttpServletRequest to set the base URL.
-     */
-    public void setBaseURL(javax.servlet.http.HttpServletRequest request) {
-        String baseURL = null;
-        // calculate base URL string from request until webapp
-        String s = request.getRequestURL().toString();
-        // get name of webapp 
-        String wn = request.getContextPath();
-        int eop = s.lastIndexOf(wn);
-        if (eop > 0) {
-            baseURL = s.substring(0, eop + wn.length());
-        } else {
-            // fall back
-            baseURL = "http://" + request.getServerName() + "/digitallibrary";
-        }
-        setValue("base.url", baseURL);
-    }
-
-    /**
-     * Returns the image.
-     * 
-     * @return DocuImage
-     */
-    public DocuImage getImage() {
-        return image;
-    }
-
-    /**
-     * Sets the image.
-     * 
-     * @param image
-     *            The image to set
-     */
-    public void setImage(DocuImage image) {
-        this.image = image;
-        setValue("docu.image", image);
-    }
-
-    /**
-     * @return
-     */
-    public HttpServletRequest getServletRequest() {
-        return servletRequest;
-    }
-
-}
--- a/servlet2/src/main/java/digilib/servlet/DocumentBean.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,329 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * 
- * DocumentBean -- Access control bean for JSP
- *
- * 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)
- */
-
-import java.util.List;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.log4j.Logger;
-
-import digilib.auth.AuthOpException;
-import digilib.auth.AuthOps;
-import digilib.io.DocuDirCache;
-import digilib.io.DocuDirectory;
-import digilib.io.FileOps.FileClass;
-import digilib.io.ImageInput;
-import digilib.io.ImageSet;
-import digilib.util.ImageSize;
-
-public class DocumentBean {
-
-	// general logger
-	private static Logger logger = Logger.getLogger("digilib.docubean");
-
-	// AuthOps object to check authorization
-	private AuthOps authOp;
-
-	// use authorization database
-	private boolean useAuthentication = true;
-
-	// path to add for authenticated access
-	private String authURLPath = "";
-
-	// DocuDirCache
-	private DocuDirCache dirCache = null;
-
-	// DigilibConfiguration object
-	private DigilibServletConfiguration dlConfig;
-
-	// DigilibRequest object
-	private DigilibServletRequest dlRequest = null;
-
-	/**
-	 * Constructor for DocumentBean.
-	 */
-	public DocumentBean() {
-        logger.debug("new DocumentBean");
-	}
-
-	public DocumentBean(ServletConfig conf) {
-        logger.debug("new DocumentBean");
-		try {
-			setConfig(conf);
-		} catch (Exception e) {
-			logger.fatal("ERROR: Unable to read config: ", e);
-		}
-	}
-
-	public void setConfig(ServletConfig conf) throws ServletException {
-		logger.debug("setConfig");
-		// get our ServletContext
-		ServletContext context = conf.getServletContext();
-		// see if there is a Configuration instance
-		dlConfig = (DigilibServletConfiguration) context
-				.getAttribute("digilib.servlet.configuration");
-		if (dlConfig == null) {
-			// create new Configuration
-			throw new ServletException("ERROR: No configuration!");
-		}
-
-		// get cache
-		dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
-
-		/*
-		 * authentication
-		 */
-		useAuthentication = dlConfig.getAsBoolean("use-authorization");
-		authOp = (AuthOps) dlConfig.getValue("servlet.auth.op");
-		authURLPath = dlConfig.getAsString("auth-url-path");
-		if (useAuthentication && (authOp == null)) {
-			throw new ServletException(
-					"ERROR: use-authorization configured but no AuthOp!");
-		}
-	}
-
-	/**
-	 * check if the request must be authorized to access filepath
-	 */
-	public boolean isAuthRequired(DigilibServletRequest request)
-			throws AuthOpException {
-		logger.debug("isAuthRequired");
-		return useAuthentication ? authOp.isAuthRequired(request) : false;
-	}
-
-	/**
-	 * check if the request is allowed to access filepath
-	 */
-	public boolean isAuthorized(DigilibServletRequest request) throws AuthOpException {
-		logger.debug("isAuthorized");
-		return useAuthentication ? authOp.isAuthorized(request) : true;
-	}
-
-	/**
-	 * return a list of authorization roles needed for request to access the
-	 * specified path
-	 */
-	public List<String> rolesForPath(DigilibServletRequest request) throws AuthOpException {
-		logger.debug("rolesForPath");
-		return useAuthentication ? authOp.rolesForPath(request) : null;
-	}
-
-	/**
-	 * check request authorization against a list of roles
-	 */
-	public boolean isRoleAuthorized(List<String> roles, DigilibServletRequest request) {
-		logger.debug("isRoleAuthorized");
-		return useAuthentication ? authOp.isRoleAuthorized(roles, request)
-				: true;
-	}
-
-	/**
-	 * check for authenticated access and redirect if necessary
-	 */
-	public boolean doAuthentication(HttpServletResponse response)
-			throws Exception {
-        logger.debug("doAuthenication-Method");
-		return doAuthentication(dlRequest, response);
-	}
-
-	/**
-	 * check for authenticated access and redirect if necessary
-	 */
-	public boolean doAuthentication(DigilibServletRequest request,
-			HttpServletResponse response) throws Exception {
-		logger.debug("doAuthentication");
-		if (!useAuthentication) {
-			// shortcut if no authentication
-			return true;
-		}
-		// quick fix: add auth-url-path to base.url
-        if (isAuthRequired(request)) {
-            String baseUrl = request.getAsString("base.url");
-            if (!baseUrl.endsWith(authURLPath)) {
-                request.setValue("base.url", baseUrl + "/" + authURLPath);
-            }
-        }
-		// check if we are already authenticated
-		if (((HttpServletRequest) request.getServletRequest()).getRemoteUser() == null) {
-			logger.debug("unauthenticated so far");
-			// if not maybe we must?
-			if (isAuthRequired(request)) {
-				logger.debug("auth required, redirect");
-				// we are not yet authenticated -> redirect
-				response.sendRedirect(request.getAsString("base.url")
-						+ ((HttpServletRequest) request.getServletRequest())
-								.getServletPath()
-						+ "?"
-						+ ((HttpServletRequest) request.getServletRequest())
-								.getQueryString());
-			}
-		}
-		return true;
-	}
-
-	/**
-	 * Sets the current DigilibRequest. Also completes information in the request.
-	 * 
-	 * @param dlRequest
-	 *            The dlRequest to set.
-	 */
-	public void setRequest(DigilibServletRequest dlRequest) throws Exception {
-		this.dlRequest = dlRequest;
-		if (dirCache == null) {
-			return;
-		}
-		String fn = dlRequest.getFilePath();
-		// get information about the file
-		ImageSet fileset = (ImageSet) dirCache.getFile(fn, dlRequest
-				.getAsInt("pn"), FileClass.IMAGE);
-		if (fileset == null) {
-			return;
-		}
-		// add file name
-		dlRequest.setValue("img.fn", fileset);
-		// add dpi
-		dlRequest.setValue("img.dpix", new Double(fileset.getResX()));
-		dlRequest.setValue("img.dpiy", new Double(fileset.getResY()));
-		// get number of pages in directory
-		DocuDirectory dd = dirCache.getDirectory(fn);
-		if (dd != null) {
-			// add pt
-			dlRequest.setValue("pt", dd.size());
-		}
-		// get original pixel size
-		ImageInput origfile = fileset.getBiggest();
-		// check image for size (TODO: just if mo=hires?)
-		ImageSize pixsize = origfile.getSize();
-		if (pixsize != null) {
-			// add pixel size
-			dlRequest.setValue("img.pix_x", new Integer(pixsize.getWidth()));
-			dlRequest.setValue("img.pix_y", new Integer(pixsize.getHeight()));
-		}
-	}
-
-	/**
-	 * get the first page number in the directory (not yet functional)
-	 */
-	public int getFirstPage(DigilibServletRequest request) {
-		logger.debug("getFirstPage");
-		return 1;
-	}
-
-	/**
-	 * get the number of pages/files in the directory
-	 */
-	public int getNumPages() throws Exception {
-		return getNumPages(dlRequest);
-	}
-
-    /**
-     * get the number of image pages/files in the directory
-     */
-    public int getNumPages(DigilibServletRequest request) throws Exception {
-        return getNumPages(request, FileClass.IMAGE);
-    }
-
-	/**
-	 * get the number of pages/files of type fc in the directory
-	 */
-	public int getNumPages(DigilibServletRequest request, FileClass fc) throws Exception {
-		logger.debug("getNumPages");
-		DocuDirectory dd = (dirCache != null) ? dirCache.getDirectory(request
-				.getFilePath()) : null;
-		if (dd != null) {
-			return dd.size(fc);
-		}
-		return 0;
-	}
-
-	/**
-	 * Returns the dlConfig.
-	 * 
-	 * @return DigilibConfiguration
-	 */
-	public DigilibServletConfiguration getDlConfig() {
-		return dlConfig;
-	}
-
-	/**
-	 * returns if the zoom area in the request can be moved
-	 * 
-	 * @return
-	 */
-	public boolean canMoveRight() {
-		float ww = dlRequest.getAsFloat("ww");
-		float wx = dlRequest.getAsFloat("wx");
-		return (ww + wx < 1.0);
-	}
-
-	/**
-	 * returns if the zoom area in the request can be moved
-	 * 
-	 * @return
-	 */
-	public boolean canMoveLeft() {
-		float ww = dlRequest.getAsFloat("ww");
-		float wx = dlRequest.getAsFloat("wx");
-		return ((ww < 1.0) && (wx > 0));
-	}
-
-	/**
-	 * returns if the zoom area in the request can be moved
-	 * 
-	 * @return
-	 */
-	public boolean canMoveUp() {
-		float wh = dlRequest.getAsFloat("wh");
-		float wy = dlRequest.getAsFloat("wy");
-		return ((wh < 1.0) && (wy > 0));
-	}
-
-	/**
-	 * returns if the zoom area in the request can be moved
-	 * 
-	 * @return
-	 */
-	public boolean canMoveDown() {
-		float wh = dlRequest.getAsFloat("wh");
-		float wy = dlRequest.getAsFloat("wy");
-		return (wh + wy < 1.0);
-	}
-
-	/**
-	 * @return Returns the dlRequest.
-	 */
-	public DigilibServletRequest getRequest() {
-		return dlRequest;
-	}
-
-}
--- a/servlet2/src/main/java/digilib/servlet/Initialiser.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/servlet2/src/main/java/digilib/servlet/Initialiser.java	Wed Mar 27 17:23:44 2013 +0100
@@ -43,6 +43,7 @@
 
 import digilib.auth.AuthOps;
 import digilib.auth.XMLAuthOps;
+import digilib.conf.DigilibServletConfiguration;
 import digilib.image.DocuImage;
 import digilib.io.AliasingDocuDirCache;
 import digilib.io.DocuDirCache;
@@ -95,6 +96,8 @@
 			// create new Configuration
 			try {
 				dlConfig = new DigilibServletConfiguration(context);
+				// add servlet version
+				dlConfig.newParameter("servlet.version", Scaler.getVersion(), null, 's');
 
 				/*
 				 * further initialization
--- a/servlet2/src/main/java/digilib/servlet/Scaler.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/servlet2/src/main/java/digilib/servlet/Scaler.java	Wed Mar 27 17:23:44 2013 +0100
@@ -42,6 +42,8 @@
 
 import digilib.auth.AuthOpException;
 import digilib.auth.AuthOps;
+import digilib.conf.DigilibServletConfiguration;
+import digilib.conf.DigilibServletRequest;
 import digilib.image.DocuImage;
 import digilib.image.ImageJobDescription;
 import digilib.image.ImageOpException;
@@ -59,7 +61,7 @@
     private static final long serialVersionUID = -5439198888139362735L;
 
     /** digilib servlet version (for all components) */
-    public static final String version = "2.1.4 noasync";
+    public static final String version = "2.1.5 noasync";
 
     /** servlet error codes */
     public static enum Error {UNKNOWN, AUTH, FILE, IMAGE};
@@ -236,13 +238,12 @@
             // check permissions
             if (useAuthorization) {
                 // get a list of required roles (empty if no restrictions)
-                List<String> rolesRequired = authOp.rolesForPath(
-                        jobTicket.getFilePath(), request);
+                List<String> rolesRequired = authOp.rolesForPath(dlRequest);
                 if (rolesRequired != null) {
                     authlog.debug("Role required: " + rolesRequired);
                     authlog.debug("User: " + request.getRemoteUser());
                     // is the current request/user authorized?
-                    if (!authOp.isRoleAuthorized(rolesRequired, request)) {
+                    if (!authOp.isRoleAuthorized(rolesRequired, dlRequest)) {
                         // send deny answer and abort
                         throw new AuthOpException();
                     }
--- a/servlet2/src/main/java/digilib/servlet/ScalerNoThread.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/servlet2/src/main/java/digilib/servlet/ScalerNoThread.java	Wed Mar 27 17:23:44 2013 +0100
@@ -38,6 +38,8 @@
 
 import digilib.auth.AuthOpException;
 import digilib.auth.AuthOps;
+import digilib.conf.DigilibServletConfiguration;
+import digilib.conf.DigilibServletRequest;
 import digilib.image.DocuImage;
 import digilib.image.ImageJobDescription;
 import digilib.image.ImageOpException;
@@ -54,7 +56,7 @@
     private static final long serialVersionUID = 1450947819851623306L;
 
     /** digilib servlet version (for all components) */
-    public static final String version = "1.9.0a5 nothread";
+    public static final String version = "2.1.5a nothread";
 
     /** servlet error codes */
     public static enum Error {UNKNOWN, AUTH, FILE, IMAGE};
@@ -224,13 +226,12 @@
             // check permissions
             if (useAuthorization) {
                 // get a list of required roles (empty if no restrictions)
-                List<String> rolesRequired = authOp.rolesForPath(
-                        jobTicket.getFilePath(), request);
+                List<String> rolesRequired = authOp.rolesForPath(dlRequest);
                 if (rolesRequired != null) {
                     authlog.debug("Role required: " + rolesRequired);
                     authlog.debug("User: " + request.getRemoteUser());
                     // is the current request/user authorized?
-                    if (!authOp.isRoleAuthorized(rolesRequired, request)) {
+                    if (!authOp.isRoleAuthorized(rolesRequired, dlRequest)) {
                         // send deny answer and abort
                         throw new AuthOpException();
                     }
--- a/servlet2/src/main/java/digilib/servlet/ServletOps.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * ServletOps -- Servlet utility class
- * 
- * 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)
- */
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.log4j.Logger;
-
-import digilib.image.DocuImage;
-import digilib.image.ImageOpException;
-import digilib.io.FileOps;
-
-public class ServletOps {
-
-    private static Logger logger = Logger.getLogger("servlet.op");
-
-    /**
-     * convert a string with a list of pathnames into an array of strings using
-     * the system's path separator string
-     */
-    public static String[] getPathArray(String paths) {
-        // split list into directories
-        StringTokenizer dirs = new StringTokenizer(paths,
-                java.io.File.pathSeparator);
-        int n = dirs.countTokens();
-        if (n < 1) {
-            return null;
-        }
-        // add directories into array
-        String[] pathArray = new String[n];
-        for (int i = 0; i < n; i++) {
-            pathArray[i] = dirs.nextToken();
-        }
-        return pathArray;
-    }
-
-    /**
-     * get a real File for a web app File.
-     * 
-     * If the File is not absolute the path is appended to the base directory of
-     * the web-app.
-     * 
-     * @param file
-     * @param sc
-     * @return
-     */
-    public static File getFile(File f, ServletContext sc) {
-        // is the filename absolute?
-        if (!f.isAbsolute()) {
-            // relative path -> use getRealPath to resolve in WEB-INF
-            String fn = sc.getRealPath(f.getPath());
-            if (fn == null) {
-                // TODO: use getResourceAsStream?
-                return null;
-            }
-            f = new File(fn);
-        }
-        return f;
-    }
-
-    /**
-     * get a real file name for a web app file pathname.
-     * 
-     * If filename starts with "/" its treated as absolute else the path is
-     * appended to the base directory of the web-app.
-     * 
-     * @param filename
-     * @param sc
-     * @return
-     */
-    public static String getFile(String filename, ServletContext sc) {
-        File f = new File(filename);
-        // is the filename absolute?
-        if (!f.isAbsolute()) {
-            // relative path -> use getRealPath to resolve in WEB-INF
-            filename = sc.getRealPath(filename);
-        }
-        return filename;
-    }
-
-    /**
-     * get a real File for a config File.
-     * 
-     * If the File is not absolute the path is appended to the WEB-INF directory
-     * of the web-app.
-     * 
-     * @param file
-     * @param sc
-     * @return
-     */
-    public static File getConfigFile(File f, ServletContext sc) {
-        String fn = f.getPath();
-        // is the filename absolute?
-        if (f.isAbsolute()) {
-            // does it exist?
-            if (f.canRead()) {
-                // fine
-                return f;
-            } else {
-                // try just the filename as relative
-                fn = f.getName();
-            }
-        }
-        // relative path -> use getRealPath to resolve in WEB-INF
-        String newfn = sc.getRealPath("WEB-INF/" + fn);
-        if (fn == null) {
-            // TODO: use getResourceAsStream?
-            return null;
-        }
-        f = new File(newfn);
-        return f;
-    }
-
-    /**
-     * get a real file name for a config file pathname.
-     * 
-     * If filename starts with "/" its treated as absolute else the path is
-     * appended to the WEB-INF directory of the web-app.
-     * 
-     * @param filename
-     * @param sc
-     * @return
-     */
-    public static String getConfigFile(String filename, ServletContext sc) {
-        File f = new File(filename);
-        // is the filename absolute?
-        if (!f.isAbsolute()) {
-            // relative path -> use getRealPath to resolve in WEB-INF
-            filename = sc.getRealPath("WEB-INF/" + filename);
-        }
-        return filename;
-    }
-
-    /**
-     * print a servlet response
-     */
-    public static void htmlMessage(String msg, HttpServletResponse response)
-            throws IOException {
-        htmlMessage("Scaler", msg, response);
-    }
-
-    /**
-     * print a servlet response
-     */
-    public static void htmlMessage(String title, String msg,
-            HttpServletResponse response) throws IOException {
-        response.setContentType("text/html; charset=iso-8859-1");
-        PrintWriter out = response.getWriter();
-        out.println("<html>");
-        out.println("<head><title>" + title + "</title></head>");
-        out.println("<body>");
-        out.println("<p>" + msg + "</p>");
-        out.println("</body></html>");
-    }
-
-    /**
-     * Transfers an image file as-is with the mime type mt.
-     * 
-     * The local file is copied to the <code>OutputStream</code> of the
-     * <code>ServletResponse</code>. If mt is null then the mime-type is
-     * auto-detected with mimeForFile.
-     * 
-     * @param f
-     *            Image file to be sent.
-     * @param mt
-     *            mime-type of the file.
-     * @param name
-     *            name of the download file (for application/x)
-     * @param res
-     *            ServletResponse where the image file will be sent.
-     * @throws ImageOpException
-     * @throws ServletException
-     *             Exception on sending data.
-     * @throws IOException
-     */
-    public static void sendFile(File f, String mt, String name,
-            HttpServletResponse response) throws ImageOpException, IOException {
-        // use default logger
-        ServletOps.sendFile(f, mt, name, response, ServletOps.logger);
-    }
-
-    /**
-     * Transfers an image file as-is with the mime type mt.
-     * 
-     * The local file is copied to the <code>OutputStream</code> of the
-     * <code>ServletResponse</code>. If mt is null then the mime-type is
-     * auto-detected with mimeForFile.
-     * @param f
-     *            Image file to be sent.
-     * @param mt
-     *            mime-type of the file.
-     * @param name 
-     *            name of the download file (for application/x)
-     * @param res
-     *            ServletResponse where the image file will be sent.
-     * @param logger
-     *            Logger to use
-     * @throws ImageOpException
-     * @throws ServletException Exception on sending data.
-     * @throws IOException 
-     */
-    public static void sendFile(File f, String mt, String name, HttpServletResponse response, Logger logger)
-            throws ImageOpException, IOException {
-        logger.debug("sendRawFile(" + mt + ", " + f + ")");
-    	if (response == null) {
-    		logger.error("No response!");
-    		return;
-    	}
-        if (mt == null) {
-            // auto-detect mime-type
-            mt = FileOps.mimeForFile(f);
-            if (mt == null) {
-                throw new ImageOpException("Unknown file type.");
-            }
-        }
-        response.setContentType(mt);
-        // open file
-        if (mt.startsWith("application")) {
-            if (name == null) {
-                // no download name -- use filename
-                name = f.getName();
-            }
-            response.addHeader("Content-Disposition", "attachment; filename=\""+name+"\"");
-        }
-        FileInputStream inFile = null;
-        try {
-            inFile = new FileInputStream(f);
-            OutputStream outStream = response.getOutputStream();
-            // TODO: should we set content length? 
-            // see http://www.prozesse-und-systeme.de/servletFlush.html
-            response.setContentLength( (int) f.length());
-            byte dataBuffer[] = new byte[4096];
-            int len;
-            while ((len = inFile.read(dataBuffer)) != -1) {
-                // copy out file
-                outStream.write(dataBuffer, 0, len);
-            }
-        } finally {
-            try {
-                if (inFile != null) {
-                    inFile.close();
-                }
-            } catch (IOException e) {
-                // nothing to do
-            }
-        }
-    }
-
-    /**
-     * Write image img to ServletResponse response.
-     * 
-     * @param img
-     * @param mimeType
-     * @param response
-     * @throws ImageOpException
-     * @throws ServletException Exception on sending data.
-     */
-    public static void sendImage(DocuImage img, String mimeType,
-            HttpServletResponse response) throws ImageOpException,
-            ServletException {
-        ServletOps.sendImage(img, mimeType, response, ServletOps.logger);
-    }
-
-    /**
-     * Write image img to ServletResponse response.
-     * 
-     * @param img
-     * @param mimeType
-     * @param response
-     * @param logger
-     * @throws ImageOpException
-     * @throws ServletException Exception on sending data.
-     */
-    public static void sendImage(DocuImage img, String mimeType,
-            HttpServletResponse response, Logger logger) throws ImageOpException,
-            ServletException {
-    	if (response == null) {
-    		logger.error("No response!");
-    		return;
-    	}
-        //logger.debug("sending to response: ("+ headersToString(response) + ") committed=" + response.isCommitted());
-        logger.debug("sending to response. committed=" + response.isCommitted());
-        // TODO: should we erase or replace old last-modified header?
-        try {
-            OutputStream outstream = response.getOutputStream();
-            // setup output -- if mime type is set use that otherwise
-            // if source is JPG then dest will be JPG else it's PNG
-            if (mimeType == null) {
-                mimeType = img.getMimetype();
-                if (mimeType == null) {
-                    // still no mime-type
-                    logger.warn("sendImage without mime-type! using image/jpeg.");
-                    mimeType = "image/jpeg";
-                }
-            }
-            if ((mimeType.equals("image/jpeg") || mimeType.equals("image/jp2") || 
-                    mimeType.equals("image/fpx"))) {
-                mimeType = "image/jpeg";
-            } else {
-                mimeType = "image/png";
-            }
-            // write the image
-            response.setContentType(mimeType);
-            img.writeImage(mimeType, outstream);
-        } catch (IOException e) {
-            throw new ServletException("Error sending image:", e);
-        }
-        // TODO: should we: finally { img.dispose(); }
-    }
-
-    /** Returns text representation of headers for debuggging purposes.
-     * @param req
-     * @return
-     */
-    public static String headersToString(HttpServletRequest req) {
-        String s = "";
-        @SuppressWarnings("unchecked")
-        Enumeration<String> hns = req.getHeaderNames();
-        while (hns.hasMoreElements()) {
-            String hn = hns.nextElement();
-            s += hn + "=" + req.getHeader(hn) + "; ";
-        }
-        return s;
-    }
-    
-    
-}
--- a/servlet3/pom.xml	Wed Mar 27 13:02:27 2013 +0100
+++ b/servlet3/pom.xml	Wed Mar 27 17:23:44 2013 +0100
@@ -23,18 +23,16 @@
   </build>
   <dependencies>
   	<dependency>
-  		<groupId>digilib</groupId>
-  		<artifactId>digilib-common</artifactId>
-  		<type>jar</type>
-  		<scope>compile</scope>
-  	</dependency>
-  	<dependency>
   		<groupId>org.mortbay.jetty</groupId>
   		<artifactId>servlet-api</artifactId>
   		<version>3.0.20100224</version>
   		<type>jar</type>
   		<scope>provided</scope>
   	</dependency>
+  	<dependency>
+  		<groupId>digilib</groupId>
+  		<artifactId>digilib-servlet</artifactId>
+  	</dependency>
   </dependencies>
   <description>digilib servlet components using asynchronous servlet API.</description>
 </project>
\ No newline at end of file
--- a/servlet3/src/main/java/digilib/servlet/AsyncServletWorker.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/servlet3/src/main/java/digilib/servlet/AsyncServletWorker.java	Wed Mar 27 17:23:44 2013 +0100
@@ -37,6 +37,7 @@
 
 import org.apache.log4j.Logger;
 
+import digilib.conf.DigilibConfiguration;
 import digilib.image.DocuImage;
 import digilib.image.ImageJobDescription;
 import digilib.image.ImageOpException;
@@ -90,11 +91,6 @@
      */
     @Override
     public void run() {
-        // get fresh response
-        HttpServletResponse response = (HttpServletResponse) asyncContext
-                .getResponse();
-        logger.debug("working on response: ("
-                + ServletOps.headersToString(response) + ")");
         try {
             // render the image
             DocuImage img = imageWorker.call();
--- a/servlet3/src/main/java/digilib/servlet/DigilibServletConfiguration.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * DigilibServletConfiguration.java
- * 
- * Class holding all parameters for digilib servlet.
- * 
- * %%
- * 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)
- * 
- */
-
-import java.io.File;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.servlet.ServletContext;
-
-import digilib.image.DocuImageImpl;
-import digilib.io.FileOps;
-import digilib.util.Parameter;
-import digilib.util.XMLListLoader;
-
-/**
- * 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 DigilibServletConfiguration extends DigilibConfiguration {
-
-    /** 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);
-
-    /** counter for open HttpRequests (mostly for debugging) */
-    public AtomicInteger openRequestCnt = new AtomicInteger(0);
-
-    /**
-     * Definition of parameters and default values.
-     */
-    protected void initParams() {
-        /*
-         * Definition of parameters and default values. System parameters that
-         * are not read from config file have a type 's'.
-         */
-
-        // digilib servlet version
-        newParameter("servlet.version", digilib.servlet.Scaler.getVersion(), null, 's');
-        // configuration file location
-        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'
-         */
-
-        // image file to send in case of error
-        newParameter("error-image", new File("img/digilib-error.png"), null, 'f');
-        // image file to send if access is denied
-        newParameter("denied-image", new File("img/digilib-denied.png"), null, 'f');
-        // image file to send if image file not found
-        newParameter("notfound-image", new File("img/digilib-notfound.png"), null, 'f');
-        // base directories in order of preference (prescaled versions last)
-        String[] bd = { "sample-images" };
-        newParameter("basedir-list", bd, null, 'f');
-        // use authentication information
-        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');
-        // 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');
-        // 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');
-        // 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');
-    }
-
-    /**
-     * 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
-     */
-    @SuppressWarnings("unchecked")
-    public void readConfig(ServletContext c) throws Exception {
-
-        /*
-         * Get config file name. The file name is first looked for as an init
-         * parameter, then in a fixed location in the webapp.
-         */
-        if (c == null) {
-            // no config no file...
-            return;
-        }
-        String fn = c.getInitParameter("config-file");
-        if (fn == null) {
-            logger.debug("readConfig: no param config-file");
-            fn = ServletOps.getConfigFile("digilib-config.xml", c);
-        }
-        File f = new File(fn);
-        if (f.canRead()) {
-            // setup config file list reader
-            XMLListLoader lilo = new XMLListLoader("digilib-config", "parameter", "name", "value");
-            // read config file into HashMap
-            Map<String, String> confTable = lilo.loadUri(f.toURI());
-
-            // set config file path parameter
-            setValue("servlet.config.file", f.getCanonicalPath());
-
-            /*
-             * read parameters
-             */
-
-            for (Entry<String, String> confEntry : confTable.entrySet()) {
-                Parameter p = get(confEntry.getKey());
-                if (p != null) {
-                    if (p.getType() == 's') {
-                        // type 's' Parameters are not overwritten.
-                        continue;
-                    }
-                    if (!p.setValueFromString(confEntry.getValue())) {
-                        /*
-                         * automatic conversion failed -- try special cases
-                         */
-
-                        // basedir-list
-                        if (confEntry.getKey().equals("basedir-list")) {
-                            // split list into directories
-                            String[] dirs = FileOps.pathToArray(confEntry.getValue());
-                            for (int j = 0; j < dirs.length; j++) {
-                                // make relative directory paths be inside the
-                                // webapp
-                                dirs[j] = ServletOps.getFile(dirs[j], c);
-                            }
-                            if (dirs != null) {
-                                p.setValue(dirs);
-                            }
-                        }
-                    }
-                } else {
-                    // parameter unknown -- just add
-                    newParameter(confEntry.getKey(), null, confEntry.getValue(), 'f');
-                }
-            }
-        } else {
-            logger.warn("No digilib config file! Using defaults!");
-            // update basedir-list
-            String[] dirs = (String[]) this.getValue("basedir-list");
-            for (int j = 0; j < dirs.length; j++) {
-                // make relative directory paths be inside the
-                // webapp
-                dirs[j] = ServletOps.getFile(dirs[j], c);
-            }
-        }
-        // initialise static DocuImage class instance
-        DigilibServletConfiguration.docuImageClass = (Class<DocuImageImpl>) Class.forName(getAsString("docuimage-class"));
-        setValue("servlet.docuimage.version", getDocuImageInstance().getVersion());
-    }
-
-}
--- a/servlet3/src/main/java/digilib/servlet/DigilibServletRequest.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,542 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * 
- * DigilibServletRequest.java
- *
- * lightweight class carrying all parameters for a request to digilib
- * 
- * %%
- * Copyright (C) 2002 - 2013 MPIWG Berlin, WTWG Uni Bern
- * %%
- * 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: Robert Casties (robcast@berlios.de),
- *          Christian Luginbuehl
- * 
- * Created on 27. August 2002, 19:43
- */
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-
-import digilib.image.DocuImage;
-import digilib.io.FileOps;
-import digilib.util.OptionsSet;
-import digilib.util.Parameter;
-
-/**
- * Class holding the parameters of a digilib user request. The parameters are
- * mostly named like the servlet parameters: <br>
- * request_path: url of the page/document. <br>
- * fn: url of the page/document. <br>
- * pn: page number. <br>
- * dw: width of result window in pixels. <br>
- * dh: height of result window in pixels. <br>
- * wx: left edge of image area (float from 0 to 1). <br>
- * wy: top edge of image area (float from 0 to 1). <br>
- * ww: width of image area(float from 0 to 1). <br>
- * wh: height of image area(float from 0 to 1). <br>
- * ws: scale factor. <br>
- * mo: special options like 'fit' for gifs. <br>
- * mk: list of marks. <br>
- * pt: total number of pages (generated by sevlet). <br>
- * baseURL: base URL (from http:// to below /servlet). <br>
- * ...et alii
- * 
- * @author casties
- * 
- */
-public class DigilibServletRequest extends DigilibRequest {
-
-    protected DocuImage image; // internal DocuImage instance for this request
-
-    protected HttpServletRequest servletRequest; // internal ServletRequest
-
-    /**
-     * Creates a new instance of DigilibRequest with parameters from a
-     * ServletRequest. All undefined parameters are set to default values.
-     * 
-     * @param request
-     */
-    public DigilibServletRequest(HttpServletRequest request) {
-        setWithRequest(request);
-        initOptions();
-    }
-
-    /**
-     * set up parameters.
-     * 
-     */
-    protected void initParams() {
-        /*
-         * Definition of parameters and default values. Parameter of type 's'
-         * are for the servlet.
-         */
-
-        // url of the page/document (second part)
-        newParameter("fn", "", null, 's');
-        // page number
-        newParameter("pn", new Integer(1), 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", this.options, 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');
-        // color conversion operation
-        newParameter("colop", "", 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
-        newParameter("docu.image", image, null, 'i');
-        image = null;
-        // HttpServletRequest for this request
-        newParameter("servlet.request", servletRequest, null, 'i');
-        servletRequest = null;
-
-        /*
-         * 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');
-        // marks
-        newParameter("mk", "", null, 'c');
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see digilib.servlet.ParameterMap#initOptions()
-     */
-    @Override
-    protected void initOptions() {
-        options = (OptionsSet) getValue("mo");
-    }
-
-    /**
-     * Populate the request object with data from a ServletRequest.
-     * 
-     * 
-     * @param request
-     */
-    public void setWithRequest(HttpServletRequest request) {
-        servletRequest = request;
-        // decide if it's old-style or new-style
-        String qs = ((HttpServletRequest) request).getQueryString();
-        if (qs != null) {
-            if (qs.indexOf("&amp;") > -1) {
-                // &amp; separator
-                setWithParamString(qs, "&amp;");
-            } else if (qs.indexOf(";") > -1) {
-                // ; separator
-                setWithParamString(qs, ";");
-            } else if (qs.indexOf('=') > -1) {
-                // standard '&' parameters
-                setWithParamRequest(request);
-            } else {
-                setWithOldString(qs);
-            }
-        }
-        setValue("servlet.request", request);
-        // add path from request
-        setValue("request.path", ((HttpServletRequest) request).getPathInfo());
-        // set the baseURL
-        setBaseURL((HttpServletRequest) request);
-    }
-
-    /**
-     * Populate a request from a string in the old "++++" parameter form.
-     * 
-     * @param queryString
-     *            String with paramters in the old "+++" form.
-     */
-    public void setWithOldString(String queryString) {
-        if (queryString == null) {
-            return;
-        }
-        // enable the passing of delimiter to get empty parameters
-        StringTokenizer query = new StringTokenizer(queryString, "+", true);
-        String token;
-        // first parameter FN
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("fn", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // second parameter PN
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("pn", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // third parameter WS
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("ws", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // fourth parameter MO
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("mo", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // fifth parameter MK
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("mk", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // sixth parameter WX
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("wx", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // seventh parameter WY
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("wy", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // eigth parameter WW
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("ww", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-        // ninth parameter WH
-        if (query.hasMoreTokens()) {
-            token = query.nextToken();
-            if (!token.equals("+")) {
-                setValueFromString("wh", token);
-                if (query.hasMoreTokens()) {
-                    query.nextToken();
-                }
-            }
-        }
-    }
-
-    /**
-     * Return the request parameters as a String in the parameter form
-     * 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not included.
-     * 
-     * @return String of request parameters in parameter form.
-     */
-    public String getAsString() {
-        return getAsString(0);
-    }
-
-    /**
-     * Return the request parameters of a given type type as a String in the
-     * parameter form 'fn=/icons&amp;pn=1'. Empty (undefined) fields are not
-     * included.
-     * 
-     * @return String of request parameters in parameter form.
-     */
-    public String getAsString(int type) {
-        StringBuffer s = new StringBuffer(50);
-        // go through all values
-        for (Parameter p : params.values()) {
-            if ((type > 0) && (p.getType() != type)) {
-                // skip the wrong types
-                continue;
-            }
-            String name = p.getName();
-            /*
-             * handling special cases
-             */
-            // request_path adds to fn
-            if (name.equals("fn")) {
-                s.append("&fn=" + getAsString("request.path") + getAsString("fn"));
-                continue;
-            }
-            /*
-             * the rest is sent with its name
-             */
-            // parameters that are not set or internal are not sent
-            if ((!p.hasValue()) || (p.getType() == 'i')) {
-                continue;
-            }
-            s.append("&" + name + "=" + p.getAsString());
-        }
-        // kill first "&"
-        s.deleteCharAt(0);
-        return s.toString();
-    }
-
-    /**
-     * Returns request parameters in old '++++' form.
-     * 
-     * @return String with parameters in old '++++' form.
-     */
-    public String getAsOldString() {
-        StringBuffer s = new StringBuffer(50);
-        s.append(getAsString("request.path"));
-        s.append(getAsString("fn"));
-        s.append("+" + getAsString("pn"));
-        s.append("+" + getAsString("ws"));
-        s.append("+" + getAsString("mo"));
-        s.append("+" + getAsString("mk"));
-        s.append("+" + getAsString("wx"));
-        s.append("+" + getAsString("wy"));
-        s.append("+" + getAsString("ww"));
-        s.append("+" + getAsString("wh"));
-        return s.toString();
-    }
-
-    /**
-     * Set request parameters from javax.servlet.ServletRequest. Uses the
-     * Requests getParameter methods for 'fn=foo' style parameters.
-     * 
-     * @param request
-     *            ServletRequest to get parameters from.
-     */
-    // @SuppressWarnings("unchecked") // ServletRequest.getParameterNames()
-    // returns naked Enumeration
-    public void setWithParamRequest(ServletRequest request) {
-        setValue("servlet.request", request);
-        // go through all request parameters
-        for (Enumeration<String> i = request.getParameterNames(); i.hasMoreElements();) {
-            String name = (String) i.nextElement();
-            // is this a known parameter?
-            if (params.containsKey(name)) {
-                Parameter p = (Parameter) this.get(name);
-                // internal parameters are not set
-                if (p.getType() == 'i') {
-                    continue;
-                }
-                p.setValueFromString(request.getParameter(name));
-                continue;
-            }
-            // unknown parameters are just added with type 'r'
-            newParameter(name, null, request.getParameter(name), 'r');
-        }
-        // add path from request
-        setValue("request.path", ((HttpServletRequest) request).getPathInfo());
-    }
-
-    /**
-     * Set request parameters from query string. Uses the separator string qs to
-     * get 'fn=foo' style parameters.
-     * 
-     * @param qs
-     *            query string
-     * @param sep
-     *            parameter-separator string
-     */
-    public void setWithParamString(String qs, String sep) {
-        // go through all request parameters
-        String[] qa = qs.split(sep);
-        for (int i = 0; i < qa.length; i++) {
-            // split names and values on "="
-            String[] nv = qa[i].split("=");
-            try {
-                String name = URLDecoder.decode(nv[0], "UTF-8");
-                String val = URLDecoder.decode(nv[1], "UTF-8");
-                // is this a known parameter?
-                if (params.containsKey(name)) {
-                    Parameter p = (Parameter) this.get(name);
-                    // internal parameters are not set
-                    if (p.getType() == 'i') {
-                        continue;
-                    }
-                    p.setValueFromString(val);
-                    continue;
-                }
-                // unknown parameters are just added with type 'r'
-                newParameter(name, null, val, 'r');
-            } catch (UnsupportedEncodingException e) {
-                // this shouldn't happen anyway
-                e.printStackTrace();
-            }
-        }
-    }
-
-    /**
-     * Test if option string <code>opt</code> is set. Checks if the substring
-     * <code>opt</code> is contained in the options string <code>param</code>.
-     * Deprecated! use hasOption(String opt) for "mo"-options.
-     * 
-     * @param opt
-     *            Option string to be tested.
-     * @return boolean
-     */
-    public boolean hasOption(String param, String opt) {
-        String s = getAsString(param);
-        if (s != null) {
-            StringTokenizer i = new StringTokenizer(s, ",");
-            while (i.hasMoreTokens()) {
-                if (i.nextToken().equals(opt)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * The image file path to be accessed.
-     * 
-     * The mage file path is assembled from the servlets RequestPath and
-     * Parameter fn and normalized.
-     * 
-     * @return String the effective filepath.
-     */
-    public String getFilePath() {
-        String s = getAsString("request.path");
-        s += getAsString("fn");
-        return FileOps.normalName(s);
-    }
-
-    /* Property getter and setter */
-
-    /**
-     * Set the requests base URL parameter from a
-     * javax.sevlet.http.HttpServletRequest.
-     * 
-     * @param request
-     *            HttpServletRequest to set the base URL.
-     */
-    public void setBaseURL(javax.servlet.http.HttpServletRequest request) {
-        String baseURL = null;
-        // calculate base URL string from request until webapp
-        String s = request.getRequestURL().toString();
-        // get name of webapp 
-        String wn = request.getContextPath();
-        int eop = s.lastIndexOf(wn);
-        if (eop > 0) {
-            baseURL = s.substring(0, eop + wn.length());
-        } else {
-            // fall back
-            baseURL = "http://" + request.getServerName() + "/digitallibrary";
-        }
-        setValue("base.url", baseURL);
-    }
-
-    /**
-     * Returns the image.
-     * 
-     * @return DocuImage
-     */
-    public DocuImage getImage() {
-        return image;
-    }
-
-    /**
-     * Sets the image.
-     * 
-     * @param image
-     *            The image to set
-     */
-    public void setImage(DocuImage image) {
-        this.image = image;
-        setValue("docu.image", image);
-    }
-
-    /**
-     * @return
-     */
-    public HttpServletRequest getServletRequest() {
-        return servletRequest;
-    }
-
-}
--- a/servlet3/src/main/java/digilib/servlet/DocumentBean.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,329 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * 
- * DocumentBean -- Access control bean for JSP
- *
- * 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)
- */
-
-import java.util.List;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.log4j.Logger;
-
-import digilib.auth.AuthOpException;
-import digilib.auth.AuthOps;
-import digilib.io.DocuDirCache;
-import digilib.io.DocuDirectory;
-import digilib.io.FileOps.FileClass;
-import digilib.io.ImageInput;
-import digilib.io.ImageSet;
-import digilib.util.ImageSize;
-
-public class DocumentBean {
-
-	// general logger
-	private static Logger logger = Logger.getLogger("digilib.docubean");
-
-	// AuthOps object to check authorization
-	private AuthOps authOp;
-
-	// use authorization database
-	private boolean useAuthentication = true;
-
-	// path to add for authenticated access
-	private String authURLPath = "";
-
-	// DocuDirCache
-	private DocuDirCache dirCache = null;
-
-	// DigilibConfiguration object
-	private DigilibServletConfiguration dlConfig;
-
-	// DigilibRequest object
-	private DigilibServletRequest dlRequest = null;
-
-	/**
-	 * Constructor for DocumentBean.
-	 */
-	public DocumentBean() {
-        logger.debug("new DocumentBean");
-	}
-
-	public DocumentBean(ServletConfig conf) {
-        logger.debug("new DocumentBean");
-		try {
-			setConfig(conf);
-		} catch (Exception e) {
-			logger.fatal("ERROR: Unable to read config: ", e);
-		}
-	}
-
-	public void setConfig(ServletConfig conf) throws ServletException {
-		logger.debug("setConfig");
-		// get our ServletContext
-		ServletContext context = conf.getServletContext();
-		// see if there is a Configuration instance
-		dlConfig = (DigilibServletConfiguration) context
-				.getAttribute("digilib.servlet.configuration");
-		if (dlConfig == null) {
-			// create new Configuration
-			throw new ServletException("ERROR: No configuration!");
-		}
-
-		// get cache
-		dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
-
-		/*
-		 * authentication
-		 */
-		useAuthentication = dlConfig.getAsBoolean("use-authorization");
-		authOp = (AuthOps) dlConfig.getValue("servlet.auth.op");
-		authURLPath = dlConfig.getAsString("auth-url-path");
-		if (useAuthentication && (authOp == null)) {
-			throw new ServletException(
-					"ERROR: use-authorization configured but no AuthOp!");
-		}
-	}
-
-	/**
-	 * check if the request must be authorized to access filepath
-	 */
-	public boolean isAuthRequired(DigilibServletRequest request)
-			throws AuthOpException {
-		logger.debug("isAuthRequired");
-		return useAuthentication ? authOp.isAuthRequired(request) : false;
-	}
-
-	/**
-	 * check if the request is allowed to access filepath
-	 */
-	public boolean isAuthorized(DigilibServletRequest request) throws AuthOpException {
-		logger.debug("isAuthorized");
-		return useAuthentication ? authOp.isAuthorized(request) : true;
-	}
-
-	/**
-	 * return a list of authorization roles needed for request to access the
-	 * specified path
-	 */
-	public List<String> rolesForPath(DigilibServletRequest request) throws AuthOpException {
-		logger.debug("rolesForPath");
-		return useAuthentication ? authOp.rolesForPath(request) : null;
-	}
-
-	/**
-	 * check request authorization against a list of roles
-	 */
-	public boolean isRoleAuthorized(List<String> roles, DigilibServletRequest request) {
-		logger.debug("isRoleAuthorized");
-		return useAuthentication ? authOp.isRoleAuthorized(roles, request)
-				: true;
-	}
-
-	/**
-	 * check for authenticated access and redirect if necessary
-	 */
-	public boolean doAuthentication(HttpServletResponse response)
-			throws Exception {
-        logger.debug("doAuthenication-Method");
-		return doAuthentication(dlRequest, response);
-	}
-
-	/**
-	 * check for authenticated access and redirect if necessary
-	 */
-	public boolean doAuthentication(DigilibServletRequest request,
-			HttpServletResponse response) throws Exception {
-		logger.debug("doAuthentication");
-		if (!useAuthentication) {
-			// shortcut if no authentication
-			return true;
-		}
-		// quick fix: add auth-url-path to base.url
-        if (isAuthRequired(request)) {
-            String baseUrl = request.getAsString("base.url");
-            if (!baseUrl.endsWith(authURLPath)) {
-                request.setValue("base.url", baseUrl + "/" + authURLPath);
-            }
-        }
-		// check if we are already authenticated
-		if (((HttpServletRequest) request.getServletRequest()).getRemoteUser() == null) {
-			logger.debug("unauthenticated so far");
-			// if not maybe we must?
-			if (isAuthRequired(request)) {
-				logger.debug("auth required, redirect");
-				// we are not yet authenticated -> redirect
-				response.sendRedirect(request.getAsString("base.url")
-						+ ((HttpServletRequest) request.getServletRequest())
-								.getServletPath()
-						+ "?"
-						+ ((HttpServletRequest) request.getServletRequest())
-								.getQueryString());
-			}
-		}
-		return true;
-	}
-
-	/**
-	 * Sets the current DigilibRequest. Also completes information in the request.
-	 * 
-	 * @param dlRequest
-	 *            The dlRequest to set.
-	 */
-	public void setRequest(DigilibServletRequest dlRequest) throws Exception {
-		this.dlRequest = dlRequest;
-		if (dirCache == null) {
-			return;
-		}
-		String fn = dlRequest.getFilePath();
-		// get information about the file
-		ImageSet fileset = (ImageSet) dirCache.getFile(fn, dlRequest
-				.getAsInt("pn"), FileClass.IMAGE);
-		if (fileset == null) {
-			return;
-		}
-		// add file name
-		dlRequest.setValue("img.fn", fileset);
-		// add dpi
-		dlRequest.setValue("img.dpix", new Double(fileset.getResX()));
-		dlRequest.setValue("img.dpiy", new Double(fileset.getResY()));
-		// get number of pages in directory
-		DocuDirectory dd = dirCache.getDirectory(fn);
-		if (dd != null) {
-			// add pt
-			dlRequest.setValue("pt", dd.size());
-		}
-		// get original pixel size
-		ImageInput origfile = fileset.getBiggest();
-		// check image for size (TODO: just if mo=hires?)
-		ImageSize pixsize = origfile.getSize();
-		if (pixsize != null) {
-			// add pixel size
-			dlRequest.setValue("img.pix_x", new Integer(pixsize.getWidth()));
-			dlRequest.setValue("img.pix_y", new Integer(pixsize.getHeight()));
-		}
-	}
-
-	/**
-	 * get the first page number in the directory (not yet functional)
-	 */
-	public int getFirstPage(DigilibServletRequest request) {
-		logger.debug("getFirstPage");
-		return 1;
-	}
-
-	/**
-	 * get the number of pages/files in the directory
-	 */
-	public int getNumPages() throws Exception {
-		return getNumPages(dlRequest);
-	}
-
-    /**
-     * get the number of image pages/files in the directory
-     */
-    public int getNumPages(DigilibServletRequest request) throws Exception {
-        return getNumPages(request, FileClass.IMAGE);
-    }
-
-	/**
-	 * get the number of pages/files of type fc in the directory
-	 */
-	public int getNumPages(DigilibServletRequest request, FileClass fc) throws Exception {
-		logger.debug("getNumPages");
-		DocuDirectory dd = (dirCache != null) ? dirCache.getDirectory(request
-				.getFilePath()) : null;
-		if (dd != null) {
-			return dd.size(fc);
-		}
-		return 0;
-	}
-
-	/**
-	 * Returns the dlConfig.
-	 * 
-	 * @return DigilibConfiguration
-	 */
-	public DigilibServletConfiguration getDlConfig() {
-		return dlConfig;
-	}
-
-	/**
-	 * returns if the zoom area in the request can be moved
-	 * 
-	 * @return
-	 */
-	public boolean canMoveRight() {
-		float ww = dlRequest.getAsFloat("ww");
-		float wx = dlRequest.getAsFloat("wx");
-		return (ww + wx < 1.0);
-	}
-
-	/**
-	 * returns if the zoom area in the request can be moved
-	 * 
-	 * @return
-	 */
-	public boolean canMoveLeft() {
-		float ww = dlRequest.getAsFloat("ww");
-		float wx = dlRequest.getAsFloat("wx");
-		return ((ww < 1.0) && (wx > 0));
-	}
-
-	/**
-	 * returns if the zoom area in the request can be moved
-	 * 
-	 * @return
-	 */
-	public boolean canMoveUp() {
-		float wh = dlRequest.getAsFloat("wh");
-		float wy = dlRequest.getAsFloat("wy");
-		return ((wh < 1.0) && (wy > 0));
-	}
-
-	/**
-	 * returns if the zoom area in the request can be moved
-	 * 
-	 * @return
-	 */
-	public boolean canMoveDown() {
-		float wh = dlRequest.getAsFloat("wh");
-		float wy = dlRequest.getAsFloat("wy");
-		return (wh + wy < 1.0);
-	}
-
-	/**
-	 * @return Returns the dlRequest.
-	 */
-	public DigilibServletRequest getRequest() {
-		return dlRequest;
-	}
-
-}
--- a/servlet3/src/main/java/digilib/servlet/Initialiser.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/servlet3/src/main/java/digilib/servlet/Initialiser.java	Wed Mar 27 17:23:44 2013 +0100
@@ -44,6 +44,8 @@
 
 import digilib.auth.AuthOps;
 import digilib.auth.XMLAuthOps;
+import digilib.conf.DigilibConfiguration;
+import digilib.conf.DigilibServletConfiguration;
 import digilib.image.DocuImage;
 import digilib.io.AliasingDocuDirCache;
 import digilib.io.DocuDirCache;
@@ -51,7 +53,7 @@
 import digilib.util.DigilibJobCenter;
 
 /**
- * Singleton initalisation listener for setup tasks and resources.
+ * Singleton initialisation listener for setup tasks and resources.
  * 
  * @author casties
  *  
@@ -96,6 +98,8 @@
 			// create new Configuration
 			try {
 				dlConfig = new DigilibServletConfiguration(context);
+                // add servlet version
+                dlConfig.newParameter("servlet.version", Scaler.getVersion(), null, 's');
 
 				/*
 				 * further initialization
--- a/servlet3/src/main/java/digilib/servlet/Scaler.java	Wed Mar 27 13:02:27 2013 +0100
+++ b/servlet3/src/main/java/digilib/servlet/Scaler.java	Wed Mar 27 17:23:44 2013 +0100
@@ -43,6 +43,8 @@
 
 import digilib.auth.AuthOpException;
 import digilib.auth.AuthOps;
+import digilib.conf.DigilibConfiguration;
+import digilib.conf.DigilibServletRequest;
 import digilib.image.DocuImage;
 import digilib.image.ImageJobDescription;
 import digilib.image.ImageOpException;
@@ -57,7 +59,7 @@
     private static final long serialVersionUID = 5289386646192471549L;
 
     /** digilib servlet version (for all components) */
-    public static final String version = "2.1.4 async";
+    public static final String version = "2.1.5 async";
 
     /** servlet error codes */
     public static enum Error {
@@ -268,13 +270,12 @@
             // check permissions
             if (useAuthorization) {
                 // get a list of required roles (empty if no restrictions)
-                List<String> rolesRequired = authOp.rolesForPath(
-                        jobTicket.getFilePath(), request);
+                List<String> rolesRequired = authOp.rolesForPath(dlRequest);
                 if (rolesRequired != null) {
                     authlog.debug("Role required: " + rolesRequired);
                     authlog.debug("User: " + request.getRemoteUser());
                     // is the current request/user authorized?
-                    if (!authOp.isRoleAuthorized(rolesRequired, request)) {
+                    if (!authOp.isRoleAuthorized(rolesRequired, dlRequest)) {
                         // send deny answer and abort
                         throw new AuthOpException();
                     }
--- a/servlet3/src/main/java/digilib/servlet/ServletOps.java	Wed Mar 27 13:02:27 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,376 +0,0 @@
-package digilib.servlet;
-
-/*
- * #%L
- * 
- * ServletOps -- Servlet utility class
- * 
- * 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)
- */
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.log4j.Logger;
-
-import digilib.image.DocuImage;
-import digilib.image.ImageOpException;
-import digilib.io.FileOps;
-
-public class ServletOps {
-
-    private static Logger logger = Logger.getLogger("servlet.op");
-
-    /**
-     * convert a string with a list of pathnames into an array of strings using
-     * the system's path separator string
-     */
-    public static String[] getPathArray(String paths) {
-        // split list into directories
-        StringTokenizer dirs = new StringTokenizer(paths,
-                java.io.File.pathSeparator);
-        int n = dirs.countTokens();
-        if (n < 1) {
-            return null;
-        }
-        // add directories into array
-        String[] pathArray = new String[n];
-        for (int i = 0; i < n; i++) {
-            pathArray[i] = dirs.nextToken();
-        }
-        return pathArray;
-    }
-
-    /**
-     * get a real File for a web app File.
-     * 
-     * If the File is not absolute the path is appended to the base directory of
-     * the web-app.
-     * 
-     * @param file
-     * @param sc
-     * @return
-     */
-    public static File getFile(File f, ServletContext sc) {
-        // is the filename absolute?
-        if (!f.isAbsolute()) {
-            // relative path -> use getRealPath to resolve in WEB-INF
-            String fn = sc.getRealPath(f.getPath());
-            if (fn == null) {
-                // TODO: use getResourceAsStream?
-                return null;
-            }
-            f = new File(fn);
-        }
-        return f;
-    }
-
-    /**
-     * get a real file name for a web app file pathname.
-     * 
-     * If filename starts with "/" its treated as absolute else the path is
-     * appended to the base directory of the web-app.
-     * 
-     * @param filename
-     * @param sc
-     * @return
-     */
-    public static String getFile(String filename, ServletContext sc) {
-        File f = new File(filename);
-        // is the filename absolute?
-        if (!f.isAbsolute()) {
-            // relative path -> use getRealPath to resolve in WEB-INF
-            filename = sc.getRealPath(filename);
-        }
-        return filename;
-    }
-
-    /**
-     * get a real File for a config File.
-     * 
-     * If the File is not absolute the path is appended to the WEB-INF directory
-     * of the web-app.
-     * 
-     * @param file
-     * @param sc
-     * @return
-     */
-    public static File getConfigFile(File f, ServletContext sc) {
-        String fn = f.getPath();
-        // is the filename absolute?
-        if (f.isAbsolute()) {
-            // does it exist?
-            if (f.canRead()) {
-                // fine
-                return f;
-            } else {
-                // try just the filename as relative
-                fn = f.getName();
-            }
-        }
-        // relative path -> use getRealPath to resolve in WEB-INF
-        String newfn = sc.getRealPath("WEB-INF/" + fn);
-        if (fn == null) {
-            // TODO: use getResourceAsStream?
-            return null;
-        }
-        f = new File(newfn);
-        return f;
-    }
-
-    /**
-     * get a real file name for a config file pathname.
-     * 
-     * If filename starts with "/" its treated as absolute else the path is
-     * appended to the WEB-INF directory of the web-app.
-     * 
-     * @param filename
-     * @param sc
-     * @return
-     */
-    public static String getConfigFile(String filename, ServletContext sc) {
-        File f = new File(filename);
-        // is the filename absolute?
-        if (!f.isAbsolute()) {
-            // relative path -> use getRealPath to resolve in WEB-INF
-            filename = sc.getRealPath("WEB-INF/" + filename);
-        }
-        return filename;
-    }
-
-    /**
-     * print a servlet response
-     */
-    public static void htmlMessage(String msg, HttpServletResponse response)
-            throws IOException {
-        htmlMessage("Scaler", msg, response);
-    }
-
-    /**
-     * print a servlet response
-     */
-    public static void htmlMessage(String title, String msg,
-            HttpServletResponse response) throws IOException {
-        response.setContentType("text/html; charset=iso-8859-1");
-        PrintWriter out = response.getWriter();
-        out.println("<html>");
-        out.println("<head><title>" + title + "</title></head>");
-        out.println("<body>");
-        out.println("<p>" + msg + "</p>");
-        out.println("</body></html>");
-    }
-
-    /**
-     * Transfers an image file as-is with the mime type mt.
-     * 
-     * The local file is copied to the <code>OutputStream</code> of the
-     * <code>ServletResponse</code>. If mt is null then the mime-type is
-     * auto-detected with mimeForFile.
-     * 
-     * @param f
-     *            Image file to be sent.
-     * @param mt
-     *            mime-type of the file.
-     * @param name
-     *            name of the download file (for application/x)
-     * @param res
-     *            ServletResponse where the image file will be sent.
-     * @throws ImageOpException
-     * @throws ServletException
-     *             Exception on sending data.
-     * @throws IOException
-     */
-    public static void sendFile(File f, String mt, String name,
-            HttpServletResponse response) throws ImageOpException, IOException {
-        // use default logger
-        ServletOps.sendFile(f, mt, name, response, ServletOps.logger);
-    }
-
-    /**
-     * Transfers an image file as-is with the mime type mt.
-     * 
-     * The local file is copied to the <code>OutputStream</code> of the
-     * <code>ServletResponse</code>. If mt is null then the mime-type is
-     * auto-detected with mimeForFile.
-     * @param f
-     *            Image file to be sent.
-     * @param mt
-     *            mime-type of the file.
-     * @param name 
-     *            name of the download file (for application/x)
-     * @param res
-     *            ServletResponse where the image file will be sent.
-     * @param logger
-     *            Logger to use
-     * @throws ImageOpException
-     * @throws ServletException Exception on sending data.
-     * @throws IOException 
-     */
-    public static void sendFile(File f, String mt, String name, HttpServletResponse response, Logger logger)
-            throws ImageOpException, IOException {
-        logger.debug("sendRawFile(" + mt + ", " + f + ")");
-    	if (response == null) {
-    		logger.error("No response!");
-    		return;
-    	}
-        if (mt == null) {
-            // auto-detect mime-type
-            mt = FileOps.mimeForFile(f);
-            if (mt == null) {
-                throw new ImageOpException("Unknown file type.");
-            }
-        }
-        response.setContentType(mt);
-        // open file
-        if (mt.startsWith("application")) {
-            if (name == null) {
-                // no download name -- use filename
-                name = f.getName();
-            }
-            response.addHeader("Content-Disposition", "attachment; filename=\""+name+"\"");
-        }
-        FileInputStream inFile = null;
-        try {
-            inFile = new FileInputStream(f);
-            OutputStream outStream = response.getOutputStream();
-            // TODO: should we set content length? 
-            // see http://www.prozesse-und-systeme.de/servletFlush.html
-            response.setContentLength( (int) f.length());
-            byte dataBuffer[] = new byte[4096];
-            int len;
-            while ((len = inFile.read(dataBuffer)) != -1) {
-                // copy out file
-                outStream.write(dataBuffer, 0, len);
-            }
-        } finally {
-            try {
-                if (inFile != null) {
-                    inFile.close();
-                }
-            } catch (IOException e) {
-                // nothing to do
-            }
-        }
-    }
-
-    /**
-     * Write image img to ServletResponse response.
-     * 
-     * @param img
-     * @param mimeType
-     * @param response
-     * @throws ImageOpException
-     * @throws ServletException Exception on sending data.
-     */
-    public static void sendImage(DocuImage img, String mimeType,
-            HttpServletResponse response) throws ImageOpException,
-            ServletException {
-        ServletOps.sendImage(img, mimeType, response, ServletOps.logger);
-    }
-
-    /**
-     * Write image img to ServletResponse response.
-     * 
-     * @param img
-     * @param mimeType
-     * @param response
-     * @param logger
-     * @throws ImageOpException
-     * @throws ServletException Exception on sending data.
-     */
-    public static void sendImage(DocuImage img, String mimeType,
-            HttpServletResponse response, Logger logger) throws ImageOpException,
-            ServletException {
-    	if (response == null) {
-    		logger.error("No response!");
-    		return;
-    	}
-        //logger.debug("sending to response: ("+ headersToString(response) + ") committed=" + response.isCommitted());
-        logger.debug("sending to response. committed=" + response.isCommitted());
-        // TODO: should we erase or replace old last-modified header?
-        try {
-            OutputStream outstream = response.getOutputStream();
-            // setup output -- if mime type is set use that otherwise
-            // if source is JPG then dest will be JPG else it's PNG
-            if (mimeType == null) {
-                mimeType = img.getMimetype();
-                if (mimeType == null) {
-                    // still no mime-type
-                    logger.warn("sendImage without mime-type! using image/jpeg.");
-                    mimeType = "image/jpeg";
-                }
-            }
-            if ((mimeType.equals("image/jpeg") || mimeType.equals("image/jp2") || 
-                    mimeType.equals("image/fpx"))) {
-                mimeType = "image/jpeg";
-            } else {
-                mimeType = "image/png";
-            }
-            // write the image
-            response.setContentType(mimeType);
-            img.writeImage(mimeType, outstream);
-        } catch (IOException e) {
-            throw new ServletException("Error sending image:", e);
-        }
-        // TODO: should we: finally { img.dispose(); }
-    }
-
-    /** Returns text representation of headers for debuggging purposes.
-     * @param req
-     * @return
-     */
-    public static String headersToString(HttpServletRequest req) {
-        String s = "";
-        Enumeration<String> hns = req.getHeaderNames();
-        while (hns.hasMoreElements()) {
-            String hn = hns.nextElement();
-            s += hn + "=" + req.getHeader(hn) + "; ";
-        }
-        return s;
-    }
-    
-    /** Returns text representation of headers for debuggging purposes.
-     * Works only with Servlet spec 3.0!
-     * @param resp
-     * @return
-     */
-    public static String headersToString(HttpServletResponse resp) {
-        String s = "";
-        Collection<String> hns = resp.getHeaderNames();
-        for (String hn : hns) {
-            s += hn + "=" + resp.getHeader(hn) + "; ";
-        }
-        return s;
-    }
-    
-}
--- a/webapp/src/main/webapp/ImgInfo-json.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/ImgInfo-json.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -20,7 +20,13 @@
   #L%
   Author: Robert Casties (robcast@berlios.de)
   --%><%@page language="java" 
-	import="digilib.io.FileOps, digilib.io.ImageFileSet, digilib.io.ImageFile, digilib.util.ImageSize, digilib.servlet.DigilibConfiguration"
+  import="digilib.io.FileOps, 
+          digilib.io.ImageFileSet, 
+          digilib.io.ImageFile, 
+          digilib.util.ImageSize,
+          digilib.io.DocuDirCache,
+          digilib.conf.DigilibServletRequest,
+          digilib.conf.DigilibServletConfiguration"
 	contentType="application/json"%><%!
 // create DocumentBean instance for all JSP requests
 digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
@@ -36,11 +42,11 @@
 }
 %><%
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 docBean.setRequest(dlRequest);
 // dir cache
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
-digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache");
+DigilibServletConfiguration dlConfig = docBean.getDlConfig();
+DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
 // get file
 FileOps.FileClass fc = FileOps.FileClass.IMAGE;
 ImageFileSet imgFile = (ImageFileSet) dirCache.getFile(dlRequest.getFilePath(), dlRequest.getAsInt("pn"), fc);
--- a/webapp/src/main/webapp/WEB-INF/web-additional.xml	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/WEB-INF/web-additional.xml	Wed Mar 27 17:23:44 2013 +0100
@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
 <web-app>
     <!--
     Additional web.xml snippets for digilib.
--- a/webapp/src/main/webapp/api/ImgInfo-json.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/api/ImgInfo-json.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -20,7 +20,13 @@
   #L%
   Author: Robert Casties (robcast@berlios.de)
   --%><%@page language="java" 
-	import="digilib.io.FileOps, digilib.io.ImageFileSet, digilib.io.ImageFile, digilib.util.ImageSize, digilib.servlet.DigilibConfiguration"
+  import="digilib.io.FileOps, 
+          digilib.io.ImageFileSet, 
+          digilib.io.ImageFile, 
+          digilib.util.ImageSize,
+          digilib.io.DocuDirCache,
+          digilib.conf.DigilibServletRequest,
+          digilib.conf.DigilibServletConfiguration"
 	contentType="application/json"%><%!
 // create DocumentBean instance for all JSP requests
 digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
@@ -36,11 +42,11 @@
 }
 %><%
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 docBean.setRequest(dlRequest);
 // dir cache
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
-digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache");
+DigilibServletConfiguration dlConfig = docBean.getDlConfig();
+DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
 // get file
 FileOps.FileClass fc = FileOps.FileClass.IMAGE;
 ImageFileSet imgFile = (ImageFileSet) dirCache.getFile(dlRequest.getFilePath(), dlRequest.getAsInt("pn"), fc);
--- a/webapp/src/main/webapp/api/dirInfo-xml.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/api/dirInfo-xml.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,9 +19,18 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@page import="digilib.io.FileOps"%><%@ page language="java" %><%!
+  --%><%@ page language="java"
+    import="digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletConfiguration,
+          digilib.conf.DigilibServletRequest,
+          digilib.io.DocuDirCache,
+          digilib.io.DocuDirectory,
+          digilib.io.DocuDirent,
+          java.io.File"%>
+   
+<%!
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -36,13 +45,13 @@
 <%
 // process request
 // get digilib config
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
+DigilibServletConfiguration dlConfig = docBean.getDlConfig();
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 // dir cache
-digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache");
+DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
 // get directory
-digilib.io.DocuDirectory dir = dirCache.getDirectory(dlRequest.getFilePath());
+DocuDirectory dir = dirCache.getDirectory(dlRequest.getFilePath());
 FileOps.FileClass fc = FileOps.FileClass.IMAGE;
 int dirSize = dir != null ? dir.size(fc) : 0;
 
@@ -54,7 +63,7 @@
 <%
     if (!dlRequest.hasOption("mo", "dir")) {
       for (int i = 0; i < dirSize; i++) {
-        digilib.io.DocuDirent f = dir.get(i, fc);
+        DocuDirent f = dir.get(i, fc);
         String fn = (f != null) ? f.getName() : "null";
 %>  <file>
     <index><%= i+1 %></index>
--- a/webapp/src/main/webapp/api/dlContext-xml.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/api/dlContext-xml.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,9 +19,14 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@ page language="java" %><%!
+  --%><%@ page language="java"
+    import="digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletConfiguration,
+          digilib.conf.DigilibServletRequest,
+          digilib.io.DocuDirCache,
+          java.io.File"%><%!
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -36,12 +41,11 @@
 <%
 // process request
 // get digilib config
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
+DigilibServletConfiguration dlConfig = docBean.getDlConfig();
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 // dir cache
-digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache");
-
+DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
 %><!-- Automatically generated XML snippet with document context -->
 <result>
 <%
@@ -54,10 +58,10 @@
     f.checkMeta();
     java.util.HashMap meta = f.getFileMeta();
     if (meta != null) {
-	//ctx = "JSP:hasmeta!";
-	if (meta.containsKey("context")) {
-	    ctx = (String) meta.get("context");
-	}
+    	//ctx = "JSP:hasmeta!";
+    	if (meta.containsKey("context")) {
+    	    ctx = (String) meta.get("context");
+    	}
     }
 }
 %><%= ctx %>
--- a/webapp/src/main/webapp/api/dlInfo-json.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/api/dlInfo-json.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,9 +19,11 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@ page language="java" %><%!
+  --%><%@ page language="java"     
+  import="digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletRequest"%><%!
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -34,7 +36,7 @@
 }
 %><%
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 docBean.setRequest(dlRequest);
 %>
 // JSON format metadata about request and image
--- a/webapp/src/main/webapp/api/dlInfo-xml.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/api/dlInfo-xml.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,9 +19,11 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@ page language="java" %><%!
+  --%><%@ page language="java" 
+    import="digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletRequest"%><%!
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -35,10 +37,8 @@
 %><?xml version="1.0" encoding="UTF-8" ?>
 <%
 // process request
-// get digilib config
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 docBean.setRequest(dlRequest);
 
 %><!-- Automatically generated XML snippet with document parameters -->
--- a/webapp/src/main/webapp/dirInfo-xml.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/dirInfo-xml.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,9 +19,18 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@page import="digilib.io.FileOps"%><%@ page language="java" %><%!
+  --%><%@ page language="java"
+    import="digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletConfiguration,
+          digilib.conf.DigilibServletRequest,
+          digilib.io.DocuDirCache,
+          digilib.io.DocuDirectory,
+          digilib.io.DocuDirent,
+          java.io.File"%>
+   
+<%!
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -36,13 +45,13 @@
 <%
 // process request
 // get digilib config
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
+DigilibServletConfiguration dlConfig = docBean.getDlConfig();
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 // dir cache
-digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache");
+DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
 // get directory
-digilib.io.DocuDirectory dir = dirCache.getDirectory(dlRequest.getFilePath());
+DocuDirectory dir = dirCache.getDirectory(dlRequest.getFilePath());
 FileOps.FileClass fc = FileOps.FileClass.IMAGE;
 int dirSize = dir != null ? dir.size(fc) : 0;
 
@@ -54,7 +63,7 @@
 <%
     if (!dlRequest.hasOption("mo", "dir")) {
       for (int i = 0; i < dirSize; i++) {
-        digilib.io.DocuDirent f = dir.get(i, fc);
+        DocuDirent f = dir.get(i, fc);
         String fn = (f != null) ? f.getName() : "null";
 %>  <file>
     <index><%= i+1 %></index>
--- a/webapp/src/main/webapp/dlContext-xml.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/dlContext-xml.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,9 +19,14 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@ page language="java" %><%!
+  --%><%@ page language="java"
+    import="digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletConfiguration,
+          digilib.conf.DigilibServletRequest,
+          digilib.io.DocuDirCache,
+          java.io.File"%><%!
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -36,12 +41,11 @@
 <%
 // process request
 // get digilib config
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
+DigilibServletConfiguration dlConfig = docBean.getDlConfig();
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 // dir cache
-digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache");
-
+DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
 %><!-- Automatically generated XML snippet with document context -->
 <result>
 <%
@@ -54,10 +58,10 @@
     f.checkMeta();
     java.util.HashMap meta = f.getFileMeta();
     if (meta != null) {
-	//ctx = "JSP:hasmeta!";
-	if (meta.containsKey("context")) {
-	    ctx = (String) meta.get("context");
-	}
+    	//ctx = "JSP:hasmeta!";
+    	if (meta.containsKey("context")) {
+    	    ctx = (String) meta.get("context");
+    	}
     }
 }
 %><%= ctx %>
--- a/webapp/src/main/webapp/dlInfo-json.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/dlInfo-json.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,9 +19,11 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@ page language="java" %><%!
+  --%><%@ page language="java"     
+  import="digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletRequest"%><%!
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -34,7 +36,7 @@
 }
 %><%
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 docBean.setRequest(dlRequest);
 %>
 // JSON format metadata about request and image
--- a/webapp/src/main/webapp/dlInfo-xml.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/dlInfo-xml.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,9 +19,11 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@ page language="java" %><%!
+  --%><%@ page language="java" 
+    import="digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletRequest"%><%!
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -35,10 +37,8 @@
 %><?xml version="1.0" encoding="UTF-8" ?>
 <%
 // process request
-// get digilib config
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 docBean.setRequest(dlRequest);
 
 %><!-- Automatically generated XML snippet with document parameters -->
--- a/webapp/src/main/webapp/greyskin/diginew.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/greyskin/diginew.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -41,7 +41,7 @@
 	
 	// parsing the query
 	// -----------------
-	digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+	digilib.conf.DigilibServletRequest dlRequest = new digilib.conf.DigilibServletRequest(request);
 	docBean.setRequest(dlRequest);
 	// check if authentication is needed and redirect if necessary
 	docBean.doAuthentication(response);
--- a/webapp/src/main/webapp/oldskin/dcMain.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/oldskin/dcMain.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -41,7 +41,7 @@
 // parsing the query
 // -----------------
 
-digilib.servlet.DigilibServletRequest dcRequest = new digilib.servlet.DigilibServletRequest(request);
+digilib.conf.DigilibServletRequest dcRequest = new digilib.conf.DigilibServletRequest(request);
 // check if authentication is needed and redirect if necessary
 docBean.doAuthentication(dcRequest, response);
 // set number of pages  
--- a/webapp/src/main/webapp/oldskin/digicat.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/oldskin/digicat.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -38,7 +38,7 @@
 // parsing the query
 // -----------------
 
-digilib.servlet.DigilibServletRequest dcRequest = new digilib.servlet.DigilibServletRequest(request);
+digilib.conf.DigilibServletRequest dcRequest = new digilib.conf.DigilibServletRequest(request);
 // check if authentication is needed and redirect if necessary
 docBean.doAuthentication(dcRequest, response);
 
--- a/webapp/src/main/webapp/oldskin/digilib.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/oldskin/digilib.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -41,7 +41,7 @@
 // parsing the query
 // -----------------
 
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+digilib.conf.DigilibServletRequest dlRequest = new digilib.conf.DigilibServletRequest(request);
 // check if authentication is needed and redirect if necessary
 docBean.doAuthentication(dlRequest, response);
     
--- a/webapp/src/main/webapp/oldskin/digimage.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/oldskin/digimage.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -39,7 +39,7 @@
 
 // parsing the query
 // -----------------
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+digilib.conf.DigilibServletRequest dlRequest = new digilib.conf.DigilibServletRequest(request);
 docBean.setRequest(dlRequest);
 // check if authentication is needed and redirect if necessary
 docBean.doAuthentication(response);
--- a/webapp/src/main/webapp/oldskin/digimage_img_inc.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/oldskin/digimage_img_inc.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -21,7 +21,7 @@
   --%><%@ page language="java" %><%
 // retrieve objects from context
 digilib.servlet.DocumentBean docBean = (digilib.servlet.DocumentBean) pageContext.getAttribute("docBean", pageContext.REQUEST_SCOPE);
-digilib.servlet.DigilibServletRequest dlRequest = docBean.getRequest();
+digilib.conf.DigilibServletRequest dlRequest = docBean.getRequest();
 String ua = request.getHeader("User-Agent");
 boolean isN4 = ((ua.indexOf("Mozilla/4.") > -1)&&(ua.indexOf("MSIE") == -1));
 %>
--- a/webapp/src/main/webapp/oldskin/digimage_tbl_inc.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/oldskin/digimage_tbl_inc.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -21,7 +21,7 @@
   --%><%@ page language="java" %><%
 // retrieve objects from context
 digilib.servlet.DocumentBean docBean = (digilib.servlet.DocumentBean) pageContext.getAttribute("docBean", PageContext.REQUEST_SCOPE);
-digilib.servlet.DigilibServletRequest dlRequest = docBean.getRequest();
+digilib.conf.DigilibServletRequest dlRequest = docBean.getRequest();
 String ua = request.getHeader("User-Agent");
 boolean isN4 = ((ua.indexOf("Mozilla/4.") > -1)&&(ua.indexOf("MSIE") == -1));
 %>
--- a/webapp/src/main/webapp/server/dlConfig.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/server/dlConfig.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,12 +19,18 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@page language="java" import="digilib.util.DigilibJobCenter,java.io.File"%>
+  --%><%@page language="java" 
+  import="digilib.util.DigilibJobCenter,
+          digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletConfiguration,
+          digilib.conf.DigilibServletRequest,
+          digilib.io.DocuDirCache,
+          java.io.File"%>
 <%!
 // authentication stuff - robert
 // -----------------------------
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -39,13 +45,13 @@
 
 <%
 // get digilib config
-digilib.servlet.DigilibServletConfiguration dlConfig = docBean.getDlConfig();
+DigilibServletConfiguration dlConfig = docBean.getDlConfig();
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 // add number of pages
 dlRequest.setValue("pt", docBean.getNumPages(dlRequest));
 // dir cache
-digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache");
+DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
 // image JobCenter
 DigilibJobCenter imageProcessor =  (DigilibJobCenter)dlConfig.getValue("servlet.worker.imageexecutor");        
 
--- a/webapp/src/main/webapp/server/dlRequest.jsp	Wed Mar 27 13:02:27 2013 +0100
+++ b/webapp/src/main/webapp/server/dlRequest.jsp	Wed Mar 27 17:23:44 2013 +0100
@@ -19,11 +19,18 @@
   <http://www.gnu.org/licenses/lgpl-3.0.html>.
   #L%
   Author: Robert Casties (robcast@berlios.de)
-  --%><%@ page language="java" %><%!
+  --%><%@ page language="java"
+          import="digilib.util.DigilibJobCenter,
+          digilib.servlet.DocumentBean,
+          digilib.conf.DigilibServletConfiguration,
+          digilib.conf.DigilibServletRequest,
+          digilib.io.DocuDirCache,
+          java.io.File"%>
+<%!
 // authentication stuff - robert
 // -----------------------------
 // create DocumentBean instance for all JSP requests
-digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean();
+DocumentBean docBean = new DocumentBean();
 
 // initialize DocumentBean instance in JSP init
 public void jspInit() {
@@ -38,13 +45,13 @@
 
 <%
 // get digilib config
-digilib.servlet.DigilibConfiguration dlConfig = docBean.getDlConfig();
+DigilibServletConfiguration dlConfig = docBean.getDlConfig();
 // parsing the query
-digilib.servlet.DigilibServletRequest dlRequest = new digilib.servlet.DigilibServletRequest(request);
+DigilibServletRequest dlRequest = new DigilibServletRequest(request);
 // add number of pages
 dlRequest.setValue("pt", docBean.getNumPages(dlRequest));
 // dir cache
-digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache");
+DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
 %>
 
 <html>