# HG changeset patch # User ksrini # Date 1288991725 25200 # Node ID ee97f78e7482fcc2bbee94e2b52b7b7f402dd7df # Parent 285c02ecbb8a9d3acf3552c82656723f965f66fa 6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions Reviewed-by: jrose, dholmes, alanb, mduigou diff -r 285c02ecbb8a -r ee97f78e7482 jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.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); + } } } diff -r 285c02ecbb8a -r ee97f78e7482 jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java --- 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 scanJar(JarFile jf) throws IOException { // Collect jar entries, preserving order. List 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; } diff -r 285c02ecbb8a -r ee97f78e7482 jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java --- 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); diff -r 285c02ecbb8a -r ee97f78e7482 jdk/src/share/classes/java/util/jar/Pack200.java --- 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. *

+ * Note: Unless otherwise noted, passing a null argument to a + * constructor or method in this class will cause a {@link NullPointerException} + * to be thrown. + *

* @since 1.5 */ public interface Packer { @@ -599,6 +600,10 @@ * "PACK200" as a zip file comment. * This allows a deployer to detect if a JAR archive was packed and unpacked. *

+ * Note: Unless otherwise noted, passing a null argument to a + * constructor or method in this class will cause a {@link NullPointerException} + * to be thrown. + *

* This version of the unpacker is compatible with all previous versions. * @since 1.5 */ diff -r 285c02ecbb8a -r ee97f78e7482 jdk/test/tools/pack200/TestExceptions.java --- /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 tlist = new ArrayList(); + 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 tlist = new ArrayList(); + 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 tlist = new ArrayList(); + 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 tlist = new ArrayList(); + 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; + } + }; +}