changeset 819:a23c4c15a6a8 stream

clean up possible resource leaks. better behaviour with unknown image types.
author robcast
date Mon, 21 Feb 2011 22:36:35 +0100
parents 0b4345866797
children dc8cda290f2f
files servlet/src/digilib/image/DocuImage.java servlet/src/digilib/image/DocuImageImpl.java servlet/src/digilib/image/ImageInfoDocuImage.java servlet/src/digilib/image/ImageJobDescription.java servlet/src/digilib/image/ImageLoaderDocuImage.java servlet/src/digilib/io/ImageInput.java servlet/src/digilib/io/ImageSet.java servlet/src/digilib/servlet/AsyncServletWorker.java servlet/src/digilib/servlet/Scaler.java servlet/src/digilib/servlet/ScalerNoAsync.java servlet/src/digilib/servlet/ScalerNoThread.java servlet/src/digilib/servlet/ServletOps.java servlet/src/digilib/servlet/Texter.java
diffstat 13 files changed, 163 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/servlet/src/digilib/image/DocuImage.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/image/DocuImage.java	Mon Feb 21 22:36:35 2011 +0100
@@ -63,15 +63,15 @@
 	public void loadSubimage(ImageInput ii, Rectangle region, int subsample)
 		throws FileOpException;
 
-	/** Writes the current image to a ServletResponse.
+	/** Writes the current image to an OutputStream.
 	 *
 	 * The image is encoded to the mime-type <code>mt</code> and sent to the output
-	 * stream of the <code>ServletResponse</code> <code>res</code>.
+	 * stream <code>ostream</code>.
 	 *
 	 * Currently only mime-types "image/jpeg" and "image/png" are supported.
 	 * 
 	 * @param mt mime-type of the image to be sent.
-	 * @param res ServletResponse where the image is sent.
+	 * @param ostream OutputStream where the image is sent.
 	 * @throws ServletException Exception thrown on sending data.
 	 * @throws ImageOpException Exception in other cases.
 	 */
--- a/servlet/src/digilib/image/DocuImageImpl.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/image/DocuImageImpl.java	Mon Feb 21 22:36:35 2011 +0100
@@ -156,11 +156,11 @@
 
     public void crop(int xoff, int yoff, int width, int height)
             throws ImageOpException {
-        // TODO Auto-generated method stub
+        // emtpy implementation
     }
 
     public Image getAwtImage() {
-        // TODO Auto-generated method stub
+        // emtpy implementation
         return null;
     }
 
--- a/servlet/src/digilib/image/ImageInfoDocuImage.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/image/ImageInfoDocuImage.java	Mon Feb 21 22:36:35 2011 +0100
@@ -21,27 +21,35 @@
     /* Check image size and type and store in ImageFile f */
     public ImageInput identify(ImageInput ii) throws IOException {
         logger.debug("identifying (ImageInfo) " + ii);
-        // set up ImageInfo object
-        ImageInfo iif = new ImageInfo();
-        if (ii.hasImageInputStream()) {
-            iif.setInput(ii.getImageInputStream());
-        } else if (ii.hasFile()) {
-            RandomAccessFile raf = new RandomAccessFile(ii.getFile(), "r");
-            iif.setInput(raf);
-        } else {
+        RandomAccessFile raf = null;
+        try {
+            // set up ImageInfo object
+            ImageInfo iif = new ImageInfo();
+            if (ii.hasImageInputStream()) {
+                iif.setInput(ii.getImageInputStream());
+            } else if (ii.hasFile()) {
+                raf = new RandomAccessFile(ii.getFile(), "r");
+                iif.setInput(raf);
+            } else {
+                return null;
+            }
+            iif.setCollectComments(false);
+            iif.setDetermineImageNumber(false);
+            // try with ImageInfo first
+            if (iif.check()) {
+                ImageSize d = new ImageSize(iif.getWidth(), iif.getHeight());
+                ii.setSize(d);
+                ii.setMimetype(iif.getMimeType());
+                logger.debug("image size: " + ii.getSize());
+                return ii;
+            }
             return null;
+        } finally {
+            // close file, don't close stream(?)
+            if (raf != null) {
+                raf.close();
+            }
         }
-        iif.setCollectComments(false);
-        iif.setDetermineImageNumber(false);
-        // try with ImageInfo first
-        if (iif.check()) {
-            ImageSize d = new ImageSize(iif.getWidth(), iif.getHeight());
-            ii.setSize(d);
-            ii.setMimetype(iif.getMimeType());
-            logger.debug("image size: " + ii.getSize());
-            return ii;
-        }
-        return null;
     }
         
 
--- a/servlet/src/digilib/image/ImageJobDescription.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/image/ImageJobDescription.java	Mon Feb 21 22:36:35 2011 +0100
@@ -166,11 +166,12 @@
 					input = imageSet.getBiggest();
 				}
 			}
