6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
authorksrini
Fri, 05 Nov 2010 14:15:25 -0700
changeset 7171 ee97f78e7482
parent 7170 285c02ecbb8a
child 7172 01308fd663b3
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions Reviewed-by: jrose, dholmes, alanb, mduigou
jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java
jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java
jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java
jdk/src/share/classes/java/util/jar/Pack200.java
jdk/test/tools/pack200/TestExceptions.java
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Fri Nov 05 17:15:44 2010 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Fri Nov 05 14:15:25 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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
@@ -30,7 +30,6 @@
 import com.sun.java.util.jar.pack.Package.Class;
 import com.sun.java.util.jar.pack.Package.InnerClass;
 import com.sun.java.util.jar.pack.ConstantPool.*;
-import com.sun.tools.classfile.AttributeException;
 
 /**
  * Reader for a class file that is being incorporated into a package.
@@ -422,7 +421,7 @@
                         readCode(m.code);
                     } catch (Instruction.FormatException iie) {
                         String message = iie.getMessage() + " in " + h;
-                        throw new ClassReader.ClassFormatException(message);
+                        throw new ClassReader.ClassFormatException(message, iie);
                     }
                 } else {
                     assert(h == cls);
@@ -477,9 +476,13 @@
         // (Later, ics may be transferred to the pkg.)
     }
 
-    class ClassFormatException extends IOException {
+    static class ClassFormatException extends IOException {
         public ClassFormatException(String message) {
             super(message);
         }
+
+        public ClassFormatException(String message, Throwable cause) {
+            super(message, cause);
+        }
     }
 }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java	Fri Nov 05 17:15:44 2010 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java	Fri Nov 05 14:15:25 2010 -0700
@@ -614,10 +614,14 @@
         List<InFile> scanJar(JarFile jf) throws IOException {
             // Collect jar entries, preserving order.
             List<InFile> inFiles = new ArrayList<>();
-            for (JarEntry je : Collections.list(jf.entries())) {
-                InFile inFile = new InFile(jf, je);
-                assert(je.isDirectory() == inFile.name.endsWith("/"));
-                inFiles.add(inFile);
+            try {
+                for (JarEntry je : Collections.list(jf.entries())) {
+                    InFile inFile = new InFile(jf, je);
+                    assert(je.isDirectory() == inFile.name.endsWith("/"));
+                    inFiles.add(inFile);
+                }
+            } catch (IllegalStateException ise) {
+                throw new IOException(ise.getLocalizedMessage(), ise);
             }
             return inFiles;
         }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java	Fri Nov 05 17:15:44 2010 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java	Fri Nov 05 14:15:25 2010 -0700
@@ -92,7 +92,13 @@
      * @param out a JarOutputStream.
      * @exception IOException if an error is encountered.
      */
