### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/core/IClasspathEntry.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java,v retrieving revision 1.65 diff -u -r1.65 IClasspathEntry.java --- model/org/eclipse/jdt/core/IClasspathEntry.java 27 Jun 2008 16:04:00 -0000 1.65 +++ model/org/eclipse/jdt/core/IClasspathEntry.java 18 Feb 2010 09:48:58 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 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 @@ -418,6 +418,48 @@ */ IPath getSourceAttachmentRootPath(); + + /** + * Returns the library entry that is referencing this classpath entry. For CPE_LIBRARY, + * return value is the entry that is representing the jar that includes this + * in the MANIFEST file's Class-Path section. For entry kinds other than CPE_LIBRARY, + * this returns null. + * + * @return the classpath entry that is referencing this entry or null if + * not applicable. + * @since 3.6 + */ + IClasspathEntry getReferencingEntry(); + + /** + * Returns an array of classpath entries that are referenced by this. For the entry + * kind CPE_LIBRARY, the method returns the libraries that are included in the Class-Path + * clause of the MANIFEST file. For other entry kinds, this method returns an empty array. + * If a referenced library is already part of the raw classpath of the project, it will not be + * included in the returned list. + *

+ * The referenced libraries attached to a particular classpath entry depends on the following + * factors apart from the MANIFEST entries: + *

  • The order in which this entry appears in the raw classpath of a project - when a same + * (referenced) library is referenced by more than one library {@link #CPE_LIBRARY}, the + * referenced library is attached only to the first raw classpath entry and not to the latter + * ones. For instance, if there are two library entries in the raw classpath and both include + * the same set of jars in the MANIFEST, then the first entry will get all the referenced jars + * while the second gets none.
  • + *
  • If a referenced library is directly part of the raw classpath, it does not get added + * as referenced library to any entry.
  • + *

    + *

    + * The referenced libraries themselves will not have any further referenced entries. The order of the + * referenced entries will be the order in which they are specified in the MANIFEST file. + *

    + * + * @return the array of classpath entries that this entry makes references to. If there are none + * returns an empty array. + * @since 3.6 + */ + IClasspathEntry[] getReferencedEntries(); + /** * Returns whether this entry is exported to dependent projects. * Always returns false for source entries (kind 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.123 diff -u -r1.123 ClasspathEntry.java --- model/org/eclipse/jdt/internal/core/ClasspathEntry.java 1 Feb 2010 11:13:25 -0000 1.123 +++ model/org/eclipse/jdt/internal/core/ClasspathEntry.java 18 Feb 2010 09:49:00 -0000 @@ -92,6 +92,8 @@ public static final String TAG_COMBINE_ACCESS_RULES = "combineaccessrules"; //$NON-NLS-1$ public static final String TAG_ACCESS_RULES = "accessrules"; //$NON-NLS-1$ public static final String TAG_ACCESS_RULE = "accessrule"; //$NON-NLS-1$ + public static final String TAG_REFERENCES = "references"; //$NON-NLS-1$ + public static final String TAG_REFERENCE = "reference"; //$NON-NLS-1$ public static final String TAG_PATTERN = "pattern"; //$NON-NLS-1$ public static final String TAG_ACCESSIBLE = "accessible"; //$NON-NLS-1$ public static final String TAG_NON_ACCESSIBLE = "nonaccessible"; //$NON-NLS-1$ @@ -141,7 +143,7 @@ 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]; + public final static ClasspathEntry[] NO_ENTRIES = new ClasspathEntry[0]; private final static IPath[] NO_PATHS = new IPath[0]; private final static IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); @@ -197,6 +199,11 @@ * a non-null value. */ public IPath sourceAttachmentRootPath; + + public IClasspathEntry[] referencedEntries; + + public IClasspathEntry referencingEntry; + /** * Specific output location (for this source entry) @@ -215,11 +222,41 @@ */ public boolean isExported; - /* + /** * The extra attributes */ - IClasspathAttribute[] extraAttributes; + public IClasspathAttribute[] extraAttributes; + public ClasspathEntry( + int contentKind, + int entryKind, + IPath path, + IPath[] inclusionPatterns, + IPath[] exclusionPatterns, + IPath sourceAttachmentPath, + IPath sourceAttachmentRootPath, + IPath specificOutputLocation, + boolean isExported, + IAccessRule[] accessRules, + boolean combineAccessRules, + IClasspathAttribute[] extraAttributes) { + + this( contentKind, + entryKind, + path, + inclusionPatterns, + exclusionPatterns, + sourceAttachmentPath, + sourceAttachmentRootPath, + specificOutputLocation, + null, + NO_ENTRIES, + isExported, + accessRules, + combineAccessRules, + extraAttributes); + } + /** * Creates a class path entry of the specified kind with the given path. */ @@ -232,6 +269,8 @@ IPath sourceAttachmentPath, IPath sourceAttachmentRootPath, IPath specificOutputLocation, + IClasspathEntry referencingEntry, + IClasspathEntry[] referencedEntries, boolean isExported, IAccessRule[] accessRules, boolean combineAccessRules, @@ -242,7 +281,9 @@ this.path = path; this.inclusionPatterns = inclusionPatterns; this.exclusionPatterns = exclusionPatterns; - + this.referencingEntry = referencingEntry; + this.referencedEntries = referencedEntries; + int length; if (accessRules != null && (length = accessRules.length) > 0) { AccessRule[] rules = new AccessRule[length]; @@ -379,6 +420,46 @@ System.arraycopy(result, 0, result = new IAccessRule[index], 0, index); return result; } + + static IClasspathEntry[] decodeReferences(NodeList list, IClasspathEntry parent, IPath projectPath) { + if (list == null) return null; + int length = list.getLength(); + if (length == 0) return null; + IClasspathEntry[] result = new IClasspathEntry[length]; + int index = 0; + for (int i = 0; i < length; i++) { + Node referencedEntry = list.item(i); + if (referencedEntry.getNodeType() == Node.ELEMENT_NODE) { + Element elementReference = (Element) referencedEntry; + IPath path = new Path(elementReference.getAttribute(TAG_PATH)); + String sourceAttachment = elementReference.getAttribute(TAG_SOURCEPATH); + String sourceRoot = elementReference.getAttribute(TAG_ROOTPATH); + + if (!(path.segmentCount() > 0 && path.segment(0).equals(ClasspathEntry.DOT_DOT))) { + path = projectPath.append(path); + } + // source attachment info (optional) + IPath sourceAttachmentPath = "".equals(sourceAttachment) ? null : new Path(sourceAttachment); //$NON-NLS-1$ + + if (sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) { + sourceAttachmentPath = projectPath.append(sourceAttachmentPath); + } + IPath sourceAttachmentRootPath = "".equals(sourceRoot) ? null : new Path(sourceRoot); //$NON-NLS-1$ + + NodeList children = referencedEntry.getChildNodes(); + NodeList attributeList = getChildAttributes(TAG_ATTRIBUTES, children, new boolean[children.getLength()]); + IClasspathAttribute[] extraAttributes = decodeExtraAttributes(attributeList); + + result[index++] = new ClasspathEntry(parent.getContentKind(), parent.getEntryKind(), path, parent + .getInclusionPatterns(), parent.getExclusionPatterns(), sourceAttachmentPath, + sourceAttachmentRootPath, parent.getOutputLocation(), parent, new IClasspathEntry[0], parent + .isExported(), parent.getAccessRules(), parent.combineAccessRules(), extraAttributes); + } + } + if (index != length) + System.arraycopy(result, 0, result = new ClasspathEntry[index], 0, index); + return result; + } /** * Decode some element tag containing a sequence of patterns into IPath[] @@ -494,36 +575,8 @@ parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind)); - IPath xmlPath = this.path; - if (this.entryKind != IClasspathEntry.CPE_VARIABLE && this.entryKind != IClasspathEntry.CPE_CONTAINER) { - // translate to project relative from absolute (unless a device path) - if (xmlPath.isAbsolute()) { - if (projectPath != null && projectPath.isPrefixOf(xmlPath)) { - if (xmlPath.segment(0).equals(projectPath.segment(0))) { - xmlPath = xmlPath.removeFirstSegments(1); - xmlPath = xmlPath.makeRelative(); - } else { - xmlPath = xmlPath.makeAbsolute(); - } - } - } - } - parameters.put(TAG_PATH, String.valueOf(xmlPath)); - - if (this.sourceAttachmentPath != null) { - xmlPath = this.sourceAttachmentPath; - // translate to project relative from absolute - if (this.entryKind != IClasspathEntry.CPE_VARIABLE && projectPath != null && projectPath.isPrefixOf(xmlPath)) { - if (xmlPath.segment(0).equals(projectPath.segment(0))) { - xmlPath = xmlPath.removeFirstSegments(1); - xmlPath = xmlPath.makeRelative(); - } - } - parameters.put(TAG_SOURCEPATH, String.valueOf(xmlPath)); - } - if (this.sourceAttachmentRootPath != null) { - parameters.put(TAG_ROOTPATH, String.valueOf(this.sourceAttachmentRootPath)); - } + encodePathAttributes(projectPath, parameters); + if (this.isExported) { parameters.put(TAG_EXPORTED, "true");//$NON-NLS-1$ } @@ -553,12 +606,15 @@ boolean hasRestrictions = getAccessRuleSet() != null; // access rule set is null if no access rules ArrayList unknownChildren = unknownXmlElements != null ? unknownXmlElements.children : null; boolean hasUnknownChildren = unknownChildren != null; + boolean hasReferencedEntries = getReferencedEntries().length > 0 ? true : false; + + /* close tag if no extra attributes, no restriction, no unknown children and no referenced classpath entries */ writer.printTag( TAG_CLASSPATHENTRY, parameters, indent, newLine, - !hasExtraAttributes && !hasRestrictions && !hasUnknownChildren/*close tag if no extra attributes, no restriction and no unknown children*/); + !hasExtraAttributes && !hasRestrictions && !hasUnknownChildren && !hasReferencedEntries); if (hasExtraAttributes) encodeExtraAttributes(writer, indent, newLine); @@ -566,13 +622,49 @@ if (hasRestrictions) encodeAccessRules(writer, indent, newLine); + if (this.getReferencedEntries().length > 0) { + encodeReferences(writer, projectPath, indent, newLine); + } if (hasUnknownChildren) encodeUnknownChildren(writer, indent, newLine, unknownChildren); - if (hasExtraAttributes || hasRestrictions || hasUnknownChildren) + if (hasExtraAttributes || hasRestrictions || hasUnknownChildren || hasReferencedEntries) writer.endTag(TAG_CLASSPATHENTRY, indent, true/*insert new line*/); } + private void encodePathAttributes(IPath projectPath, HashMap parameters) { + IPath xmlPath = this.path; + if (this.entryKind != IClasspathEntry.CPE_VARIABLE && this.entryKind != IClasspathEntry.CPE_CONTAINER) { + // translate to project relative from absolute (unless a device path) + if (xmlPath.isAbsolute()) { + if (projectPath != null && projectPath.isPrefixOf(xmlPath)) { + if (xmlPath.segment(0).equals(projectPath.segment(0))) { + xmlPath = xmlPath.removeFirstSegments(1); + xmlPath = xmlPath.makeRelative(); + } else { + xmlPath = xmlPath.makeAbsolute(); + } + } + } + } + parameters.put(TAG_PATH, String.valueOf(xmlPath)); + + if (this.sourceAttachmentPath != null) { + xmlPath = this.sourceAttachmentPath; + // translate to project relative from absolute + if (this.entryKind != IClasspathEntry.CPE_VARIABLE && projectPath != null && projectPath.isPrefixOf(xmlPath)) { + if (xmlPath.segment(0).equals(projectPath.segment(0))) { + xmlPath = xmlPath.removeFirstSegments(1); + xmlPath = xmlPath.makeRelative(); + } + } + parameters.put(TAG_SOURCEPATH, String.valueOf(xmlPath)); + } + if (this.sourceAttachmentRootPath != null) { + parameters.put(TAG_ROOTPATH, String.valueOf(this.sourceAttachmentRootPath)); + } + } + void encodeExtraAttributes(XMLWriter writer, boolean indent, boolean newLine) { writer.startTag(TAG_ATTRIBUTES, indent); for (int i = 0; i < this.extraAttributes.length; i++) { @@ -617,6 +709,25 @@ writer.printTag(TAG_ACCESS_RULE, parameters, indent, newLine, true); } + + void encodeReferences(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine) { + writer.startTag(TAG_REFERENCES, indent); + IClasspathEntry[] references = getReferencedEntries(); + for (int index = 0, length = references.length; index < length; index++) { + // Set the capacity to maximum possible + HashMap parameters = new HashMap(3); + ClasspathEntry reference = (ClasspathEntry)references[index]; + boolean hasExtraAttributes = reference.extraAttributes.length != 0; + reference.encodePathAttributes(projectPath, parameters); + writer.printTag(TAG_REFERENCE, parameters, indent, newLine, !hasExtraAttributes); + + if (hasExtraAttributes) { + reference.encodeExtraAttributes(writer, indent, newLine); + writer.endTag(TAG_REFERENCE, indent, newLine); + } + } + writer.endTag(TAG_REFERENCES, indent, true/*insert new line*/); + } private void encodeUnknownChildren(XMLWriter writer, boolean indent, boolean newLine, ArrayList unknownChildren) { for (int i = 0, length = unknownChildren.size(); i < length; i++) { @@ -685,35 +796,6 @@ // custom output location IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(removeAttribute(TAG_OUTPUT, attributes)) : null; - String[] unknownAttributes = null; - ArrayList unknownChildren = null; - - if (unknownElements != null) { - // unknown attributes - int unknownAttributeLength = attributes.getLength(); - if (unknownAttributeLength != 0) { - unknownAttributes = new String[unknownAttributeLength*2]; - for (int i = 0; i < unknownAttributeLength; i++) { - Node attribute = attributes.item(i); - unknownAttributes[i*2] = attribute.getNodeName(); - unknownAttributes[i*2 + 1] = attribute.getNodeValue(); - } - } - - // unknown children - for (int i = 0, length = foundChildren.length; i < length; i++) { - if (!foundChildren[i]) { - Node node = children.item(i); - if (node.getNodeType() != Node.ELEMENT_NODE) continue; - if (unknownChildren == null) - unknownChildren = new ArrayList(); - StringBuffer buffer = new StringBuffer(); - decodeUnknownNode(node, buffer, project); - unknownChildren.add(buffer.toString()); - } - } - } - // recreate the CP entry IClasspathEntry entry = null; switch (kind) { @@ -741,6 +823,10 @@ accessRules, extraAttributes, isExported); + ((ClasspathEntry)entry).referencingEntry = null; + NodeList referencesList = getChildAttributes(TAG_REFERENCES, children, foundChildren); + IClasspathEntry[] references = decodeReferences(referencesList, entry, projectPath); + ((ClasspathEntry)entry).setReferencedEntries(references); break; case IClasspathEntry.CPE_SOURCE : // must be an entry in this project or specify another project @@ -807,6 +893,35 @@ default : throw new AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr)); } + + String[] unknownAttributes = null; + ArrayList unknownChildren = null; + + if (unknownElements != null) { + // unknown attributes + int unknownAttributeLength = attributes.getLength(); + if (unknownAttributeLength != 0) { + unknownAttributes = new String[unknownAttributeLength*2]; + for (int i = 0; i < unknownAttributeLength; i++) { + Node attribute = attributes.item(i); + unknownAttributes[i*2] = attribute.getNodeName(); + unknownAttributes[i*2 + 1] = attribute.getNodeValue(); + } + } + + // unknown children + for (int i = 0, length = foundChildren.length; i < length; i++) { + if (!foundChildren[i]) { + Node node = children.item(i); + if (node.getNodeType() != Node.ELEMENT_NODE) continue; + if (unknownChildren == null) + unknownChildren = new ArrayList(); + StringBuffer buffer = new StringBuffer(); + decodeUnknownNode(node, buffer, project); + unknownChildren.add(buffer.toString()); + } + } + } if (unknownAttributes != null || unknownChildren != null) { UnknownXmlElements unknownXmlElements = new UnknownXmlElements(); @@ -1065,12 +1180,30 @@ } if (!equalAttributes(this.extraAttributes, otherEntry.getExtraAttributes())) return false; + + if (!equalReferencedEntries(this.getReferencedEntries(), otherEntry.getReferencedEntries())) + return false; + return true; } else { return false; } } + private static boolean equalReferencedEntries(IClasspathEntry[] firstChains, IClasspathEntry[] secondChains) { + if (firstChains != secondChains){ + if (firstChains == null) return false; + int length = firstChains.length; + if (secondChains == null || secondChains.length != length) + return false; + for (int i = 0; i < length; i++) { + if (!firstChains[i].equals(secondChains[i])) + return false; + } + } + return true; + } + private static boolean equalAttributes(IClasspathAttribute[] firstAttributes, IClasspathAttribute[] secondAttributes) { if (firstAttributes != secondAttributes){ if (firstAttributes == null) return false; @@ -1178,6 +1311,22 @@ return this.sourceAttachmentRootPath; } + + public IClasspathEntry getReferencingEntry() { + return this.referencingEntry; + } + + public IClasspathEntry[] getReferencedEntries() { + if (this.referencedEntries == null) { + this.referencedEntries = new IClasspathEntry[0]; + } + return this.referencedEntries; + } + + public void setReferencedEntries(IClasspathEntry[] entries) { + this.referencedEntries = entries; + } + /** * Returns the hash code for this classpath entry */ @@ -1380,6 +1529,8 @@ getSourceAttachmentPath(), getSourceAttachmentRootPath(), getOutputLocation(), + this.getReferencingEntry(), + this.getReferencedEntries(), this.isExported, getAccessRules(), this.combineAccessRules, @@ -1397,19 +1548,22 @@ return NO_ENTRIES; ClasspathEntry[] result = new ClasspathEntry[length]; for (int i = 0; i < length; i++) { + // Chained/referenced libraries can have their own attachment path. Hence, set them to null result[i] = new ClasspathEntry( - getContentKind(), - getEntryKind(), - paths[i], - this.inclusionPatterns, - this.exclusionPatterns, - getSourceAttachmentPath(), - getSourceAttachmentRootPath(), - getOutputLocation(), - this.isExported, - getAccessRules(), - this.combineAccessRules, - this.extraAttributes); + getContentKind(), + getEntryKind(), + paths[i], + this.inclusionPatterns, + this.exclusionPatterns, + null, + null, + getOutputLocation(), + this, + null, + this.isExported, + getAccessRules(), + this.combineAccessRules, + NO_EXTRA_ATTRIBUTES); } return result; } 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.427 diff -u -r1.427 JavaProject.java --- model/org/eclipse/jdt/internal/core/JavaProject.java 8 Jul 2009 07:12:08 -0000 1.427 +++ model/org/eclipse/jdt/internal/core/JavaProject.java 18 Feb 2010 09:49:02 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2010 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 @@ -18,6 +18,7 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; @@ -45,6 +46,7 @@ import org.eclipse.core.runtime.content.IContentDescription; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IScopeContext; +import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; @@ -2533,6 +2535,7 @@ IJavaModelStatus unresolvedEntryStatus = JavaModelStatus.VERIFIED_OK; HashMap rawReverseMap = new HashMap(); Map rootPathToResolvedEntries = new HashMap(); + Map rawPathToReferencedEntries = new HashMap(); } public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException { @@ -2540,7 +2543,23 @@ ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager(); ResolvedClasspath result = new ResolvedClasspath(); + Map oldChainedEntries = new HashMap(); + List rawLibrariesPath = new ArrayList(); LinkedHashSet resolvedEntries = new LinkedHashSet(); + + if(resolveChainedLibraries) { + for (int index = 0; index < rawClasspath.length; index++) { + IClasspathEntry currentEntry = rawClasspath[index]; + if (currentEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + IClasspathEntry[] chainedEntries = ((ClasspathEntry)currentEntry).getReferencedEntries(); + for (int chainIndex = 0; chainIndex < chainedEntries.length; chainIndex++) { + oldChainedEntries.put(chainedEntries[chainIndex].getPath(), chainedEntries[chainIndex]); + } + rawLibrariesPath.add(ClasspathEntry.resolveDotDot(currentEntry.getPath())); + } + } + } + int length = rawClasspath.length; for (int i = 0; i < length; i++) { @@ -2561,14 +2580,19 @@ if (resolvedEntry == null) { result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath()); } else { - if (resolveChainedLibraries && resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + // If the entry is already present in the rawReversetMap, it means the entry and the chained libraries + // have already been processed. So, skip it. + if (resolveChainedLibraries && resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY + && result.rawReverseMap.get(resolvedEntry.getPath()) == null) { // 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); + if (!rawLibrariesPath.contains(extraEntries[j].getPath())) { + addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager, null, null, false); + } } } - addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, null, null, false); } break; @@ -2603,34 +2627,44 @@ // resolve ".." in library path cEntry = cEntry.resolvedDotDot(); - if (resolveChainedLibraries) { + if (resolveChainedLibraries && result.rawReverseMap.get(cEntry.getPath()) == null) { // 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 (!rawLibrariesPath.contains(extraEntries[k].getPath())) { + addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, null, null, false); + } } } } - addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager, null, null, false); } break; case IClasspathEntry.CPE_LIBRARY: // resolve ".." in library path resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot(); - - if (resolveChainedLibraries) { + if (resolveChainedLibraries && result.rawReverseMap.get(resolvedEntry.getPath()) == null) { // resolve Class-Path: in manifest ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries(); + // Set the capacity to the maximum possible, although all of them may not be filled + List chainedEntriesList = (extraEntries.length > 0) ? new ArrayList(extraEntries.length) : null; for (int k = 0, length2 = extraEntries.length; k < length2; k++) { - addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager); + if (!rawLibrariesPath.contains(extraEntries[k].getPath())) { + addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, + oldChainedEntries, chainedEntriesList, true); + } + } + if (extraEntries.length > 0) { + result.rawPathToReferencedEntries.put(rawEntry.getPath(), chainedEntriesList + .toArray(new IClasspathEntry[chainedEntriesList.size()])); } } - addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, oldChainedEntries, null, false); break; default : - addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, oldChainedEntries, null, false); break; } } @@ -2639,9 +2673,28 @@ return result; } - private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager) { - IPath resolvedPath; - if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) { + private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, + LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager, + Map oldChainedEntriesMap, List newChainedEntries, boolean addAsChainedEntry) { + + IPath resolvedPath; + // If it's already been resolved, do not add to resolvedEntries or newChainedEntries lists + if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) { + IClasspathEntry chainedEntry = null; + if (rawEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + chainedEntry = (ClasspathEntry)oldChainedEntriesMap.get(resolvedPath); + if (chainedEntry == null) { + chainedEntry = resolvedEntry; + } + else { + // This is required to keep the attributes if any added by the user in + // the previous session such as source attachment path etc. + copyFromOldChainedEntry((ClasspathEntry)resolvedEntry, (ClasspathEntry)chainedEntry); + } + if (addAsChainedEntry) { + newChainedEntries.add(chainedEntry); + } + } result.rawReverseMap.put(resolvedPath, rawEntry); result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry); } @@ -2651,6 +2704,21 @@ } } + private void copyFromOldChainedEntry(ClasspathEntry resolvedEntry, ClasspathEntry chainedEntry) { + IPath path = chainedEntry.getSourceAttachmentPath(); + if ( path != null) { + resolvedEntry.sourceAttachmentPath = path; + } + path = chainedEntry.getSourceAttachmentRootPath(); + if (path != null) { + resolvedEntry.sourceAttachmentRootPath = path; + } + IClasspathAttribute[] attributes = chainedEntry.getExtraAttributes(); + if (attributes != null) { + resolvedEntry.extraAttributes = attributes; + } + } + /* * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo. */ @@ -2673,8 +2741,18 @@ rawClasspath = perProjectInfo.readAndCacheClasspath(this); timeStamp = perProjectInfo.rawTimeStamp; } - + ResolvedClasspath result = resolveClasspath(rawClasspath, usePreviousSession, true/*resolve chained libraries*/); + + synchronized (perProjectInfo) { + for (int index = 0; index < rawClasspath.length; index++) { + IClasspathEntry tEntry = rawClasspath[index]; + if (tEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + ((ClasspathEntry) tEntry).setReferencedEntries( + (IClasspathEntry[]) result.rawPathToReferencedEntries.get(tEntry.getPath())); + } + } + } if (CP_RESOLUTION_BP_LISTENERS != null) breakpoint(2, this); #P org.eclipse.jdt.core.tests.model 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.206 diff -u -r1.206 ClasspathTests.java --- src/org/eclipse/jdt/core/tests/model/ClasspathTests.java 3 Feb 2010 06:38:02 -0000 1.206 +++ src/org/eclipse/jdt/core/tests/model/ClasspathTests.java 18 Feb 2010 09:49:12 -0000 @@ -88,8 +88,8 @@ // All specified tests which do not belong to the class are skipped... static { // Names of tests to run: can be "testBugXXXX" or "BugXXXX") -// TESTS_PREFIX = "testClasspathDuplicateExtraAttribute"; -// TESTS_NAMES = new String[] {"testClasspathValidation42"}; +// TESTS_PREFIX = "testBug252341"; +// TESTS_NAMES = new String[] {"testClasspathWithNonExistentLibraryEntry"}; // TESTS_NUMBERS = new int[] { 23, 28, 38 }; // TESTS_RANGE = new int[] { 21, 38 }; } @@ -4881,7 +4881,7 @@ */ public void testNoResourceChange06() throws CoreException { ILogListener listener = new ILogListener(){ - private StringBuffer buffer = new StringBuffer(); + private final StringBuffer buffer = new StringBuffer(); public void logging(IStatus status, String plugin) { this.buffer.append(status); this.buffer.append('\n'); @@ -6026,7 +6026,7 @@ } } /** - * Additional test for bug 300136 - Test that the the errors are reported when the + * Additional test for bug 300136 - Test that the errors are reported when the * optional attribute is not used. * * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=300136" @@ -6069,5 +6069,284 @@ JavaCore.removeClasspathVariable("INVALID_LIB", null); } } +/** + * @bug 252431:New API is needed to better identify referenced jars in the Class-Path: entry + * Test that 1) referenced libraries are added to the resolved classpath in the right order + * 2) referenced libraries are added to the appropriate referencing library in the correct order + * 3) referenced libraries and top-level libraries retain the source attachment and source attachment root path + * 4) referenced libraries point to the correct entry as their referencingEntry. + * + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=252431" + * @throws Exception + */ +public void testBug252341a() throws Exception { + try { + IJavaProject p = createJavaProject("P"); + addLibrary(p, "lib1.jar", "abc.zip", 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", ""); + IClasspathEntry[] resolvedClasspath = p.getResolvedClasspath(true); + assertClasspathEquals(resolvedClasspath, + "/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][sourcePath:/P/abc.zip][isExported:true]"); + + IClasspathEntry[] rawClasspath = p.getRawClasspath(); + assertClasspathEquals(rawClasspath, + "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + + "JCL_LIB[CPE_VARIABLE][K_SOURCE][isExported:false]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/abc.zip][isExported:true]"); + + IClasspathEntry[] chains = rawClasspath[2].getReferencedEntries(); + + assertClasspathEquals(chains, + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + assertSame("Referencing Entry", chains[0].getReferencingEntry(), rawClasspath[2]); + assertSame("Referencing Entry", chains[1].getReferencingEntry(), rawClasspath[2]); + + assertEquals("source attachment", resolvedClasspath[4].getSourceAttachmentPath().toPortableString(), "/P/abc.zip"); + assertNull("source attachment", chains[0].getSourceAttachmentPath()); + assertNull("source attachment", chains[1].getSourceAttachmentPath()); + assertNull("source attachment root", chains[0].getSourceAttachmentRootPath()); + assertNull("source attachment root", chains[1].getSourceAttachmentRootPath()); + + ((ClasspathEntry)chains[0]).sourceAttachmentPath = new Path("/P/efg.zip"); + ((ClasspathEntry)chains[1]).sourceAttachmentPath = new Path("/P/xyz.zip"); + ((ClasspathEntry)chains[0]).sourceAttachmentRootPath = new Path("/src2"); + ((ClasspathEntry)chains[1]).sourceAttachmentRootPath = new Path("/src3"); + + IClasspathAttribute javadocLoc = JavaCore.newClasspathAttribute("javadoc_location", "/P/efg.zip"); + ((ClasspathEntry)chains[0]).extraAttributes = new IClasspathAttribute[]{javadocLoc}; + + p.setRawClasspath(rawClasspath, null); + p.close(); + p.open(null); + rawClasspath = p.getRawClasspath(); + resolvedClasspath = p.getResolvedClasspath(true); + + assertClasspathEquals(resolvedClasspath, + "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + + ""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/efg.zip][rootPath:/src2][isExported:true][attributes:javadoc_location=/P/efg.zip]\n" + + "/P/lib3.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/xyz.zip][rootPath:/src3][isExported:true]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/abc.zip][isExported:true]"); + + } finally { + deleteProject("P"); + } +} +/** + * Additional tests for bug 252431. + * When multiple libraries have one or more common referenced library in their MANIFEST + * 1) The common referenced libries are added to the first library entry in the raw classpath + * 3) Removing one of the top-level library from the raw classpath removes the libraries referenced only + * by that entry from the resolved classpath and resolved classpath is updated + * + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=252431" + * @throws Exception + */ +public void testBug252341b() 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: lib3.jar lib4.jar\n", + }, + JavaCore.VERSION_1_4); + + addLibrary(p, "lib2.jar", null, new String[0], + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Class-Path: lib3.jar lib5.jar\n", + }, + JavaCore.VERSION_1_4); + createFile("/P/lib3.jar", ""); + createFile("/P/lib4.jar", ""); + createFile("/P/lib5.jar", ""); + + IClasspathEntry[] rawClasspath = p.getRawClasspath(); + assertClasspathEquals( + rawClasspath, + "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + + "JCL_LIB[CPE_VARIABLE][K_SOURCE][isExported:false]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + IClasspathEntry[] resolvedClasspath = p.getResolvedClasspath(true); + assertClasspathEquals(resolvedClasspath, + "/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/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + assertClasspathEquals( + rawClasspath[2].getReferencedEntries(), + "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + assertClasspathEquals( + rawClasspath[3].getReferencedEntries(), + "/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + assertSame("Referencing Entry", resolvedClasspath[2].getReferencingEntry(), rawClasspath[2]); + + p.setRawClasspath(rawClasspath, null); + resolvedClasspath = p.getResolvedClasspath(true); + + assertClasspathEquals(resolvedClasspath, + "/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/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + //Remove the first jar entirely from the classpath + IClasspathEntry[] newRawClasspath = new IClasspathEntry[rawClasspath.length-1]; + System.arraycopy(rawClasspath, 0, newRawClasspath, 0, 2); + System.arraycopy(rawClasspath, 3, newRawClasspath, 2, 1); + p.setRawClasspath(newRawClasspath, null); + resolvedClasspath = p.getResolvedClasspath(true); + assertClasspathEquals(resolvedClasspath, + "/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/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + } finally { + deleteProject("P"); + } +} +/** + * Additional tests for bug 252431. + * Test that when the path of a library entry with referenced entries is replaced with that of + * a jar with NO referenced entries, the referenced entries list and resolved classpath + * are updated accordingly. + * + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=252431" + * @throws Exception + */ +public void testBug252341c() 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 lib4.jar\n", + }, + JavaCore.VERSION_1_4); + + createFile("/P/lib3.jar", ""); + createFile("/P/lib4.jar", ""); + createFile("/P/lib2.jar", ""); + + IClasspathEntry[] rawClasspath = p.getRawClasspath(); + assertClasspathEquals( + rawClasspath, + "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + + "JCL_LIB[CPE_VARIABLE][K_SOURCE][isExported:false]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + IClasspathEntry[] resolvedClasspath = p.getResolvedClasspath(true); + assertClasspathEquals(resolvedClasspath, + "/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/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + ((ClasspathEntry)rawClasspath[2]).path = resolvedClasspath[4].getPath(); + + p.setRawClasspath(rawClasspath, null); + resolvedClasspath = p.getResolvedClasspath(true); + + rawClasspath = p.getRawClasspath(); + assertClasspathEquals( + rawClasspath, + "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + + "JCL_LIB[CPE_VARIABLE][K_SOURCE][isExported:false]\n" + + "/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + resolvedClasspath = p.getResolvedClasspath(true); + assertClasspathEquals(resolvedClasspath, + "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + + ""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + + "/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + } finally { + deleteProject("P"); + } +} +/** + * Additional tests for bug 252431. + * Test that when lib2.jar is referred in the manifest of lib1.jar and vice versa + * and both are in the raw classpath in this order - lib1.jar, lib2.jar + * 1) both jars have referencingEntry as null + * 2) both jars have referencedEntries as emptry + * + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=252431" + * @throws Exception + */ +public void testBug252341d() 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); + + addLibrary(p, "lib2.jar", null, new String[0], + new String[] { + "META-INF/MANIFEST.MF", + "Manifest-Version: 1.0\n" + + "Class-Path: lib1.jar \n", + }, + JavaCore.VERSION_1_4); + + IClasspathEntry[] rawClasspath = p.getRawClasspath(); + assertClasspathEquals( + rawClasspath, + "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + + "JCL_LIB[CPE_VARIABLE][K_SOURCE][isExported:false]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + assertClasspathEquals(rawClasspath[2].getReferencedEntries(), ""); + assertClasspathEquals(rawClasspath[3].getReferencedEntries(), ""); + assertNull("Referencing Entry", rawClasspath[2].getReferencingEntry()); + assertNull("Referencing Entry", rawClasspath[3].getReferencingEntry()); + + IClasspathEntry[] resolvedClasspath = p.getResolvedClasspath(true); + assertClasspathEquals(resolvedClasspath, + "/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + + ""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + } finally { + deleteProject("P"); + } +} } #P org.eclipse.jdt.core.tests.performance Index: src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceModelTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceModelTests.java,v retrieving revision 1.48 diff -u -r1.48 FullSourceWorkspaceModelTests.java --- src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceModelTests.java 27 Oct 2009 13:05:53 -0000 1.48 +++ src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceModelTests.java 18 Feb 2010 09:49:16 -0000 @@ -62,6 +62,7 @@ import org.eclipse.jdt.internal.core.JavaElement; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.NameLookup; +import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; /** */ @@ -71,6 +72,7 @@ static int TESTS_COUNT = 0; private final static int WARMUP_COUNT = 50; private final static int FOLDERS_COUNT = 200; + private final static int JARS_COUNT = 50; private final static int PACKAGES_COUNT = 200; static int TESTS_LENGTH; @@ -201,6 +203,42 @@ } } + +private void setUpBigClasspath(IJavaProject javaProject) throws Exception { + final String JAR_NAME = "lib"; + final String JAR_EXTENSION = ".jar"; + String bigProjectLocation = BIG_PROJECT.getResource().getLocation().toOSString(); + String MANIFEST_NAME = "META-INF/MANIFEST.MF"; + String manifestContent = new String("Manifest-Version: 1.0\n" + + "Class-Path: \n"); + + IClasspathEntry[] classpath = new IClasspathEntry[JARS_COUNT]; + for (int index = 0; index < JARS_COUNT; index++) { + String jarName = JAR_NAME + index + JAR_EXTENSION; + File jar = new File(bigProjectLocation, jarName); + int chainedJar = (index +1) % JARS_COUNT; + if (!jar.exists()) { + String[] jarContents = new String[]{ + "p/Test" + index + ".java", + "package p;\n public class Test" + index + " {\n}\n"}; + + String[] nonJava = new String[] { + MANIFEST_NAME, + "Manifest-Version: 1.0\n" + + "Class-Path: " + JAR_NAME + (chainedJar) + JAR_EXTENSION + " " + + JAR_NAME + (chainedJar + JARS_COUNT) + JAR_EXTENSION + " " + + JAR_NAME + (chainedJar + JARS_COUNT * 2) + JAR_EXTENSION + "\n"}; + + String[] chainManifest = new String[] {MANIFEST_NAME, manifestContent}; + org.eclipse.jdt.core.tests.util.Util.createJar(jarContents, nonJava, jar.getAbsolutePath(), new String[0], JavaCore.VERSION_1_3); + org.eclipse.jdt.core.tests.util.Util.createJar(new String[0], chainManifest, (bigProjectLocation + JAR_NAME + (chainedJar + JARS_COUNT) + JAR_EXTENSION), new String[0], JavaCore.VERSION_1_3); + org.eclipse.jdt.core.tests.util.Util.createJar(new String[0], chainManifest, (bigProjectLocation + JAR_NAME + (chainedJar + JARS_COUNT * 2) + JAR_EXTENSION), new String[0], JavaCore.VERSION_1_3); + } + classpath[index] = JavaCore.newLibraryEntry(new Path(jar.getAbsolutePath()), null, null); + } + javaProject.setRawClasspath(classpath, null); +} + private void setUpBigJars() throws Exception { String bigProjectLocation = BIG_PROJECT.getResource().getLocation().toOSString(); int size = PACKAGES_COUNT * 10; @@ -1283,6 +1321,43 @@ } } +public void testProjectResolveClasspath() throws Exception { + + IClasspathEntry[] oldClasspath = BIG_PROJECT.getRawClasspath(); + + try { + tagAsSummary("Find resolved classpath for project", false); // do NOT put in fingerprint + + // Wait for indexing end + AbstractJavaModelTests.waitUntilIndexesReady(); + + // Reset classpath + setUpBigClasspath(BIG_PROJECT); + + // Warm up + PerProjectInfo projectInfo = BIG_PROJECT.getPerProjectInfo(); + for (int i=0; i