diff -r 90c28923e449 -r 35e29f51a7c3 test/tools/javac/api/T6877206.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/api/T6877206.java Tue Sep 08 11:12:13 2009 -0700 @@ -0,0 +1,263 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6877206 + * @summary JavaFileObject.toUri returns bogus URI (win) + */ + +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.jar.*; +import java.util.zip.*; +import javax.tools.*; + +import com.sun.tools.javac.file.JavacFileManager; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Options; + +// Test URIs returned from JavacFileManager and its support classes. +// For a variety of file objects, verify the validity of FileObject.toUri() +// by verifying the URI exists and points to the same contents as the file +// object itself + +public class T6877206 { + public static void main(String... args) throws Exception { + new T6877206().run(); + } + + Set foundClasses = new TreeSet(); + Set foundJars = new TreeSet(); + + void run() throws Exception { + File rt_jar = findRtJar(); + + // names for entries to be created in directories and jar files + String[] entries = { "p/A.class", "p/resources/A-1.jpg" }; + + // test various combinations of directories and jar files, intended to + // cover all sources of URIs within JavacFileManager's support classes + + test(createFileManager(), createDir("dir", entries), "p", entries.length); + test(createFileManager(), createDir("a b/dir", entries), "p", entries.length); + + for (boolean useJavaUtilZip: new boolean[] { false, true }) { + test(createFileManager(useJavaUtilZip), createJar("jar", entries), "p", entries.length); + test(createFileManager(useJavaUtilZip), createJar("jar jar", entries), "p", entries.length); + + for (boolean useSymbolFile: new boolean[] { false, true }) { + test(createFileManager(useJavaUtilZip, useSymbolFile), rt_jar, "java.lang.ref", -1); + } + } + + // Verify that we hit all the impl classes we intended + checkCoverage("classes", foundClasses, + "RegularFileObject", "SymbolFileObject", "ZipFileIndexFileObject", "ZipFileObject"); + + // Verify that we hit the jar files we intended, specifically ct.sym as well as rt.jar + checkCoverage("jar files", foundJars, + "ct.sym", "jar", "jar jar", "rt.jar"); + } + + // use a new file manager for each test + void test(StandardJavaFileManager fm, File f, String pkg, int expect) throws Exception { + JarURLConnection c; + System.err.println("Test " + f); + try { + fm.setLocation(StandardLocation.CLASS_PATH, Collections.singleton(f)); + + int count = 0; + for (JavaFileObject fo: fm.list(StandardLocation.CLASS_PATH, + pkg, EnumSet.allOf(JavaFileObject.Kind.class), true)) { + System.err.println("checking " + fo); + // record the file object class name for coverage checks later + foundClasses.add(fo.getClass().getSimpleName()); + testFileObject(fo); + count++; + } + + if (expect > 0 && count != expect) + throw new Exception("wrong number of entries found: " + + count + ", expected " + expect); + } finally { + fm.close(); + } + } + + void testFileObject(JavaFileObject fo) throws Exception { + // test the validity of the result of toUri() by using URLConnection + // and comparing the results of reading from the connection with the + // result of reading from the file object directly. + URI uri = fo.toUri(); + System.err.println("uri: " + uri); + + URLConnection urlconn = uri.toURL().openConnection(); + if (urlconn instanceof JarURLConnection) { + JarURLConnection jarconn = (JarURLConnection) urlconn; + File f = new File(jarconn.getJarFile().getName()); + // record access to the jar file for coverage checks later + foundJars.add(f.getName()); + } + + try { + byte[] uriData = read(urlconn.getInputStream()); + byte[] foData = read(fo.openInputStream()); + if (!Arrays.equals(uriData, foData)) { + if (uriData.length != foData.length) + throw new Exception("data size differs: uri data " + + uriData.length + " bytes, fo data " + foData.length+ " bytes"); + for (int i = 0; i < uriData.length; i++) { + if (uriData[i] != foData[i]) + throw new Exception("unexpected data returned at offset " + i + + ", uri data " + uriData[i] + ", fo data " + foData[i]); + } + throw new AssertionError("cannot find difference"); + } + } finally { + // In principle, simply closing the result of urlconn.getInputStream() + // should have been sufficient. But the internal JarURLConnection + // does not close the JarFile in an expeditious manner, thus preventing + // jtreg from deleting the jar file before starting the next test. + // Therefore we force access to the JarURLConnection to close the + // JarFile when necessary. + if (urlconn instanceof JarURLConnection) { + JarURLConnection jarconn = (JarURLConnection) urlconn; + jarconn.getJarFile().close(); + } + } + } + + void checkCoverage(String label, Set found, String... expect) throws Exception { + Set e = new TreeSet(Arrays.asList(expect)); + if (!found.equals(e)) { + e.removeAll(found); + throw new Exception("expected " + label + " not used: " + e); + } + } + + JavacFileManager createFileManager() { + return createFileManager(false, false); + } + + JavacFileManager createFileManager(boolean useJavaUtilZip) { + return createFileManager(useJavaUtilZip, false); + } + + JavacFileManager createFileManager(boolean useJavaUtilZip, boolean useSymbolFile) { + // javac should really not be using system properties like this + // -- it should really be using (hidden) options -- but until then + // take care to leave system properties as we find them, so as not + // to adversely affect other tests that might follow. + String prev = System.getProperty("useJavaUtilZip"); + boolean resetProperties = false; + try { + if (useJavaUtilZip) { + System.setProperty("useJavaUtilZip", "true"); + resetProperties = true; + } else if (System.getProperty("useJavaUtilZip") != null) { + System.getProperties().remove("useJavaUtilZip"); + resetProperties = true; + } + + Context c = new Context(); + if (!useSymbolFile) { + Options options = Options.instance(c); + options.put("ignore.symbol.file", "true"); + } + + return new JavacFileManager(c, false, null); + } finally { + if (resetProperties) { + if (prev == null) { + System.getProperties().remove("useJavaUtilZip"); + } else { + System.setProperty("useJavaUtilZip", prev); + } + } + } + } + + File createDir(String name, String... entries) throws Exception { + File dir = new File(name); + if (!dir.mkdirs()) + throw new Exception("cannot create directories " + dir); + for (String e: entries) { + writeFile(new File(dir, e), e); + } + return dir; + } + + File createJar(String name, String... entries) throws IOException { + File jar = new File(name); + OutputStream out = new FileOutputStream(jar); + try { + JarOutputStream jos = new JarOutputStream(out); + for (String e: entries) { + jos.putNextEntry(new ZipEntry(e)); + jos.write(e.getBytes()); + } + jos.close(); + } finally { + out.close(); + } + return jar; + } + + File findRtJar() throws Exception { + File java_home = new File(System.getProperty("java.home")); + if (java_home.getName().equals("jre")) + java_home = java_home.getParentFile(); + File rt_jar = new File(new File(new File(java_home, "jre"), "lib"), "rt.jar"); + if (!rt_jar.exists()) + throw new Exception("can't find rt.jar"); + return rt_jar; + } + + byte[] read(InputStream in) throws IOException { + byte[] data = new byte[1024]; + int offset = 0; + try { + int n; + while ((n = in.read(data, offset, data.length - offset)) != -1) { + offset += n; + if (offset == data.length) + data = Arrays.copyOf(data, 2 * data.length); + } + } finally { + in.close(); + } + return Arrays.copyOf(data, offset); + } + + void writeFile(File f, String s) throws IOException { + f.getParentFile().mkdirs(); + FileWriter out = new FileWriter(f); + try { + out.write(s); + } finally { + out.close(); + } + } +}