7021927: javac: regression in performance

Mon, 07 Mar 2011 17:39:42 -0800

author
ksrini
date
Mon, 07 Mar 2011 17:39:42 -0800
changeset 923
6970d9fb8e02
parent 916
cb9493a80341
child 924
4fd20d5b7295

7021927: javac: regression in performance
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/file/JavacFileManager.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/Options.java file | annotate | diff | comparison | revisions
test/tools/javac/6508981/TestInferBinaryName.java file | annotate | diff | comparison | revisions
test/tools/javac/api/6411310/Test.java file | annotate | diff | comparison | revisions
test/tools/javac/api/T6838467.java file | annotate | diff | comparison | revisions
test/tools/javac/api/T6877206.java file | annotate | diff | comparison | revisions
test/tools/javac/file/zip/T6836682.java file | annotate | diff | comparison | revisions
test/tools/javac/file/zip/T6865530.java file | annotate | diff | comparison | revisions
test/tools/javac/file/zip/Utils.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Mar 07 13:45:06 2011 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Mar 07 17:39:42 2011 -0800
     1.3 @@ -89,7 +89,7 @@
     1.4  
     1.5      private FSInfo fsInfo;
     1.6  
     1.7 -    private boolean useZipFileIndex;
     1.8 +    private boolean contextUseOptimizedZip;
     1.9      private ZipFileIndexCache zipFileIndexCache;
    1.10  
    1.11      private final File uninited = new File("U N I N I T E D");
    1.12 @@ -164,8 +164,8 @@
    1.13  
    1.14          fsInfo = FSInfo.instance(context);
    1.15  
    1.16 -        useZipFileIndex = options.isSet("useOptimizedZip");
    1.17 -        if (useZipFileIndex)
    1.18 +        contextUseOptimizedZip = options.getBoolean("useOptimizedZip", true);
    1.19 +        if (contextUseOptimizedZip)
    1.20              zipFileIndexCache = ZipFileIndexCache.getSharedInstance();
    1.21  
    1.22          mmappedIO = options.isSet("mmappedIO");
    1.23 @@ -471,9 +471,27 @@
    1.24      private static final RelativeDirectory symbolFilePrefix
    1.25              = new RelativeDirectory("META-INF/sym/rt.jar/");
    1.26  
    1.27 +    /*
    1.28 +     * This method looks for a ZipFormatException and takes appropriate
    1.29 +     * evasive action. If there is a failure in the fast mode then we
    1.30 +     * fail over to the platform zip, and allow it to deal with a potentially
    1.31 +     * non compliant zip file.
    1.32 +     */
    1.33 +    protected Archive openArchive(File zipFilename) throws IOException {
    1.34 +        try {
    1.35 +            return openArchive(zipFilename, contextUseOptimizedZip);
    1.36 +        } catch (IOException ioe) {
    1.37 +            if (ioe instanceof ZipFileIndex.ZipFormatException) {
    1.38 +                return openArchive(zipFilename, false);
    1.39 +            } else {
    1.40 +                throw ioe;
    1.41 +            }
    1.42 +        }
    1.43 +    }
    1.44 +
    1.45      /** Open a new zip file directory, and cache it.
    1.46       */
    1.47 -    protected Archive openArchive(File zipFileName) throws IOException {
    1.48 +    private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException {
    1.49          File origZipFileName = zipFileName;
    1.50          if (!ignoreSymbolFile && paths.isDefaultBootClassPathRtJar(zipFileName)) {
    1.51              File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
    1.52 @@ -495,7 +513,7 @@
    1.53              boolean usePreindexedCache = false;
    1.54              String preindexCacheLocation = null;
    1.55  
    1.56 -            if (!useZipFileIndex) {
    1.57 +            if (!useOptimizedZip) {
    1.58                  zdir = new ZipFile(zipFileName);
    1.59              } else {
    1.60                  usePreindexedCache = options.isSet("usezipindex");
    1.61 @@ -524,23 +542,22 @@
    1.62              }
    1.63  
    1.64              if (origZipFileName == zipFileName) {
    1.65 -                if (!useZipFileIndex) {
    1.66 +                if (!useOptimizedZip) {
    1.67                      archive = new ZipArchive(this, zdir);
    1.68                  } else {
    1.69                      archive = new ZipFileIndexArchive(this,
    1.70 -                                zipFileIndexCache.getZipFileIndex(zipFileName,
    1.71 +                                    zipFileIndexCache.getZipFileIndex(zipFileName,
    1.72                                      null,
    1.73                                      usePreindexedCache,
    1.74                                      preindexCacheLocation,
    1.75                                      options.isSet("writezipindexfiles")));
    1.76                  }
    1.77              } else {
    1.78 -                if (!useZipFileIndex) {
    1.79 +                if (!useOptimizedZip) {
    1.80                      archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix);
    1.81 -                }
    1.82 -                else {
    1.83 +                } else {
    1.84                      archive = new ZipFileIndexArchive(this,
    1.85 -                                zipFileIndexCache.getZipFileIndex(zipFileName,
    1.86 +                                    zipFileIndexCache.getZipFileIndex(zipFileName,
    1.87                                      symbolFilePrefix,
    1.88                                      usePreindexedCache,
    1.89                                      preindexCacheLocation,
    1.90 @@ -549,6 +566,8 @@
    1.91              }
    1.92          } catch (FileNotFoundException ex) {
    1.93              archive = new MissingArchive(zipFileName);
    1.94 +        } catch (ZipFileIndex.ZipFormatException zfe) {
    1.95 +            throw zfe;
    1.96          } catch (IOException ex) {
    1.97              if (zipFileName.exists())
    1.98                  log.error("error.reading.file", zipFileName, getMessage(ex));
     2.1 --- a/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java	Mon Mar 07 13:45:06 2011 -0800
     2.2 +++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java	Mon Mar 07 17:39:42 2011 -0800
     2.3 @@ -492,8 +492,30 @@
     2.4          public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
     2.5              this.zipRandomFile = zipRandomFile;
     2.6              this.zipFileIndex = index;
     2.7 +            hasValidHeader();
     2.8 +            findCENRecord(start, end);
     2.9 +        }
    2.10  
    2.11 -            findCENRecord(start, end);
    2.12 +        /*
    2.13 +         * the zip entry signature should be at offset 0, otherwise allow the
    2.14 +         * calling logic to take evasive action by throwing ZipFormatException.
    2.15 +         */
    2.16 +        private boolean hasValidHeader() throws IOException {
    2.17 +            final long pos = zipRandomFile.getFilePointer();
    2.18 +            try {
    2.19 +                if (zipRandomFile.read() == 'P') {
    2.20 +                    if (zipRandomFile.read() == 'K') {
    2.21 +                        if (zipRandomFile.read() == 0x03) {
    2.22 +                            if (zipRandomFile.read() == 0x04) {
    2.23 +                                return true;
    2.24 +                            }
    2.25 +                        }
    2.26 +                    }
    2.27 +                }
    2.28 +            } finally {
    2.29 +                zipRandomFile.seek(pos);
    2.30 +            }
    2.31 +            throw new ZipFormatException("invalid zip magic");
    2.32          }
    2.33  
    2.34          /*
    2.35 @@ -529,7 +551,13 @@
    2.36                      zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12) + 2];
    2.37                      zipDir[0] = endbuf[i + 10];
    2.38                      zipDir[1] = endbuf[i + 11];
    2.39 -                    zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
    2.40 +                    int sz = get4ByteLittleEndian(endbuf, i + 16);
    2.41 +                    // a negative offset or the entries field indicates a
    2.42 +                    // potential zip64 archive
    2.43 +                    if (sz < 0 || get2ByteLittleEndian(zipDir, 0) == 0xffff) {
    2.44 +                        throw new ZipFormatException("detected a zip64 archive");
    2.45 +                    }
    2.46 +                    zipRandomFile.seek(start + sz);
    2.47                      zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
    2.48                      return;
    2.49                  } else {
    2.50 @@ -1127,4 +1155,18 @@
    2.51          }
    2.52      }
    2.53  
    2.54 +    /*
    2.55 +     * Exception primarily used to implement a failover, used exclusively here.
    2.56 +     */
    2.57 +
    2.58 +    static final class ZipFormatException extends IOException {
    2.59 +        private static final long serialVersionUID = 8000196834066748623L;
    2.60 +        protected ZipFormatException(String message) {
    2.61 +            super(message);
    2.62 +        }
    2.63 +
    2.64 +        protected ZipFormatException(String message, Throwable cause) {
    2.65 +            super(message, cause);
    2.66 +        }
    2.67 +    }
    2.68  }
     3.1 --- a/src/share/classes/com/sun/tools/javac/util/Options.java	Mon Mar 07 13:45:06 2011 -0800
     3.2 +++ b/src/share/classes/com/sun/tools/javac/util/Options.java	Mon Mar 07 17:39:42 2011 -0800
     3.3 @@ -76,6 +76,22 @@
     3.4      }
     3.5  
     3.6      /**
     3.7 +     * Get the boolean value for an option, patterned after Boolean.getBoolean,
     3.8 +     * essentially will return true, iff the value exists and is set to "true".
     3.9 +     */
    3.10 +    public boolean getBoolean(String name) {
    3.11 +        return getBoolean(name, false);
    3.12 +    }
    3.13 +
    3.14 +    /**
    3.15 +     * Get the boolean with a default value if the option is not set.
    3.16 +     */
    3.17 +    public boolean getBoolean(String name, boolean defaultValue) {
    3.18 +        String value = get(name);
    3.19 +        return (value == null) ? defaultValue : Boolean.parseBoolean(value);
    3.20 +    }
    3.21 +
    3.22 +    /**
    3.23       * Check if the value for an undocumented option has been set.
    3.24       */
    3.25      public boolean isSet(String name) {
     4.1 --- a/test/tools/javac/6508981/TestInferBinaryName.java	Mon Mar 07 13:45:06 2011 -0800
     4.2 +++ b/test/tools/javac/6508981/TestInferBinaryName.java	Mon Mar 07 17:39:42 2011 -0800
     4.3 @@ -139,9 +139,8 @@
     4.4              throws IOException {
     4.5          Context ctx = new Context();
     4.6          Options options = Options.instance(ctx);
     4.7 -        // uugh, ugly back door, should be cleaned up, someday
     4.8 -        if (zipFileIndexKind == USE_ZIP_FILE_INDEX)
     4.9 -            options.put("useOptimizedZip", "true");
    4.10 +        options.put("useOptimizedZip",
    4.11 +                Boolean.toString(zipFileIndexKind == USE_ZIP_FILE_INDEX));
    4.12  
    4.13          if (symFileKind == IGNORE_SYMBOL_FILE)
    4.14              options.put("ignore.symbol.file", "true");
     5.1 --- a/test/tools/javac/api/6411310/Test.java	Mon Mar 07 13:45:06 2011 -0800
     5.2 +++ b/test/tools/javac/api/6411310/Test.java	Mon Mar 07 17:39:42 2011 -0800
     5.3 @@ -153,14 +153,12 @@
     5.4          Context c = new Context();
     5.5          Options options = Options.instance(c);
     5.6  
     5.7 -            if (useOptimizedZip) {
     5.8 -                options.put("useOptimizedZip", "true");
     5.9 -            }
    5.10 +        options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
    5.11  
    5.12 -            if (!useSymbolFile) {
    5.13 -                options.put("ignore.symbol.file", "true");
    5.14 -            }
    5.15 -            return new JavacFileManager(c, false, null);
    5.16 +        if (!useSymbolFile) {
    5.17 +            options.put("ignore.symbol.file", "true");
    5.18 +        }
    5.19 +        return new JavacFileManager(c, false, null);
    5.20      }
    5.21  
    5.22      File createDir(String name, String... entries) throws Exception {
     6.1 --- a/test/tools/javac/api/T6838467.java	Mon Mar 07 13:45:06 2011 -0800
     6.2 +++ b/test/tools/javac/api/T6838467.java	Mon Mar 07 17:39:42 2011 -0800
     6.3 @@ -178,12 +178,10 @@
     6.4          return fm;
     6.5      }
     6.6  
     6.7 -    JavacFileManager createFileManager(boolean useOptimedZipIndex) {
     6.8 +    JavacFileManager createFileManager(boolean useOptimizedZip) {
     6.9          Context ctx = new Context();
    6.10 -        if (useOptimedZipIndex) {
    6.11 -            Options options = Options.instance(ctx);
    6.12 -            options.put("useOptimizedZip", "true");
    6.13 -        }
    6.14 +        Options options = Options.instance(ctx);
    6.15 +        options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
    6.16          return new JavacFileManager(ctx, false, null);
    6.17      }
    6.18  
     7.1 --- a/test/tools/javac/api/T6877206.java	Mon Mar 07 13:45:06 2011 -0800
     7.2 +++ b/test/tools/javac/api/T6877206.java	Mon Mar 07 17:39:42 2011 -0800
     7.3 @@ -168,9 +168,7 @@
     7.4      JavacFileManager createFileManager(boolean useOptimizedZip, boolean useSymbolFile) {
     7.5          Context ctx = new Context();
     7.6          Options options = Options.instance(ctx);
     7.7 -        if (useOptimizedZip) {
     7.8 -            options.put("useOptimizedZip", "true");
     7.9 -        }
    7.10 +        options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
    7.11          if (!useSymbolFile) {
    7.12              options.put("ignore.symbol.file", "true");
    7.13          }
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/tools/javac/file/zip/T6836682.java	Mon Mar 07 17:39:42 2011 -0800
     8.3 @@ -0,0 +1,156 @@
     8.4 +/*
     8.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.
    8.11 + *
    8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.15 + * version 2 for more details (a copy is included in the LICENSE file that
    8.16 + * accompanied this code).
    8.17 + *
    8.18 + * You should have received a copy of the GNU General Public License version
    8.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.21 + *
    8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.23 + * or visit www.oracle.com if you need additional information or have any
    8.24 + * questions.
    8.25 + */
    8.26 +
    8.27 +/*
    8.28 + * @test
    8.29 + * @bug 6836682
    8.30 + * @summary JavacFileManager handles zip64 archives (64K+ entries and large file support)
    8.31 + * @compile  -XDignore.symbol.file T6836682.java Utils.java
    8.32 + * @run main T6836682
    8.33 + */
    8.34 +import java.io.BufferedOutputStream;
    8.35 +import java.io.File;
    8.36 +import java.io.FileInputStream;
    8.37 +import java.io.FileOutputStream;
    8.38 +import java.io.IOException;
    8.39 +import java.nio.file.Files;
    8.40 +import java.nio.file.Path;
    8.41 +import java.util.jar.JarOutputStream;
    8.42 +import java.util.zip.ZipEntry;
    8.43 +
    8.44 +public class T6836682 {
    8.45 +
    8.46 +    private static final long GIGA = 1024 * 1024 * 1024;
    8.47 +
    8.48 +    static void createLargeFile(File outFile, long minlength) throws IOException {
    8.49 +        FileOutputStream fos = null;
    8.50 +        BufferedOutputStream bos = null;
    8.51 +        byte[] buffer = new byte[Short.MAX_VALUE * 2];
    8.52 +        try {
    8.53 +            fos = new FileOutputStream(outFile);
    8.54 +            bos = new BufferedOutputStream(fos);
    8.55 +            long count = minlength / ( Short.MAX_VALUE * 2)  + 1;
    8.56 +            for (long i = 0 ; i < count ; i++) {
    8.57 +                bos.write(buffer);
    8.58 +            }
    8.59 +        } finally {
    8.60 +            Utils.close(bos);
    8.61 +            Utils.close(fos);
    8.62 +        }
    8.63 +        if (outFile.length() < minlength) {
    8.64 +            throw new RuntimeException("could not create large file " + outFile.getAbsolutePath());
    8.65 +        }
    8.66 +    }
    8.67 +
    8.68 +    static void createJarWithLargeFile(File jarFile, File javaFile,
    8.69 +            long minlength) throws IOException {
    8.70 +        Utils.createClassFile(javaFile, null, true);
    8.71 +        File largeFile = new File("large.data");
    8.72 +        createLargeFile(largeFile, minlength);
    8.73 +        String[] jarArgs = {
    8.74 +            "0cvf",
    8.75 +            jarFile.getAbsolutePath(),
    8.76 +            largeFile.getName(),
    8.77 +            Utils.getClassFileName(javaFile)
    8.78 +        };
    8.79 +        Utils.jarTool.run(jarArgs);
    8.80 +        // deleted to prevent accidental linkage
    8.81 +        new File(Utils.getClassFileName(javaFile)).delete();
    8.82 +    }
    8.83 +
    8.84 +    static void createLargeJar(File jarFile, File javaFile) throws IOException {
    8.85 +        File classFile = new File(Utils.getClassFileName(javaFile));
    8.86 +        Utils.createClassFile(javaFile, null, true);
    8.87 +        JarOutputStream jos = null;
    8.88 +        FileInputStream fis = null;
    8.89 +        try {
    8.90 +            jos = new JarOutputStream(new FileOutputStream(jarFile));
    8.91 +
    8.92 +            for (int i = 0; i < Short.MAX_VALUE * 2 + 10; i++) {
    8.93 +                jos.putNextEntry(new ZipEntry("X" + i + ".txt"));
    8.94 +            }
    8.95 +            jos.putNextEntry(new ZipEntry(classFile.getName()));
    8.96 +            fis = new FileInputStream(classFile);
    8.97 +            Utils.copyStream(fis, jos);
    8.98 +        } finally {
    8.99 +            Utils.close(jos);
   8.100 +            Utils.close(fis);
   8.101 +        }
   8.102 +        // deleted to prevent accidental linkage
   8.103 +        new File(Utils.getClassFileName(javaFile)).delete();
   8.104 +    }
   8.105 +
   8.106 +    // a jar with entries exceeding 64k + a class file for the existential test
   8.107 +    public static void testLargeJar(String... args) throws IOException {
   8.108 +        File largeJar = new File("large.jar");
   8.109 +        File javaFile = new File("Foo.java");
   8.110 +        createLargeJar(largeJar, javaFile);
   8.111 +
   8.112 +        File testFile = new File("Bar.java");
   8.113 +        try {
   8.114 +            Utils.createJavaFile(testFile, javaFile);
   8.115 +            if (!Utils.compile("-doe", "-verbose", "-cp",
   8.116 +                    largeJar.getAbsolutePath(), testFile.getAbsolutePath())) {
   8.117 +                throw new IOException("test failed");
   8.118 +            }
   8.119 +        } finally {
   8.120 +            Utils.deleteFile(largeJar);
   8.121 +        }
   8.122 +    }
   8.123 +
   8.124 +    // a jar with an enormous file + a class file for the existential test
   8.125 +    public static void testHugeJar(String... args) throws IOException {
   8.126 +        final File largeJar = new File("huge.jar");
   8.127 +        final File javaFile = new File("Foo.java");
   8.128 +
   8.129 +        final Path path = largeJar.getAbsoluteFile().getParentFile().toPath();
   8.130 +        final long available = Files.getFileStore(path).getUsableSpace();
   8.131 +        final long MAX_VALUE = 0xFFFF_FFFFL;
   8.132 +
   8.133 +        final long absolute  = MAX_VALUE + 1L;
   8.134 +        final long required  = (long)(absolute * 1.1); // pad for sundries
   8.135 +        System.out.println("\tavailable: " + available / GIGA + " GB");
   8.136 +        System.out.println("\required: " + required / GIGA + " GB");
   8.137 +
   8.138 +        if (available > required) {
   8.139 +            createJarWithLargeFile(largeJar, javaFile, absolute);
   8.140 +            File testFile = new File("Bar.java");
   8.141 +            Utils.createJavaFile(testFile, javaFile);
   8.142 +            try {
   8.143 +                if (!Utils.compile("-doe", "-verbose", "-cp",
   8.144 +                        largeJar.getAbsolutePath(), testFile.getAbsolutePath())) {
   8.145 +                    throw new IOException("test failed");
   8.146 +                }
   8.147 +            } finally {
   8.148 +                Utils.deleteFile(largeJar);
   8.149 +            }
   8.150 +        } else {
   8.151 +            System.out.println("Warning: test passes vacuously, requirements exceeds available space");
   8.152 +        }
   8.153 +    }
   8.154 +
   8.155 +    public static void main(String... args) throws IOException {
   8.156 +        testLargeJar();
   8.157 +        testHugeJar();
   8.158 +    }
   8.159 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/tools/javac/file/zip/T6865530.java	Mon Mar 07 17:39:42 2011 -0800
     9.3 @@ -0,0 +1,66 @@
     9.4 +/*
     9.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.
    9.11 + *
    9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.15 + * version 2 for more details (a copy is included in the LICENSE file that
    9.16 + * accompanied this code).
    9.17 + *
    9.18 + * You should have received a copy of the GNU General Public License version
    9.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.21 + *
    9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.23 + * or visit www.oracle.com if you need additional information or have any
    9.24 + * questions.
    9.25 + */
    9.26 +
    9.27 +/*
    9.28 + * @test
    9.29 + * @bug 6865530
    9.30 + * @summary ensure JavacFileManager handles non-standard zipfiles.
    9.31 + * @compile  -XDignore.symbol.file T6865530.java
    9.32 + * @run main T6865530
    9.33 + */
    9.34 +
    9.35 +
    9.36 +import java.io.File;
    9.37 +
    9.38 +
    9.39 +public class T6865530 {
    9.40 +
    9.41 +    public static void main(String... args) throws Exception {
    9.42 +        File badFile = new File("bad.exe");
    9.43 +        File testJar = new File("test.jar");
    9.44 +        File fooJava = new File("Foo.java");
    9.45 +        File barJava = new File("Bar.java");
    9.46 +
    9.47 +        // create a jar by compiling a file, and append the jar to some
    9.48 +        // arbitrary data to offset the start of the zip/jar archive
    9.49 +        Utils.createJavaFile(fooJava);
    9.50 +        Utils.compile("-doe", "-verbose", fooJava.getName());
    9.51 +        String[] jarArgs = {
    9.52 +            "cvf", testJar.getAbsolutePath(), "Foo.class"
    9.53 +        };
    9.54 +        Utils.jarTool.run(jarArgs);
    9.55 +        Utils.cat(badFile, fooJava, testJar);
    9.56 +
    9.57 +        // create test file and use the above file as a classpath
    9.58 +        Utils.createJavaFile(barJava);
    9.59 +        try {
    9.60 +            if (!Utils.compile("-doe", "-verbose", "-cp", badFile.getAbsolutePath(), "Bar.java")) {
    9.61 +                throw new RuntimeException("test fails javac did not compile");
    9.62 +            }
    9.63 +        } finally {
    9.64 +            Utils.deleteFile(badFile);
    9.65 +            Utils.deleteFile(testJar);
    9.66 +        }
    9.67 +    }
    9.68 +}
    9.69 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/test/tools/javac/file/zip/Utils.java	Mon Mar 07 17:39:42 2011 -0800
    10.3 @@ -0,0 +1,131 @@
    10.4 +/*
    10.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.
   10.11 + *
   10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.15 + * version 2 for more details (a copy is included in the LICENSE file that
   10.16 + * accompanied this code).
   10.17 + *
   10.18 + * You should have received a copy of the GNU General Public License version
   10.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.21 + *
   10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   10.23 + * or visit www.oracle.com if you need additional information or have any
   10.24 + * questions.
   10.25 + */
   10.26 +
   10.27 +import java.io.BufferedInputStream;
   10.28 +import java.io.BufferedOutputStream;
   10.29 +import java.io.Closeable;
   10.30 +import java.io.File;
   10.31 +import java.io.FileInputStream;
   10.32 +import java.io.FileOutputStream;
   10.33 +import java.io.IOException;
   10.34 +import java.io.InputStream;
   10.35 +import java.io.OutputStream;
   10.36 +import java.io.PrintStream;
   10.37 +
   10.38 +public class Utils {
   10.39 +
   10.40 +    static final sun.tools.jar.Main jarTool =
   10.41 +            new sun.tools.jar.Main(System.out, System.err, "jar-tool");
   10.42 +
   10.43 +    static final com.sun.tools.javac.Main javac =
   10.44 +            new com.sun.tools.javac.Main();
   10.45 +
   10.46 +    private Utils(){}
   10.47 +
   10.48 +    public static boolean compile(String... args) {
   10.49 +        return javac.compile(args) == 0;
   10.50 +    }
   10.51 +
   10.52 +    public static void createClassFile(File javaFile, File superClass,
   10.53 +            boolean delete) throws IOException {
   10.54 +        createJavaFile(javaFile, superClass);
   10.55 +        if (!compile(javaFile.getName())) {
   10.56 +            throw new RuntimeException("compile failed unexpectedly");
   10.57 +        }
   10.58 +        if (delete) javaFile.delete();
   10.59 +    }
   10.60 +
   10.61 +    public static void createJavaFile(File outFile) throws IOException {
   10.62 +        createJavaFile(outFile, null);
   10.63 +    }
   10.64 +
   10.65 +    public static void createJavaFile(File outFile, File superClass) throws IOException {
   10.66 +        PrintStream ps = null;
   10.67 +        String srcStr = "public class " + getSimpleName(outFile) + " ";
   10.68 +        if (superClass != null) {
   10.69 +            srcStr = srcStr.concat("extends " + getSimpleName(superClass) + " ");
   10.70 +        }
   10.71 +        srcStr = srcStr.concat("{}");
   10.72 +        try {
   10.73 +            FileOutputStream fos = new FileOutputStream(outFile);
   10.74 +            ps = new PrintStream(fos);
   10.75 +            ps.println(srcStr);
   10.76 +        } finally {
   10.77 +            close(ps);
   10.78 +        }
   10.79 +    }
   10.80 +
   10.81 +    static String getClassFileName(File javaFile) {
   10.82 +        return javaFile.getName().endsWith(".java")
   10.83 +                ? javaFile.getName().replace(".java", ".class")
   10.84 +                : null;
   10.85 +    }
   10.86 +
   10.87 +    static String getSimpleName(File inFile) {
   10.88 +        String fname = inFile.getName();
   10.89 +        return fname.substring(0, fname.indexOf("."));
   10.90 +    }
   10.91 +
   10.92 +    public static void copyStream(InputStream in, OutputStream out) throws IOException {
   10.93 +        byte[] buf = new byte[8192];
   10.94 +        int n = in.read(buf);
   10.95 +        while (n > 0) {
   10.96 +            out.write(buf, 0, n);
   10.97 +            n = in.read(buf);
   10.98 +        }
   10.99 +    }
  10.100 +
  10.101 +    public static void close(Closeable c) {
  10.102 +        if (c != null) {
  10.103 +            try {
  10.104 +                c.close();
  10.105 +            } catch (IOException ignore) {}
  10.106 +        }
  10.107 +    }
  10.108 +
  10.109 +    public static void deleteFile(File f) {
  10.110 +        if (!f.delete()) {
  10.111 +            throw new RuntimeException("could not delete file: " + f.getAbsolutePath());
  10.112 +        }
  10.113 +    }
  10.114 +
  10.115 +    public static void cat(File output, File... files) throws IOException {
  10.116 +        BufferedInputStream bis = null;
  10.117 +        BufferedOutputStream bos = null;
  10.118 +        FileOutputStream fos = null;
  10.119 +        try {
  10.120 +            fos = new FileOutputStream(output);
  10.121 +            bos = new BufferedOutputStream(fos);
  10.122 +            for (File x : files) {
  10.123 +                FileInputStream fis = new FileInputStream(x);
  10.124 +                bis = new BufferedInputStream(fis);
  10.125 +                copyStream(bis, bos);
  10.126 +                Utils.close(bis);
  10.127 +            }
  10.128 +        } finally {
  10.129 +            Utils.close(bis);
  10.130 +            Utils.close(bos);
  10.131 +            Utils.close(fos);
  10.132 +        }
  10.133 +    }
  10.134 +}

mercurial