### Eclipse Workspace Patch 1.0
#P org.eclipse.jdt.core.tests.compiler
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.70
diff -u -r1.70 Util.java
--- src/org/eclipse/jdt/core/tests/util/Util.java 22 Sep 2008 15:04:25 -0000 1.70
+++ src/org/eclipse/jdt/core/tests/util/Util.java 8 Oct 2008 13:48:30 -0000
@@ -349,10 +349,12 @@
if (pathsAndContents != null) {
compile(pathsAndContents, options, classpath, 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());
+ if (extraPathsAndContents != null) {
+ 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);
}
#P org.eclipse.jdt.core.tests.model
Index: src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java,v
retrieving revision 1.141
diff -u -r1.141 ReconcilerTests.java
--- src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java 26 Sep 2008 10:20:16 -0000 1.141
+++ src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java 8 Oct 2008 13:48:32 -0000
@@ -309,10 +309,11 @@
"public class X {\n" +
"}",
},
+ null/*no non-Java resources*/,
new String[] {
"**/*"
},
- null,
+ null,
"1.4"
);
createJavaProject("P2", new String[] {"src"}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "bin");
Index: src/org/eclipse/jdt/core/tests/model/ClasspathTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java,v
retrieving revision 1.187
diff -u -r1.187 ClasspathTests.java
--- src/org/eclipse/jdt/core/tests/model/ClasspathTests.java 26 Sep 2008 09:01:25 -0000 1.187
+++ src/org/eclipse/jdt/core/tests/model/ClasspathTests.java 8 Oct 2008 13:48:31 -0000
@@ -2970,6 +2970,375 @@
}
}
/*
+ * Ensures that the extra libraries in the Class-Path: clause of a jar are taken into account.
+ */
+public void testExtraLibraries01() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addLibrary(p, "lib1.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createFile("/P/lib2.jar", "");
+ assertClasspathEquals(
+ p.getResolvedClasspath(true),
+ "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" +
+ ""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" +
+ "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
+ "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
+ );
+ } finally {
+ deleteProject("P");
+ }
+}
+/*
+ * Ensures that the extra libraries in the Class-Path: clause of a jar are taken into account.
+ */
+public void testExtraLibraries02() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addLibrary(p, "lib1.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar lib3.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createFile("/P/lib2.jar", "");
+ createFile("/P/lib3.jar", "");
+ assertClasspathEquals(
+ p.getResolvedClasspath(true),
+ "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" +
+ ""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" +
+ "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
+ "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
+ "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
+ );
+ } finally {
+ deleteProject("P");
+ }
+}
+/*
+ * Ensures that the extra libraries in the Class-Path: clause of a jar are taken into account.
+ */
+public void testExtraLibraries03() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ createFile("/P/lib3.jar", "");
+ createLibrary(p, "lib2.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib3.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ addLibrary(p, "lib1.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ assertClasspathEquals(
+ p.getResolvedClasspath(true),
+ "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" +
+ ""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" +
+ "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
+ "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
+ "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
+ );
+ } finally {
+ deleteProject("P");
+ }
+}
+/*
+ * Ensures that the extra libraries in the Class-Path: clause of a jar are taken into account.
+ */
+public void testExtraLibraries04() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addLibrary(p, "lib1.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createLibrary(p, "lib2.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib3.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createFile("/P/lib3.jar", "");
+ assertClasspathEquals(
+ p.getResolvedClasspath(true),
+ "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" +
+ ""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" +
+ "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
+ "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
+ "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
+ );
+ } finally {
+ deleteProject("P");
+ }
+}
+/*
+ * Ensures that no markers are created for correct extra libraries in the Class-Path: clause of a jar
+ */
+public void testExtraLibraries05() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addLibrary(p, "lib1.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createFile("/P/lib2.jar", "");
+ assertMarkers(
+ "Unexpected markers",
+ "",
+ p);
+ } finally {
+ deleteProject("P");
+ }
+}
+/*
+ * Ensures that a marker is created for incorrect extra libraries in the Class-Path: clause of a jar
+ */
+public void testExtraLibraries06() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addLibrary(p, "lib1.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ assertMarkers(
+ "Unexpected markers",
+ "Project \'P\' is missing required library: \'lib2.jar\'",
+ p);
+ } finally {
+ deleteProject("P");
+ }
+}
+/*
+ * Ensures that the extra libraries in the Class-Path: clause of an external jar are taken into account.
+ */
+public void testExtraLibraries07() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createExternalFile("lib2.jar", "");
+ assertClasspathEquals(
+ p.getResolvedClasspath(true),
+ "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" +
+ ""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" +
+ ""+ getExternalPath() + "lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
+ ""+ getExternalPath() + "lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
+ );
+ } finally {
+ deleteProject("P");
+ deleteExternalResource("lib1.jar");
+ deleteExternalResource("lib2.jar");
+ }
+}
+/*
+ * Ensures that no markers are created for correct extra libraries in the Class-Path: clause of an external jar
+ */
+public void testExtraLibraries08() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createExternalFile("lib2.jar", "");
+ refreshExternalArchives(p);
+ assertMarkers(
+ "Unexpected markers",
+ "",
+ p);
+ } finally {
+ deleteProject("P");
+ deleteExternalResource("lib1.jar");
+ deleteExternalResource("lib2.jar");
+ }
+}
+/*
+ * Ensures that a marker is created for incorrect extra libraries in the Class-Path: clause of an external jar
+ */
+public void testExtraLibraries09() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ assertMarkers(
+ "Unexpected markers",
+ "Project \'P\' is missing required library: \'"+ getExternalPath() + "lib2.jar\'",
+ p);
+ } finally {
+ deleteProject("P");
+ deleteExternalResource("lib1.jar");
+ deleteExternalResource("lib2.jar");
+ }
+}
+/*
+ * Ensures that a marker is created for incorrect extra libraries in the Class-Path: clause of an external jar
+ */
+public void testExtraLibraries10() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createExternalFile("lib2.jar", "");
+ refreshExternalArchives(p);
+ waitForAutoBuild(); // wait until classpath is validated -> no markers
+
+ deleteExternalResource("lib2.jar");
+ refreshExternalArchives(p);
+ assertMarkers(
+ "Unexpected markers",
+ "Project \'P\' is missing required library: \'"+ getExternalPath() + "lib2.jar\'",
+ p);
+ } finally {
+ deleteProject("P");
+ deleteExternalResource("lib1.jar");
+ deleteExternalResource("lib2.jar");
+ }
+}
+/*
+ * Ensures that the correct delta is reported when editing the Class-Path: clause of a jar
+ */
+public void testExtraLibraries11() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addLibrary(p, "lib1.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createFile("/P/lib2.jar", "");
+ startDeltas();
+ createLibrary(p, "lib1.jar", null, new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib3.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ assertDeltas(
+ "Unexpected delta",
+ "P[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" +
+ " lib1.jar[*]: {CONTENT | ARCHIVE CONTENT CHANGED}\n" +
+ " lib2.jar[*]: {REMOVED FROM CLASSPATH}"
+ );
+ } finally {
+ stopDeltas();
+ deleteProject("P");
+ }
+}
+/*
+ * Ensures that the correct delta is reported when editing the Class-Path: clause of an external jar
+ */
+public void testExtraLibraries12() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createExternalFile("lib2.jar", "");
+ refreshExternalArchives(p);
+
+ startDeltas();
+ org.eclipse.jdt.core.tests.util.Util.createJar(new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib3.jar\n",
+ },
+ getExternalResourcePath("lib1.jar"),
+ JavaCore.VERSION_1_4);
+ refreshExternalArchives(p);
+ assertDeltas(
+ "Unexpected delta",
+ "P[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" +
+ " "+ getExternalPath() + "lib1.jar[*]: {CONTENT | ARCHIVE CONTENT CHANGED}\n" +
+ " "+ getExternalPath() + "lib2.jar[*]: {REMOVED FROM CLASSPATH}"
+ );
+ } finally {
+ stopDeltas();
+ deleteProject("P");
+ deleteExternalResource("lib1.jar");
+ deleteExternalResource("lib2.jar");
+ }
+}
+/*
+ * Ensures that the correct delta is reported when removing an external jar with a Class-Path: clause
+ */
+public void testExtraLibraries13() throws Exception {
+ try {
+ IJavaProject p = createJavaProject("P");
+ addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0],
+ new String[] {
+ "META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n" +
+ "Class-Path: lib2.jar\n",
+ },
+ JavaCore.VERSION_1_4);
+ createExternalFile("lib2.jar", "");
+ refreshExternalArchives(p);
+
+ startDeltas();
+ deleteExternalResource("lib1.jar");
+ refreshExternalArchives(p);
+ assertDeltas(
+ "Unexpected delta",
+ "P[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" +
+ " "+ getExternalPath() + "lib1.jar[-]: {}\n" +
+ " "+ getExternalPath() + "lib2.jar[*]: {REMOVED FROM CLASSPATH}"
+ );
+ } finally {
+ stopDeltas();
+ deleteProject("P");
+ deleteExternalResource("lib1.jar");
+ deleteExternalResource("lib2.jar");
+ }
+}
+/*
* Ensures that a marker is removed if adding an internal jar that is on the classpath in another project
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=213723 )
*/
Index: src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java,v
retrieving revision 1.222
diff -u -r1.222 AbstractJavaModelTests.java
--- src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java 26 Sep 2008 09:01:25 -0000 1.222
+++ src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java 8 Oct 2008 13:48:31 -0000
@@ -391,31 +391,47 @@
);
}
+ protected void addExternalLibrary(IJavaProject javaProject, String jarPath, String[] pathAndContents, String[] nonJavaResources, String compliance) throws Exception {
+ org.eclipse.jdt.core.tests.util.Util.createJar(pathAndContents, nonJavaResources, jarPath, compliance);
+ addLibraryEntry(javaProject, new Path(jarPath), true/*exported*/);
+ }
protected void addLibrary(String jarName, String sourceZipName, String[] pathAndContents, String compliance) throws CoreException, IOException {
- addLibrary(this.currentProject, jarName, sourceZipName, pathAndContents, null, null, compliance);
+ addLibrary(this.currentProject, jarName, sourceZipName, pathAndContents, null/*no non-Java resources*/, null, null, compliance);
}
protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String compliance) throws CoreException, IOException {
- addLibrary(javaProject, jarName, sourceZipName, pathAndContents, null, null, compliance);
+ addLibrary(javaProject, jarName, sourceZipName, pathAndContents, null/*no non-Java resources*/, null, null, compliance);
}
- protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] librariesInclusionPatterns, String[] librariesExclusionPatterns, String compliance) throws CoreException, IOException {
- IProject project = javaProject.getProject();
- String projectLocation = project.getLocation().toOSString();
- String jarPath = projectLocation + File.separator + jarName;
- String sourceZipPath = projectLocation + File.separator + sourceZipName;
- org.eclipse.jdt.core.tests.util.Util.createJar(pathAndContents, jarPath, compliance);
- org.eclipse.jdt.core.tests.util.Util.createSourceZip(pathAndContents, sourceZipPath);
- project.refreshLocal(IResource.DEPTH_INFINITE, null);
+ protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] nonJavaResources, String compliance) throws CoreException, IOException {
+ addLibrary(javaProject, jarName, sourceZipName, pathAndContents, nonJavaResources, null, null, compliance);
+ }
+ protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] nonJavaResources, String[] librariesInclusionPatterns, String[] librariesExclusionPatterns, String compliance) throws CoreException, IOException {
+ IProject project = createLibrary(javaProject, jarName, sourceZipName, pathAndContents, nonJavaResources, compliance);
String projectPath = '/' + project.getName() + '/';
addLibraryEntry(
javaProject,
new Path(projectPath + jarName),
- new Path(projectPath + sourceZipName),
+ sourceZipName == null ? null : new Path(projectPath + sourceZipName),
null,
toIPathArray(librariesInclusionPatterns),
toIPathArray(librariesExclusionPatterns),
true
);
}
+
+ protected IProject createLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] nonJavaResources, String compliance) throws IOException, CoreException {
+ IProject project = javaProject.getProject();
+ String projectLocation = project.getLocation().toOSString();
+ String jarPath = projectLocation + File.separator + jarName;
+ org.eclipse.jdt.core.tests.util.Util.createJar(pathAndContents, nonJavaResources, jarPath, compliance);
+ touch(new File(jarPath));
+ if (pathAndContents != null && pathAndContents.length != 0) {
+ String sourceZipPath = projectLocation + File.separator + sourceZipName;
+ org.eclipse.jdt.core.tests.util.Util.createSourceZip(pathAndContents, sourceZipPath);
+ touch(new File(sourceZipPath));
+ }
+ project.refreshLocal(IResource.DEPTH_INFINITE, null);
+ return project;
+ }
protected void addLibraryEntry(String path, boolean exported) throws JavaModelException {
addLibraryEntry(this.currentProject, new Path(path), null, null, null, null, exported);
}
@@ -878,7 +894,7 @@
actual = buffer.toString();
}
if (!actual.equals(expected)) {
- System.out.print(org.eclipse.jdt.core.tests.util.Util.displayString(actual, 2));
+ System.out.print(displayString(actual, 2));
}
assertEquals(expected, actual);
}
#P org.eclipse.jdt.core
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.46
diff -u -r1.46 ClasspathJar.java
--- batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java 27 Jun 2008 16:04:12 -0000 1.46
+++ batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java 8 Oct 2008 13:48:33 -0000
@@ -14,7 +14,6 @@
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;
@@ -28,6 +27,7 @@
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.ManifestAnalyzer;
import org.eclipse.jdt.internal.compiler.util.Util;
public class ClasspathJar extends ClasspathLocation {
@@ -44,120 +44,6 @@
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) {
Index: model/org/eclipse/jdt/internal/core/JavaProject.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java,v
retrieving revision 1.416
diff -u -r1.416 JavaProject.java
--- model/org/eclipse/jdt/internal/core/JavaProject.java 1 Oct 2008 16:33:13 -0000 1.416
+++ model/org/eclipse/jdt/internal/core/JavaProject.java 8 Oct 2008 13:48:35 -0000
@@ -1848,7 +1848,7 @@
resolvedClasspath = perProjectInfo.getResolvedClasspath();
if (resolvedClasspath == null) {
// another thread reset the resolved classpath, use a temporary PerProjectInfo
- PerProjectInfo temporaryInfo = new PerProjectInfo(getProject());
+ PerProjectInfo temporaryInfo = newTemporaryInfo();
resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
resolvedClasspath = temporaryInfo.getResolvedClasspath();
}
@@ -1884,7 +1884,7 @@
}
if (resolvedClasspath == null) {
// another thread reset the resolved classpath, use a temporary PerProjectInfo
- PerProjectInfo temporaryInfo = new PerProjectInfo(getProject());
+ PerProjectInfo temporaryInfo = newTemporaryInfo();
resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
resolvedClasspath = temporaryInfo.getResolvedClasspath();
unresolvedEntryStatus = temporaryInfo.unresolvedEntryStatus;
@@ -2251,6 +2251,19 @@
return new SearchableEnvironment(this, owner);
}
+ /*
+ * Returns a PerProjectInfo that doesn't register classpath change
+ * and that should be used as a temporary info.
+ */
+ public PerProjectInfo newTemporaryInfo() {
+ return
+ new PerProjectInfo(this.project.getProject()) {
+ protected ClasspathChange addClasspathChange() {
+ return null;
+ }
+ };
+ }
+
/**
* @see IJavaProject
*/
@@ -2469,6 +2482,15 @@
}
}
+ public ClasspathChange resetResolvedClasspath() {
+ try {
+ return getPerProjectInfo().resetResolvedClasspath();
+ } catch (JavaModelException e) {
+ // project doesn't exist
+ return null;
+ }
+ }
+
/*
* Resolve the given raw classpath.
*/
@@ -2494,13 +2516,12 @@
IClasspathEntry rawEntry = rawClasspath[i];
IClasspathEntry resolvedEntry = rawEntry;
- IPath resolvedPath;
switch (rawEntry.getEntryKind()){
case IClasspathEntry.CPE_VARIABLE :
try {
- resolvedEntry = manager.getResolvedClasspathEntry(rawEntry, usePreviousSession);
+ resolvedEntry = manager.resolveVariableEntry(rawEntry, usePreviousSession);
} catch (ClasspathEntry.AssertionFailedException e) {
// Catch the assertion failure and set status instead
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
@@ -2510,14 +2531,14 @@
if (resolvedEntry == null) {
result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath());
} else {
- if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
- result.rawReverseMap.put(resolvedPath , rawEntry);
- result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
- }
- resolvedEntries.add(resolvedEntry);
- if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
- externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
+ if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
+ // resolve Class-Path: in manifest
+ ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
+ for (int j = 0, length2 = extraEntries.length; j < length2; j++) {
+ addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager);
+ }
}
+ addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
}
break;
@@ -2547,34 +2568,36 @@
}
// if container is exported or restricted, then its nested entries must in turn be exported (21749) and/or propagate restrictions
cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
- // resolve ".." in library path
+
if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
+ // resolve ".." in library path
cEntry = cEntry.resolvedDotDot();
+
+ // resolve Class-Path: in manifest
+ ClasspathEntry[] extraEntries = cEntry.resolvedChainedLibraries();
+ for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
+ addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager);
+ }
}
- if (result.rawReverseMap.get(resolvedPath = cEntry.getPath()) == null) {
- result.rawReverseMap.put(resolvedPath , rawEntry);
- result.rootPathToResolvedEntries.put(resolvedPath, cEntry);
- }
- resolvedEntries.add(cEntry);
- if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
- externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
- }
+ addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager);
}
break;
case IClasspathEntry.CPE_LIBRARY:
+ // resolve ".." in library path
resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot();
- // $FALL-THROUGH$ use the default code below
- default :
- if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
- result.rawReverseMap.put(resolvedPath , rawEntry);
- result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
- }
- resolvedEntries.add(resolvedEntry);
- if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
- externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
+
+ // resolve Class-Path: in manifest
+ ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
+ for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
+ addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager);
}
+ addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
+ break;
+ default :
+ addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
+ break;
}
}
result.resolvedClasspath = new IClasspathEntry[resolvedEntries.size()];
@@ -2582,6 +2605,18 @@
return result;
}
+ private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, ArrayList resolvedEntries, ExternalFoldersManager externalFoldersManager) {
+ IPath resolvedPath;
+ if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
+ result.rawReverseMap.put(resolvedPath, rawEntry);
+ result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
+ }
+ resolvedEntries.add(resolvedEntry);
+ if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
+ externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
+ }
+ }
+
/*
* Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo.
*/
@@ -2620,7 +2655,7 @@
breakpoint(3, this);
}
}
-
+
/**
* Answers an ID which is used to distinguish project/entries during package
* fragment root computations
Index: model/org/eclipse/jdt/internal/core/ClasspathEntry.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java,v
retrieving revision 1.104
diff -u -r1.104 ClasspathEntry.java
--- model/org/eclipse/jdt/internal/core/ClasspathEntry.java 26 Sep 2008 09:01:23 -0000 1.104
+++ model/org/eclipse/jdt/internal/core/ClasspathEntry.java 8 Oct 2008 13:48:34 -0000
@@ -10,16 +10,24 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
@@ -44,6 +52,7 @@
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.AccessRule;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.util.ManifestAnalyzer;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
import org.w3c.dom.DOMException;
@@ -133,6 +142,8 @@
private IPath[] exclusionPatterns;
private char[][] fullExclusionPatternChars;
private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
+ private final static ClasspathEntry[] NO_ENTRIES = new ClasspathEntry[0];
+ private final static IPath[] NO_PATHS = new IPath[0];
private boolean combineAccessRules;
@@ -848,6 +859,74 @@
}
/*
+ * Read the Class-Path clause of the manifest of the jar pointed by this path, and return
+ * the corresponding paths.
+ */
+ public static IPath[] resolvedChainedLibraries(IPath jarPath) {
+ ArrayList result = new ArrayList();
+ resolvedChainedLibraries(jarPath, new HashSet(), result);
+ if (result.size() == 0)
+ return NO_PATHS;
+ return (IPath[]) result.toArray(new IPath[result.size()]);
+ }
+
+ private static void resolvedChainedLibraries(IPath jarPath, HashSet visited, ArrayList result) {
+ if (visited.contains( jarPath))
+ return;
+ visited.add(jarPath);
+ Object target = JavaModel.getTarget(jarPath, true/*check existence, otherwise the manifest cannot be read*/);
+ if (target instanceof IFile || target instanceof File) {
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ ZipFile zip = null;
+ BufferedReader reader = null;
+ try {
+ zip = manager.getZipFile(jarPath);
+ ZipEntry manifest = zip.getEntry("META-INF/MANIFEST.MF"); //$NON-NLS-1$
+ if (manifest != null) { // non-null implies regular file
+ reader = new BufferedReader(new InputStreamReader(zip.getInputStream(manifest)));
+ ManifestAnalyzer analyzer = new ManifestAnalyzer();
+ boolean success = analyzer.analyzeManifestContents(reader);
+ List calledFileNames = analyzer.getCalledFileNames();
+ if (!success || analyzer.getClasspathSectionsCount() == 1 && calledFileNames == null) {
+ Util.log(IStatus.WARNING, "Invalid Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
+ return;
+ } else if (analyzer.getClasspathSectionsCount() > 1) {
+ Util.log(IStatus.WARNING, "Multiple Class-Path headers in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
+ return;
+ }
+ if (calledFileNames != null) {
+ Iterator calledFilesIterator = calledFileNames.iterator();
+ IPath directoryPath = jarPath.removeLastSegments(1);
+ while (calledFilesIterator.hasNext()) {
+ String calledFileName = (String) calledFilesIterator.next();
+ if (!directoryPath.isValidPath(calledFileName)) {
+ Util.log(IStatus.WARNING, "Invalid Class-Path entry " + calledFileName + " in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ IPath calledJar = directoryPath.append(new Path(calledFileName));
+ resolvedChainedLibraries(calledJar, visited, result);
+ result.add(calledJar);
+ }
+ }
+ }
+ }
+ } catch (CoreException e) {
+ // not a zip file
+ } catch (IOException e) {
+ Util.log(e, "Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
+ } finally {
+ manager.closeZipFile(zip);
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // best effort
+ }
+ }
+ }
+ }
+ }
+
+ /*
* Resolves the ".." in the given path. Returns the given path if it contains no ".." segment.
*/
public static IPath resolveDotDot(IPath path) {
@@ -1163,7 +1242,11 @@
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
- buffer.append(String.valueOf(getPath()));
+ Object target = JavaModel.getTarget(getPath(), true);
+ if (target instanceof File)
+ buffer.append(getPath().toOSString());
+ else
+ buffer.append(String.valueOf(getPath()));
buffer.append('[');
switch (getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY :
@@ -1278,6 +1361,34 @@
this.extraAttributes);
}
+ /*
+ * Read the Class-Path clause of the manifest of the jar pointed by this entry, and return
+ * the corresponding library entries.
+ */
+ public ClasspathEntry[] resolvedChainedLibraries() {
+ IPath[] paths = resolvedChainedLibraries(getPath());
+ int length = paths.length;
+ if (length == 0)
+ return NO_ENTRIES;
+ ClasspathEntry[] result = new ClasspathEntry[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = new ClasspathEntry(
+ getContentKind(),
+ getEntryKind(),
+ paths[i],
+ this.inclusionPatterns,
+ this.exclusionPatterns,
+ getSourceAttachmentPath(),
+ getSourceAttachmentRootPath(),
+ getOutputLocation(),
+ this.isExported,
+ getAccessRules(),
+ this.combineAccessRules,
+ this.extraAttributes);
+ }
+ return result;
+ }
+
/**
* Answers an ID which is used to distinguish entries during package
* fragment root computations
@@ -1614,7 +1725,7 @@
*
* @param project the given java project
* @param entry the given classpath entry
- * @param checkSourceAttachment a flag to determine if source attachement should be checked
+ * @param checkSourceAttachment a flag to determine if source attachment should be checked
* @param recurseInContainers flag indicating whether validation should be applied to container entries recursively
* @return a java model status describing the problem related to this classpath entry if any, a status object with code IStatus.OK
if the entry is fine
*/
@@ -1625,8 +1736,7 @@
// Build some common strings for status message
String projectName = project.getElementName();
- boolean pathStartsWithProject = projectName.equals(path.segment(0));
- String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
+ String entryPathMsg = projectName.equals(path.segment(0)) ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
switch(entry.getEntryKind()){
@@ -1719,56 +1829,19 @@
// library entry check
case IClasspathEntry.CPE_LIBRARY :
path = ClasspathEntry.resolveDotDot(path);
- if (path.isAbsolute() && !path.isEmpty()) {
- IPath sourceAttachment = entry.getSourceAttachmentPath();
- Object target = JavaModel.getTarget(path, true);
- if (target != null && !JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) {
- long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
- long libraryJDK = Util.getJdkLevel(target);
- if (libraryJDK != 0 && libraryJDK > projectTargetJDK) {
- return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(libraryJDK));
- }
- }
- if (target instanceof IResource){
- IResource resolvedResource = (IResource) target;
- switch(resolvedResource.getType()){
- case IResource.FILE :
- if (checkSourceAttachment
- && sourceAttachment != null
- && !sourceAttachment.isEmpty()
- && JavaModel.getTarget(sourceAttachment, true) == null){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName}));
- }
- break;
- case IResource.FOLDER : // internal binary folder
- if (checkSourceAttachment
- && sourceAttachment != null
- && !sourceAttachment.isEmpty()
- && JavaModel.getTarget(sourceAttachment, true) == null){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName}));
- }
- }
- } else if (target instanceof File){
- File file = JavaModel.getFile(target);
- if (file == null) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalExternalFolder, new String[] {path.toOSString(), projectName}));
- } else if (checkSourceAttachment
- && sourceAttachment != null
- && !sourceAttachment.isEmpty()
- && JavaModel.getTarget(sourceAttachment, true) == null){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toOSString(), projectName}));
- }
- } else {
- boolean isExternal = path.getDevice() != null || !workspaceRoot.getProject(path.segment(0)).exists();
- if (isExternal) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {path.toOSString(), projectName}));
- } else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {entryPathMsg, projectName}));
- }
- }
- } else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryPath, new String[] {entryPathMsg, projectName}));
- }
+
+ // resolve Class-Path: in manifest
+ IPath[] chainedJars = ClasspathEntry.resolvedChainedLibraries(path);
+ for (int i = 0, length = chainedJars.length; i < length; i++) {
+ IPath chainedJar = chainedJars[i];
+ IJavaModelStatus status = validateLibraryEntry(chainedJar, project, null/*don't check source attachment*/, null/*force computing of entryPathMsg*/);
+ if (!status.isOK())
+ return status;
+ }
+
+ IJavaModelStatus status = validateLibraryEntry(path, project, checkSourceAttachment ? entry.getSourceAttachmentPath() : null, entryPathMsg);
+ if (!status.isOK())
+ return status;
break;
// project entry check
@@ -1834,4 +1907,58 @@
return JavaModelStatus.VERIFIED_OK;
}
+
+ private static IJavaModelStatus validateLibraryEntry(IPath path, IJavaProject project, IPath sourceAttachment, String entryPathMsg) {
+ if (path.isAbsolute() && !path.isEmpty()) {
+ Object target = JavaModel.getTarget(path, true);
+ if (target != null && !JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) {
+ long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
+ long libraryJDK = Util.getJdkLevel(target);
+ if (libraryJDK != 0 && libraryJDK > projectTargetJDK) {
+ return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(libraryJDK));
+ }
+ }
+ if (target instanceof IResource){
+ IResource resolvedResource = (IResource) target;
+ switch(resolvedResource.getType()){
+ case IResource.FILE :
+ if (sourceAttachment != null
+ && !sourceAttachment.isEmpty()
+ && JavaModel.getTarget(sourceAttachment, true) == null){
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), project.getElementName()}));
+ }
+ break;
+ case IResource.FOLDER : // internal binary folder
+ if (sourceAttachment != null
+ && !sourceAttachment.isEmpty()
+ && JavaModel.getTarget(sourceAttachment, true) == null){
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), project.getElementName()}));
+ }
+ }
+ } else if (target instanceof File){
+ File file = JavaModel.getFile(target);
+ if (file == null) {
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalExternalFolder, new String[] {path.toOSString(), project.getElementName()}));
+ } else if (sourceAttachment != null
+ && !sourceAttachment.isEmpty()
+ && JavaModel.getTarget(sourceAttachment, true) == null){
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toOSString(), project.getElementName()}));
+ }
+ } else {
+ boolean isExternal = path.getDevice() != null || !ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0)).exists();
+ if (isExternal) {
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {path.toOSString(), project.getElementName()}));
+ } else {
+ if (entryPathMsg == null)
+ entryPathMsg = project.getElementName().equals(path.segment(0)) ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {entryPathMsg, project.getElementName()}));
+ }
+ }
+ } else {
+ if (entryPathMsg == null)
+ entryPathMsg = project.getElementName().equals(path.segment(0)) ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryPath, new String[] {entryPathMsg, project.getElementName()}));
+ }
+ return JavaModelStatus.VERIFIED_OK;
+ }
}
Index: model/org/eclipse/jdt/internal/core/JavaModelManager.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java,v
retrieving revision 1.413
diff -u -r1.413 JavaModelManager.java
--- model/org/eclipse/jdt/internal/core/JavaModelManager.java 26 Sep 2008 10:20:18 -0000 1.413
+++ model/org/eclipse/jdt/internal/core/JavaModelManager.java 8 Oct 2008 13:48:35 -0000
@@ -1098,10 +1098,7 @@
}
private ClasspathChange setClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus) {
- // remember old info
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- DeltaProcessor deltaProcessor = manager.deltaState.getDeltaProcessor();
- ClasspathChange classpathChange = deltaProcessor.addClasspathChange(this.project, this.rawClasspath, this.outputLocation, this.resolvedClasspath);
+ ClasspathChange classpathChange = addClasspathChange();
this.rawClasspath = newRawClasspath;
this.outputLocation = newOutputLocation;
@@ -1115,6 +1112,14 @@
return classpathChange;
}
+ protected ClasspathChange addClasspathChange() {
+ // remember old info
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ DeltaProcessor deltaProcessor = manager.deltaState.getDeltaProcessor();
+ ClasspathChange classpathChange = deltaProcessor.addClasspathChange(this.project, this.rawClasspath, this.outputLocation, this.resolvedClasspath);
+ return classpathChange;
+ }
+
public synchronized ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) {
this.rawTimeStamp++;
return setClasspath(newRawClasspath, newOutputLocation, newRawClasspathStatus, null/*resolved classpath*/, null/*root to raw map*/, null/*root to resolved map*/, null/*unresolved status*/);
@@ -2178,7 +2183,7 @@
return containerIDs;
}
- public IClasspathEntry getResolvedClasspathEntry(IClasspathEntry entry, boolean usePreviousSession) {
+ public IClasspathEntry resolveVariableEntry(IClasspathEntry entry, boolean usePreviousSession) {
if (entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE)
return entry;
Index: model/org/eclipse/jdt/internal/core/DeltaProcessor.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java,v
retrieving revision 1.329
diff -u -r1.329 DeltaProcessor.java
--- model/org/eclipse/jdt/internal/core/DeltaProcessor.java 9 Sep 2008 14:53:17 -0000 1.329
+++ model/org/eclipse/jdt/internal/core/DeltaProcessor.java 8 Oct 2008 13:48:34 -0000
@@ -313,7 +313,7 @@
* In all cases, add the project's dependents to the list of projects to update
* so that the classpath related markers can be updated.
*/
- private void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
+ private void checkProjectsAndClasspathChanges(IResourceDelta delta) {
IResource resource = delta.getResource();
IResourceDelta[] children = null;
@@ -438,12 +438,19 @@
}
break;
+ case IResource.FOLDER:
+ if (delta.getKind() == IResourceDelta.CHANGED) { // look for .jar file change to update classpath
+ children = delta.getAffectedChildren();
+ }
+ break;
case IResource.FILE :
IFile file = (IFile) resource;
- /* classpath file change */
+ int kind = delta.getKind();
+ RootInfo rootInfo;
if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
+ /* classpath file change */
this.manager.forceBatchInitializations(false/*not initAfterLoad*/);
- switch (delta.getKind()) {
+ switch (kind) {
case IResourceDelta.CHANGED :
int flags = delta.getFlags();
if ((flags & IResourceDelta.CONTENT) == 0 // only consider content change
@@ -463,13 +470,17 @@
break;
}
this.state.rootsAreStale = true;
+ } else if ((rootInfo = rootInfo(file.getFullPath(), kind)) != null && rootInfo.entryKind == IClasspathEntry.CPE_LIBRARY) {
+ javaProject = (JavaProject)JavaCore.create(file.getProject());
+ javaProject.resetResolvedClasspath();
+ this.state.rootsAreStale = true;
}
break;
}
if (children != null) {
for (int i = 0; i < children.length; i++) {
- checkProjectsBeingAddedOrRemoved(children[i]);
+ checkProjectsAndClasspathChanges(children[i]);
}
}
}
@@ -815,15 +826,15 @@
javaProject = (JavaProject) JavaCore.create(project);
try {
classpath = javaProject.getResolvedClasspath();
+ for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
+ if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
+ archivePathsToRefresh.add(classpath[k].getPath());
+ }
+ }
} catch (JavaModelException e2) {
// project doesn't exist -> ignore
continue;
}
- for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
- if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
- archivePathsToRefresh.add(classpath[k].getPath());
- }
- }
}
break;
}
@@ -852,7 +863,6 @@
}
for (int j = 0; j < entries.length; j++){
if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
-
IPath entryPath = entries[j].getPath();
if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
@@ -919,6 +929,7 @@
System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
elementAdded(root, null, null);
+ javaProject.resetResolvedClasspath(); // in case it contains a chained jar
this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
hasDelta = true;
} else if (status == EXTERNAL_JAR_CHANGED) {
@@ -927,6 +938,7 @@
System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
contentChanged(root);
+ javaProject.resetResolvedClasspath(); // in case it contains a chained jar
hasDelta = true;
} else if (status == EXTERNAL_JAR_REMOVED) {
PackageFragmentRoot root = (PackageFragmentRoot) javaProject.getPackageFragmentRoot(entryPath.toString());
@@ -934,6 +946,7 @@
System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
elementRemoved(root, null, null);
+ javaProject.resetResolvedClasspath(); // in case it contains a chained jar
this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
hasDelta = true;
}
@@ -1894,7 +1907,12 @@
try {
try {
stopDeltas();
- checkProjectsBeingAddedOrRemoved(delta);
+ checkProjectsAndClasspathChanges(delta);
+
+ // generate external archive change deltas
+ if (elementsToRefresh != null) {
+ createExternalArchiveDelta(elementsToRefresh, null);
+ }
// generate classpath change deltas
if (this.classpathChanges.size() > 0) {
@@ -1920,25 +1938,16 @@
this.state.addExternalFolderChange(change.project, change.oldResolvedClasspath);
}
}
+ // process late coming external elements to refresh (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769 )
+ elementsToRefresh = this.state.removeExternalElementsToRefresh();
+ if (elementsToRefresh != null) {
+ hasDelta |= createExternalArchiveDelta(elementsToRefresh, null);
+ }
this.classpathChanges.clear();
if (!hasDelta)
this.currentDelta = null;
}
- // add late coming elements to refresh (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769 )
- if (elementsToRefresh == null) {
- elementsToRefresh = this.state.removeExternalElementsToRefresh();
- } else {
- HashSet newElementsToRefresh = this.state.removeExternalElementsToRefresh();
- if (newElementsToRefresh != null)
- elementsToRefresh.addAll(newElementsToRefresh);
- }
-
- // generate external archive change deltas
- if (elementsToRefresh != null) {
- createExternalArchiveDelta(elementsToRefresh, null);
- }
-
// generate Java deltas from resource changes
IJavaElementDelta translatedDelta = processResourceDelta(delta);
if (translatedDelta != null) {
Index: model/org/eclipse/jdt/internal/core/ClasspathChange.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java,v
retrieving revision 1.21
diff -u -r1.21 ClasspathChange.java
--- model/org/eclipse/jdt/internal/core/ClasspathChange.java 3 Oct 2008 11:11:37 -0000 1.21
+++ model/org/eclipse/jdt/internal/core/ClasspathChange.java 8 Oct 2008 13:48:34 -0000
@@ -226,7 +226,7 @@
if (newResolvedClasspath == null) {
// another thread reset the resolved classpath, use a temporary PerProjectInfo
- PerProjectInfo temporaryInfo = new PerProjectInfo(this.project.getProject());
+ PerProjectInfo temporaryInfo = this.project.newTemporaryInfo();
this.project.resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
newRawClasspath = temporaryInfo.rawClasspath;
newResolvedClasspath = temporaryInfo.getResolvedClasspath();
Index: model/org/eclipse/jdt/core/JavaCore.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java,v
retrieving revision 1.627
diff -u -r1.627 JavaCore.java
--- model/org/eclipse/jdt/core/JavaCore.java 3 Oct 2008 08:39:29 -0000 1.627
+++ model/org/eclipse/jdt/core/JavaCore.java 8 Oct 2008 13:48:34 -0000
@@ -3234,7 +3234,7 @@
* if the given variable entry could not be resolved to a valid classpath entry
*/
public static IClasspathEntry getResolvedClasspathEntry(IClasspathEntry entry) {
- return JavaModelManager.getJavaModelManager().getResolvedClasspathEntry(entry, false/*don't use previous session value*/);
+ return JavaModelManager.getJavaModelManager().resolveVariableEntry(entry, false/*don't use previous session value*/);
}
@@ -3929,6 +3929,10 @@
* accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
* with the non accessible files patterns of the project.
*
+ * Since 3.5, if the libray is a ZIP archive, the "Class-Path" clause (if any) in the "META-INF/MANIFEST.MF" is read + * and referenced ZIP archives are added to the {@link IJavaProject#getResolvedClasspath(boolean) resolved classpath}. + *
* * @param path the path to the library * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, Index: compiler/org/eclipse/jdt/internal/compiler/util/ManifestAnalyzer.java =================================================================== RCS file: compiler/org/eclipse/jdt/internal/compiler/util/ManifestAnalyzer.java diff -N compiler/org/eclipse/jdt/internal/compiler/util/ManifestAnalyzer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ compiler/org/eclipse/jdt/internal/compiler/util/ManifestAnalyzer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,130 @@ +/******************************************************************************* + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.util; + +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +public 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' || currentChar == '\r') { + // 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; + } +}