Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 114417 Details for
Bug 198572
eclipse does not respect class-path manifest of external jars
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Proposed fix and regression tests
198572.txt (text/plain), 57.84 KB, created by
Jerome Lanneluc
on 2008-10-07 09:51:24 EDT
(
hide
)
Description:
Proposed fix and regression tests
Filename:
MIME Type:
Creator:
Jerome Lanneluc
Created:
2008-10-07 09:51:24 EDT
Size:
57.84 KB
patch
obsolete
>### 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 7 Oct 2008 13:41:13 -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 >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 7 Oct 2008 13:41:15 -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 7 Oct 2008 13:41:17 -0000 >@@ -2469,6 +2469,15 @@ > } > } > >+ public ClasspathChange resetResolvedClasspath() { >+ try { >+ return getPerProjectInfo().resetResolvedClasspath(); >+ } catch (JavaModelException e) { >+ // project doesn't exist >+ return null; >+ } >+ } >+ > /* > * Resolve the given raw classpath. > */ >@@ -2494,13 +2503,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 +2518,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 +2555,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 +2592,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. > */ >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 7 Oct 2008 13:41:16 -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 <code>IStatus.OK</code> 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 7 Oct 2008 13:41:17 -0000 >@@ -2178,7 +2178,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 7 Oct 2008 13:41:16 -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) { >@@ -1926,13 +1944,7 @@ > } > > // 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); >- } >+ elementsToRefresh = this.state.removeExternalElementsToRefresh(); > > // generate external archive change deltas > if (elementsToRefresh != null) { >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 7 Oct 2008 13:41:16 -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. > * </p> >+ * <p> >+ * 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}. >+ * </p> > * > * @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; >+ } >+} >#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 7 Oct 2008 13:41:21 -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 7 Oct 2008 13:41:20 -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 7 Oct 2008 13:41:19 -0000 >@@ -391,31 +391,45 @@ > ); > > } >+ 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); >+ if (pathAndContents != null && pathAndContents.length != 0) { >+ String sourceZipPath = projectLocation + File.separator + sourceZipName; >+ org.eclipse.jdt.core.tests.util.Util.createSourceZip(pathAndContents, 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 +892,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); > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 198572
:
114413
|
114414
|
114417
|
114534
|
114548