### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java,v retrieving revision 1.79 diff -u -r1.79 AbstractRegressionTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java 27 Nov 2007 22:20:53 -0000 1.79 +++ src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java 10 Jan 2008 15:47:14 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -104,6 +104,7 @@ protected static IPath jdkRootDirPath; public static final String OUTPUT_DIR = Util.getOutputDirectory() + File.separator + "regression"; + public static final String LIB_DIR = Util.getOutputDirectory() + File.separator + "lib"; public final static String PACKAGE_INFO_NAME = new String(TypeConstants.PACKAGE_INFO_NAME); Index: src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java,v retrieving revision 1.141 diff -u -r1.141 BatchCompilerTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 3 Jan 2008 08:34:13 -0000 1.141 +++ src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 10 Jan 2008 15:47:16 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -26,12 +26,14 @@ import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.core.tests.util.Util; +import org.eclipse.jdt.internal.compiler.batch.ClasspathJar; import org.eclipse.jdt.internal.compiler.batch.ClasspathLocation; import org.eclipse.jdt.internal.compiler.batch.Main; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; public class BatchCompilerTest extends AbstractRegressionTest { public static final String OUTPUT_DIR_PLACEHOLDER = "---OUTPUT_DIR_PLACEHOLDER---"; + public static final String LIB_DIR_PLACEHOLDER = "---LIB_DIR_PLACEHOLDER---"; static final String JRE_HOME_DIR = Util.getJREDirectory(); private static final Main MAIN = new Main(null, null, false); @@ -53,6 +56,283 @@ return buildUniqueComplianceTestSuite(testClass(), ClassFileConstants.JDK1_5); } +private static boolean CASCADED_JARS_CREATED; +private void createCascadedJars() { + if (!CASCADED_JARS_CREATED) { + File libDir = new File(LIB_DIR); + Util.delete(libDir); // make sure we recycle the libs + libDir.mkdirs(); + try { + Util.createJar( + new String[] { + "p/A.java", + "package p;\n" + + "public class A {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib2.jar\n", + "p/S1.java", + "package p;\n" + + "public class S1 {\n" + + "}", + }, + LIB_DIR + "/lib1.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/B.java", + "package p;\n" + + "public class B {\n" + + "}", + "p/R.java", + "package p;\n" + + "public class R {\n" + + " public static final int R2 = 2;\n" + + "}", + }, + new String[] { + "p/S2.java", + "package p;\n" + + "public class S2 {\n" + + "}", + }, + LIB_DIR + "/lib2.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/C.java", + "package p;\n" + + "public class C {\n" + + "}", + "p/R.java", + "package p;\n" + + "public class R {\n" + + " public static final int R3 = 3;\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib4.jar\n", + }, + LIB_DIR + "/lib3.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/D.java", + "package p;\n" + + "public class D {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib1.jar lib3.jar\n", + }, + LIB_DIR + "/lib4.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/C.java", + "package p;\n" + + "public class C {\n" + + "}", + "p/R.java", + "package p;\n" + + "public class R {\n" + + " public static final int R3 = 3;\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: s/lib6.jar\n", + }, + LIB_DIR + "/lib5.jar", + JavaCore.VERSION_1_4); + new File(LIB_DIR + "/s").mkdir(); + Util.createJar( + new String[] { + "p/D.java", + "package p;\n" + + "public class D {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: ../lib7.jar\n", + }, + LIB_DIR + "/s/lib6.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/A.java", + "package p;\n" + + "public class A {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib2.jar\n", + }, + LIB_DIR + "/lib7.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/F.java", + "package p;\n" + + "public class F {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: " + LIB_DIR + "/lib3.jar lib1.jar\n", + }, + LIB_DIR + "/lib8.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/G.java", + "package p;\n" + + "public class G {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib1.jar\n" + + "Class-Path: lib3.jar\n", + }, + LIB_DIR + "/lib9.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/A.java", + "package p;\n" + + "public class A {\n" + + "}", + }, + // spoiled jar: MANIFEST.MF is a directory + new String[] { + "META-INF/MANIFEST.MF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib2.jar\n", + }, + LIB_DIR + "/lib10.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/A.java", + "package p;\n" + + "public class A {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path:\n", + }, + LIB_DIR + "/lib11.jar", + JavaCore.VERSION_1_4); + Util.createJar( + null, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path:lib1.jar\n", // missing space + }, + LIB_DIR + "/lib12.jar", + JavaCore.VERSION_1_4); + Util.createJar( + null, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path:lib1.jar lib1.jar\n", // missing space + }, + LIB_DIR + "/lib13.jar", + JavaCore.VERSION_1_4); + Util.createJar( + null, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + " Class-Path: lib1.jar\n", // extra space at line start + }, + LIB_DIR + "/lib14.jar", + JavaCore.VERSION_1_4); + Util.createJar( + null, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib1.jar", // missing newline at end + }, + LIB_DIR + "/lib15.jar", + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/A.java", + "package p;\n" + + "public class A {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: \n" + + " lib2.jar\n", + "p/S1.java", + "package p;\n" + + "public class S1 {\n" + + "}", + }, + LIB_DIR + "/lib16.jar", + JavaCore.VERSION_1_4); + new File(LIB_DIR + "/dir").mkdir(); + Util.createJar( + new String[] { + "p/A.java", + "package p;\n" + + "public class A {\n" + + "}", + }, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: ../lib2.jar\n", + }, + LIB_DIR + "/dir/lib17.jar", + JavaCore.VERSION_1_4); + CASCADED_JARS_CREATED = true; + } catch (IOException e) { + // ignore + } + } +} + private String getLibraryClassesAsQuotedString() { String[] paths = Util.getJavaClassLibs(); StringBuffer buffer = new StringBuffer(); @@ -157,7 +437,10 @@ * pass true to get the output directory flushed before the test * runs */ - private void runTest(boolean shouldCompileOK, String[] testFiles, String commandLine, + private void runTest( + boolean shouldCompileOK, + String[] testFiles, + String commandLine, String expectedOutOutputString, String expectedErrOutputString, boolean shouldFlushOutputDirectory) { @@ -279,6 +562,140 @@ errOutputString); } } +private void runTest( + boolean shouldCompileOK, + String[] testFiles, + String commandLine, + Matcher outOutputStringMatcher, + Matcher errOutputStringMatcher, + boolean shouldFlushOutputDirectory) { + File outputDirectory = new File(OUTPUT_DIR); + if (shouldFlushOutputDirectory) + Util.flushDirectoryContent(outputDirectory); + try { + if (!outputDirectory.isDirectory()) { + outputDirectory.mkdirs(); + } + PrintWriter sourceFileWriter; + for (int i = 0; i < testFiles.length; i += 2) { + String fileName = OUTPUT_DIR + File.separator + testFiles[i]; + File file = new File(fileName), innerOutputDirectory = file + .getParentFile(); + if (!innerOutputDirectory.isDirectory()) { + innerOutputDirectory.mkdirs(); + } + sourceFileWriter = new PrintWriter(new FileOutputStream(file)); + sourceFileWriter.write(testFiles[i + 1]); + sourceFileWriter.close(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + String printerWritersNameRoot = OUTPUT_DIR + File.separator + testName(); + String outFileName = printerWritersNameRoot + "out.txt", + errFileName = printerWritersNameRoot + "err.txt"; + Main batchCompiler; + PrintWriter out = null; + PrintWriter err = null; + boolean compileOK; + try { + try { + out = new PrintWriter(new FileOutputStream(outFileName)); + err = new PrintWriter(new FileOutputStream(errFileName)); + batchCompiler = new Main(out, err, false); + } catch (FileNotFoundException e) { + System.out.println(getClass().getName() + '#' + getName()); + e.printStackTrace(); + throw new RuntimeException(e); + } + try { + final String[] tokenizeCommandLine = Main.tokenize(commandLine); + compileOK = batchCompiler.compile(tokenizeCommandLine); + } catch (RuntimeException e) { + compileOK = false; + System.out.println(getClass().getName() + '#' + getName()); + e.printStackTrace(); + throw e; + } + } finally { + if (out != null) + out.close(); + if (err != null) + err.close(); + } + String outOutputString = Util.fileContent(outFileName), + errOutputString = Util.fileContent(errFileName); + boolean compareOK = false, outCompareOK = false, errCompareOK = false; + String expectedErrOutputString = null, expectedOutOutputString = null; + if (compileOK == shouldCompileOK) { + if (outOutputStringMatcher == null) { + outCompareOK = true; + } else { + outCompareOK = outOutputStringMatcher.match(outOutputString); + expectedOutOutputString = outOutputStringMatcher.expected(); + } + if (errOutputStringMatcher == null) { + errCompareOK = true; + } else { + errCompareOK = errOutputStringMatcher.match(errOutputString); + expectedErrOutputString = errOutputStringMatcher.expected(); + } + compareOK = outCompareOK && errCompareOK; + } + if (compileOK != shouldCompileOK || !compareOK) { + System.out.println(getClass().getName() + '#' + getName()); + for (int i = 0; i < testFiles.length; i += 2) { + System.out.print(testFiles[i]); + System.out.println(" ["); + System.out.println(testFiles[i + 1]); + System.out.println("]"); + } + } + if (compileOK != shouldCompileOK) + System.out.println(errOutputString); + if (compileOK == shouldCompileOK && !compareOK) { + System.out.println( + "------------ [START OUT] ------------\n" + + "------------- Expected: -------------\n" + + expectedOutOutputString + + "\n------------- but was: -------------\n" + + outOutputString + + "\n--------- (cut and paste:) ----------\n" + + Util.displayString(outputDirNormalizer + .normalized(outOutputString)) + + "\n------------- [END OUT] -------------\n" + + "------------ [START ERR] ------------\n" + + "------------- Expected: -------------\n" + + expectedErrOutputString + + "\n------------- but was: -------------\n" + + errOutputString + + "\n--------- (cut and paste:) ----------\n" + + Util.displayString(outputDirNormalizer + .normalized(errOutputString)) + + "\n------------- [END ERR] -------------\n"); + } + if (shouldCompileOK) + assertTrue("Unexpected problems: " + errOutputString, compileOK); + else + assertTrue("Unexpected success: " + errOutputString, !compileOK); + if (!outCompareOK) { + // calling assertEquals to benefit from the comparison UI + // (need appropriate exception) + assertEquals( + "Unexpected standard output for invocation with arguments [" + + commandLine + "]", + expectedOutOutputString, + outOutputString); + } + if (!errCompareOK) { + assertEquals( + "Unexpected error output for invocation with arguments [" + + commandLine + "]", + expectedErrOutputString, + errOutputString); + } +} private void runClasspathTest(String classpathInput, String[] expectedClasspathEntries, String expectedError) { File outputDirectory = new File(OUTPUT_DIR); @@ -356,6 +773,53 @@ } } +static abstract class Matcher { + abstract boolean match(String effective); + abstract String expected(); // for use in JUnit comparison framework +} +static class StringMatcher extends Matcher { + private String expected; + private Normalizer normalizer; + StringMatcher(String expected, Normalizer normalizer) { + this.expected = expected; + this.normalizer = normalizer; + } + boolean match(String effective) { + if (this.expected == null) { + return effective == null; + } + if (this.normalizer == null) { + return this.expected.equals(effective); + } + return this.expected.equals(this.normalizer.normalized(effective)); + } + String expected() { + return this.expected; + } +} +static class SubstringMatcher extends Matcher { + private String substring; + SubstringMatcher(String substring) { + this.substring = substring; + } + boolean match(String effective) { + effective = outputDirNormalizer.normalized(effective); + return effective.indexOf(this.substring) != -1; + } + String expected() { + return "*" + this.substring + "*"; + } +} +static final Matcher EMPTY_STRING_MATCHER = new Matcher() { + String expected() { + return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING; + } + boolean match(String effective) { + return effective != null && effective.length() == 0; + } +}; +static final Matcher ONE_FILE_GENERATED_MATCHER = new SubstringMatcher("[1 .class file generated]"); +static final Matcher TWO_FILES_GENERATED_MATCHER = new SubstringMatcher("[2 .class files generated]"); /** * Abstract normalizer for output comparison. This class merely embodies a * chain of responsibility, plus the signature of the method of interest @@ -556,17 +1020,23 @@ * OUTPUT_DIR_PLACEHOLDER and changes file separator to / if the * platform file separator is different from /. */ - private static Normalizer outputDirNormalizer; + static Normalizer outputDirNormalizer; static { if (File.separatorChar == '/') { - outputDirNormalizer = new StringNormalizer( - null, OUTPUT_DIR, OUTPUT_DIR_PLACEHOLDER); + outputDirNormalizer = + new StringNormalizer( + new StringNormalizer( + null, OUTPUT_DIR, OUTPUT_DIR_PLACEHOLDER), + LIB_DIR, LIB_DIR_PLACEHOLDER); } else { - outputDirNormalizer = new StringNormalizer( + outputDirNormalizer = + new StringNormalizer( new StringNormalizer( + new StringNormalizer( null, File.separator, "/"), - OUTPUT_DIR, OUTPUT_DIR_PLACEHOLDER); + OUTPUT_DIR, OUTPUT_DIR_PLACEHOLDER), + LIB_DIR, LIB_DIR_PLACEHOLDER); } } @@ -1503,82 +1973,159 @@ "incorrect classpath: dummmy_dir\n", true); } -// we tolerate inexisting jars on the classpath -// TODO (maxime) check and document -public void _test017b(){ - this.runConformTest( +// we tolerate inexisting jars on the classpath, and we don't even warn about +// them (javac does the same as us) +public void test017b(){ + this.runTest( + true, new String[] { - "X.java", - "/** */\n" + - "public class X {\n" + - " OK1 ok1;\n" + - "}", - "OK1.java", - "/** */\n" + - "public class OK1 {\n" + - " // empty\n" + - "}" + "X.java", + "/** */\n" + + "public class X {\n" + + " OK1 ok1;\n" + + "}", + "OK1.java", + "/** */\n" + + "public class OK1 {\n" + + " // empty\n" + + "}" }, "\"" + OUTPUT_DIR + File.separator + "X.java\"" + " -1.5 -g -preserveAllLocals" + " -cp dummy.jar" + File.pathSeparator + File.pathSeparator + "\"" + OUTPUT_DIR + "\"" + " -verbose -proceedOnError -referenceInfo" + " -d \"" + OUTPUT_DIR + "\"", - "[2 .class files generated]\n", - "incorrect classpath: dummmy.jar\n", + TWO_FILES_GENERATED_MATCHER, + EMPTY_STRING_MATCHER, true); } -// we tolerate empty classpath entries -// TODO (maxime) check and document -public void _test017c(){ - this.runConformTest( +// we tolerate empty classpath entries, and we don't even warn about +// them (javac does the same as us) +public void test017c(){ + this.runTest( + true, new String[] { - "X.java", - "/** */\n" + - "public class X {\n" + - " OK1 ok1;\n" + - "}", - "OK1.java", - "/** */\n" + - "public class OK1 {\n" + - " // empty\n" + - "}" + "X.java", + "/** */\n" + + "public class X {\n" + + " OK1 ok1;\n" + + "}", + "OK1.java", + "/** */\n" + + "public class OK1 {\n" + + " // empty\n" + + "}" }, "\"" + OUTPUT_DIR + File.separator + "X.java\"" + " -1.5 -g -preserveAllLocals" + " -cp " + File.pathSeparator + File.pathSeparator + "\"" + OUTPUT_DIR + "\"" + " -verbose -proceedOnError -referenceInfo" + " -d \"" + OUTPUT_DIR + "\"", - "[2 .class files generated]\n", - "incorrect classpath\n", + TWO_FILES_GENERATED_MATCHER, + EMPTY_STRING_MATCHER, true); } -// command line - unusual classpath (empty, but using current directory, still OK provided -// that we execute from the appropriate directory); since there is no notion -// of current directory for this tests suite, the test is not executed -// TODO (maxime) enforce working directory - public void _test018(){ - this.runConformTest( - new String[] { - "X.java", - "/** */\n" + - "public class X {\n" + - " OK1 ok1;\n" + - "}", - "OK1.java", - "/** */\n" + - "public class OK1 {\n" + - " // empty\n" + - "}" - }, - "\"" + OUTPUT_DIR + File.separator + "X.java\"" - + " -1.5 -g -preserveAllLocals" - + " -verbose -proceedOnError -referenceInfo" - + " -d \"" + OUTPUT_DIR + "\"", - "[2 .class files generated]\n", - "", - true); +// command line - unusual classpath (empty) +// ok provided we explicit the sourcepath +public void test018a(){ + String currentWorkingDirectoryPath = System.getProperty("user.dir"); + if (currentWorkingDirectoryPath == null) { + System.err.println("BatchCompilerTest#18a could not access the current working directory " + currentWorkingDirectoryPath); + } else if (!new File(currentWorkingDirectoryPath).isDirectory()) { + System.err.println("BatchCompilerTest#18a current working directory is not a directory " + currentWorkingDirectoryPath); + } else { + String xPath = currentWorkingDirectoryPath + File.separator + "X.java"; + String ok1Path = currentWorkingDirectoryPath + File.separator + "OK1.java"; + PrintWriter sourceFileWriter; + try { + File file = new File(xPath); + sourceFileWriter = new PrintWriter(new FileOutputStream(file)); + sourceFileWriter.write( + "/** */\n" + + "public class X {\n" + + " OK1 ok1;\n" + + "}"); + sourceFileWriter.close(); + file = new File(ok1Path); + sourceFileWriter = new PrintWriter(new FileOutputStream(file)); + sourceFileWriter.write( + "/** */\n" + + "public class OK1 {\n" + + " // empty\n" + + "}"); + sourceFileWriter.close(); + this.runTest( + true, + new String[] { + "dummy.java", // enforce output directory creation + "" + }, + "X.java" + + " -1.5 -g -preserveAllLocals" + + " -verbose -proceedOnError" + + " -sourcepath ." + + " -d \"" + OUTPUT_DIR + "\"", + TWO_FILES_GENERATED_MATCHER, + EMPTY_STRING_MATCHER, + false); + } catch (FileNotFoundException e) { + System.err.println("BatchCompilerTest#18a could not write to current working directory " + currentWorkingDirectoryPath); + } finally { + new File(xPath).delete(); + new File(ok1Path).delete(); + } + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=214725 +// empty sourcepath works with javac but not with ecj +public void _test018b(){ + String currentWorkingDirectoryPath = System.getProperty("user.dir"); + if (currentWorkingDirectoryPath == null) { + System.err.println("BatchCompilerTest#18b could not access the current working directory " + currentWorkingDirectoryPath); + } else if (!new File(currentWorkingDirectoryPath).isDirectory()) { + System.err.println("BatchCompilerTest#18b current working directory is not a directory " + currentWorkingDirectoryPath); + } else { + String xPath = currentWorkingDirectoryPath + File.separator + "X.java"; + String ok1Path = currentWorkingDirectoryPath + File.separator + "OK1.java"; + PrintWriter sourceFileWriter; + try { + File file = new File(xPath); + sourceFileWriter = new PrintWriter(new FileOutputStream(file)); + sourceFileWriter.write( + "/** */\n" + + "public class X {\n" + + " OK1 ok1;\n" + + "}"); + sourceFileWriter.close(); + file = new File(ok1Path); + sourceFileWriter = new PrintWriter(new FileOutputStream(file)); + sourceFileWriter.write( + "/** */\n" + + "public class OK1 {\n" + + " // empty\n" + + "}"); + sourceFileWriter.close(); + this.runTest( + true, + new String[] { + "dummy.java", // enforce output directory creation + "" + }, + "X.java" + + " -1.5 -g -preserveAllLocals" + + " -verbose -proceedOnError" + + " -d \"" + OUTPUT_DIR + "\"", + TWO_FILES_GENERATED_MATCHER, + EMPTY_STRING_MATCHER, + false); + } catch (FileNotFoundException e) { + System.err.println("BatchCompilerTest#18b could not write to current working directory " + currentWorkingDirectoryPath); + } finally { + new File(xPath).delete(); + new File(ok1Path).delete(); + } } +} public void test019(){ this.runNegativeTest( new String[] { @@ -7857,6 +8404,987 @@ "invalid warning option: -warn:null,+unused. Must specify a warning token\n", true); } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// basic link: a jar only referenced in the manifest of the first one is found +public void test216_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib1.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// may want a specific option to mimick javac 1.4 +// caveat: javac 1.5 with -source 1.4 and -target 1.4 still uses the links +public void _test216_jar_ref_in_jar_suppress(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib1.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -ignoreJarClassPath -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 5)\n" + + " B b;\n" + + " ^\n" + + "B cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// links are followed recursively, eliminating dupes +public void test217_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + " C c;\n" + + " D d;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib3.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// at first level, this is depth first, masking tailing libs +public void test218_jar_ref_in_jar(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " int i = R.R2;\n" + + " int j = R.R3;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib1.jar\"" + + " -cp \"" + LIB_DIR + File.separator + "lib3.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 5)\n" + + " int j = R.R3;\n" + + " ^^^^\n" + + "R.R3 cannot be resolved\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// using only links, we adopt a depth first algorithm +public void test219_jar_ref_in_jar(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " int i = R.R2;\n" + + " int j = R.R3;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib4.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 5)\n" + + " int j = R.R3;\n" + + " ^^^^\n" + + "R.R3 cannot be resolved\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// managing subdirectories and .. properly +public void test220_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + " C c;\n" + + " D d;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib5.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// variant: the second jar on a line is found as well +public void test221_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " C c;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib4.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// we eat up absolute links silently +public void test222_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " F f;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib8.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// absolute links do not mask following relative links +public void test223_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " F f;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib8.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// absolute links are not followed +public void test224_jar_ref_in_jar(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " C c;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib8.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 4)\n" + + " C c;\n" + + " ^\n" + + "C cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// we accept duplicate classpath lines in manifest and we follow the jars of the +// second and following lines as well as the first line (emit a warning as javac does) +public void test225_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " G g;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib9.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "multiple Class-Path headers in manifest of jar file: ---LIB_DIR_PLACEHOLDER---/lib9.jar\n", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// we accept duplicate classpath lines in manifest and we follow the jars of the +// second and following lines as well as the first line (emit a warning as javac does) +public void test226_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " C c;\n" + + " G g;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib9.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "multiple Class-Path headers in manifest of jar file: ---LIB_DIR_PLACEHOLDER---/lib9.jar\n", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// bootclasspath does not get expanded with linked files +public void test227_jar_ref_in_jar(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -bootclasspath " + getLibraryClassesAsQuotedString() + + File.pathSeparator + "\"" + LIB_DIR + File.separator + "lib1.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 5)\n" + + " B b;\n" + + " ^\n" + + "B cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// jar files reached indirectly bear the access rules of the entry that +// references them +public void test228_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib3.jar[~p/A]\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 4)\n" + + " A a;\n" + + " ^\n" + + "Discouraged access: The type A is not accessible due to restriction on classpath entry ---LIB_DIR_PLACEHOLDER---/lib3.jar\n" + + "----------\n" + + "1 problem (1 warning)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// jar files reached indirectly bear the access rules of the entry that +// references them - this hides the access rules of further instances of the +// same jar on the classpath +public void test229_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib3.jar[~p/A]\"" + + " -cp \"" + LIB_DIR + File.separator + "lib1.jar[-p/A]\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 4)\n" + + " A a;\n" + + " ^\n" + + "Discouraged access: The type A is not accessible due to restriction on classpath entry ---LIB_DIR_PLACEHOLDER---/lib3.jar\n" + + "----------\n" + + "1 problem (1 warning)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// jar files reached indirectly bear the access rules of the entry that +// references them - this hides the access rules of further instances of the +// same jar on the classpath +public void test230_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib3.jar[-DUMMY]\"" + + " -cp \"" + LIB_DIR + File.separator + "lib1.jar[-p/A]\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// jar files reached indirectly bear the access rules of the entry that +// references them - this hides the access rules of further instances of the +// same jar on the classpath, to the point of absorbing it if none is specified +public void test231_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib3.jar\"" + + " -cp \"" + LIB_DIR + File.separator + "lib1.jar[-p/A]\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// -sourcepath is OK at first level +public void test232_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " S1 s;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -sourcepath \"" + LIB_DIR + File.separator + "lib1.jar\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// -sourcepath is KO at second level (that is, it does not leverage the links +// at all) +public void test233_jar_ref_in_jar(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " S2 s;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -sourcepath \"" + LIB_DIR + File.separator + "lib1.jar\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 4)\n" + + " S2 s;\n" + + " ^^\n" + + "S2 cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// error case: the MANIFEST.MF is a directory; should fail gracefully +public void test234_jar_ref_in_jar(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib10.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 5)\n" + + " B b;\n" + + " ^\n" + + "B cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// using relative paths for libs +public void test235_jar_ref_in_jar(){ + String currentWorkingDirectoryPath = System.getProperty("user.dir"); + if (currentWorkingDirectoryPath == null) { + System.err.println("BatchCompilerTest#235 could not access the current working directory " + currentWorkingDirectoryPath); + } else if (!new File(currentWorkingDirectoryPath).isDirectory()) { + System.err.println("BatchCompilerTest#235 current working directory is not a directory " + currentWorkingDirectoryPath); + } else { + String lib1Path = currentWorkingDirectoryPath + File.separator + "lib1.jar"; + String lib2Path = currentWorkingDirectoryPath + File.separator + "lib2.jar"; + try { + Util.createJar( + null, + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib2.jar\n", + }, + lib1Path, + JavaCore.VERSION_1_4); + Util.createJar( + new String[] { + "p/A.java", + "package p;\n" + + "public class A {\n" + + "}", + }, + null, + lib2Path, + JavaCore.VERSION_1_4); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp lib1.jar" // relative + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); + } catch (IOException e) { + System.err.println("BatchCompilerTest#235 could not write to current working directory " + currentWorkingDirectoryPath); + } finally { + new File(lib1Path).delete(); + new File(lib2Path).delete(); + } + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// empty Class-Path header +// javac 1.4.2 passes, later versions fail in error +// java accepts the same jar (which makes the compiler responsible for the +// error detection) +// design: will issue a warning +public void test236_jar_ref_in_jar(){ + createCascadedJars(); + this.runTest( + true, + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -classpath \"" + LIB_DIR + File.separator + "lib11.jar\"" + + " -1.5 -g -preserveAllLocals" + + " -verbose -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + ONE_FILE_GENERATED_MATCHER, + new StringMatcher( + "invalid Class-Path header in manifest of jar file: ---LIB_DIR_PLACEHOLDER---/lib11.jar\n", + outputDirNormalizer), + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// missing space after ClassPath: +public void test237_jar_ref_in_jar(){ + createCascadedJars(); + this.runTest( + false, + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -classpath \"" + LIB_DIR + File.separator + "lib12.jar\"" + + " -1.5 -g -preserveAllLocals" + + " -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "invalid Class-Path header in manifest of jar file: ---LIB_DIR_PLACEHOLDER---/lib12.jar\n" + + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 4)\n" + + " A a;\n" + + " ^\n" + + "A cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// missing space after ClassPath +// javac reports an error (including an explicit manifest header error since +// version 1.5); moreover, it stops interpreting the said header +// design: we report a warning and eat up the remainding of the line +public void test238_jar_ref_in_jar(){ + createCascadedJars(); + this.runTest( + false, + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -classpath \"" + LIB_DIR + File.separator + "lib13.jar\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "invalid Class-Path header in manifest of jar file: ---LIB_DIR_PLACEHOLDER---/lib13.jar\n" + + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 4)\n" + + " A a;\n" + + " ^\n" + + "A cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// extra space before Class-Path header +// the net result is that the line is part of the value of the previous header +// we then simply don't see the remainding of the line as jars +public void test239_jar_ref_in_jar(){ + createCascadedJars(); + this.runTest( + false, + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -classpath \"" + LIB_DIR + File.separator + "lib14.jar\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 4)\n" + + " A a;\n" + + " ^\n" + + "A cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// missing newline at the end of the line +// javac eats the line silently, which results into not finding A +// design: we report a warning and eat up the remainding of the line +public void test240_jar_ref_in_jar(){ + createCascadedJars(); + this.runTest( + false, + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -classpath \"" + LIB_DIR + File.separator + "lib15.jar\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "invalid Class-Path header in manifest of jar file: ---LIB_DIR_PLACEHOLDER---/lib15.jar\n" + + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 4)\n" + + " A a;\n" + + " ^\n" + + "A cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// white-box test for duplicate classpath lines variant (empty line between the +// entries) +public void test241_jar_ref_in_jar(){ + try { + assertTrue(ClasspathJar.MANIFEST_ANALYZER.analyzeManifestContents( + new StringReader( + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib1.jar\n" + + "\n" + + "Class-Path: lib3.jar\n"))); + assertEquals(2, ClasspathJar.MANIFEST_ANALYZER.getClasspathSectionsCount()); + assertEquals(2, ClasspathJar.MANIFEST_ANALYZER.getCalledFileNames().size()); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// white-box test for duplicate classpath lines variant (other header between the +// entries - note that since we are not doing a full-fledged manifest analysis, +// a dummy header passes) +public void test242_jar_ref_in_jar(){ + try { + assertTrue(ClasspathJar.MANIFEST_ANALYZER.analyzeManifestContents( + new StringReader( + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib1.jar\n" + + "Dummy:\n" + + "Class-Path: lib3.jar\n"))); + assertEquals(2, ClasspathJar.MANIFEST_ANALYZER.getClasspathSectionsCount()); + assertEquals(2, ClasspathJar.MANIFEST_ANALYZER.getCalledFileNames().size()); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// white-box test: tabs are not seen as URI separator, but as parts of URI instead +// will trigger downstream errors if the jars are really needed +public void test243_jar_ref_in_jar(){ + try { + assertTrue(ClasspathJar.MANIFEST_ANALYZER.analyzeManifestContents( + new StringReader( + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: lib1.jar\tlib2.jar\n"))); + assertEquals(1, ClasspathJar.MANIFEST_ANALYZER.getClasspathSectionsCount()); + assertEquals(1, ClasspathJar.MANIFEST_ANALYZER.getCalledFileNames().size()); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// managing continuations properly +public void test244_jar_ref_in_jar(){ + createCascadedJars(); + this.runConformTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -cp \"" + LIB_DIR + File.separator + "lib16.jar\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// white-box test: variants on continuations +public void test245_jar_ref_in_jar(){ + try { + assertTrue(ClasspathJar.MANIFEST_ANALYZER.analyzeManifestContents( + new StringReader( + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: \n" + + " lib1.jar \n" + + "\n"))); + assertEquals(1, ClasspathJar.MANIFEST_ANALYZER.getClasspathSectionsCount()); + assertEquals(1, ClasspathJar.MANIFEST_ANALYZER.getCalledFileNames().size()); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// white-box test: variants on continuations +public void test246_jar_ref_in_jar(){ + try { + assertTrue(ClasspathJar.MANIFEST_ANALYZER.analyzeManifestContents( + new StringReader( + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: \n" + + " \n" + + " lib1.jar \n" + + " \n" + + " lib1.jar \n" + + "\n"))); + assertEquals(1, ClasspathJar.MANIFEST_ANALYZER.getClasspathSectionsCount()); + assertEquals(2, ClasspathJar.MANIFEST_ANALYZER.getCalledFileNames().size()); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// white-box test: variants on continuations +public void test247_jar_ref_in_jar(){ + try { + assertFalse(ClasspathJar.MANIFEST_ANALYZER.analyzeManifestContents( + new StringReader( + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: \n" + + " lib1.jar"))); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// white-box test: variants on continuations +public void test248_jar_ref_in_jar(){ + try { + assertFalse(ClasspathJar.MANIFEST_ANALYZER.analyzeManifestContents( + new StringReader( + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: \n" + + " \n" + + " lib1.jar"))); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// white-box test: variants on continuations +public void test249_jar_ref_in_jar(){ + try { + assertFalse(ClasspathJar.MANIFEST_ANALYZER.analyzeManifestContents( + new StringReader( + "Manifest-Version: 1.0\n" + + "Created-By: Eclipse JDT Test Harness\n" + + "Class-Path: \n" + + "lib1.jar"))); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// extdirs jars do not follow links +public void test250_jar_ref_in_jar(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -extdirs \"" + LIB_DIR + File.separator + "dir\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 5)\n" + + " B b;\n" + + " ^\n" + + "B cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97332 - jars pointed by jars +// endorseddirs does not get expanded with linked files +public void test251_jar_ref_in_jar(){ + createCascadedJars(); + this.runNegativeTest( + new String[] { + "src/p/X.java", + "package p;\n" + + "/** */\n" + + "public class X {\n" + + " A a;\n" + + " B b;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + "src/p/X.java\"" + + " -endorseddirs \"" + LIB_DIR + File.separator + "dir\"" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + "src\"" + + " -1.5 -g -preserveAllLocals" + + " -proceedOnError -referenceInfo" + + " -d \"" + OUTPUT_DIR + File.separator + "bin\" ", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/p/X.java (at line 5)\n" + + " B b;\n" + + " ^\n" + + "B cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} public static Class testClass() { return BatchCompilerTest.class; } Index: src/org/eclipse/jdt/core/tests/util/Util.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java,v retrieving revision 1.60 diff -u -r1.60 Util.java --- src/org/eclipse/jdt/core/tests/util/Util.java 9 Jan 2008 14:49:28 -0000 1.60 +++ src/org/eclipse/jdt/core/tests/util/Util.java 10 Jan 2008 15:47:16 -0000 @@ -317,14 +317,27 @@ compile(pathsAndContents, getCompileOptions(compliance), folderPath); } public static void createJar(String[] pathsAndContents, Map options, String jarPath) throws IOException { + createJar(pathsAndContents, null, options, jarPath); +} +public static void createJar(String[] pathsAndContents, String[] extraPathsAndContents, Map options, String jarPath) throws IOException { String classesPath = getOutputDirectory() + File.separator + "classes"; File classesDir = new File(classesPath); flushDirectoryContent(classesDir); - compile(pathsAndContents, options, classesPath); + if (pathsAndContents != null) { + compile(pathsAndContents, options, classesPath); + } + for (int i = 0, l = extraPathsAndContents == null ? 0 : extraPathsAndContents.length; i < l; /* inc in loop */) { + File outputFile = new File(classesPath, extraPathsAndContents[i++]); + outputFile.getParentFile().mkdirs(); + Util.writeToFile(extraPathsAndContents[i++], outputFile.getAbsolutePath()); + } zip(classesDir, jarPath); } -public static void createJar(String[] pathsAndContents, String jarPath, String compliance) throws IOException { - createJar(pathsAndContents, getCompileOptions(compliance), jarPath); +public static void createJar(String[] javaPathsAndContents, String jarPath, String compliance) throws IOException { + createJar(javaPathsAndContents, null, jarPath, compliance); +} +public static void createJar(String[] javaPathsAndContents, String[] extraPathsAndContents, String jarPath, String compliance) throws IOException { + createJar(javaPathsAndContents, extraPathsAndContents, getCompileOptions(compliance), jarPath); } public static void createSourceZip(String[] pathsAndContents, String zipPath) throws IOException { String sourcesPath = getOutputDirectory() + File.separator + "sources"; #P org.eclipse.jdt.core Index: batch/org/eclipse/jdt/internal/compiler/batch/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties,v retrieving revision 1.692 diff -u -r1.692 messages.properties --- batch/org/eclipse/jdt/internal/compiler/batch/messages.properties 8 Jan 2008 22:10:43 -0000 1.692 +++ batch/org/eclipse/jdt/internal/compiler/batch/messages.properties 10 Jan 2008 15:47:33 -0000 @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2007 IBM Corporation and others. +# Copyright (c) 2000, 2008 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -82,6 +82,8 @@ configure.incorrectVMVersionforAPT = Annotation processing got disabled, since it requires a 1.6 compliant JVM configure.incompatibleSourceForCldcTarget=Target level ''{0}'' is incompatible with source level ''{1}''. A source level ''1.3'' or lower is required configure.incompatibleComplianceForCldcTarget=Target level ''{0}'' is incompatible with compliance level ''{1}''. A compliance level ''1.4''or lower is required +configure.invalidClasspathSection = invalid Class-Path header in manifest of jar file: {0} +configure.multipleClasspathSections = multiple Class-Path headers in manifest of jar file: {0} ### requestor requestor.error = {0}. ERROR in {1} Index: batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java,v retrieving revision 1.43 diff -u -r1.43 ClasspathJar.java --- batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java 27 Apr 2007 15:51:38 -0000 1.43 +++ batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java 10 Jan 2008 15:47:32 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,11 +10,16 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.batch; +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -39,6 +44,166 @@ this.file = file; this.closeZipFileAtEnd = closeZipFileAtEnd; } + +// manifest file analyzer limited to Class-Path sections analysis +public static class ManifestAnalyzer { + private static final int + START = 0, + IN_CLASSPATH_HEADER = 1, // multistate + PAST_CLASSPATH_HEADER = 2, + SKIPPING_WHITESPACE = 3, + READING_JAR = 4, + CONTINUING = 5, + SKIP_LINE = 6; + private static final char[] CLASSPATH_HEADER_TOKEN = + "Class-Path:".toCharArray(); //$NON-NLS-1$ + private int ClasspathSectionsCount; + private ArrayList calledFilesNames; + public boolean analyzeManifestContents(Reader reader) throws IOException { + int state = START, substate = 0; + StringBuffer currentJarToken = new StringBuffer(); + int currentChar; + this.ClasspathSectionsCount = 0; + this.calledFilesNames = null; + for (;;) { + currentChar = reader.read(); + switch (state) { + case START: + if (currentChar == -1) { + return true; + } else if (currentChar == CLASSPATH_HEADER_TOKEN[0]) { + state = IN_CLASSPATH_HEADER; + substate = 1; + } else { + state = SKIP_LINE; + } + break; + case IN_CLASSPATH_HEADER: + if (currentChar == -1) { + return true; + } else if (currentChar == '\n') { + state = START; + } else if (currentChar != CLASSPATH_HEADER_TOKEN[substate++]) { + state = SKIP_LINE; + } else if (substate == CLASSPATH_HEADER_TOKEN.length) { + state = PAST_CLASSPATH_HEADER; + } + break; + case PAST_CLASSPATH_HEADER: + if (currentChar == ' ') { + state = SKIPPING_WHITESPACE; + this.ClasspathSectionsCount++; + } else { + return false; + } + break; + case SKIPPING_WHITESPACE: + if (currentChar == -1) { + return true; + } else if (currentChar == '\n') { + state = CONTINUING; + } else if (currentChar != ' ') { + currentJarToken.append((char) currentChar); + state = READING_JAR; + } + break; + case CONTINUING: + if (currentChar == -1) { + return true; + } else if (currentChar == '\n') { + state = START; + } else if (currentChar == ' ') { + state = SKIPPING_WHITESPACE; + } else if (currentChar == CLASSPATH_HEADER_TOKEN[0]) { + state = IN_CLASSPATH_HEADER; + substate = 1; + } else if (this.calledFilesNames == null) { + return false; + } else { + state = SKIP_LINE; + } + break; + case SKIP_LINE: + if (currentChar == -1) { + return true; + } else if (currentChar == '\n') { + state = START; + } + break; + case READING_JAR: + if (currentChar == -1) { + return false; + } else if (currentChar == '\n') { + // appends token below + state = CONTINUING; + } else if (currentChar == ' ') { + // appends token below + state = SKIPPING_WHITESPACE; + } else { + currentJarToken.append((char) currentChar); + break; + } + if (this.calledFilesNames == null) { + this.calledFilesNames = new ArrayList(); + } + this.calledFilesNames.add(currentJarToken.toString()); + currentJarToken.setLength(0); + break; + } + } + } + public int getClasspathSectionsCount() { + return this.ClasspathSectionsCount; + } + public List getCalledFileNames() { + return this.calledFilesNames; + } +} +public static final ManifestAnalyzer MANIFEST_ANALYZER = new ManifestAnalyzer(); + +public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) { + // expected to be called once only - if multiple calls desired, consider + // using a cache + BufferedReader reader = null; + try { + initialize(); + ArrayList result = new ArrayList(); + ZipEntry manifest = this.zipFile.getEntry("META-INF/MANIFEST.MF"); //$NON-NLS-1$ + if (manifest != null) { // non-null implies regular file + reader = new BufferedReader(new InputStreamReader(this.zipFile.getInputStream(manifest))); + boolean success = MANIFEST_ANALYZER.analyzeManifestContents(reader); + List calledFileNames = MANIFEST_ANALYZER.getCalledFileNames(); + if (problemReporter != null) { + if (!success || + MANIFEST_ANALYZER.getClasspathSectionsCount() == 1 && calledFileNames == null) { + problemReporter.invalidClasspathSection(this.getPath()); + } else if (MANIFEST_ANALYZER.getClasspathSectionsCount() > 1) { + problemReporter.multipleClasspathSections(this.getPath()); + } + } + if (calledFileNames != null) { + Iterator calledFilesIterator = calledFileNames.iterator(); + String directoryPath = this.getPath(); + int lastSeparator = directoryPath.lastIndexOf(File.separatorChar); + directoryPath = directoryPath.substring(0, lastSeparator + 1); // potentially empty (see bug 214731) + while (calledFilesIterator.hasNext()) { + result.add(new ClasspathJar(new File(directoryPath + (String) calledFilesIterator.next()), this.closeZipFileAtEnd, this.accessRuleSet, this.destinationPath)); + } + } + } + return result; + } catch (IOException e) { + return null; + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + // best effort + } + } + } +} public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) { return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false); } @@ -92,7 +257,9 @@ return null; } public void initialize() throws IOException { - this.zipFile = new ZipFile(this.file); + if (this.zipFile == null) { + this.zipFile = new ZipFile(this.file); + } } public boolean isPackage(String qualifiedPackageName) { if (this.packageCache != null) Index: batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java,v retrieving revision 1.48 diff -u -r1.48 FileSystem.java --- batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java 5 Jul 2007 13:52:50 -0000 1.48 +++ batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java 10 Jan 2008 15:47:32 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; @@ -31,6 +32,16 @@ NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly); boolean isPackage(String qualifiedPackageName); /** + * Return a list of the jar file names defined in the Class-Path section + * of the jar file manifest if any, null else. Only ClasspathJar (and + * extending classes) instances may return a non-null result. + * @param problemReporter problem reporter with which potential + * misconfiguration issues are raised + * @return a list of the jar file names defined in the Class-Path + * section of the jar file manifest if any + */ + List fetchLinkedJars(ClasspathSectionProblemReporter problemReporter); + /** * This method resets the environment. The resulting state is equivalent to * a new name environment without creating a new object. */ @@ -54,6 +65,10 @@ */ void initialize() throws IOException; } + public interface ClasspathSectionProblemReporter { + void invalidClasspathSection(String jarFilePath); + void multipleClasspathSections(String jarFilePath); + } /** * This class is defined how to normalize the classpath entries. Index: batch/org/eclipse/jdt/internal/compiler/batch/Main.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java,v retrieving revision 1.315 diff -u -r1.315 Main.java --- batch/org/eclipse/jdt/internal/compiler/batch/Main.java 3 Jan 2008 08:34:10 -0000 1.315 +++ batch/org/eclipse/jdt/internal/compiler/batch/Main.java 10 Jan 2008 15:47:33 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -33,6 +33,7 @@ import java.util.Date; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; @@ -1436,7 +1437,7 @@ addPendingErrors(this.bind("configure.incorrectClasspath", currentClasspathName));//$NON-NLS-1$ } } -private void addPendingErrors(String message) { +void addPendingErrors(String message) { if (this.pendingErrors == null) { this.pendingErrors = new ArrayList(); } @@ -2090,7 +2091,30 @@ } } } - return classpaths; + ArrayList result = new ArrayList(); + HashMap knownNames = new HashMap(); + FileSystem.ClasspathSectionProblemReporter problemReporter = + new FileSystem.ClasspathSectionProblemReporter() { + public void invalidClasspathSection(String jarFilePath) { + addPendingErrors(bind("configure.invalidClasspathSection", jarFilePath)); //$NON-NLS-1$ + } + public void multipleClasspathSections(String jarFilePath) { + addPendingErrors(bind("configure.multipleClasspathSections", jarFilePath)); //$NON-NLS-1$ + } + }; + while (! classpaths.isEmpty()) { + Classpath current = (Classpath) classpaths.remove(0); + String currentPath = current.getPath(); + if (knownNames.get(currentPath) == null) { + knownNames.put(currentPath, current); + result.add(current); + List linkedJars = current.fetchLinkedJars(problemReporter); + if (linkedJars != null) { + classpaths.addAll(0, linkedJars); + } + } + } + return result; } /* * External API Index: batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java,v retrieving revision 1.47 diff -u -r1.47 ClasspathDirectory.java --- batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java 24 Apr 2007 04:36:10 -0000 1.47 +++ batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java 10 Jan 2008 15:47:32 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,6 +14,7 @@ import java.io.FilenameFilter; import java.io.IOException; import java.util.Hashtable; +import java.util.List; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; @@ -81,6 +82,9 @@ return true; return false; } +public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) { + return null; +} public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) { return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false); }