You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by je...@apache.org on 2008/04/03 15:38:52 UTC

svn commit: r644313 - in /xmlgraphics/commons/trunk: ./ src/java/org/apache/xmlgraphics/image/loader/impl/ src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ test/java/org/apache/xmlgraphics/image/loader/

Author: jeremias
Date: Thu Apr  3 06:38:50 2008
New Revision: 644313

URL: http://svn.apache.org/viewvc?rev=644313&view=rev
Log:
Fixed two cases of unclosed input streams in image loader code.

Added:
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableInputStream.java   (with props)
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableStream.java   (with props)
Modified:
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderEPS.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java
    xmlgraphics/commons/trunk/status.xml
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ImageLoaderTestCase.java

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderEPS.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderEPS.java?rev=644313&r1=644312&r2=644313&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderEPS.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderEPS.java Thu Apr  3 06:38:50 2008
@@ -67,7 +67,7 @@
         if (binaryHeader != null) {
             //Binary EPS: just extract the EPS part
             in.skip(binaryHeader.getPSStart());
-            in = new SubInputStream(in, binaryHeader.getPSLength());
+            in = new SubInputStream(in, binaryHeader.getPSLength(), true);
         }
         
         ImageRawEPS epsImage = new ImageRawEPS(info, in);

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java?rev=644313&r1=644312&r2=644313&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java Thu Apr  3 06:38:50 2008
@@ -137,8 +137,8 @@
                 }
             }
         } finally {
-            //ImageUtil.closeQuietly(src); //Cannot do that as codecs my do late reading
-            ImageUtil.removeStreams(src);
+            ImageUtil.closeQuietly(src);
+            //TODO Some codecs may do late reading.
         }
         if (firstException != null) {
             throw new ImageException("Error while loading image: "

Modified: xmlgraphics/commons/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/status.xml?rev=644313&r1=644312&r2=644313&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/status.xml (original)
+++ xmlgraphics/commons/trunk/status.xml Thu Apr  3 06:38:50 2008
@@ -41,6 +41,9 @@
   <changes>
     <release version="Trunk" date="n/a">
       <action context="Code" dev="JM" type="fix">
+        Fixed two cases of unclosed input streams in image loader code.
+      </action>
+      <action context="Code" dev="JM" type="fix">
         Bugfix for unhandled NumberFormatException in Glpyhs when a unknown glyph name starting
         with "u" is found.
       </action>

Modified: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ImageLoaderTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ImageLoaderTestCase.java?rev=644313&r1=644312&r2=644313&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ImageLoaderTestCase.java (original)
+++ xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ImageLoaderTestCase.java Thu Apr  3 06:38:50 2008
@@ -22,6 +22,12 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.imageio.stream.ImageInputStream;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
 
 import junit.framework.TestCase;
 
@@ -41,10 +47,14 @@
         super(name);
     }
     
+    private MyImageSessionContext createImageSessionContext() {
+        return new MyImageSessionContext(imageContext);
+    }
+    
     public void testPNG() throws Exception {
         String uri = "asf-logo.png";
         
-        ImageSessionContext sessionContext = imageContext.newSessionContext();
+        MyImageSessionContext sessionContext = createImageSessionContext();
         ImageManager manager = imageContext.getImageManager();
 
         ImageInfo info = manager.preloadImage(uri, sessionContext);
@@ -60,12 +70,14 @@
         info = imgRed.getInfo(); //Switch to the ImageInfo returned by the image
         assertEquals(126734, info.getSize().getWidthMpt());
         assertEquals(38245, info.getSize().getHeightMpt());
+        
+        sessionContext.checkAllStreamsClosed();
     }
     
     public void testGIF() throws Exception {
         String uri = "bgimg72dpi.gif";
         
-        ImageSessionContext sessionContext = imageContext.newSessionContext();
+        MyImageSessionContext sessionContext = createImageSessionContext();
         ImageManager manager = imageContext.getImageManager();
 
         ImageInfo info = manager.preloadImage(uri, sessionContext);
@@ -81,12 +93,14 @@
         info = imgRed.getInfo(); //Switch to the ImageInfo returned by the image
         assertEquals(192000, info.getSize().getWidthMpt());
         assertEquals(192000, info.getSize().getHeightMpt());
+        
+        sessionContext.checkAllStreamsClosed();
     }
     
     public void testEPSASCII() throws Exception {
         String uri = "barcode.eps";
         
-        ImageSessionContext sessionContext = imageContext.newSessionContext();
+        MyImageSessionContext sessionContext = createImageSessionContext();
         ImageManager manager = imageContext.getImageManager();
 
         ImageInfo info = manager.preloadImage(uri, sessionContext);
@@ -108,12 +122,14 @@
         } finally {
             IOUtils.closeQuietly(in);
         }
+        
+        sessionContext.checkAllStreamsClosed();
     }
  
     public void testEPSBinary() throws Exception {
         String uri = "img-with-tiff-preview.eps";
         
-        ImageSessionContext sessionContext = imageContext.newSessionContext();
+        MyImageSessionContext sessionContext = createImageSessionContext();
         ImageManager manager = imageContext.getImageManager();
 
         ImageInfo info = manager.preloadImage(uri, sessionContext);
@@ -135,6 +151,57 @@
         } finally {
             IOUtils.closeQuietly(in);
         }
+        
+        sessionContext.checkAllStreamsClosed();
     }
  
