changeset 1219:74363771603f

Merge with e543b88b3cfa5e6574bfc2b66835e6895b1491f8
author robcast
date Tue, 01 Oct 2013 12:24:29 +0200
parents bd7dfa8b164e (diff) e543b88b3cfa (current diff)
children cde51f04895c
files
diffstat 18 files changed, 1115 insertions(+), 379 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Sep 30 16:06:13 2013 +0200
+++ b/.hgignore	Tue Oct 01 12:24:29 2013 +0200
@@ -113,4 +113,10 @@
 syntax: regexp
 ^servlet/\.project$
 syntax: regexp
-^servlet/bin$
\ No newline at end of file
+^servlet/bin$
+syntax: regexp
+^doc/\.settings$
+syntax: regexp
+^doc/\.project$
+syntax: regexp
+^doc/target$
\ No newline at end of file
--- a/common/src/main/java/digilib/conf/DigilibConfiguration.java	Mon Sep 30 16:06:13 2013 +0200
+++ b/common/src/main/java/digilib/conf/DigilibConfiguration.java	Tue Oct 01 12:24:29 2013 +0200
@@ -43,9 +43,12 @@
 
     /** Log4J logger */
     protected static Logger logger = Logger.getLogger(DigilibConfiguration.class);
+    
+    private static boolean isLoggerConfigured = false;
 
+    /** digilib version */
     public static String getVersion() {
-        return "2.2.1";
+        return "2.2.2";
     }
     
     /**
@@ -87,8 +90,13 @@
     @SuppressWarnings("unchecked")
     public void configure() {
         DigilibConfiguration config = this;
-        // we start log4j with a default logger config TODO: is this the right place?
-        BasicConfigurator.configure();
+        if (DigilibConfiguration.isLoggerConfigured) {
+            logger.debug("Logger already configured!");
+        } else {
+            // we start log4j with a default logger config
+            BasicConfigurator.configure();
+            DigilibConfiguration.isLoggerConfigured = true;
+        }
         /*
          * initialise static DocuImage class instance
          */
--- a/common/src/main/java/digilib/conf/DigilibRequest.java	Mon Sep 30 16:06:13 2013 +0200
+++ b/common/src/main/java/digilib/conf/DigilibRequest.java	Tue Oct 01 12:24:29 2013 +0200
@@ -282,8 +282,14 @@
         if (path == null) {
             return false;
         }
-        // alway set HTTP status code error reporting
-        options.setOption("errcode");
+        
+        String identifier = null;
+        String region = null;
+        String size = null;
+        String rotation = null;
+        String quality = null;
+        String format = null;
+
         // enable passing of delimiter to get empty parameters
         StringTokenizer query = new StringTokenizer(path, "/", true);
         String token;
