8044289: In ImageIO.write() and ImageIO.read() null stream is not handled properly.
authorjdv
Wed, 06 Apr 2016 12:25:21 +0530
changeset 37563 2c09d2f09cd1
parent 37562 5b36d70170d6
child 37564 82296146c864
8044289: In ImageIO.write() and ImageIO.read() null stream is not handled properly. Reviewed-by: prr, serb, psadhukhan
jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java
jdk/test/javax/imageio/stream/NullStreamCheckTest.java
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java	Tue Apr 05 11:52:52 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java	Wed Apr 06 12:25:21 2016 +0530
@@ -1294,7 +1294,8 @@
      *
      * @exception IllegalArgumentException if {@code input} is
      * {@code null}.
-     * @exception IOException if an error occurs during reading.
+     * @exception IOException if an error occurs during reading or when not
+     * able to create required ImageInputStream.
      */
     public static BufferedImage read(File input) throws IOException {
         if (input == null) {
@@ -1344,7 +1345,8 @@
      *
      * @exception IllegalArgumentException if {@code input} is
      * {@code null}.
-     * @exception IOException if an error occurs during reading.
+     * @exception IOException if an error occurs during reading or when not
+     * able to create required ImageInputStream.
      */
     public static BufferedImage read(InputStream input) throws IOException {
         if (input == null) {
@@ -1352,6 +1354,9 @@
         }
 
         ImageInputStream stream = createImageInputStream(input);
+        if (stream == null) {
+            throw new IIOException("Can't create an ImageInputStream!");
+        }
         BufferedImage bi = read(stream);
         if (bi == null) {
             stream.close();
@@ -1384,7 +1389,8 @@
      *
      * @exception IllegalArgumentException if {@code input} is
      * {@code null}.
-     * @exception IOException if an error occurs during reading.
+     * @exception IOException if an error occurs during reading or when not
+     * able to create required ImageInputStream.
      */
     public static BufferedImage read(URL input) throws IOException {
         if (input == null) {
@@ -1398,6 +1404,14 @@
             throw new IIOException("Can't get input stream from URL!", e);
         }
         ImageInputStream stream = createImageInputStream(istream);
+        if (stream == null) {
+            /* close the istream when stream is null so that if user has
+             * given filepath as URL he can delete it, otherwise stream will
+             * be open to that file and he will not be able to delete it.
+             */
+            istream.close();
+            throw new IIOException("Can't create an ImageInputStream!");
+        }
         BufferedImage bi;
         try {
             bi = read(stream);
@@ -1510,7 +1524,8 @@
      *
      * @exception IllegalArgumentException if any parameter is
      * {@code null}.
-     * @exception IOException if an error occurs during writing.
+     * @exception IOException if an error occurs during writing or when not
+     * able to create required ImageOutputStream.
      */
     public static boolean write(RenderedImage im,
                                 String formatName,
@@ -1518,7 +1533,6 @@
         if (output == null) {
             throw new IllegalArgumentException("output == null!");
         }
-        ImageOutputStream stream = null;
 
         ImageWriter writer = getWriter(im, formatName);
         if (writer == null) {
@@ -1528,13 +1542,11 @@
             return false;
         }
 
-        try {
-            output.delete();
-            stream = createImageOutputStream(output);
-        } catch (IOException e) {
-            throw new IIOException("Can't create output stream!", e);
+        output.delete();
+        ImageOutputStream stream = createImageOutputStream(output);
+        if (stream == null) {
+            throw new IIOException("Can't create an ImageOutputStream!");
         }
-
         try {
             return doWrite(im, writer, stream);
         } finally {
@@ -1562,7 +1574,8 @@
      *
      * @exception IllegalArgumentException if any parameter is
      * {@code null}.
-     * @exception IOException if an error occurs during writing.
+     * @exception IOException if an error occurs during writing or when not
+     * able to create required ImageOutputStream.
      */
     public static boolean write(RenderedImage im,
                                 String formatName,
@@ -1570,13 +1583,10 @@
         if (output == null) {
             throw new IllegalArgumentException("output == null!");
         }
-        ImageOutputStream stream = null;
-        try {
-            stream = createImageOutputStream(output);
-        } catch (IOException e) {
-            throw new IIOException("Can't create output stream!", e);
+        ImageOutputStream stream = createImageOutputStream(output);
+        if (stream == null) {
+            throw new IIOException("Can't create an ImageOutputStream!");
         }
-
         try {
             return doWrite(im, getWriter(im, formatName), stream);
         } finally {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/stream/NullStreamCheckTest.java	Wed Apr 06 12:25:21 2016 +0530
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug     8044289
+ * @summary Test verifies that when some of the read() and write() methods
+ *          are not able to get stream from createImageInputStream() and
+ *          createImageOutputStream() are we doing null check for stream
+ *          and throwing IOException as per specification.
+ * @run     main NullStreamCheckTest
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.imageio.ImageIO;
+import javax.imageio.spi.IIORegistry;
+import javax.imageio.spi.ImageInputStreamSpi;
+import javax.imageio.spi.ImageOutputStreamSpi;
+
+public class NullStreamCheckTest {
+
+    // get ImageIORegistry default instance.
+    private static final IIORegistry localRegistry = IIORegistry.
+            getDefaultInstance();
+    // stream variables needed for input and output.
+    static LocalOutputStream outputStream = new LocalOutputStream();
+    static LocalInputStream inputStream = new LocalInputStream();
+
+    static final int width = 50, height = 50;
+
+    // input and output BufferedImage needed while read and write.
+    static BufferedImage inputImage = new BufferedImage(width, height,
+            BufferedImage.TYPE_INT_ARGB);
+
+    // creates test file needed for read and write in local directory.
+    private static File createTestFile(String name) throws IOException {
+        String sep = System.getProperty("file.separator");
+        String dir = System.getProperty("test.src", ".");
+        String filePath = dir+sep;
+        File directory = new File(filePath);
+        File tmpTestFile = File.createTempFile(name, ".png", directory);
+        directory.delete();
+        return tmpTestFile;
+    }
+
+    /* if we catch expected IOException message return
+     * false otherwise return true.
+     */
+    private static boolean verifyOutputExceptionMessage(IOException ex) {
+        String message = ex.getMessage();
+        return (!message.equals("Can't create an ImageOutputStream!"));
+    }
+
+    /* if we catch expected IOException message return
+     * false otherwise return true.
+     */
+    private static boolean verifyInputExceptionMessage(IOException ex) {
+        String message = ex.getMessage();
+        return (!message.equals("Can't create an ImageInputStream!"));
+    }
+
+    private static void verifyFileWrite() throws IOException {
+        File outputTestFile = createTestFile("outputTestFile");
+        try {
+            ImageIO.write(inputImage, "png", outputTestFile);
+        } catch (IOException ex) {
+            if (verifyOutputExceptionMessage(ex))
+                throw ex;
+        } finally {
+            outputTestFile.delete();
+        }
+    }
+
+    private static void verifyStreamWrite() throws IOException {
+        try {
+            ImageIO.write(inputImage, "png", outputStream);
+        } catch (IOException ex) {
+            if (verifyOutputExceptionMessage(ex))
+                throw ex;
+        } finally {
+            try {
+                outputStream.close();
+            } catch (IOException ex) {
+                throw ex;
+            }
+        }
+    }
+
+    private static void verifyFileRead() throws IOException {
+        File inputTestFile = createTestFile("inputTestFile");
+        try {
+            ImageIO.read(inputTestFile);
+        } catch (IOException ex) {
+            if (verifyInputExceptionMessage(ex))
+                throw ex;
+        } finally {
+            inputTestFile.delete();
+        }
+    }
+
+    private static void verifyStreamRead() throws IOException {
+        try {
+            ImageIO.read(inputStream);
+        } catch (IOException ex) {
+            if (verifyInputExceptionMessage(ex))
+                throw ex;
+        } finally {
+            try {
+                inputStream.close();
+            } catch (IOException ex) {
+                throw ex;
+            }
+        }
+    }
+
+    private static void verifyUrlRead() throws IOException {
+        URL url;
+        File inputTestUrlFile = createTestFile("inputTestFile");
+        try {
+            try {
+                url = inputTestUrlFile.toURI().toURL();
+            } catch (MalformedURLException ex) {
+                throw ex;
+            }
+
+            try {
+                ImageIO.read(url);
+            } catch (IOException ex) {
+                if (verifyInputExceptionMessage(ex))
+                    throw ex;
+            }
+        } finally {
+            inputTestUrlFile.delete();
+        }
+    }
+
+    public static void main(String[] args) throws IOException,
+                                                  MalformedURLException {
+
+        /* deregister ImageOutputStreamSpi so that we creatImageOutputStream
+         * returns null while writing.
+         */
+        localRegistry.deregisterAll(ImageOutputStreamSpi.class);
+        /* verify possible ImageIO.write() scenario's for null stream output
+         * from createImageOutputStream() API in ImageIO class.
+         */
+        verifyFileWrite();
+        verifyStreamWrite();
+
+        /* deregister ImageInputStreamSpi so that we creatImageInputStream
+         * returns null while reading.
+         */
+        localRegistry.deregisterAll(ImageInputStreamSpi.class);
+        /* verify possible ImageIO.read() scenario's for null stream output
+         * from createImageInputStream API in ImageIO class.
+         */
+        verifyFileRead();
+        verifyStreamRead();
+        verifyUrlRead();
+    }
+
+    static class LocalOutputStream extends OutputStream {
+
+        @Override
+        public void write(int i) throws IOException {
+        }
+    }
+
+    static class LocalInputStream extends InputStream {
+
+        @Override
+        public int read() throws IOException {
+            return 0;
+        }
+    }
+}