-			logger.info("Planning to load: " + input);
+			if (input == null || input.getMimetype() == null) {
+			    throw new FileOpException("Unable to load "+input);
+			}
+            logger.info("Planning to load: " + input);
 		}
-		
 		return input;
-
 	}
 	
 	/** Returns the DocuDirectory for the input (file). 
@@ -503,33 +504,27 @@
 		|| hasOption("rawfile");
 	}
 	
-	/**
-	 * Returns if the image can be sent without processing. Takes image type and
-	 * additional image operations into account. Does not check requested size
-	 * transformation.
-	 * 
-	 * @return
-	 * @throws IOException
-	 */
-	public boolean isImageSendable() throws IOException {
-		// cached result?
-		if (imageSendable == null) {
-			String mimeType = getMimeType();
-			imageSendable = ( (mimeType.equals("image/jpeg")
-				        	|| mimeType.equals("image/png")
-				        	|| mimeType.equals("image/gif") )
-				        	&& 
-				        	!(hasOption("hmir")
-							|| hasOption("vmir") 
-							|| (getAsFloat("rot") != 0.0)
-							|| (getRGBM() != null) 
-							|| (getRGBA() != null)
-							|| (getAsFloat("cont") != 0.0) 
-							|| (getAsFloat("brgt") != 0.0)));
-		}
-		
-		return imageSendable;
-	}
+    /**
+     * Returns if the image can be sent without processing. Takes image type and
+     * additional image operations into account. Does not check requested size
+     * transformation.
+     * 
+     * @return
+     * @throws IOException
+     */
+    public boolean isImageSendable() throws IOException {
+        if (imageSendable == null) {
+            String mimeType = getMimeType();
+            imageSendable = (mimeType != null
+                    && (mimeType.equals("image/jpeg") || mimeType.equals("image/png") 
+                            || mimeType.equals("image/gif"))
+                    && !(hasOption("hmir")
+                    || hasOption("vmir") || (getAsFloat("rot") != 0.0)
+                    || (getRGBM() != null) || (getRGBA() != null)
+                    || (getAsFloat("cont") != 0.0) || (getAsFloat("brgt") != 0.0)));
+        }
+        return imageSendable;
+    }
 	
 	
 	/**
--- a/servlet/src/digilib/image/ImageLoaderDocuImage.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java	Mon Feb 21 22:36:35 2011 +0100
@@ -2,7 +2,7 @@
 
  Digital Image Library servlet components
 
- Copyright (C) 2002, 2003 Robert Casties (robcast@mail.berlios.de)
+ Copyright (C) 2002 - 2011 Robert Casties (robcast@mail.berlios.de)
 
  This program is free software; you can redistribute  it and/or modify it
  under  the terms of  the GNU General  Public License as published by the
@@ -60,15 +60,15 @@
 	/** interpolation type */
 	protected RenderingHints renderHint;
 
-	/** ImageIO image reader */
-	protected ImageReader reader;
-
 	protected static Kernel[] convolutionKernels = {
 	        null,
 	        new Kernel(1, 1, new float[] {1f}),
             new Kernel(2, 2, new float[] {0.25f, 0.25f, 0.25f, 0.25f}),
             new Kernel(3, 3, new float[] {1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f})
 	};
+
+	/** the size of the current image */
+    protected ImageSize imageSize;
 	
 	
 	/* loadSubimage is supported. */