+    private static class MyImageSessionContext extends MockImageSessionContext {
+
+        private List streams = new java.util.ArrayList();
+        
+        public MyImageSessionContext(ImageContext context) {
+            super(context);
+        }
+
+        public Source newSource(String uri) {
+            Source src = super.newSource(uri);
+            if (src instanceof ImageSource) {
+                ImageSource is = (ImageSource)src;
+                ImageInputStream in = is.getImageInputStream();
+                //in = new ObservableImageInputStream(in, is.getSystemId());
+                in = ObservableStream.Factory.observe(in, is.getSystemId());
+                streams.add(in);
+                is.setImageInputStream(in);
+            }
+            return src;
+        }
+        
+        /** {@inheritDoc} */
+        protected Source resolveURI(String uri) {
+            Source src = super.resolveURI(uri);
+            if (src instanceof StreamSource) {
+                StreamSource ss = (StreamSource)src;
+                if (ss.getInputStream() != null) {
+                    InputStream in = new ObservableInputStream(
+                            ss.getInputStream(), ss.getSystemId());
+                    streams.add(in);
+                    ss.setInputStream(in);
+                }
+            }
+            return src;
+        }
+        
+        public void checkAllStreamsClosed() {
+            Iterator iter = streams.iterator();
+            while (iter.hasNext()) {
+                ObservableStream stream = (ObservableStream)iter.next();
+                iter.remove();
+                if (!stream.isClosed()) {
+                    fail(stream.getClass().getName() + " is NOT closed: " + stream.getSystemID());
+                }
+            }
+        }
+        
+    }
+    
 }

Added: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableInputStream.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableInputStream.java?rev=644313&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableInputStream.java (added)
+++ xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableInputStream.java Thu Apr  3 06:38:50 2008
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+ 
+package org.apache.xmlgraphics.image.loader;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * This is a proxying input stream that records whether a stream has been closed or not.
+ */
+public class ObservableInputStream extends FilterInputStream implements ObservableStream {
+
+    /** logger */
+    protected static Log log = LogFactory.getLog(ObservableInputStream.class);
+    
+    private boolean closed;
+    private String systemID;
+    
+    /**
+     * Main constructor.
+     * @param in the underlying input stream
+     * @param systemID the system ID for the input stream for reference
+     */
+    public ObservableInputStream(InputStream in, String systemID) {
+        super(in);
+        this.systemID = systemID;
+    }
+
+    /** {@inheritDoc} */
+    public void close() throws IOException {
+        if (!closed) {
+            log.debug("Stream is being closed: " + getSystemID());
+            try {
+                this.in.close();
+            } catch (IOException ioe) {
+                log.error("Error while closing underlying stream: " + ioe.getMessage());
+            }
+            closed = true;
+        } else {
+            throw new IllegalStateException("Stream is already closed!");
+        }
+    }
+    
+    /** {@inheritDoc} */
+    public boolean isClosed() {
+        return this.closed;
+    }
+    
+    /** {@inheritDoc} */
+    public String getSystemID() {
+        return this.systemID;
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableInputStream.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableStream.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableStream.java?rev=644313&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableStream.java (added)
+++ xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableStream.java Thu Apr  3 06:38:50 2008
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+ 
+package org.apache.xmlgraphics.image.loader;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import javax.imageio.stream.ImageInputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Implemented by observable streams.
+ */
+public interface ObservableStream {
+
+    /**
+     * Indicates whether the stream has been closed.
+     * @return true if the stream is closed
+     */
+    boolean isClosed();
+    
+    /**
+     * Returns the system ID for the stream being observed.
+     * @return the system ID
+     */
+    String getSystemID();
+    
+    public static class Factory {
+        
+        public static ImageInputStream observe(ImageInputStream iin, String systemID) {
+            return (ImageInputStream)Proxy.newProxyInstance(
+                    Factory.class.getClassLoader(),
+                    new Class[] {ImageInputStream.class, ObservableStream.class},
+                    new ObservingImageInputStreamInvocationHandler(iin, systemID));
+        }
+        
+    }
+    
+    public static class ObservingImageInputStreamInvocationHandler
+            implements InvocationHandler, ObservableStream {
+
+        /** logger */
+        protected static Log log = LogFactory.getLog(ObservableInputStream.class);
+        
+        private ImageInputStream iin;
+        private boolean closed;
+        private String systemID;
+
+        public ObservingImageInputStreamInvocationHandler(ImageInputStream iin, String systemID) {
+            this.iin = iin;
+            this.systemID = systemID;
+        }
+        
+        /** {@inheritDoc} */
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (method.getDeclaringClass().equals(ObservableStream.class)) {
+                return method.invoke(this, args);
+            } else if ("close".equals(method.getName())) {
+                if (!closed) {
+                    log.debug("Stream is being closed: " + getSystemID());
+                    closed = true;
+                    try {
+                        return method.invoke(iin, args);
+                    } catch (InvocationTargetException ite) {
+                        log.error("Error while closing underlying stream: " + ite.getMessage());
+                        throw ite;
+                    }
+                } else {
+                    throw new IllegalStateException("Stream is already closed!");
+                }
+            } else {
+                return method.invoke(iin, args);
+            }
+        }
+
+        /** {@inheritDoc} */
+        public String getSystemID() {
+            return this.systemID;
+        }
+
+        /** {@inheritDoc} */
+        public boolean isClosed() {
+            return this.closed;
+        }
+
+    }
+    
+}

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/ObservableStream.java
------------------------------------------------------------------------------
    svn:keywords = Id



---------------------------------------------------------------------
Apache XML Graphics Project URL: http://xmlgraphics.apache.org/
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: commits-help@xmlgraphics.apache.org