-    public void unpack(InputStream in0, JarOutputStream out) throws IOException {
+    public void unpack(InputStream in, JarOutputStream out) throws IOException {
+        if (in == null) {
+            throw new NullPointerException("null input");
+        }
+        if (out == null) {
+            throw new NullPointerException("null output");
+        }
         assert(Utils.currentInstance.get() == null);
         TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
                       ? null
@@ -102,18 +108,18 @@
             Utils.currentInstance.set(this);
             if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
             final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
-            BufferedInputStream in = new BufferedInputStream(in0);
-            if (Utils.isJarMagic(Utils.readMagic(in))) {
+            BufferedInputStream in0 = new BufferedInputStream(in);
+            if (Utils.isJarMagic(Utils.readMagic(in0))) {
                 if (verbose > 0)
                     Utils.log.info("Copying unpacked JAR file...");
-                Utils.copyJarFile(new JarInputStream(in), out);
+                Utils.copyJarFile(new JarInputStream(in0), out);
             } else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
-                (new DoUnpack()).run(in, out);
-                in.close();
+                (new DoUnpack()).run(in0, out);
+                in0.close();
                 Utils.markJarFile(out);
             } else {
-                (new NativeUnpack(this)).run(in, out);
-                in.close();
+                (new NativeUnpack(this)).run(in0, out);
+                in0.close();
                 Utils.markJarFile(out);
             }
         } finally {
@@ -132,6 +138,12 @@
      * @exception IOException if an error is encountered.
      */
     public void unpack(File in, JarOutputStream out) throws IOException {
+        if (in == null) {
+            throw new NullPointerException("null input");
+        }
+        if (out == null) {
+            throw new NullPointerException("null output");
+        }
         // Use the stream-based implementation.
         // %%% Reconsider if native unpacker learns to memory-map the file.
         FileInputStream instr = new FileInputStream(in);
--- a/jdk/src/share/classes/java/util/jar/Pack200.java	Fri Nov 05 17:15:44 2010 +0000
+++ b/jdk/src/share/classes/java/util/jar/Pack200.java	Fri Nov 05 14:15:25 2010 -0700
@@ -30,9 +30,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeEvent;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 
 
 
@@ -225,6 +222,10 @@
      *    If the input JAR-files contains a 1.6 class file, then the pack file
      * version will be set to 1.6.
      * <p>
+     * Note: Unless otherwise noted, passing a <tt>null</tt> argument to a
+     * constructor or method in this class will cause a {@link NullPointerException}
+     * to be thrown.
+     * <p>
      * @since 1.5
      */
     public interface Packer {
@@ -599,6 +600,10 @@
      * "<tt>PACK200</tt>" as a zip file comment.
      * This allows a deployer to detect if a JAR archive was packed and unpacked.
      * <p>
+     * Note: Unless otherwise noted, passing a <tt>null</tt> argument to a
+     * constructor or method in this class will cause a {@link NullPointerException}
+     * to be thrown.
+     * <p>
      * This version of the unpacker is compatible with all previous versions.
      * @since 1.5
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/pack200/TestExceptions.java	Fri Nov 05 14:15:25 2010 -0700
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Pack200;
+
+/*
+ * @test
+ * @bug 6985763
+ * @summary verify that proper exceptions are thrown
+ * @compile -XDignore.symbol.file Utils.java TestExceptions.java
+ * @run main TestExceptions
+ * @author ksrini
+ */
+
+public class TestExceptions {
+
+    static final File testJar = new File("test.jar");
+    static final File testPackFile = new File("test.pack");
+
+    static void init() {
+        Utils.jar("cvf", testJar.getAbsolutePath(), ".");
+        JarFile jf = null;
+        try {
+            jf = new JarFile(testJar);
+            Utils.pack(jf, testPackFile);
+        } catch (IOException ioe) {
+            throw new Error("Initialization error", ioe);
+        } finally {
+            Utils.close(jf);
+        }
+    }
+
+    // a test that closes the input jarFile.
+    static void pack200Test1() {
+        PackTestInput ti = null;
+        // setup the scenario
+        try {
+            ti = new PackTestInput(new JarFile(testJar), new ByteArrayOutputStream());
+        } catch (Exception e) {
+            throw new Error("Initialization error", e);
+        } finally {
+            Utils.close(ti.getJarFile());
+        }
+        // test the scenario
+        try {
+            System.out.println(ti);
+            Pack200.Packer p = Pack200.newPacker();
+            p.pack(ti.getJarFile(), ti.getOutputStream());
+        } catch (Exception e) {
+            ti.checkException(e);
+        } finally {
+            if (ti != null) {
+                ti.close();
+            }
+        }
+    }
+
+    // test the Pack200.pack(JarFile, OutputStream);
+    static void pack200Test2() {
+        List<PackTestInput> tlist = new ArrayList<PackTestInput>();
+        try {
+            // setup the test scenarios
+            try {
+                tlist.add(new PackTestInput((JarFile)null, null));
+                tlist.add(new PackTestInput(new JarFile(testJar), null));
+                tlist.add(new PackTestInput((JarFile)null, new ByteArrayOutputStream()));
+            } catch (Exception e) {
+                throw new Error("Initialization error", e);
+            }
+
+            // test the scenarios
+            for (PackTestInput ti : tlist) {
+                System.out.println(ti);
+                try {
+                    Pack200.Packer p = Pack200.newPacker();
+                    p.pack(ti.getJarFile(), ti.getOutputStream());
+                } catch (Exception e) {
+                    ti.checkException(e);
+                }
+            }
+        } finally { // keep jprt happy
+            for (TestInput ti : tlist) {
+                if (ti != null) {
+                    ti.close();
+                }
+            }
+        }
+    }
+
+    // test the Pack200.pack(JarInputStream, OutputStream);
+    static void pack200Test3() {
+        List<PackTestJarInputStream> tlist = new ArrayList<PackTestJarInputStream>();
+        try {
+            // setup the test scenarios
+            try {
+                tlist.add(new PackTestJarInputStream((JarInputStream)null, null));
+                tlist.add(new PackTestJarInputStream((JarInputStream)null,
+                        new ByteArrayOutputStream()));
+                tlist.add(new PackTestJarInputStream(
+                        new JarInputStream(new FileInputStream(testJar)), null));
+
+            } catch (Exception e) {
+                throw new Error("Initialization error", e);
+            }
+            for (PackTestJarInputStream ti : tlist) {
+                System.out.println(ti);
+                try {
+                    Pack200.Packer p = Pack200.newPacker();
+                    p.pack(ti.getJarInputStream(), ti.getOutputStream());
+                } catch (Exception e) {
+                    ti.checkException(e);
+                }
+            }
+        } finally { // keep jprt happy
+            for (PackTestJarInputStream ti : tlist) {
+                if (ti != null) {
+                    ti.close();
+                }
+            }
+        }
+    }
+
+    // test the Pack200.unpack(InputStream, OutputStream);
+    static void unpack200Test1() {
+        List<UnpackTestInput> tlist = new ArrayList<UnpackTestInput>();
+        try {
+            // setup the test scenarios
+            try {
+                tlist.add(new UnpackTestInput((InputStream)null, null));
+                tlist.add(new UnpackTestInput(new FileInputStream(testPackFile),
+                        null));
+                tlist.add(new UnpackTestInput((InputStream) null,
+                        new JarOutputStream(new ByteArrayOutputStream())));
+            } catch (Exception e) {
+                throw new Error("Initialization error", e);
+            }
+
+            // test the scenarios
+            for (UnpackTestInput ti : tlist) {
+                System.out.println(ti);
+                try {
+                    Pack200.Unpacker unpacker = Pack200.newUnpacker();
+                    unpacker.unpack(ti.getInputStream(), ti.getJarOutputStream());
+                } catch (Exception e) {
+                    ti.checkException(e);
+                }
+            }
+        } finally { // keep jprt happy
+            for (TestInput ti : tlist) {
+                if (ti != null) {
+                    ti.close();
+                }
+            }
+        }
+    }
+
+    // test the Pack200.unpack(File, OutputStream);
+    static void unpack200Test2() {
+        List<UnpackTestFileInput> tlist = new ArrayList<UnpackTestFileInput>();
+        try {
+            // setup the test scenarios
+            try {
+                tlist.add(new UnpackTestFileInput((File)null, null));
+                tlist.add(new UnpackTestFileInput(testPackFile, null));
+                tlist.add(new UnpackTestFileInput((File)null,
+                        new JarOutputStream(new ByteArrayOutputStream())));
+            } catch (Exception e) {
+                throw new Error("Initialization error", e);
+            }
+
+            // test the scenarios
+            for (UnpackTestFileInput ti : tlist) {
+                System.out.println(ti);
+                try {
+                    Pack200.Unpacker unpacker = Pack200.newUnpacker();
+                    unpacker.unpack(ti.getInputFile(), ti.getJarOutputStream());
+                } catch (Exception e) {
+                    ti.checkException(e);
+                }
+            }
+        } finally { // keep jprt happy
+            for (TestInput ti : tlist) {
+                if (ti != null) {
+                    ti.close();
+                }
+            }
+        }
+    }
+
+    public static void main(String... args) {
+        init();
+        pack200Test1();
+        pack200Test2();
+        pack200Test3();
+        unpack200Test1();
+    }
+
+    // containers for test inputs and management
+    static abstract class TestInput {
+
+        private final Object in;
+        private final Object out;
+        final boolean shouldNPE;
+        final String testname;
+
+        public TestInput(String name, Object in, Object out) {
+            this.testname = name;
+            this.in = in;
+            this.out = out;
+            shouldNPE = (in == null || out == null);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder outStr = new StringBuilder(testname);
+            outStr.append(", input:").append(in);
+            outStr.append(", output:").append(this.out);
+            outStr.append(", should NPE:").append(shouldNPE);
+            return outStr.toString();
+        }
+
+        void close() {
+            if (in != null && (in instanceof Closeable)) {
+                Utils.close((Closeable) in);
+            }
+            if (out != null && (out instanceof Closeable)) {
+                Utils.close((Closeable) out);
+            }
+        }
+
+        void checkException(Throwable t) {
+            if (shouldNPE) {
+                if (t instanceof NullPointerException) {
+                    System.out.println("Got expected exception");
+                    return;
+                } else {
+                    throw new RuntimeException("Expected NPE, but got ", t);
+                }
+            }
+            if (t instanceof IOException) {
+                System.out.println("Got expected exception");
+                return;
+            } else {
+                throw new RuntimeException("Expected IOException but got ", t);
+            }
+        }
+    }
+
+    static class PackTestInput extends TestInput {
+
+        public PackTestInput(JarFile jf, OutputStream out) {
+            super("PackTestInput", jf, out);
+        }
+
+        JarFile getJarFile() {
+            return (JarFile) super.in;
+        }
+
+        OutputStream getOutputStream() {
+            return (OutputStream) super.out;
+        }
+    };
+
+    static class PackTestJarInputStream extends TestInput {
+
+        public PackTestJarInputStream(JarInputStream in, OutputStream out) {
+            super("PackTestJarInputStream", in, out);
+        }
+
+        JarInputStream getJarInputStream() {
+            return (JarInputStream) super.in;
+        }
+
+        OutputStream getOutputStream() {
+            return (OutputStream) super.out;
+        }
+    };
+
+    static class UnpackTestInput extends TestInput {
+
+        public UnpackTestInput(InputStream in, JarOutputStream out) {
+            super("UnpackTestInput", in, out);
+        }
+
+        InputStream getInputStream() {
+            return (InputStream) super.in;
+        }
+
+        JarOutputStream getJarOutputStream() {
+            return (JarOutputStream) super.out;
+        }
+    };
+
+    static class UnpackTestFileInput extends TestInput {
+
+        public UnpackTestFileInput(File in, JarOutputStream out) {
+            super("UnpackTestInput", in, out);
+        }
+
+        File getInputFile() {
+            return (File) super.in;
+        }
+
+        JarOutputStream getJarOutputStream() {
+            return (JarOutputStream) super.out;
+        }
+    };
+}