@@ -95,25 +95,26 @@
 
     /* returns the size of the current image */
     public ImageSize getSize() {
-        ImageSize is = null;
-        // TODO: do we want to cache imageSize?
-        int h = 0;
-        int w = 0;
-        try {
-            if (img == null) {
-                // get size from ImageReader
-                h = reader.getHeight(0);
-                w = reader.getWidth(0);
-            } else {
-                // get size from image
-                h = img.getHeight();
-                w = img.getWidth();
+        if (imageSize == null) {
+            int h = 0;
+            int w = 0;
+            try {
+                if (img == null) {
+                    ImageReader reader = getReader(input);
+                    // get size from ImageReader
+                    h = reader.getHeight(0);
+                    w = reader.getWidth(0);
+                } else {
+                    // get size from image
+                    h = img.getHeight();
+                    w = img.getWidth();
+                }
+                imageSize = new ImageSize(w, h);
+            } catch (IOException e) {
+                logger.debug("error in getSize:", e);
             }
-            is = new ImageSize(w, h);
-        } catch (IOException e) {
-            logger.debug("error in getSize:", e);
         }
-        return is;
+        return imageSize;
     }
 
 	/* returns a list of supported image formats */
@@ -130,30 +131,36 @@
             return ii;
         }
         logger.debug("identifying (ImageIO) " + input);
-        /*
-         * try ImageReader
-         */
+        ImageReader reader = null;
         try {
+            /*
+             * try ImageReader
+             */
             reader = getReader(input);
+            // set size
+            ImageSize d = new ImageSize(reader.getWidth(0), reader.getHeight(0));
+            input.setSize(d);
+            // set mime type
+            if (input.getMimetype() == null) {
+                if (input.hasFile()) {
+                    String t = FileOps.mimeForFile(input.getFile());
+                    input.setMimetype(t);
+                } else {
+                    // FIXME: is format name a mime type???
+                    String t = reader.getFormatName();
+                    input.setMimetype(t);
+                }
+            }
+            return input;
         } catch (FileOpException e) {
             // maybe just our class doesn't know what to do
+            logger.error("ImageLoaderDocuimage unable to identify:", e);
             return null;
-        }
-        // set size
-        ImageSize d = new ImageSize(reader.getWidth(0), reader.getHeight(0));
-        input.setSize(d);
-        // set mime type
-        if (input.getMimetype() == null) {
-            if (input.hasFile()) {
-                String t = FileOps.mimeForFile(input.getFile());
-                input.setMimetype(t);
-            } else {
-                // FIXME: is format name a mime type???
-                String t = reader.getFormatName();
-                input.setMimetype(t);
+        } finally {
+            if (reader != null) {
+                reader.dispose();
             }
         }
-        return input;
     }
     
     /* load image file */
@@ -178,17 +185,6 @@
 	 */
 	public ImageReader getReader(ImageInput input) throws IOException {
 		logger.debug("get ImageReader for " + input);
-		if (this.reader != null) {
-			if (this.input == input) {
-				// it was the same input
-				logger.debug("reusing Reader");
-				return reader;
-			}
-			// clean up old reader (this shouldn't really happen)
-			logger.debug("cleaning Reader!");
-			dispose();
-		}
-		this.input = input;
 		ImageInputStream istream = null;
 		if (input.hasImageInputStream()) {
 			// stream input
@@ -201,7 +197,11 @@
 			throw new FileOpException("Unable to get data from ImageInput");
 		}
 		Iterator<ImageReader> readers;
-		String mt = input.getMimetype();
+		String mt = null;
+		if (input.hasMimetype()) {
+	        // check hasMimetype first or we might get into a loop
+		    mt = input.getMimetype();
+		}
 		if (mt == null) {
 			logger.debug("No mime-type. Trying automagic.");
 			readers = ImageIO.getImageReaders(istream);
@@ -212,7 +212,7 @@
 		if (!readers.hasNext()) {
 			throw new FileOpException("Can't find Reader to load File!");
 		}
-		reader = readers.next();
+		ImageReader reader = readers.next();
 		/* are there more readers? */
 		logger.debug("ImageIO: this reader: " + reader.getClass());
 		/* while (readers.hasNext()) {
@@ -226,6 +226,8 @@
 	public void loadSubimage(ImageInput ii, Rectangle region, int prescale)
 			throws FileOpException {
 		logger.debug("loadSubimage");
+        this.input = ii;
+        ImageReader reader = null;
 		try {
 			reader = getReader(ii);
 			// set up reader parameters
@@ -240,6 +242,10 @@
 			logger.debug("loaded");
 		} catch (IOException e) {
 			throw new FileOpException("Unable to load File!");
+		} finally {
+		    if (reader != null) {
+		        reader.dispose();
+		    }
 		}
 	}
 
@@ -310,7 +316,7 @@
 	}
 
 	public void scale(double scale, double scaleY) throws ImageOpException {
-		logger.debug("scale");
+		logger.debug("scale: " + scale);
 		/* for downscaling in high quality the image is blurred first */
 		if ((scale <= 0.5) && (quality > 1)) {
 			int bl = (int) Math.floor(1 / scale);
@@ -524,23 +530,8 @@
 		img = mirImg;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see java.lang.Object#finalize()
-	 */
-	protected void finalize() throws Throwable {
-		dispose();
-		super.finalize();
-	}
-
 	public void dispose() {
-		// we must dispose the ImageReader because it keeps the filehandle
-		// open!
-		if (reader != null) {
-			reader.dispose();
-			reader = null;
-		}
+	    // is this necessary?
 		img = null;
 	}
 
--- a/servlet/src/digilib/io/ImageInput.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/io/ImageInput.java	Mon Feb 21 22:36:35 2011 +0100
@@ -51,7 +51,15 @@
 		this.pixelSize = imageSize;
 	}
 
-	/**
+    /** returns if mimetype has been set.
+     * 
+     * @return String
+     */
+    public boolean hasMimetype() {
+        return (mimetype != null);
+    }
+
+    /**
 	 * @return String
 	 */
 	public String getMimetype() {
--- a/servlet/src/digilib/io/ImageSet.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/io/ImageSet.java	Mon Feb 21 22:36:35 2011 +0100
@@ -92,7 +92,8 @@
 	public ImageInput getNextSmaller(ImageSize size) {
 		for (ListIterator<ImageInput> i = getHiresIterator(); i.hasNext();) {
 			ImageInput f = i.next();
-			if (f.getSize().isTotallySmallerThan(size)) {
+            ImageSize is = f.getSize();
+            if (is != null && is.isTotallySmallerThan(size)) {
 				return f;
 			}
 		}
@@ -112,7 +113,8 @@
 	public ImageInput getNextBigger(ImageSize size) {
 		for (ListIterator<ImageInput> i = getLoresIterator(); i.hasPrevious();) {
 			ImageInput f = i.previous();
-			if (f.getSize().isBiggerThan(size)) {
+			ImageSize is = f.getSize();
+			if (is != null && is.isBiggerThan(size)) {
 				return f;
 			}
 		}
--- a/servlet/src/digilib/servlet/AsyncServletWorker.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/servlet/AsyncServletWorker.java	Mon Feb 21 22:36:35 2011 +0100
@@ -50,7 +50,7 @@
     }
 
     /**
-     * runs the ImakeWorker and writes the image to the ServletResponse.
+     * runs the ImageWorker and writes the image to the ServletResponse.
      */
     public void run() {
         // get fresh response
@@ -60,7 +60,7 @@
             DocuImage img = imageWorker.call();
             // send image
             ServletOps.sendImage(img, null, response, logger);
-            logger.debug("Job Processing Time: "
+            logger.debug("Job done in: "
                     + (System.currentTimeMillis() - startTime) + "ms");
         } catch (ImageOpException e) {
             logger.error(e.getClass() + ": " + e.getMessage());
@@ -70,8 +70,11 @@
             Scaler.digilibError(errMsgType, Error.FILE, null, response);
         } catch (ServletException e) {
             logger.error("Servlet error: ", e);
+        } catch (Exception e) {
+            logger.error("Other error: ", e);
         } finally {
             // submit response
+            logger.debug("context complete.");
             asyncContext.complete();
         }
 
--- a/servlet/src/digilib/servlet/Scaler.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/servlet/Scaler.java	Mon Feb 21 22:36:35 2011 +0100
@@ -31,7 +31,7 @@
     private static final long serialVersionUID = 5289386646192471549L;
 
     /** digilib servlet version (for all components) */
-    public static final String version = "1.9.1a3";
+    public static final String version = "1.9.1a7";
 
     /** servlet error codes */
     public static enum Error {UNKNOWN, AUTH, FILE, IMAGE};
--- a/servlet/src/digilib/servlet/ScalerNoAsync.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/servlet/ScalerNoAsync.java	Mon Feb 21 22:36:35 2011 +0100
@@ -34,7 +34,7 @@
     private static final long serialVersionUID = -5439198888139362735L;
 
     /** digilib servlet version (for all components) */
-    public static final String version = "1.9.0a3 noasync";
+    public static final String version = "1.9.0a5 noasync";
 
     /** servlet error codes */
     public static enum Error {UNKNOWN, AUTH, FILE, IMAGE};
--- a/servlet/src/digilib/servlet/ScalerNoThread.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/servlet/ScalerNoThread.java	Mon Feb 21 22:36:35 2011 +0100
@@ -31,7 +31,7 @@
     private static final long serialVersionUID = 1450947819851623306L;
 
     /** digilib servlet version (for all components) */
-    public static final String version = "1.9.0a3 nothread";
+    public static final String version = "1.9.0a5 nothread";
 
     /** servlet error codes */
     public static enum Error {UNKNOWN, AUTH, FILE, IMAGE};
--- a/servlet/src/digilib/servlet/ServletOps.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/servlet/ServletOps.java	Mon Feb 21 22:36:35 2011 +0100
@@ -191,10 +191,10 @@
      * @throws ImageOpException
      * @throws ServletException
      *             Exception on sending data.
+     * @throws IOException
      */
     public static void sendFile(File f, String mt, String name,
-            HttpServletResponse response) throws ImageOpException,
-            ServletException {
+            HttpServletResponse response) throws ImageOpException, IOException {
         // use default logger
         ServletOps.sendFile(f, mt, name, response, ServletOps.logger);
     }
@@ -217,14 +217,11 @@
      *            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, ServletException {
+            throws ImageOpException, IOException {
         logger.debug("sendRawFile(" + mt + ", " + f + ")");
-    	if (response.isCommitted()) {
-        	logger.warn("sendFile: response already committed!");
-        	//return;
-    	}
         if (mt == null) {
             // auto-detect mime-type
             mt = FileOps.mimeForFile(f);
@@ -254,9 +251,6 @@
                 // copy out file
                 outStream.write(dataBuffer, 0, len);
             }
-        } catch (IOException e) {
-            logger.error("Error sending file:", e);
-            throw new ServletException("Error sending file:", e);
         } finally {
             try {
                 if (inFile != null) {
@@ -297,19 +291,20 @@
             HttpServletResponse response, Logger logger) throws ImageOpException,
             ServletException {
         logger.debug("sending to response:"+ response + " committed=" + response.isCommitted());
-    	if (response.isCommitted()) {
-        	logger.warn("sendImage: response already committed!");
-        	//return;
-    	}
         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"))) {
+            if ((mimeType.equals("image/jpeg") || mimeType.equals("image/jp2") || 
+                    mimeType.equals("image/fpx"))) {
                 mimeType = "image/jpeg";
             } else {
                 mimeType = "image/png";
@@ -318,7 +313,6 @@
             response.setContentType(mimeType);
             img.writeImage(mimeType, outstream);
         } catch (IOException e) {
-            logger.error("Error sending image:", e);
             throw new ServletException("Error sending image:", e);
         }
         // TODO: should we: finally { img.dispose(); }
--- a/servlet/src/digilib/servlet/Texter.java	Mon Feb 21 10:24:48 2011 +0100
+++ b/servlet/src/digilib/servlet/Texter.java	Mon Feb 21 22:36:35 2011 +0100
@@ -43,8 +43,10 @@
  */
 public class Texter extends HttpServlet {
 
-	/** Servlet version */
-	public static String tlVersion = "0.1b2";
+    private static final long serialVersionUID = 6678666342141409867L;
+
+    /** Servlet version */
+	public static String tlVersion = "0.1b3";
 
 	/** DigilibConfiguration instance */
 	DigilibConfiguration dlConfig = null;
@@ -128,7 +130,7 @@
 	}
 
 	protected void processRequest(HttpServletRequest request,
-			HttpServletResponse response) throws ServletException, IOException {
+			HttpServletResponse response) {
 		
 		/*
 		 * request parameters
@@ -146,7 +148,7 @@
 			} else {
 				f = getTextFile(dlRequest, "");
 				if (f != null) {
-					ServletOps.sendFile(f.getFile(),	null, null, response, logger);
+					ServletOps.sendFile(f.getFile(), null, null, response, logger);
 				} else {
 					response.sendError(HttpServletResponse.SC_NOT_FOUND, "Text-File not found!");
 					//ServletOps.htmlMessage("No Text-File!", response);
@@ -156,7 +158,13 @@
 		} catch (ImageOpException e) {
             // most likely wrong file format...
             logger.error("ERROR sending text file: ", e);
-            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+            try {
+                response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+            } catch (IOException e1) {
+                logger.error("ERROR sending error: ", e1);
+            }
+        } catch (IOException e) {
+            logger.error("ERROR sending text file: ", e);
         }
     }
 	
@@ -175,7 +183,7 @@
 	private TextFile getTextFile(DigilibRequest dlRequest, String subDirectory) {
 		String loadPathName = dlRequest.getFilePath() + subDirectory;
 		// find the file(set)
-		return (TextFile) dirCache.getFile(loadPathName, dlRequest
-				.getAsInt("pn"), FileClass.TEXT);
+		return (TextFile) dirCache.getFile(loadPathName, dlRequest.getAsInt("pn"), 
+		        FileClass.TEXT);
 	}
 }
\ No newline at end of file