@@ -308,17 +314,7 @@
         if (query.hasMoreTokens()) {
             token = getNextDecodedToken(query);
             if (!token.equals("/")) {
-                try {
-                    if (token.contains("%")) {
-                        // still escape chars -- decode again
-                        token = URLDecoder.decode(token, "UTF-8");
-                    }
-                    setValueFromString("fn", token);
-                } catch (UnsupportedEncodingException e) {
-                    errorMessage = "Error decoding identifier in IIIF path!";
-                    logger.error(errorMessage);
-                    return false;
-                }
+                identifier = token;
                 // skip /
                 if (query.hasMoreTokens()) {
                     query.nextToken();
@@ -331,53 +327,12 @@
         if (query.hasMoreTokens()) {
             token = getNextDecodedToken(query);
             if (!token.equals("/")) {
-                if (token.equals("info.json")) {
-                    // info request
-                    options.setOption("info");
-                    return true;
-                } else if (token.equals("full")) {
-                    // full region -- default
-                } else if (token.startsWith("pct:")) {
-                    // pct:x,y,w,h -- region in % of original image
-                    String[] parms = token.substring(4).split(",");
-                    try {
-                        float x = Float.parseFloat(parms[0]);
-                        setValue("wx", x / 100f);
-                        float y = Float.parseFloat(parms[1]);
-                        setValue("wy", y / 100f);
-                        float w = Float.parseFloat(parms[2]);
-                        setValue("ww", w / 100f);
-                        float h = Float.parseFloat(parms[3]);
-                        setValue("wh", h / 100f);
-                    } catch (Exception e) {
-                        errorMessage = "Error parsing range parameter in IIIF path!";
-                        logger.error(errorMessage, e);
-                        return false;
-                    }
-                } else {
-                    // x,y,w,h -- region in pixel of original image :-(
-                    String[] parms = token.split(",");
-                    if (parms.length != 4) {
-                        errorMessage = "Error parsing range parameter in IIIF path!";
-                        logger.error(errorMessage);
-                        return false;
-                    } else {
-                        options.setOption("pxarea");
-                        setValueFromString("wx", parms[0]);
-                        setValueFromString("wy", parms[1]);
-                        setValueFromString("ww", parms[2]);
-                        setValueFromString("wh", parms[3]);
-                    }
-                }
+                region = token;
                 // skip /
                 if (query.hasMoreTokens()) {
                     query.nextToken();
                 }
             }
-        } else {
-            // region omitted -- assume info request
-            options.setOption("info");
-            return true;
         }
         /*
          * fourth parameter size
@@ -385,60 +340,12 @@
         if (query.hasMoreTokens()) {
             token = getNextDecodedToken(query);
             if (!token.equals("/")) {
-                if (token.equals("full")) {
-                    // full -- size of original
-                    options.setOption("ascale");
-                    setValue("scale", 1f);
-                } else if (token.startsWith("pct:")) {
-                    // pct:n -- n% size of original
-                    try {
-                        float pct = Float.parseFloat(token.substring(4));
-                        options.setOption("ascale");
-                        setValue("scale", pct / 100);
-                    } catch (NumberFormatException e) {
-                        errorMessage = "Error parsing size parameter in IIIF path!";
-                        logger.error(errorMessage, e);
-                        return false;
-                    }
-                } else {
-                    // w,h -- pixel size
-                    try {
-                        String[] parms = token.split(",", 2);
-                        if (parms[0].length() > 0) {
-                            // width param
-                            if (parms[0].startsWith("!")) {
-                                // width (in digilib-like bounding box)
-                                setValueFromString("dw", parms[0].substring(1));
-                            } else if (parms[1].length() == 0) {
-                                // width only
-                                setValueFromString("dw", parms[0]);
-                            } else {
-                                // w,h -- according to spec, we should distort the image to match ;-(
-                                errorMessage = "Non-uniform-scale size parameter in IIIF path not supported!";
-                                logger.error(errorMessage);
-                                return false;
-                            }
-                        }
-                        if (parms[1].length() > 0) {
-                            // height param
-                            setValueFromString("dh", parms[1]);
-                        }
-                    } catch (Exception e) {
-                        errorMessage = "Error parsing size parameter in IIIF path!";
-                        logger.error(errorMessage, e);
-                        return false;
-                    }
-                }
+                size = token;
                 // skip /
                 if (query.hasMoreTokens()) {
                     query.nextToken();
                 }
             }
-        } else {
-            // size omitted -- assume "full"
-            options.setOption("ascale");
-            setValue("scale", 1f);
-            return true;
         }
         /*
          * fifth parameter rotation
@@ -446,14 +353,7 @@
         if (query.hasMoreTokens()) {
             token = getNextDecodedToken(query);
             if (!token.equals("/")) {
-                try {
-                    float rot = Float.parseFloat(token);
-                    setValue("rot", rot);
-                } catch (NumberFormatException e) {
-                    errorMessage = "Error parsing rotation parameter in IIIF path!";
-                    logger.error(errorMessage, e);
-                    return false;
-                }
+                rotation = token;
                 // skip /
                 if (query.hasMoreTokens()) {
                     query.nextToken();
@@ -469,26 +369,10 @@
             try {
                 String[] parms = token.split("\\.");
                 // quality param
-                if (parms[0].equals("native")||parms[0].equals("color")) {
-                    // native is default anyway
-                } else if (parms[0].equals("grey")) {
-                    setValueFromString("colop", "grayscale");
-                } else {
-                    errorMessage = "Invalid quality parameter in IIIF path!";
-                    logger.error(errorMessage);
-                    return false;
-                }
-                // format param (we only support jpg and png)
-                if (parms.length > 1 && parms[1].equals("jpg")) {
-                    // force jpg
-                    options.setOption("jpg");
-                } else if (parms.length > 1 && parms[1].equals("png")) {
-                    // force png
-                    options.setOption("png");
-                } else if (parms.length > 1) {
-                    errorMessage = "Invalid format parameter in IIIF path!";
-                    logger.error(errorMessage);
-                    return false;
+                quality = parms[0];
+                // format param
+                if (parms.length > 1) {
+                    format = parms[1];
                 }
             } catch (Exception e) {
                 errorMessage = "Error parsing quality and format parameters in IIIF path!";
@@ -496,7 +380,9 @@
                 return false;
             }
         }
-        return true;
+
+        // set request with these parameters
+        return setWithIiifParams(identifier, region, size, rotation, quality, format);        
     }
 
     private String getNextDecodedToken(StringTokenizer tokens) {
@@ -510,6 +396,195 @@
         return null;
     }
 
+	/**
+	 * Populate a request from IIIF image API parameters.
+	 * 
+	 * {scheme}://{server}{/prefix}/{identifier}/{region}/{size}/{rotation}/{quality}{.format}
+	 * 
+	 * @see <a href="http://www-sul.stanford.edu/iiif/image-api/1.1/">IIIF Image
+	 *      API</a>
+	 */
+	public boolean setWithIiifParams(String identifier, String region, String size, 
+			String rotation, String quality, String format) {
+        // alway set HTTP status code error reporting
+        options.setOption("errcode");
+        
+        /*
+         * parameter identifier (encoded)
+         */
+        if (identifier != null) {
+            try {
+                if (identifier.contains("%")) {
+                    // still escape chars -- decode again
+                    identifier = URLDecoder.decode(identifier, "UTF-8");
+                }
+                setValueFromString("fn", identifier);
+            } catch (UnsupportedEncodingException e) {
+                errorMessage = "Error decoding identifier in IIIF path!";
+                logger.error(errorMessage);
+                return false;
+            }
+        } else {
+            errorMessage = "Missing identifier in IIIF path!";
+            logger.error(errorMessage);
+            return false;
+        }
+
+        /*
+         * parameter region
+         */
+        if (region != null) {
+            if (region.equals("info.json")) {
+                // info request
+                options.setOption("info");
+                return true;
+            } else if (region.equals("full")) {
+                // full region -- default
+            } else if (region.startsWith("pct:")) {
+                // pct:x,y,w,h -- region in % of original image
+                String[] parms = region.substring(4).split(",");
+                try {
+                    float x = Float.parseFloat(parms[0]);
+                    setValue("wx", x / 100f);
+                    float y = Float.parseFloat(parms[1]);
+                    setValue("wy", y / 100f);
+                    float w = Float.parseFloat(parms[2]);
+                    setValue("ww", w / 100f);
+                    float h = Float.parseFloat(parms[3]);
+                    setValue("wh", h / 100f);
+                } catch (Exception e) {
+                    errorMessage = "Error parsing range parameter in IIIF path!";
+                    logger.error(errorMessage, e);
+                    return false;
+                }
+            } else {
+                // x,y,w,h -- region in pixel of original image :-(
+                String[] parms = region.split(",");
+                if (parms.length != 4) {
+                    errorMessage = "Error parsing range parameter in IIIF path!";
+                    logger.error(errorMessage);
+                    return false;
+                } else {
+                    options.setOption("pxarea");
+                    setValueFromString("wx", parms[0]);
+                    setValueFromString("wy", parms[1]);
+                    setValueFromString("ww", parms[2]);
+                    setValueFromString("wh", parms[3]);
+                }
+            }
+        } else {
+            // region omitted -- assume info request
+            options.setOption("info");
+            return true;
+        }
+        
+        /*
+         * parameter size
+         */
+        if (size != null) {
+            if (size.equals("full")) {
+                // full -- size of original
+                options.setOption("ascale");
+                setValue("scale", 1f);
+            } else if (size.startsWith("pct:")) {
+                // pct:n -- n% size of original
+                try {
+                    float pct = Float.parseFloat(size.substring(4));
+                    options.setOption("ascale");
+                    setValue("scale", pct / 100);
+                } catch (NumberFormatException e) {
+                    errorMessage = "Error parsing size parameter in IIIF path!";
+                    logger.error(errorMessage, e);
+                    return false;
+                }
+            } else {
+                // w,h -- pixel size
+                try {
+                    String[] parms = size.split(",", 2);
+                    if (parms[0].length() > 0) {
+                        // width param
+                        if (parms[0].startsWith("!")) {
+                            // width (in digilib-like bounding box)
+                            setValueFromString("dw", parms[0].substring(1));
+                        } else if (parms[1].length() == 0) {
+                            // width only
+                            setValueFromString("dw", parms[0]);
+                        } else {
+                            // w,h -- according to spec, we should distort the
+                            // image to match ;-(
+                            errorMessage = "Non-uniform-scale size parameter in IIIF path not supported!";
+                            logger.error(errorMessage);
+                            return false;
+                        }
+                    }
+                    if (parms[1].length() > 0) {
+                        // height param
+                        setValueFromString("dh", parms[1]);
+                    }
+                } catch (Exception e) {
+                    errorMessage = "Error parsing size parameter in IIIF path!";
+                    logger.error(errorMessage, e);
+                    return false;
+                }
+            }
+        } else {
+            // size omitted -- assume "full"
+            options.setOption("ascale");
+            setValue("scale", 1f);
+            return true;
+        }
+        
+        /*
+         * parameter rotation
+         */
+        if (rotation != null) {
+            try {
+                float rot = Float.parseFloat(rotation);
+                setValue("rot", rot);
+            } catch (NumberFormatException e) {
+                errorMessage = "Error parsing rotation parameter in IIIF path!";
+                logger.error(errorMessage, e);
+                return false;
+            }
+        }
+        
+        /*
+         * parameter quality
+         */
+        if (quality != null) {
+            // quality param
+            if (quality.equals("native") || quality.equals("color")) {
+                // native is default anyway
+            } else if (quality.equals("grey")) {
+                setValueFromString("colop", "grayscale");
+            } else {
+                errorMessage = "Invalid quality parameter in IIIF path!";
+                logger.error(errorMessage);
+                return false;
+            }
+        }
+        
+        /*
+         * parameter format
+         */
+        if (format != null) {
+            // format param (we only support jpg and png)
+            if (format.equals("jpg")) {
+                // force jpg
+                options.setOption("jpg");
+            } else if (format.equals("png")) {
+                // force png
+                options.setOption("png");
+            } else {
+                errorMessage = "Invalid format parameter in IIIF path!";
+                logger.error(errorMessage);
+                return false;
+            }
+        }
+        return true;
+	}
+
+	
     /**
      * 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>.
--- a/common/src/main/java/digilib/image/ImageJobDescription.java	Mon Sep 30 16:06:13 2013 +0200
+++ b/common/src/main/java/digilib/image/ImageJobDescription.java	Tue Oct 01 12:24:29 2013 +0200
@@ -78,6 +78,7 @@
     String mimeType = null;
     Integer paramDW = null;
     Integer paramDH = null;
+    DocuDirCache dirCache = null;
 
     /**
      * create empty ImageJobDescription.
@@ -87,6 +88,7 @@
     public ImageJobDescription(DigilibConfiguration dlcfg) {
         super(30);
         dlConfig = dlcfg;
+        dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
     }
 
     /**
@@ -184,7 +186,7 @@
     }
 
     /**
-     * Returns the mime-type (of the input).
+     * Returns the mime-type of the input.
      * 
      * @return
      * @throws IOException
@@ -197,12 +199,46 @@
         return mimeType;
     }
 
+
     /**
+     * Return the mime-type of the output.
+     * 
+     * @return
+     */
+    public String getOutputMimeType() {
+        // forced destination image type
+        if (hasOption("jpg")) {
+            return "image/jpeg";
+        } else if (hasOption("png")) {
+            return "image/png";
+        }
+        // use input image type
+        try {
+            String mt = getMimeType();
+            if ((mt.equals("image/jpeg") || mt.equals("image/jp2") || mt.equals("image/fpx"))) {
+                return "image/jpeg";
+            } else {
+                return "image/png";
+            }
+        } catch (IOException e) {
+            logger.error("No input when trying to getOutputMimeType!");
+        }
+        return null;
+    }
+    
+    /**
+     * Set the current ImageInput.
+     * 
      * @param input
      *            the input to set
      */
     public void setInput(ImageInput input) {
         this.input = input;
+        // create and set ImageSet if needed
+        if (dirCache == null && imageSet == null) {
+            imageSet = new ImageSet();
+            imageSet.add(input);
+        }
     }
 
     /**
@@ -250,7 +286,6 @@
      */
     public DocuDirectory getFileDirectory() throws FileOpException {
         if (fileDir == null) {
-            DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
             String fp = getFilePath();
             fileDir = dirCache.getDirectory(fp);
             if (fileDir == null) {
@@ -268,8 +303,9 @@
      */
     public ImageSet getImageSet() throws FileOpException {
         if (imageSet == null) {
-            DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
-
+            if (dirCache == null) {
+                throw new FileOpException("No DirCache configured!");
+            }
             imageSet = (ImageSet) dirCache.getFile(getFilePath(), getAsInt("pn"), FileClass.IMAGE);
             if (imageSet == null) {
                 throw new FileOpException("File " + getFilePath() + "(" + getAsInt("pn") + ") not found.");
@@ -279,6 +315,16 @@
     }
 
     /**
+     * Set the current ImageSet.
+     * 
+     * @param imageSet
+     */
+    public void setImageSet(ImageSet imageSet) {
+        this.imageSet = imageSet;
+    }
+    
+    
+    /**
      * Returns the file path name from the request.
      * 
      * @return
@@ -667,6 +713,8 @@
     }
 
     /**
+     * Set the current docuImage.
+     * 
      * @param docuImage
      *            the docuImage to set
      */
--- a/common/src/main/java/digilib/io/ImageFileSet.java	Mon Sep 30 16:06:13 2013 +0200
+++ b/common/src/main/java/digilib/io/ImageFileSet.java	Tue Oct 01 12:24:29 2013 +0200
@@ -115,22 +115,6 @@
     }
 
     /**
-     * Adds an ImageFile to this Fileset.
-     * 
-     * The files should be added in the order of higher to lower resolutions.
-     * The first file is considered the hires "original".
-     * 
-     * 
-     * @param f
-     *            file to add
-     * @return true (always)
-     */
-    public boolean add(ImageInput f) {
-    	f.setParent(this);
-    	return list.add(f);
-    }
-
-    /**
      * Fill the ImageSet with files from different base directories.
      * 
      * 
--- a/common/src/main/java/digilib/io/ImageSet.java	Mon Sep 30 16:06:13 2013 +0200
+++ b/common/src/main/java/digilib/io/ImageSet.java	Tue Oct 01 12:24:29 2013 +0200
@@ -217,4 +217,20 @@
         
     }
 
+    /**
+     * Adds an ImageImput to this ImageSet.
+     * 
+     * The images should be added in the order of higher to lower resolutions.
+     * The first image is considered the hires "original".
+     * 
+     * 
+     * @param f
+     *            ImageInput to add
+     * @return true (always)
+     */
+    public boolean add(ImageInput f) {
+    	f.setParent(this);
+    	return list.add(f);
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/pom.xml	Tue Oct 01 12:24:29 2013 +0200
@@ -0,0 +1,50 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>digilib</groupId>
+    <artifactId>digilib</artifactId>
+    <version>2.2-SNAPSHOT</version>
+  </parent>
+  <artifactId>digilib-doc</artifactId>
+  <packaging>pom</packaging>
+  <name>digilib-doc</name>
+  <description>The Digital Image Library - documentation</description>
+  <url>http://digilib.berlios.de</url>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-site-plugin</artifactId>
+        <version>3.3</version>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.maven.doxia</groupId>
+            <artifactId>doxia-module-markdown</artifactId>
+            <version>1.4</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+    </plugins>
+  </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-project-info-reports-plugin</artifactId>
+        <version>2.7</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>project-team</report>
+              <report>mailing-list</report>
+              <report>scm</report>
+              <report>issue-tracking</report>
+              <!-- <report>cim</report> -->
+              <report>license</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/site/markdown/build-maven.md	Tue Oct 01 12:24:29 2013 +0200
@@ -0,0 +1,91 @@
+# Building digilib with Maven
+
+The easiest way to get the latest and greatest digilib is the [Maven](http://maven.apache.org/) build tool. 
+It will download, compile, and install the latest digilib version and all required libraries.
+
+## What you need
+
+* [Java](http://www.java.com/) (1.5 or higher)
+* [Maven](http://maven.apache.org/)
+* [Mercurial](http://mercurial.selenic.com/)
+* A Servlet container like [Tomcat](http://tomcat.apache.org/) 
+or [Jetty](http://www.eclipse.org/jetty/) to run the web application.
+
+## Quick build
+
+The fastest way to build the digilib web application is to download the digilib 
+project file [pom.xml](http://hg.berlios.de/repos/digilib/raw-file/tip/pom.xml)
+(download and save it) and run
+	
+	mvn scm:bootstrap -N
+
+in the same directory as the `pom.xml` file.
+
+This will create a web application directory `digilib-webapp-2.2-SNAPSHOT` 
+and a WAR file `digilib-webapp-2.2-SNAPSHOT-srv3.war` (or similar) 
+in the subdirectory `target/checkout/webapp/target/`
+
+Digilib uses the Asynchronous Servlet API (3.0) by default. You will need Java version 6 
+and Tomcat version 7 or Jetty version 8 or later to use it.
+If you want to use the old non-Asynchronous Servlet API (2.3) add `-Pservlet2`
+to the Maven command line above.
+
+## Developer build
+
+If you are developing with digilib it is helpful to check out the source
+code separately so you can keep it around, modify it or change the configuration
+before you deploy.
+
+To check out the latest source code into the directory `digilib` run
+	
+	hg clone http://hg.berlios.de/repos/digilib
+
+The digilib configuration files are now in `digilib/webapp/src/main/webapp/WEB-INF/`
+
+If you want to update your copy of digilib to the latest version at some time in the future 
+just run
+
+	hg pull
+	hg up
+	
+in the `digilib` directory.
+
+To build the resulting source code, change into the `digilib`
+directory you checked out above and run
+
+	mvn package
+
+This will create a web application directory `digilib-webapp-2.2-SNAPSHOT`
+and a WAR file `digilib-webapp-2.2-SNAPSHOT-srv3.war` (or similar) in
+the subdirectory `webapp/target/` .
+
+Digilib uses the Asynchronous Servlet API (3.0) by default. You will need Java version 6 
+and Tomcat version 7 or Jetty version 8 or later to use it.
+If you want to use the old non-Asynchronous Servlet API (2.3) add `-Pservlet2`
+to the Maven command line above.
+
+## Deploying the web application by hand
+
+To deploy digilib just copy the web application directory or the WAR file into the `webapp`
+directory of the Servlet container.
+
+Since the URL of your digilib server starts with the name of the web application
+and the name of the web application is derived from the name of the web
+application directory or the WAR file **please rename the web application directory or WAR file 
+to `digitallibrary` before you start**
+
+Then you should see your digilib running at the URL 
+[http://localhost:8080/digitallibrary/jquery/digilib.html](http://localhost:8080/digitallibrary/jquery/digilib.html)
+
+If you use the unmodified default configuration you should see the digilib logo
+and other sample images from the `sample-images` directory of the web application.
+
+## Configuring digilib
+
+To change the configuration of digilib just edit the file `digilib-config.xml`
+in the web application directory (`digitallibrary/WEB-INF/digilib-config.xml`).
+Documentation of the configuration options is [here](digilib-config.html).
+
+You can see a summary of your running digilib configuration at the URL 
+[http://localhost:8080/digitallibrary/server/dlConfig.jsp](http://localhost:8080/digitallibrary/server/dlConfig.jsp)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/site/markdown/digilib-config.md	Tue Oct 01 12:24:29 2013 +0200
@@ -0,0 +1,154 @@
+# Configuring digilib
+
+## digilib-config.xml
+
+The main configuration for digilib is `digilib-config.xml` in the `WEB-INF` 
+directory in the webapp. 
+(If you really need a different location you can define it in the `config-file`
+init-parameter to the Servlet.)
+
+In the XML-based configuration file you can set several paths and options. 
+
+You have to adjust the **`basedir-list`** parameter to the directories
+where your images are installed. The directory path has to be an absolute 
+path following the conventions of your operating system (a relative path 
+is taken to be relative to the web application directory).
+
+You need only one directory if you don't want to provide pre-scaled low resolution 
+versions of your images. If you have pre-scaled images the directory with the 
+high-resolution images must be the first entry in the list.
+
+Documentation on the directory layout and on using pre-scaled images is 
+[here](image-directories.md).
+
+A minimal configuration looks like this:
+
+	<!-- Digilib servlet config file -->
+	<digilib-config>
+	  <!-- List of directories where images are searched.
+	       The authoritative directory with the high-resolution images
+	       is first in list. -->
+	  <parameter name="basedir-list" value="/docuserver/images" />
+	</digilib-config>
+	
+A more customized configuration may look like this (for a full list of
+configuration options use the source: 
+[1](http://hg.berlios.de/repos/digilib/file/default/common/src/main/java/digilib/conf/DigilibConfiguration.java) 
+[2](http://hg.berlios.de/repos/digilib/file/default/servlet/src/main/java/digilib/conf/DigilibServletConfiguration.java)
+[3](http://hg.berlios.de/repos/digilib/file/default/servlet3/src/main/java/digilib/conf/DigilibServlet3Configuration.java)
+):
+
+	<!-- Digilib servlet config file -->
+	<digilib-config>
+	  <!--  Image to be sent to indicate general failure. -->
+	  <parameter name="error-image" value="/docuserver/images/icons/broken.gif" />
+	
+	  <!--  Image to be sent to indicate authorization failure. -->
+	  <parameter name="denied-image" value="/docuserver/images/icons/alert.red.gif" />
+	
+	  <!--  Image to be sent to indicate file-not-found. -->
+	  <parameter name="notfound-image" value="/docuserver/images/icons/notfound.gif" />
+	
+	  <!-- List of directories where images are searched.
+	       The authoritative directory with the high-resolution images
+	       is first in list. -->
+	  <parameter name="basedir-list" value="/docuserver/images:/docuserver/scaled/small" />
+	
+	  <!-- mimimum amount of scaling done with antialiasing -->
+	  <parameter name="subsample-minimum" value="2"/>
+	
+	  <!-- default interpolation quality (0=worst) -->
+	  <parameter name="default-quality" value="2"/>
+	
+	  <!-- is sending whole image files with mo=file allowed? -->
+	  <parameter name="sendfile-allowed" value="true" />
+	
+	  <!-- the a maximum size of any sent image. (0 means no limit) -->
+	  <parameter name="max-image-size" value="0" />
+	
+	  <!-- number of working threads -->
+	  <parameter name="worker-threads" value="2" />
+	
+	  <!-- number of waiting requests in queue -->
+	  <parameter name="max-waiting-threads" value="20" />
+	
+	  <!-- Restrict access to authorized users.
+	       User authentication and roles are provided by the servlet container 
+	       (see tomcat-users.xml).
+	       Authorization for resources (directories) is evaluated by the servlet 
+	       (see auth-file). -->
+	  <parameter name="use-authorization" value="false"/>
+	
+	  <!-- Location of XML file with authorization requirements. -->
+	  <parameter name="auth-file" value="digilib-auth.xml"/>
+	
+	  <!-- Part of URL to indicate authenticated access to Tomcat. -->
+	  <parameter name="auth-url-path" value="authenticated/"/>
+	
+	  <!-- use mapping of "virtual directories" to real directories on the server -->
+	  <parameter name="use-mapping" value="false"/>
+	
+	  <!-- location of XML mapping file -->
+	  <parameter name="mapping-file" value="digilib-map.xml"/>
+	
+	  <!-- location of logger config file -->
+	  <parameter name="log-config-file" value="log4j-config.xml"/>
+	</digilib-config>
+
+You can supply your own icons for the "error" and "access denied" 
+messages by the servlet. Standard images will be used if these
+parameters are not defined.
+
+You can specify the Java toolkit implementation with the `docuimage-class`
+parameter. The `ImageLoaderDocuImage` usually gives best performance
+and works with JDK 1.4 and up.
+
+You can see a summary of your running digilib configuration at the URL 
+[http://localhost:8080/digitallibrary/server/dlConfig.jsp](http://localhost:8080/digitallibrary/server/dlConfig.jsp)
+
+
+## digilib-auth.xml
+
+The digilib access authorization is defined in the file defined by the `auth-file`
+parameter (default: `digilib-auth.xml` in `WEB-INF` ).
+
+The file has two parts `diglib-paths` and `diglib-addresses`. It looks like this:
+
+	<auth-config>
+	
+	  <digilib-paths>
+	    <!-- 
+	      A user must supply one of the roles under "role"
+	      to access the directory "name".
+	      Roles under "role" must be separated by comma only (no spaces).  
+	    -->
+	    <path name="histast/eastwood-collection" role="eastwood-coll" />
+	    <path name="ptolemaios_geo" role="ptolemaios-geo" />
+	  </digilib-paths>
+	
+	  <digilib-addresses>
+	    <!-- 
+	      A computer with an ip address that matches "ip"
+	      is automatically granted all roles under "role".
+	      The ip address is matched from the left (in full quads).
+	      Roles under "role" must be separated by comma only (no spaces). 
+	    -->
+	    <address ip="127" role="local" />
+	    <address ip="130.92.68" role="eastwood-coll,ptolemaios-geo" />
+	    <address ip="130.92.151" role="ALL" />
+	  </digilib-addresses>
+	
+	</auth-config>
+
+`diglib-paths` defines restricted directories and the roles needed
+for access. The roles are defined with the users in `tomcat-users.xml`
+(see above). All subdirectories of the given directories have the same
+restrictions. All directories not listed here (and not subdirectories of listed
+directories) are freely accessible.
+
+`diglib-addresses` defines hosts or networks of computers that are
+automatically authenticated without username and password. Hosts can be assigned
+roles. The special keyword `ALL` authorizes for everything. If the
+role assigned to the computer is not sufficient to access a resource the user
+will be asked for username and password.
+        
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/site/markdown/history.md	Tue Oct 01 12:24:29 2013 +0200
@@ -0,0 +1,36 @@
+## Early history of digilib (in German)
+
+### docuedit (auch DocumentDatabase, später doculight)
+
+Imageviewer mit Dokumenten-Baum Ansicht, in Java geschrieben, komplett
+Client-seitig. Entstanden vor März 1998 (müsste am MPIWG gewesen sein).
+Wesentlicher Autor Michael May (glaube ich).
+
+Von doculight gibt es hier sogar noch eine "Web-Version" von Anfang 2000
+aus Bern, die aber nicht mehr ganz funktioniert:
+
+[http://pythia2.unibe.ch/docuserver/viewerlite/frame.htm](http://pythia2.unibe.ch/docuserver/viewerlite/frame.htm)
+
+Und hier ist der Übergang zur Client-Server Lösung "gg.jsp" (noch ohne
+serverseitige Skalierung der Seiten) vom Juni 2000, das leider mangels
+JSP auf dem Server nicht mehr geht: 
+
+[http://pythia2.unibe.ch/docuserver/viewerlite/gg.jsp](http://pythia2.unibe.ch/docuserver/viewerlite/gg.jsp)
+
+(Die Knöpfe sind zwar noch schlicht haben aber schon die gleichen
+Funktionen wie später)
+
+### digilib (ScaleServlet, später Scaler)
+
+Client-Server Lösung mit Javascript auf dem Client und Java auf dem Server. 
+Entstanden ca. Juli 2000. Wesentlicher Autor zunächst Robert Gordesch (Stud. 
+Hilfskraft MPIWG) für den Server-Teil in Java und Gerd Graßhoff (Bern) fürs 
+Javascript (glaube ich), seit Februar 2001 Robert Casties (Bern, ab 2002 MPIWG), 
+danach auch Christian Luginbühl. Seit Anfang 2002 Open Source Projekt bei 
+BerliOS.
+
+## Articles on digilib
+
+1. Raspe, Martin; Casties, Robert; "Digilib: Wissenschaftliches Bildmaterial 
+studieren und kommentierenim Internet", Jahrbuch der Max-Planck-Gesellschaft 2006, 
+[http://www.mpg.de/411123/pdf.pdf](http://www.mpg.de/411123/pdf.pdf)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/site/markdown/image-directories.md	Tue Oct 01 12:24:29 2013 +0200
@@ -0,0 +1,85 @@
+# Directory layout for images
+
+In digilib all images are identified by the `fn` and (optional) `pn` parameters. 
+The value for `fn` can be a directory path or a directory path and a filename, 
+separated by slashes, e.g. "`fn=books/book1/page0002`".
+
+If `fn` is a directory path without filename `pn` is the index number of the 
+image files in this directory in alphabetical order, e.g.
+"`fn=books/book1&pn=2`". The default for `pn` is 1 i.e. the first image. 
+
+If `fn` ends in a filename `pn` is ignored. File extensions are also ignored,
+i.e. "`books/book1/page0002`" and "`books/book1/page0002.tif`" identify the same 
+image. It is recommended to omit the file extension.
+
+The directory path in `fn` is relative to the base directory in the `basedir-list`
+parameter of the `digilib-config.xml` file, e.g. if
+
+	<parameter name="basedir-list" value="/docuserver/images" />
+
+and
+
+	fn=books/book1/page0002
+
+then digilib will try to load the file
+
+	/docuserver/images/books/book1/page0002.tif
+	
+(automatically finding the right file extension)
+	
+
+## Prescaled images
+
+You can provide any number of scaled-down versions of your images that
+digilib can use when a smaller version of an image is requested. Since less data
+has to be read and processed this can speed up digilib's performance considerably.
+
+The actual process is that the client requests a certain target size,
+digilib scans all available scaled-down versions of the same image, selects the
+smallest image that is larger than the requested size and scales it down to the
+requested size.
+
+There is another optimization in digilib: if the requested image is *exactly*
+the same size and type as the pre-scaled image then the pre-scaled image is sent
+unmodified to the client which is a lot faster. So it makes sense to produce
+thumbnails of exactly 90 pixel width when they are used in an HTML page where
+all images are 90 pixel wide.
+
+The scaled-down versions of the image have to have the same file name as
+the original hi-res file. They can have a different type and extension (e.g.
+`img002.jpg` for `img002.TIFF`)
+
+The scaled down images have to have the same directory path (the part that
+shows up in digilib's "fn" parameter) as the hi-res file wile the first part of each
+directory tree is configured by the `basedir-list` parameter in
+`digilib-config.xml`.
+
+The sequence of directories in `basedir-list` is from high-res to low-res.
+Images must be present in the hires directory but they need not be present in
+all lower-res directories.
+
+e.g. if digilib-config.xml contains
+
+	<parameter name="basedir-list" value="/images:/scaled:/thumb" />
+
+and a user requests the image `books/book1/page0002` digilib looks for
+
+1. `/thumb/books/book1/page0002.jpg`
+2. `/scaled/books/book1/page002.jpg`
+3. `/images/books/book1/page002.tif`
+
+(automatically finding the right file extension) 
+and uses the first image that is bigger than or equal to the requested size.
+
+For batch-prescaling our images we use a script called "scale-o-mat" that uses a
+lot of freely available imaging libraries (ImageMagick, libtiff, netpbm) and is
+available in our public CVS [[1]](http://itgroup.mpiwg-berlin.mpg.de/cgi-bin/cvsweb.cgi/scaleomat/). 
+The script is given a
+hi-res base directory, a destination base directory, a destination size and a
+starting directory. It then processes all files in the starting directory and
+all its subdirectories and creates scaled images in corresponding directories
+under the destination base directory.
+
+We currently use prescaled thumbnails of 100 pixels and images for browser
+display of 1500 pixels. Remember that the prescaled image has to be larger (or
+the same size) than the requested image size!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/site/markdown/index.md	Tue Oct 01 12:24:29 2013 +0200
@@ -0,0 +1,33 @@
+![digilib](images/digilib-logo-big.png)
+
+## What is digilib?
+
+* `digilib` is a web based client/server technology for images. The image
+  content is processed on-the-fly by a Java Servlet on the server side so that
+  only the visible portion of the image is sent to the web browser on the client
+  side.
+* `digilib` supports a wide range of image formats and viewing options on
+  the server side while only requiring an internet browser with Javascript and a
+  low bandwidth internet connection on the client side.
+* `digilib` enables very detailed work on an image as required by
+  scholars with elaborate viewing features like an option to show images on the
+  screen in their original size.
+* `digilib` facilitates cooperation of scholars over the internet and
+  novel uses of source material by image annotations and stable references that
+  can be embedded in URLs.
+* `digilib` is Open Source Software under the Lesser General Public License,
+  jointly developed by the
+  [Max-Planck-Institute for the History of Science](http://www.mpiwg-berlin.mpg.de),
+  the [Bibliotheca Hertziana](http://www.biblhertz.it), 
+  the [University of Bern](http://philoscience.unibe.ch) and others.
+
+## Where can I get digilib?
+
+`digilib` source code, binaries and documentation can be found on the 
+[digilib project pages](http://developer.berlios.de/projects/digilib/)
+on [BerliOS](http://developer.berlios.de):
+
+* [Source code](http://hg.berlios.de/repos/digilib)
+* Daily built [WAR files](http://digilib.berlios.de/downloads/daily-build/)
+* Daily built [Javadoc](http://digilib.berlios.de/downloads/daily-build/javadoc/)
+* [Maven repository](http://it-dev.mpiwg-berlin.mpg.de/maven-repo/)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/site/markdown/java-settings.md	Tue Oct 01 12:24:29 2013 +0200
@@ -0,0 +1,55 @@
+# Java VM settings for digilib
+
+The Java virtual machine (Java-VM) only uses a fixed amount of memory for
+its operations. When an operation needs more memory than available it aborts
+with an error ("out of memory error").
+
+digilib can need a lot of memory depending on the size and type of images.
+Since digilib runs as a servlet under Tomcat its in the same VM as the Tomcat
+server.
+
+The amount of memory Tomcat (version 5.0) uses is configured by creating a
+`setenv.sh` (or `setenbv.bat`) script with a line
+
+    CATALINA_OPTS="-Xmx512m"
+
+in Tomcat's `bin` directory (giving 512MB RAM in this case).
+
+You can check the amount of memory your digilib instance has available on the
+bottom of the web page `/server/dlConfig.jsp` in your digilib instance (e.g. 
+<http://localhost:8080/digilib/server/dlConfig.jsp>
+
+# Installing JAI ImageIO
+
+In principle you should be able to install the 
+[Java Advanced Imaging](http://java.sun.com/javase/technologies/desktop/media/jai/) JAI-ImageIO
+JAR file `jai_imageio.jar` (and native
+library files if available) in the `/WEB-INF/lib/` directory of the
+digilib web application as part of the default installation.
+
+You can see if the Jai-ImageIO plugin is active by checking for the 
+availability of the TIFF image format under "Supported image types" on the 
+[`/server/dlConfig.jsp`](http://localhost:8080/digilib/server/dlConfig.jsp)
+status page.
+
+Sometimes there are memory issues. Newer versions of Tomcat refuse to load
+the libraries and I found that in some cases digilib stopped reading TIFF files
+after a period of running. In these cases it helped to install the JAI files in 
+Tomcats `lib/` directory or globally in the local Java JDK
+installation (i.e. in the Java's 'jre/lib/ext/' directory on linux).
+
+# Sample setup
+
+The current digilib setup at the MPIWG (as of December 2010):
+
+* One frontend server running the lightweight web-multiplexer [pound](http://www.apsis.ch/pound/)
+    on port 80 that distributes requests to three servers runnning digilib
+* the three servers run digilib under [Jetty](http://www.eclipse.org/jetty/) on port 8080 without Apache
+   * one server is the frontend server (Linux 32bit, Dual 2.4GHz Xeon, 2GB RAM)
+   * the other server is a separate, newer machine (Linux 64bit, Dual 1.8GHz Opteron, 2GB RAM)
+   * the third server is a separate, newer machine (Linux 32bit, Dual 2.8GHz Xeon, 4GB RAM)
+* the digilib instances (digilib 2.0b1 as of 12.12.2011) run on Jetty 8.0.4 on Java
+   1.6.0_26 with 1GB of Java VM memory for digilib (-Xmx1024m) with JAI (1.1.3) and JAI-ImageIO (1.1)
+   installed in `Jetty/lib/ext`
+* both digilib servers access all image files over NFS (over GBit Ethernet) from a central file server 
+   (Solaris 10, Sun Fire 240, multiple RAIDs on Fibrechannel)
\ No newline at end of file
Binary file doc/src/site/resources/images/digilib-logo-big.png has changed
Binary file doc/src/site/resources/images/digilib-logo-small.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/site/site.xml	Tue Oct 01 12:24:29 2013 +0200
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/DECORATION/1.3.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/DECORATION/1.3.0 http://maven.apache.org/xsd/decoration-1.3.0.xsd">
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-fluido-skin</artifactId>
+    <version>1.3.0</version>
+  </skin>
+  <bannerLeft>
+    <name>digilib - a versatile image viewing environment for the internet</name>
+    <href>http://digilib.berlios.de/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>images/digilib-logo-small.png</src>
+    <href>http://digilib.berlios.de/</href>
+  </bannerRight>
+  <body>
+    <menu name="Overview">
+      <item name="About digilib" href="index.html"/>
+      <item name="How digilib works" href="digilib-short.html"/>
+      <item name="Ancient history" href="history.html"/>
+    </menu>
+    <menu name="Installation">
+      <item name="Installing digilib" href="install-digilib.html"/>
+      <item name="Building digilib" href="build-maven.html"/>
+    </menu>
+    <menu name="Configuration">
+      <item name="Configuring digilib" href="digilib-config.html"/>
+      <item name="Directory layout" href="image-directories.html"/>
+      <item name="Java settings" href="java-settings.html"/>
+    </menu>
+    <menu name="Development">
+      <item name="The digilib Scaler API" href="scaler-api.html"/>
+      <!-- <item name="Integrating digilib into your page" href=""/>
+      <item name="Integrating digilib into your server" href=""/> -->
+    </menu>
+    <menu ref="reports"/>
+  </body>
+</project>
--- a/pom.xml	Mon Sep 30 16:06:13 2013 +0200
+++ b/pom.xml	Tue Oct 01 12:24:29 2013 +0200
@@ -1,217 +1,260 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
 
-	<groupId>digilib</groupId>
-	<artifactId>digilib</artifactId>
-	<version>2.2-SNAPSHOT</version>
-	<packaging>pom</packaging>
+  <groupId>digilib</groupId>
+  <artifactId>digilib</artifactId>
+  <version>2.2-SNAPSHOT</version>
+  <packaging>pom</packaging>
 
-	<name>digilib</name>
-	<description>The Digital Image Library</description>
-	<url>http://digilib.berlios.de</url>
-	<inceptionYear>2001</inceptionYear>
+  <name>digilib</name>
+  <description>The Digital Image Library</description>
+  <url>http://digilib.berlios.de</url>
+  <inceptionYear>2001</inceptionYear>
 
-	<organization>
-		<name>digilib Community</name>
-		<url>http://digilib.berlios.de</url>
-	</organization>
+  <organization>
+    <name>digilib Community</name>
+    <url>http://digilib.berlios.de</url>
+  </organization>
 
-	<developers>
-		<developer>
-			<id>robcast</id>
-			<name>Robert Casties</name>
-			<email>robcast@berlios.de</email>
-			<organization>Max Planck Institute for the History of Science (MPIWG)</organization>
-			<organizationUrl>http://www.mpiwg-berlin.mpg.de</organizationUrl>
-			<roles>
-			</roles>
-		</developer>
-		<developer>
-			<id>hertzhaft</id>
-			<name>Martin Raspe</name>
-			<email>hertzhaft@berlios.de</email>
-			<organization>Bibliotheca Hertziana</organization>
-			<organizationUrl>http://www.biblhertz.it</organizationUrl>
-		</developer>
-	</developers>
-	<licenses>
-		<license>
-			<name>GNU General Lesser Public License (LGPL) version 3.0</name>
-			<url>http://www.gnu.org/licenses/lgpl-3.0.html</url>
-			<distribution>repo</distribution>
-		</license>
-	</licenses>
-	<scm>
-		<connection>scm:hg:http://hg.berlios.de/repos/digilib</connection>
-		<developerConnection>scm:hg:https://hg.berlios.de/repos/digilib</developerConnection>
-		<url>http://hg.berlios.de/repos/digilib</url>
-	</scm>
-	<issueManagement>
-		<system>Trac</system>
-		<url>https://it-dev.mpiwg-berlin.mpg.de/tracs/digilib</url>
-	</issueManagement>
+  <developers>
+    <developer>
+      <id>robcast</id>
+      <name>Robert Casties</name>
+      <email>robcast@berlios.de</email>
+      <organization>Max Planck Institute for the History of Science (MPIWG)</organization>
+      <organizationUrl>http://www.mpiwg-berlin.mpg.de</organizationUrl>
+      <roles>
+        <role>developer</role>
+        <role>architect</role>
+      </roles>
+    </developer>
+    <developer>
+      <id>hertzhaft</id>
+      <name>Martin Raspe</name>
+      <email>hertzhaft@berlios.de</email>
+      <organization>Bibliotheca Hertziana</organization>
+      <organizationUrl>http://www.biblhertz.it</organizationUrl>
+      <roles>
+        <role>developer</role>
+      </roles>
+    </developer>
+  </developers>
+  <contributors>
+    <contributor>
+      <name>Gerd Grasshoff</name>
+      <organization>Humboldt Universität Berlin</organization>
+      <organizationUrl>http://www.hu-berlin.de</organizationUrl>
+      <roles>
+        <role>former developer</role>
+      </roles>
+    </contributor>
+    <contributor>
+      <name>Robert Gordesch</name>
+      <organization>Max Planck Institute for the History of Science (MPIWG)</organization>
+      <roles>
+        <role>former developer</role>
+      </roles>
+    </contributor>
+    <contributor>
+      <name>Christian Luginbuehl</name>
+      <organization>Universität Bern</organization>
+      <roles>
+        <role>former developer</role>
+      </roles>
+    </contributor>
+  </contributors>
+  <licenses>
+    <license>
+      <name>GNU General Lesser Public License (LGPL) version 3.0</name>
+      <url>http://www.gnu.org/licenses/lgpl-3.0-standalone.html</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <scm>
+    <connection>scm:hg:http://hg.berlios.de/repos/digilib</connection>
+    <developerConnection>scm:hg:https://hg.berlios.de/repos/digilib</developerConnection>
+    <url>http://hg.berlios.de/repos/digilib</url>
+  </scm>
+  <issueManagement>
+    <system>Trac</system>
+    <url>https://it-dev.mpiwg-berlin.mpg.de/tracs/digilib</url>
+  </issueManagement>
+  <mailingLists>
+    <mailingList>
+      <name>Developer List</name>
+      <subscribe>https://lists.berlios.de/mailman/listinfo/digilib-devel</subscribe>
+      <unsubscribe>https://lists.berlios.de/mailman/listinfo/digilib-devel</unsubscribe>
+      <archive>https://lists.berlios.de/pipermail/digilib-devel/</archive>
+    </mailingList>
+  </mailingLists>
 
-	<build>
-		<pluginManagement>
-			<plugins>
-				<plugin>
-					<groupId>org.apache.maven.plugins</groupId>
-					<artifactId>maven-compiler-plugin</artifactId>
-					<version>2.3.2</version>
-				</plugin>
-			</plugins>
-		</pluginManagement>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-scm-plugin</artifactId>
-				<version>1.5</version>
-				<configuration>
-					<goals>install</goals>
-				</configuration>
-			</plugin>
-			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>license-maven-plugin</artifactId>
-				<version>1.4</version>
-				<configuration>
-					<!--  <verbose>false</verbose> -->
-                    <licenseName>lgpl_v3</licenseName>
-                    <!-- <useMissingFile>true</useMissingFile> -->
-                    <!-- servlet-api is never included in packaging -->
-                    <excludedArtifacts>servlet-api</excludedArtifacts>
-				</configuration>
-			</plugin>
-  			<plugin>
-		        <groupId>org.apache.maven.plugins</groupId>
-    		    <artifactId>maven-javadoc-plugin</artifactId>
-				<version>2.9.1</version>
-        		<configuration>
-          			<show>package</show>
-          			<nohelp>true</nohelp>
-        		</configuration>
-   		    </plugin>
-		</plugins>
-	</build>
-	<profiles>
-		<profile>
-			<id>servlet2</id>
-		</profile>
-		<profile>
-			<id>servlet3</id>
-			<activation>
-				<activeByDefault>true</activeByDefault>
-			</activation>
-		</profile>
-		<!-- optional modules with dependencies selected by profile -->
-		<profile>
-			<id>text</id>
-			<modules>
-				<module>text</module>
-			</modules>
-		</profile>
-		<profile>
-			<id>pdf</id>
-			<modules>
-				<module>pdf</module>
-			</modules>
-		</profile>
-		<profile>
-			<id>codec-jai</id>
-			<modules>
-				<module>common-jai</module>
-			</modules>
-		</profile>
-		<profile>
-			<id>codec-imagej</id>
-			<modules>
-				<module>common-imagej</module>
-			</modules>
-		</profile>
-		<profile>
-			<id>codec-bioformats</id>
-			<modules>
-				<module>common-bioformats</module>
-			</modules>
-		</profile>
-	</profiles>
-	<repositories>
-	</repositories>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>2.3.2</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-scm-plugin</artifactId>
+        <version>1.5</version>
+        <configuration>
+          <goals>install</goals>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>license-maven-plugin</artifactId>
+        <version>1.4</version>
+        <configuration>
+          <!-- <verbose>false</verbose> -->
+          <licenseName>lgpl_v3</licenseName>
+          <!-- <useMissingFile>true</useMissingFile> -->
+          <!-- servlet-api is never included in packaging -->
+          <excludedArtifacts>servlet-api</excludedArtifacts>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.9.1</version>
+        <configuration>
+          <show>package</show>
+          <nohelp>true</nohelp>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>servlet2</id>
+    </profile>
+    <profile>
+      <id>servlet3</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+    </profile>
+    <!-- optional modules with dependencies selected by profile -->
+    <profile>
+      <id>text</id>
+      <modules>
+        <module>text</module>
+      </modules>
+    </profile>
+    <profile>
+      <id>pdf</id>
+      <modules>
+        <module>pdf</module>
+      </modules>
+    </profile>
+    <profile>
+      <id>codec-jai</id>
+      <modules>
+        <module>common-jai</module>
+      </modules>
+    </profile>
+    <profile>
+      <id>codec-imagej</id>
+      <modules>
+        <module>common-imagej</module>
+      </modules>
+    </profile>
+    <profile>
+      <id>codec-bioformats</id>
+      <modules>
+        <module>common-bioformats</module>
+      </modules>
+    </profile>
+  </profiles>
+  <repositories>
+  </repositories>
 
-	<dependencyManagement>
-		<dependencies>
-			<dependency>
-				<groupId>log4j</groupId>
-				<artifactId>log4j</artifactId>
-				<version>1.2.14</version>
-			</dependency>
-			<!-- digilib module versions -->
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-common</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-common-jai</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-common-imagej</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-common-bioformats</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-pdf</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-text</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-servlet</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-servlet2</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-servlet3</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-			<dependency>
-				<groupId>digilib</groupId>
-				<artifactId>digilib-webapp</artifactId>
-				<version>2.2-SNAPSHOT</version>
-			</dependency>
-		</dependencies>
-	</dependencyManagement>
-	<properties>
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-	</properties>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>log4j</groupId>
+        <artifactId>log4j</artifactId>
+        <version>1.2.14</version>
+      </dependency>
+      <!-- digilib module versions -->
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-common</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-common-jai</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-common-imagej</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-common-bioformats</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-doc</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-pdf</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-text</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-servlet</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-servlet2</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-servlet3</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>digilib</groupId>
+        <artifactId>digilib-webapp</artifactId>
+        <version>2.2-SNAPSHOT</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
 
-	<dependencies>
-	</dependencies>
-	<!-- default modules -->
-	<modules>
-		<module>common</module>
-		<module>servlet</module>
-		<module>servlet2</module>
-		<module>servlet3</module>
-		<module>webapp</module>
-	</modules>
+  <dependencies>
+  </dependencies>
+  <!-- default modules -->
+  <modules>
+    <module>common</module>
+    <module>servlet</module>
+    <module>servlet2</module>
+    <module>servlet3</module>
+    <module>webapp</module>
+    <module>doc</module>
+  </modules>
 </project>
\ No newline at end of file
--- a/servlet/src/main/java/digilib/servlet/ServletOps.java	Mon Sep 30 16:06:13 2013 +0200
+++ b/servlet/src/main/java/digilib/servlet/ServletOps.java	Tue Oct 01 12:24:29 2013 +0200
@@ -44,6 +44,7 @@
 import digilib.conf.DigilibServletRequest;
 import digilib.image.DocuImage;
 import digilib.image.ImageOpException;
+import digilib.io.FileOpException;
 import digilib.io.FileOps;
 import digilib.io.ImageInput;
 import digilib.util.ImageSize;
@@ -353,6 +354,7 @@
      * @param dlReq
      * @param response
      * @param logger
+     * @throws FileOpException 
      * @throws ServletException
      * @see <a href="http://www-sul.stanford.edu/iiif/image-api/1.1/#info">IIIF Image Information Request</a>
      */
@@ -361,34 +363,44 @@
             logger.error("No response!");
             return;
         }
+        ImageSize size = null;
         try {
             // get original image size
-            ImageInput img = dlReq.getJobDescription().getImageSet().getBiggest();
-            ImageSize size = img.getSize();
-            String url = dlReq.getServletRequest().getRequestURL().toString();
-            if (url.endsWith("/info.json")) {
-                url = url.substring(0, url.lastIndexOf("/info.json"));
-            } else if (url.endsWith("/")) {
-                url = url.substring(0, url.lastIndexOf("/"));
+            ImageInput img;
+            img = dlReq.getJobDescription().getImageSet().getBiggest();
+            size = img.getSize();
+        } catch (FileOpException e) {
+            try {
+                response.sendError(HttpServletResponse.SC_NOT_FOUND);
+                return;
+            } catch (IOException e1) {
+                throw new ServletException("Unable to write error response!", e);
             }
-            response.setContentType("application/json;charset=UTF-8");
-            PrintWriter writer = response.getWriter();
+        }
+        String url = dlReq.getServletRequest().getRequestURL().toString();
+        if (url.endsWith("/info.json")) {
+            url = url.substring(0, url.lastIndexOf("/info.json"));
+        } else if (url.endsWith("/")) {
+            url = url.substring(0, url.lastIndexOf("/"));
+        }
+        response.setContentType("application/json;charset=UTF-8");
+        PrintWriter writer;
+        try {
+            writer = response.getWriter();
             writer.println("{");
             writer.println("\"@context\" : \"http://library.stanford.edu/iiif/image-api/1.1/context.json\",");
-            writer.println("\"@id\" : \""+url+"\",");
-            writer.println("\"width\" : "+size.width+",");
-            writer.println("\"height\" : "+size.height+",");
+            writer.println("\"@id\" : \"" + url + "\",");
+            writer.println("\"width\" : " + size.width + ",");
+            writer.println("\"height\" : " + size.height + ",");
             writer.println("\"formats\" : [\"jpg\", \"png\"],");
             writer.println("\"qualities\" : [\"native\", \"color\", \"grey\"],");
             writer.println("\"profile\" : \"http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2\"");
             writer.println("}");
         } catch (IOException e) {
-            throw new ServletException("Error sending info:", e);
+            throw new ServletException("Unable to write response!", e);
         }
-        // TODO: should we: finally { img.dispose(); }
     }
 
-
     /** Returns text representation of headers for debuggging purposes.
      * @param req
      * @return