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 160356 Details for
Bug 281551
[build path] Source attachments wrong for automatically added libraries
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Updated patch
patch_281551.txt (text/plain), 72.60 KB, created by
Olivier Thomann
on 2010-02-26 14:39:46 EST
(
hide
)
Description:
Updated patch
Filename:
MIME Type:
Creator:
Olivier Thomann
Created:
2010-02-26 14:39:46 EST
Size:
72.60 KB
patch
obsolete
>### 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 26 Feb 2010 19:37:59 -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,28 @@ > */ > IPath getSourceAttachmentRootPath(); > >+ >+ /** >+ * Returns the classpath entry that is making a reference to this classpath entry. For entry kinds >+ * {@link #CPE_LIBRARY}, the return value is the entry that is representing the JAR that includes >+ * <code>this</code> in the MANIFEST.MF file's Class-Path section. For entry kinds other than >+ * {@link #CPE_LIBRARY}, this returns null. For those entries that are on the raw classpath already, >+ * this returns <code>null</code> >+ * <p> >+ * It is possible that multiple library entries refer to the same entry >+ * via the MANIFEST.MF file. In those cases, this method returns the first classpath entry >+ * that appears in the raw classpath. However, this does not mean that the other referencing >+ * entries do not relate to their referenced entries. >+ * See {@link JavaCore#getReferencedClasspathEntries(IClasspathEntry, IJavaProject)} for >+ * more details. >+ * </p> >+ * >+ * @return the classpath entry that is referencing this entry or <code>null</code> if >+ * not applicable. >+ * @since 3.6 >+ */ >+ IClasspathEntry getReferencingEntry(); >+ > /** > * Returns whether this entry is exported to dependent projects. > * Always returns <code>false</code> for source entries (kind >Index: model/org/eclipse/jdt/core/IJavaProject.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java,v >retrieving revision 1.103 >diff -u -r1.103 IJavaProject.java >--- model/org/eclipse/jdt/core/IJavaProject.java 27 Oct 2008 14:47:36 -0000 1.103 >+++ model/org/eclipse/jdt/core/IJavaProject.java 26 Feb 2010 19:37:59 -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 >@@ -1008,6 +1008,54 @@ > void setRawClasspath(IClasspathEntry[] entries, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException; > > /** >+ * Works same as {@link #setRawClasspath(IClasspathEntry[], IPath, IProgressMonitor)} and >+ * additionally allows persisting the given array of referenced entries for this project. >+ * The referenced entries and their attributes are stores in the .classpath file of this >+ * project. For details on referenced entries, see >+ * {@link JavaCore#getReferencedClasspathEntries(IClasspathEntry, IJavaProject)} >+ * and {@link IClasspathEntry#getReferencingEntry()}. >+ * <p> >+ * Since the referenced entries are stored in the .classpath file, clients can store additional >+ * information that belong to these entries and retrieve them across sessions, though the referenced >+ * entries themselves may not be present in the raw classpath. By passing a <code>null</code> >+ * referencedEntries, clients can choose not to modify the already persisted referenced entries, >+ * which is fully equivalent to {@link #setRawClasspath(IClasspathEntry[], IPath, IProgressMonitor)}. >+ * If an empty array is passed as referencedEntries, the already persisted referenced entries, >+ * if any, will be cleared. >+ * </p> <p> >+ * If there are duplicates of a referenced entry or if any of the <code>referencedEntries</code> >+ * is already present in the raw classpath(<code>entries</code>) those referenced entries will >+ * be excluded and will not be persisted. >+ *</p> >+ * @param entries a list of classpath entries >+ * @param referencedEntries the list of referenced classpath entries to be persisted >+ * @param outputLocation the default output location >+ * @param monitor the given progress monitor >+ * @exception JavaModelException if the classpath could not be set. Reasons include: >+ * <ul> >+ * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li> >+ * <li> The classpath is being modified during resource change event notification (CORE_EXCEPTION) >+ * <li> The classpath failed the validation check as defined by {@link JavaConventions#validateClasspath(IJavaProject, IClasspathEntry[], IPath)} >+ * </ul> >+ * @see IClasspathEntry >+ * @see #getReferencedClasspathEntries() >+ * @since 3.6 >+ */ >+ void setRawClasspath(IClasspathEntry[] entries, IClasspathEntry[] referencedEntries, IPath outputLocation, >+ IProgressMonitor monitor) throws JavaModelException; >+ >+ /** >+ * Returns the list of referenced classpath entries stored in the .classpath file of <code>this</code> >+ * java project. Clients can store the referenced classpath entries using >+ * {@link #setRawClasspath(IClasspathEntry[], IClasspathEntry[], IPath, IProgressMonitor)} >+ * >+ * @throws JavaModelException >+ * @return an array of referenced classpath entries stored for this java project >+ * @since 3.6 >+ */ >+ IClasspathEntry[] getReferencedClasspathEntries() throws JavaModelException; >+ >+ /** > * Sets the classpath of this project using a list of classpath entries. In particular such a classpath may contain > * classpath variable entries. Classpath variable entries can be resolved individually ({@link JavaCore#getClasspathVariable(String)}), > * or the full classpath can be resolved at once using the helper method {@link #getResolvedClasspath(boolean)}. >Index: model/org/eclipse/jdt/core/IPackageFragmentRoot.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java,v >retrieving revision 1.54 >diff -u -r1.54 IPackageFragmentRoot.java >--- model/org/eclipse/jdt/core/IPackageFragmentRoot.java 27 Jun 2008 16:04:00 -0000 1.54 >+++ model/org/eclipse/jdt/core/IPackageFragmentRoot.java 26 Feb 2010 19:37:59 -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 >@@ -311,6 +311,18 @@ > * @since 2.0 > */ > IClasspathEntry getRawClasspathEntry() throws JavaModelException; >+ >+ /** >+ * Returns the first resolved classpath entry that corresponds to this package fragment root. >+ * A resolved classpath entry is said to correspond to a root if the path of the resolved >+ * entry is equal to the root's path. >+ * >+ * @return the first resolved classpath entry that corresponds to this package fragment root >+ * @throws JavaModelException if this element does not exist or if an >+ * exception occurs while accessing its corresponding resource. >+ * @since 3.6 >+ */ >+ IClasspathEntry getResolvedClasspathEntry() throws JavaModelException; > > /** > * Returns the absolute path to the source archive attached to >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.648 >diff -u -r1.648 JavaCore.java >--- model/org/eclipse/jdt/core/JavaCore.java 25 Feb 2010 19:17:02 -0000 1.648 >+++ model/org/eclipse/jdt/core/JavaCore.java 26 Feb 2010 19:37:59 -0000 >@@ -4587,6 +4587,33 @@ > false, // no access rules to combine > extraAttributes); > } >+ >+ /** >+ * Returns an array of classpath entries that are referenced directly or indirectly >+ * by a given classpath entry. For the entry kind {@link IClasspathEntry#CPE_LIBRARY}, >+ * the method returns the libraries that are included in the Class-Path section of >+ * the MANIFEST.MF file. If a referenced JAR file has further references to other library >+ * entries, they are processed recursively and added to the list. For entry kinds other >+ * than {@link IClasspathEntry#CPE_LIBRARY}, this method returns an empty array. >+ * <p> >+ * If a referenced entry has already been stored >+ * in the given project's .classpath, the stored attributes are populated in the corresponding >+ * referenced entry. For more details on storing referenced entries see >+ * see {@link IJavaProject#setRawClasspath(IClasspathEntry[], IClasspathEntry[], IPath, >+ * IProgressMonitor)}. >+ * </p> >+ * >+ * @param libraryEntry the library entry whose referenced entries are sought >+ * @param project project where the persisted referenced entries to be retrieved from >+ * @return an array of classpath entries that are referenced directly or indirectly by the given entry. >+ * If not applicable, returns an emptry array. >+ * @since 3.6 >+ */ >+ public static IClasspathEntry[] getReferencedClasspathEntries(IClasspathEntry libraryEntry, IJavaProject project) { >+ JavaModelManager manager = JavaModelManager.getJavaModelManager(); >+ return manager.getReferencedClasspathEntries(libraryEntry, project); >+ } >+ > /** > * Removed the given classpath variable. Does nothing if no value was > * set for this classpath variable. >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 26 Feb 2010 19:38:00 -0000 >@@ -77,6 +77,7 @@ > > public static final String TAG_CLASSPATH = "classpath"; //$NON-NLS-1$ > public static final String TAG_CLASSPATHENTRY = "classpathentry"; //$NON-NLS-1$ >+ public static final String TAG_REFERENCED_ENTRY = "referencedentry"; //$NON-NLS-1$ > public static final String TAG_OUTPUT = "output"; //$NON-NLS-1$ > public static final String TAG_KIND = "kind"; //$NON-NLS-1$ > public static final String TAG_PATH = "path"; //$NON-NLS-1$ >@@ -141,7 +142,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 +198,11 @@ > * a non-<code>null</code> value. > */ > public IPath sourceAttachmentRootPath; >+ >+ /** >+ * See {@link IClasspathEntry#getReferencingEntry()} >+ */ >+ public IClasspathEntry referencingEntry; > > /** > * Specific output location (for this source entry) >@@ -215,11 +221,40 @@ > */ > 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, >+ isExported, >+ accessRules, >+ combineAccessRules, >+ extraAttributes); >+ } >+ > /** > * Creates a class path entry of the specified kind with the given path. > */ >@@ -232,6 +267,7 @@ > IPath sourceAttachmentPath, > IPath sourceAttachmentRootPath, > IPath specificOutputLocation, >+ IClasspathEntry referencingEntry, > boolean isExported, > IAccessRule[] accessRules, > boolean combineAccessRules, >@@ -242,7 +278,8 @@ > this.path = path; > this.inclusionPatterns = inclusionPatterns; > this.exclusionPatterns = exclusionPatterns; >- >+ this.referencingEntry = referencingEntry; >+ > int length; > if (accessRules != null && (length = accessRules.length) > 0) { > AccessRule[] rules = new AccessRule[length]; >@@ -489,7 +526,7 @@ > /** > * Returns the XML encoding of the class path. > */ >- public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine, Map unknownElements) { >+ public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine, Map unknownElements, boolean isReferencedEntry) { > HashMap parameters = new HashMap(); > > parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind)); >@@ -553,12 +590,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; >+ >+ /* close tag if no extra attributes, no restriction and no unknown children */ >+ String tagName = isReferencedEntry ? TAG_REFERENCED_ENTRY : TAG_CLASSPATHENTRY; > writer.printTag( >- TAG_CLASSPATHENTRY, >+ tagName, > parameters, > indent, > newLine, >- !hasExtraAttributes && !hasRestrictions && !hasUnknownChildren/*close tag if no extra attributes, no restriction and no unknown children*/); >+ !hasExtraAttributes && !hasRestrictions && !hasUnknownChildren); > > if (hasExtraAttributes) > encodeExtraAttributes(writer, indent, newLine); >@@ -570,7 +610,7 @@ > encodeUnknownChildren(writer, indent, newLine, unknownChildren); > > if (hasExtraAttributes || hasRestrictions || hasUnknownChildren) >- writer.endTag(TAG_CLASSPATHENTRY, indent, true/*insert new line*/); >+ writer.endTag(tagName, indent, true/*insert new line*/); > } > > void encodeExtraAttributes(XMLWriter writer, boolean indent, boolean newLine) { >@@ -1178,6 +1218,11 @@ > return this.sourceAttachmentRootPath; > } > >+ >+ public IClasspathEntry getReferencingEntry() { >+ return this.referencingEntry; >+ } >+ > /** > * Returns the hash code for this classpath entry > */ >@@ -1380,6 +1425,7 @@ > getSourceAttachmentPath(), > getSourceAttachmentRootPath(), > getOutputLocation(), >+ this.getReferencingEntry(), > this.isExported, > getAccessRules(), > this.combineAccessRules, >@@ -1397,19 +1443,21 @@ > 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, >+ this.isExported, >+ getAccessRules(), >+ this.combineAccessRules, >+ NO_EXTRA_ATTRIBUTES); > } > return result; > } >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.444 >diff -u -r1.444 JavaModelManager.java >--- model/org/eclipse/jdt/internal/core/JavaModelManager.java 24 Feb 2010 11:02:18 -0000 1.444 >+++ model/org/eclipse/jdt/internal/core/JavaModelManager.java 26 Feb 2010 19:38:00 -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 >@@ -1095,6 +1095,7 @@ > public Object savedState; > public boolean triedRead; > public IClasspathEntry[] rawClasspath; >+ public IClasspathEntry[] referencedEntries; > public IJavaModelStatus rawClasspathStatus; > public int rawTimeStamp = 0; > public boolean writtingRawClasspath = false; >@@ -1169,9 +1170,11 @@ > return setResolvedClasspath(null, null, null, null, this.rawTimeStamp, true/*add classpath change*/); > } > >- private ClasspathChange setClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, boolean addClasspathChange) { >+ private ClasspathChange setClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, boolean addClasspathChange) { > ClasspathChange classpathChange = addClasspathChange ? addClasspathChange() : null; > >+ if (referencedEntries != null) this.referencedEntries = referencedEntries; >+ if (this.referencedEntries == null) this.referencedEntries = ClasspathEntry.NO_ENTRIES; > this.rawClasspath = newRawClasspath; > this.outputLocation = newOutputLocation; > this.rawClasspathStatus = newRawClasspathStatus; >@@ -1191,32 +1194,40 @@ > return classpathChange; > } > >- public synchronized ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) { >+ public ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) { >+ return setRawClasspath(newRawClasspath, null, newOutputLocation, newRawClasspathStatus); >+ } >+ >+ public synchronized ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) { > this.rawTimeStamp++; >- return setClasspath(newRawClasspath, newOutputLocation, newRawClasspathStatus, null/*resolved classpath*/, null/*root to raw map*/, null/*root to resolved map*/, null/*unresolved status*/, true/*add classpath change*/); >+ return setClasspath(newRawClasspath, referencedEntries, newOutputLocation, newRawClasspathStatus, null/*resolved classpath*/, null/*root to raw map*/, null/*root to resolved map*/, null/*unresolved status*/, true/*add classpath change*/); > } > >- public synchronized ClasspathChange setResolvedClasspath(IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, int timeStamp, boolean addClasspathChange) { >+ public ClasspathChange setResolvedClasspath(IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, int timeStamp, boolean addClasspathChange) { >+ return setResolvedClasspath(newResolvedClasspath, null, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, timeStamp, addClasspathChange); >+ } >+ >+ public synchronized ClasspathChange setResolvedClasspath(IClasspathEntry[] newResolvedClasspath, IClasspathEntry[] referencedEntries, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, int timeStamp, boolean addClasspathChange) { > if (this.rawTimeStamp != timeStamp) > return null; >- return setClasspath(this.rawClasspath, this.outputLocation, this.rawClasspathStatus, newResolvedClasspath, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, addClasspathChange); >+ return setClasspath(this.rawClasspath, referencedEntries, this.outputLocation, this.rawClasspathStatus, newResolvedClasspath, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, addClasspathChange); > } > >- public synchronized IClasspathEntry[] readAndCacheClasspath(JavaProject javaProject) { >+ public synchronized IClasspathEntry[][] readAndCacheClasspath(JavaProject javaProject) { > // read file entries and update status >- IClasspathEntry[] classpath; >+ IClasspathEntry[][] classpath; > IJavaModelStatus status; > try { > classpath = javaProject.readFileEntriesWithException(null/*not interested in unknown elements*/); > status = JavaModelStatus.VERIFIED_OK; > } catch (CoreException e) { >- classpath = JavaProject.INVALID_CLASSPATH; >+ classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES}; > status = > new JavaModelStatus( > IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT, > Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName())); > } catch (IOException e) { >- classpath = JavaProject.INVALID_CLASSPATH; >+ classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES}; > if (Messages.file_badFormat.equals(e.getMessage())) > status = > new JavaModelStatus( >@@ -1228,7 +1239,7 @@ > IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT, > Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName())); > } catch (ClasspathEntry.AssertionFailedException e) { >- classpath = JavaProject.INVALID_CLASSPATH; >+ classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES}; > status = > new JavaModelStatus( > IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT, >@@ -1236,19 +1247,20 @@ > } > > // extract out the output location >+ int rawClasspathLength = classpath[0].length; > IPath output = null; >- if (classpath.length > 0) { >- IClasspathEntry entry = classpath[classpath.length - 1]; >+ if (rawClasspathLength > 0) { >+ IClasspathEntry entry = classpath[0][rawClasspathLength - 1]; > if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { > output = entry.getPath(); >- IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1]; >- System.arraycopy(classpath, 0, copy, 0, copy.length); >- classpath = copy; >+ IClasspathEntry[] copy = new IClasspathEntry[rawClasspathLength - 1]; >+ System.arraycopy(classpath[0], 0, copy, 0, copy.length); >+ classpath[0] = copy; > } > } > > // store new raw classpath, new output and new status, and null out resolved info >- setRawClasspath(classpath, output, status); >+ setRawClasspath(classpath[0], classpath[1], output, status); > > return classpath; > } >@@ -1292,20 +1304,31 @@ > return buffer.toString(); > } > >- public boolean writeAndCacheClasspath(JavaProject javaProject, final IClasspathEntry[] newRawClasspath, final IPath newOutputLocation) throws JavaModelException { >+ public boolean writeAndCacheClasspath( >+ JavaProject javaProject, >+ final IClasspathEntry[] newRawClasspath, >+ IClasspathEntry[] newReferencedEntries, >+ final IPath newOutputLocation) throws JavaModelException { > try { > this.writtingRawClasspath = true; >+ if (newReferencedEntries == null) newReferencedEntries = this.referencedEntries; >+ > // write .classpath >- if (!javaProject.writeFileEntries(newRawClasspath, newOutputLocation)) { >+ if (!javaProject.writeFileEntries(newRawClasspath, newReferencedEntries, newOutputLocation)) { > return false; > } > // store new raw classpath, new output and new status, and null out resolved info >- setRawClasspath(newRawClasspath, newOutputLocation, JavaModelStatus.VERIFIED_OK); >+ setRawClasspath(newRawClasspath, newReferencedEntries, newOutputLocation, JavaModelStatus.VERIFIED_OK); > } finally { > this.writtingRawClasspath = false; > } > return true; > } >+ >+ public boolean writeAndCacheClasspath(JavaProject javaProject, final IClasspathEntry[] newRawClasspath, final IPath newOutputLocation) throws JavaModelException { >+ return writeAndCacheClasspath(javaProject, newRawClasspath, null, newOutputLocation); >+ } >+ > } > > public static class PerWorkingCopyInfo implements IProblemRequestor { >@@ -1819,6 +1842,30 @@ > return container; > } > >+ public IClasspathEntry[] getReferencedClasspathEntries(IClasspathEntry libraryEntry, IJavaProject project) { >+ >+ IClasspathEntry[] referencedEntries = ((ClasspathEntry)libraryEntry).resolvedChainedLibraries(); >+ PerProjectInfo perProjectInfo = getPerProjectInfo(project.getProject(), false); >+ >+ if(perProjectInfo == null) >+ return referencedEntries; >+ >+ List pathToReferencedEntries = new ArrayList(referencedEntries.length); >+ for (int index = 0; index < referencedEntries.length; index++) { >+ >+ if (pathToReferencedEntries.contains(referencedEntries[index].getPath())) >+ continue; >+ >+ IClasspathEntry persistedEntry = null; >+ if ((persistedEntry = (IClasspathEntry)perProjectInfo.rootPathToResolvedEntries.get(referencedEntries[index].getPath())) != null) { >+ // TODO: reconsider this - may want to copy the values instead of reference assignment? >+ referencedEntries[index] = persistedEntry; >+ } >+ pathToReferencedEntries.add(referencedEntries[index].getPath()); >+ } >+ return referencedEntries; >+ } >+ > public DeltaProcessor getDeltaProcessor() { > return this.deltaState.getDeltaProcessor(); > } >@@ -3488,7 +3535,7 @@ > } else { > IClasspathEntry[] entries; > try { >- entries = ((JavaProject) project).decodeClasspath(containerString, null/*not interested in unknown elements*/); >+ entries = ((JavaProject) project).decodeClasspath(containerString, null/*not interested in unknown elements*/)[0]; > } catch (IOException e) { > Util.log(e, "Could not recreate persisted container: \n" + containerString); //$NON-NLS-1$ > entries = JavaProject.INVALID_CLASSPATH; >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.428 >diff -u -r1.428 JavaProject.java >--- model/org/eclipse/jdt/internal/core/JavaProject.java 22 Feb 2010 07:50:00 -0000 1.428 >+++ model/org/eclipse/jdt/internal/core/JavaProject.java 26 Feb 2010 19:38:00 -0000 >@@ -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; >@@ -260,6 +262,20 @@ > return false; > return true; > } >+ >+ private static boolean areClasspathEqual(IClasspathEntry[] first, IClasspathEntry[] second) { >+ if (first != second){ >+ if (first == null) return false; >+ int length = first.length; >+ if (second == null || second.length != length) >+ return false; >+ for (int i = 0; i < length; i++) { >+ if (!first[i].equals(second[i])) >+ return false; >+ } >+ } >+ return true; >+ } > > /** > * Returns a canonicalized path from the given external path. >@@ -848,7 +864,7 @@ > /* > * Reads and decode an XML classpath string > */ >- public IClasspathEntry[] decodeClasspath(String xmlClasspath, Map unknownElements) throws IOException, ClasspathEntry.AssertionFailedException { >+ public IClasspathEntry[][] decodeClasspath(String xmlClasspath, Map unknownElements) throws IOException, ClasspathEntry.AssertionFailedException { > > ArrayList paths = new ArrayList(); > IClasspathEntry defaultOutput = null; >@@ -868,7 +884,7 @@ > if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$ > throw new IOException(Messages.file_badFormat); > } >- NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$ >+ NodeList list = cpElement.getElementsByTagName(ClasspathEntry.TAG_CLASSPATHENTRY); > int length = list.getLength(); > > for (int i = 0; i < length; ++i) { >@@ -880,15 +896,32 @@ > defaultOutput = entry; // separate output > } else { > paths.add(entry); >+ } >+ } > } > } >+ int pathSize = paths.size(); >+ IClasspathEntry[][] entries = new IClasspathEntry[2][]; >+ entries[0] = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)]; >+ paths.toArray(entries[0]); >+ if (defaultOutput != null) entries[0][pathSize] = defaultOutput; // ensure output is last item >+ >+ paths.clear(); >+ list = cpElement.getElementsByTagName(ClasspathEntry.TAG_REFERENCED_ENTRY); >+ length = list.getLength(); >+ >+ for (int i = 0; i < length; ++i) { >+ Node node = list.item(i); >+ if (node.getNodeType() == Node.ELEMENT_NODE) { >+ IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this, unknownElements); >+ if (entry != null){ >+ paths.add(entry); >+ } > } > } >- // return a new empty classpath is it size is 0, to differenciate from an INVALID_CLASSPATH >- int pathSize = paths.size(); >- IClasspathEntry[] entries = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)]; >- paths.toArray(entries); >- if (defaultOutput != null) entries[pathSize] = defaultOutput; // ensure output is last item >+ entries[1] = new IClasspathEntry[paths.size()]; >+ paths.toArray(entries[1]); >+ > return entries; > } > >@@ -911,7 +944,7 @@ > reader.close(); > } > >- if (!node.getNodeName().equalsIgnoreCase("classpathentry") //$NON-NLS-1$ >+ if (!node.getNodeName().equalsIgnoreCase(ClasspathEntry.TAG_CLASSPATHENTRY) > || node.getNodeType() != Node.ELEMENT_NODE) { > return null; > } >@@ -956,7 +989,7 @@ > /** > * Returns the XML String encoding of the class path. > */ >- protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent, Map unknownElements) throws JavaModelException { >+ protected String encodeClasspath(IClasspathEntry[] classpath, IClasspathEntry[] referencedEntries, IPath outputLocation, boolean indent, Map unknownElements) throws JavaModelException { > try { > ByteArrayOutputStream s = new ByteArrayOutputStream(); > OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$ >@@ -964,7 +997,7 @@ > > xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent); > for (int i = 0; i < classpath.length; ++i) { >- ((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements); >+ ((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements, false); > } > > if (outputLocation != null) { >@@ -976,6 +1009,12 @@ > xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true); > } > >+ if (referencedEntries != null) { >+ for (int i = 0; i < referencedEntries.length; ++i) { >+ ((ClasspathEntry) referencedEntries[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements, true); >+ } >+ } >+ > xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent, true/*insert new line*/); > writer.flush(); > writer.close(); >@@ -991,7 +1030,7 @@ > OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$ > XMLWriter xmlWriter = new XMLWriter(writer, this, false/*don't print XML version*/); > >- ((ClasspathEntry)classpathEntry).elementEncode(xmlWriter, this.project.getFullPath(), true/*indent*/, true/*insert new line*/, null/*not interested in unknown elements*/); >+ ((ClasspathEntry)classpathEntry).elementEncode(xmlWriter, this.project.getFullPath(), true/*indent*/, true/*insert new line*/, null/*not interested in unknown elements*/, (classpathEntry.getReferencingEntry() != null)); > > writer.flush(); > writer.close(); >@@ -1841,7 +1880,7 @@ > IClasspathEntry[] classpath = perProjectInfo.rawClasspath; > if (classpath != null) return classpath; > >- classpath = perProjectInfo.readAndCacheClasspath(this); >+ classpath = perProjectInfo.readAndCacheClasspath(this)[0]; > > if (classpath == JavaProject.INVALID_CLASSPATH) > return defaultClasspath(); >@@ -1850,6 +1889,13 @@ > } > > /** >+ * @see IJavaProject >+ */ >+ public IClasspathEntry[] getReferencedClasspathEntries() throws JavaModelException { >+ return getPerProjectInfo().referencedEntries; >+ } >+ >+ /** > * @see IJavaProject#getRequiredProjectNames() > */ > public String[] getRequiredProjectNames() throws JavaModelException { >@@ -2384,7 +2430,7 @@ > * As a side effect, unknown elements are stored in the given map (if not null) > * Throws exceptions if the file cannot be accessed or is malformed. > */ >- public IClasspathEntry[] readFileEntriesWithException(Map unknownElements) throws CoreException, IOException, ClasspathEntry.AssertionFailedException { >+ public IClasspathEntry[][] readFileEntriesWithException(Map unknownElements) throws CoreException, IOException, ClasspathEntry.AssertionFailedException { > IFile rscFile = this.project.getFile(JavaProject.CLASSPATH_FILENAME); > byte[] bytes; > if (rscFile.exists()) { >@@ -2403,7 +2449,7 @@ > bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file); > } catch (IOException e) { > if (!file.exists()) >- return defaultClasspath(); >+ return new IClasspathEntry[][]{defaultClasspath(), ClasspathEntry.NO_ENTRIES}; > throw e; > } > } >@@ -2427,18 +2473,18 @@ > * This includes the output entry. > * As a side effect, unknown elements are stored in the given map (if not null) > */ >- private IClasspathEntry[] readFileEntries(Map unkwownElements) { >+ private IClasspathEntry[][] readFileEntries(Map unkwownElements) { > try { > return readFileEntriesWithException(unkwownElements); > } catch (CoreException e) { > Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$ >- return JavaProject.INVALID_CLASSPATH; >+ return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES}; > } catch (IOException e) { > Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$ >- return JavaProject.INVALID_CLASSPATH; >+ return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES}; > } catch (ClasspathEntry.AssertionFailedException e) { > Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$ >- return JavaProject.INVALID_CLASSPATH; >+ return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES}; > } > } > >@@ -2447,14 +2493,14 @@ > */ > public IPath readOutputLocation() { > // Read classpath file without creating markers nor logging problems >- IClasspathEntry[] classpath = readFileEntries(null/*not interested in unknown elements*/); >- if (classpath == JavaProject.INVALID_CLASSPATH) >+ IClasspathEntry[][] classpath = readFileEntries(null/*not interested in unknown elements*/); >+ if (classpath[0] == JavaProject.INVALID_CLASSPATH) > return defaultOutputLocation(); > > // extract the output location > IPath outputLocation = null; >- if (classpath.length > 0) { >- IClasspathEntry entry = classpath[classpath.length - 1]; >+ if (classpath[0].length > 0) { >+ IClasspathEntry entry = classpath[0][classpath[0].length - 1]; > if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { > outputLocation = entry.getPath(); > } >@@ -2467,20 +2513,20 @@ > */ > public IClasspathEntry[] readRawClasspath() { > // Read classpath file without creating markers nor logging problems >- IClasspathEntry[] classpath = readFileEntries(null/*not interested in unknown elements*/); >- if (classpath == JavaProject.INVALID_CLASSPATH) >+ IClasspathEntry[][] classpath = readFileEntries(null/*not interested in unknown elements*/); >+ if (classpath[0] == JavaProject.INVALID_CLASSPATH) > return defaultClasspath(); > > // discard the output location >- if (classpath.length > 0) { >- IClasspathEntry entry = classpath[classpath.length - 1]; >+ if (classpath[0].length > 0) { >+ IClasspathEntry entry = classpath[0][classpath[0].length - 1]; > if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { >- IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1]; >- System.arraycopy(classpath, 0, copy, 0, copy.length); >- classpath = copy; >+ IClasspathEntry[] copy = new IClasspathEntry[classpath[0].length - 1]; >+ System.arraycopy(classpath[0], 0, copy, 0, copy.length); >+ classpath[0] = copy; > } > } >- return classpath; >+ return classpath[0]; > } > > /** >@@ -2533,14 +2579,45 @@ > IJavaModelStatus unresolvedEntryStatus = JavaModelStatus.VERIFIED_OK; > HashMap rawReverseMap = new HashMap(); > Map rootPathToResolvedEntries = new HashMap(); >+ IClasspathEntry[] referencedEntries = null; > } > > public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException { >+ return resolveClasspath(rawClasspath, null, usePreviousSession, resolveChainedLibraries); >+ } >+ >+ public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, IClasspathEntry[] referencedEntries, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException { > JavaModelManager manager = JavaModelManager.getJavaModelManager(); > ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager(); > ResolvedClasspath result = new ResolvedClasspath(); > >+ Map referencedEntriesMap = 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) { >+ rawLibrariesPath.add(ClasspathEntry.resolveDotDot(currentEntry.getPath())); >+ } >+ } >+ if (referencedEntries != null) { >+ // The Set is required to keep the order intact while the referencedEntriesMap (Map) >+ // is used to map the referenced entries with path >+ LinkedHashSet referencedEntriesSet = new LinkedHashSet(); >+ for (int index = 0; index < referencedEntries.length; index++) { >+ IPath path = referencedEntries[index].getPath(); >+ if (!rawLibrariesPath.contains(path) && referencedEntriesMap.get(path) == null) { >+ referencedEntriesMap.put(path, referencedEntries[index]); >+ referencedEntriesSet.add(referencedEntries[index]); >+ } >+ } >+ result.referencedEntries = new IClasspathEntry[referencedEntriesSet.size()]; >+ referencedEntriesSet.toArray(result.referencedEntries); >+ } >+ } >+ > int length = rawClasspath.length; > for (int i = 0; i < length; i++) { > >@@ -2561,14 +2638,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, referencedEntriesMap, true); >+ } > } > } >- addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); >+ addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false); > } > break; > >@@ -2603,15 +2685,17 @@ > // 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, referencedEntriesMap, true); >+ } > } > } > } >- addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager); >+ addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false); > } > break; > >@@ -2619,18 +2703,20 @@ > // 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(); > 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, referencedEntriesMap, true); >+ } > } > } > >- addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); >+ addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false); > break; > default : >- addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); >+ addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false); > break; > } > } >@@ -2639,18 +2725,49 @@ > return result; > } > >- private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager) { >+ private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, >+ LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager, >+ Map oldChainedEntriesMap, 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) { > result.rawReverseMap.put(resolvedPath, rawEntry); > result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry); > resolvedEntries.add(resolvedEntry); >+ if (addAsChainedEntry) { >+ IClasspathEntry chainedEntry = null; >+ if (rawEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { >+ >+ chainedEntry = (ClasspathEntry) oldChainedEntriesMap.get(resolvedPath); >+ if (chainedEntry != null) { >+ // 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 (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) { > externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered > } > } > >+ 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. > */ >@@ -2665,22 +2782,24 @@ > } > > // get raw info inside a synchronized block to ensure that it is consistent >- IClasspathEntry[] rawClasspath; >+ IClasspathEntry[][] classpath = new IClasspathEntry[2][]; > int timeStamp; > synchronized (perProjectInfo) { >- rawClasspath= perProjectInfo.rawClasspath; >- if (rawClasspath == null) >- rawClasspath = perProjectInfo.readAndCacheClasspath(this); >+ classpath[0] = perProjectInfo.rawClasspath; >+ classpath[1] = perProjectInfo.referencedEntries; >+ // Checking null only for rawClasspath enough >+ if (classpath[0] == null) >+ classpath = perProjectInfo.readAndCacheClasspath(this); > timeStamp = perProjectInfo.rawTimeStamp; > } >- >- ResolvedClasspath result = resolveClasspath(rawClasspath, usePreviousSession, true/*resolve chained libraries*/); > >+ ResolvedClasspath result = resolveClasspath(classpath[0], classpath[1], usePreviousSession, true/*resolve chained libraries*/); >+ > if (CP_RESOLUTION_BP_LISTENERS != null) > breakpoint(2, this); > > // store resolved info along with the raw info to ensure consistency >- perProjectInfo.setResolvedClasspath(result.resolvedClasspath, result.rawReverseMap, result.rootPathToResolvedEntries, usePreviousSession ? PerProjectInfo.NEED_RESOLUTION : result.unresolvedEntryStatus, timeStamp, addClasspathChange); >+ perProjectInfo.setResolvedClasspath(result.resolvedClasspath, result.referencedEntries, result.rawReverseMap, result.rootPathToResolvedEntries, usePreviousSession ? PerProjectInfo.NEED_RESOLUTION : result.unresolvedEntryStatus, timeStamp, addClasspathChange); > } finally { > if (!isClasspathBeingResolved) { > manager.setClasspathBeingResolved(this, false); >@@ -2708,25 +2827,30 @@ > * @return boolean Return whether the .classpath file was modified. > * @throws JavaModelException > */ >- public boolean writeFileEntries(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException { >+ public boolean writeFileEntries(IClasspathEntry[] newClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation) throws JavaModelException { > > if (!this.project.isAccessible()) return false; > > Map unknownElements = new HashMap(); >- IClasspathEntry[] fileEntries = readFileEntries(unknownElements); >- if (fileEntries != JavaProject.INVALID_CLASSPATH && areClasspathsEqual(newClasspath, newOutputLocation, fileEntries)) { >+ IClasspathEntry[][] fileEntries = readFileEntries(unknownElements); >+ if (fileEntries[0] != JavaProject.INVALID_CLASSPATH && >+ areClasspathsEqual(newClasspath, newOutputLocation, fileEntries[0]) >+ && areClasspathEqual(referencedEntries, fileEntries[1])) { > // no need to save it, it is the same > return false; > } > > // actual file saving > try { >- setSharedProperty(JavaProject.CLASSPATH_FILENAME, encodeClasspath(newClasspath, newOutputLocation, true, unknownElements)); >+ setSharedProperty(JavaProject.CLASSPATH_FILENAME, encodeClasspath(newClasspath, referencedEntries, newOutputLocation, true, unknownElements)); > return true; > } catch (CoreException e) { > throw new JavaModelException(e); > } > } >+ public boolean writeFileEntries(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException { >+ return writeFileEntries(newClasspath, ClasspathEntry.NO_ENTRIES, newOutputLocation); >+ } > > /** > * Update the Java command in the build spec (replace existing one if present, >@@ -2874,22 +2998,7 @@ > boolean canModifyResources, > IProgressMonitor monitor) > throws JavaModelException { >- >- try { >- if (newRawClasspath == null) //are we already with the default classpath >- newRawClasspath = defaultClasspath(); >- >- SetClasspathOperation op = >- new SetClasspathOperation( >- this, >- newRawClasspath, >- newOutputLocation, >- canModifyResources); >- op.runOperation(monitor); >- } catch (JavaModelException e) { >- JavaModelManager.getJavaModelManager().getDeltaProcessor().flush(); >- throw e; >- } >+ setRawClasspath(newRawClasspath, null, newOutputLocation, canModifyResources, monitor); > } > > /** >@@ -2907,6 +3016,32 @@ > true/*can change resource (as per API contract)*/, > monitor); > } >+ >+ public void setRawClasspath(IClasspathEntry[] entries, IClasspathEntry[] referencedEntries, IPath outputLocation, >+ IProgressMonitor monitor) throws JavaModelException { >+ setRawClasspath(entries, referencedEntries, outputLocation, true, monitor); >+ } >+ >+ protected void setRawClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation, >+ boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException { >+ >+ try { >+ if (newRawClasspath == null) //are we already with the default classpath >+ newRawClasspath = defaultClasspath(); >+ >+ SetClasspathOperation op = >+ new SetClasspathOperation( >+ this, >+ newRawClasspath, >+ referencedEntries, >+ newOutputLocation, >+ canModifyResources); >+ op.runOperation(monitor); >+ } catch (JavaModelException e) { >+ JavaModelManager.getJavaModelManager().getDeltaProcessor().flush(); >+ throw e; >+ } >+ } > > /** > * @see IJavaProject >Index: model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java,v >retrieving revision 1.134 >diff -u -r1.134 PackageFragmentRoot.java >--- model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java 25 Nov 2008 14:38:15 -0000 1.134 >+++ model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java 26 Feb 2010 19:38:00 -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 >@@ -554,6 +554,22 @@ > } > return rawEntry; > } >+/* >+ * @see IPackageFragmentRoot >+ */ >+public IClasspathEntry getResolvedClasspathEntry() throws JavaModelException { >+ IClasspathEntry resolvedEntry = null; >+ JavaProject project = (JavaProject)getJavaProject(); >+ project.getResolvedClasspath(); // force the reverse rawEntry cache to be populated >+ Map rootPathToResolvedEntries = project.getPerProjectInfo().rootPathToResolvedEntries; >+ if (rootPathToResolvedEntries != null) { >+ resolvedEntry = (IClasspathEntry) rootPathToResolvedEntries.get(getPath()); >+ } >+ if (resolvedEntry == null) { >+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH, this)); >+ } >+ return resolvedEntry; >+} > > > public IResource resource() { >Index: model/org/eclipse/jdt/internal/core/SetClasspathOperation.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java,v >retrieving revision 1.156 >diff -u -r1.156 SetClasspathOperation.java >--- model/org/eclipse/jdt/internal/core/SetClasspathOperation.java 10 Oct 2008 09:48:05 -0000 1.156 >+++ model/org/eclipse/jdt/internal/core/SetClasspathOperation.java 26 Feb 2010 19:38:00 -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 >@@ -30,21 +30,33 @@ > public class SetClasspathOperation extends ChangeClasspathOperation { > > IClasspathEntry[] newRawClasspath; >+ IClasspathEntry[] referencedEntries; > IPath newOutputLocation; > JavaProject project; > >+ public SetClasspathOperation( >+ JavaProject project, >+ IClasspathEntry[] newRawClasspath, >+ IPath newOutputLocation, >+ boolean canChangeResource) { >+ >+ this(project, newRawClasspath, null, newOutputLocation, canChangeResource); >+ } >+ > /** > * When executed, this operation sets the raw classpath and output location of the given project. > */ > public SetClasspathOperation( > JavaProject project, > IClasspathEntry[] newRawClasspath, >+ IClasspathEntry[] referencedEntries, > IPath newOutputLocation, > boolean canChangeResource) { > > super(new IJavaElement[] { project }, canChangeResource); > this.project = project; > this.newRawClasspath = newRawClasspath; >+ this.referencedEntries = referencedEntries; > this.newOutputLocation = newOutputLocation; > } > >@@ -56,7 +68,7 @@ > try { > // set raw classpath and null out resolved info > PerProjectInfo perProjectInfo = this.project.getPerProjectInfo(); >- ClasspathChange classpathChange = perProjectInfo.setRawClasspath(this.newRawClasspath, this.newOutputLocation, JavaModelStatus.VERIFIED_OK/*format is ok*/); >+ ClasspathChange classpathChange = perProjectInfo.setRawClasspath(this.newRawClasspath, this.referencedEntries, this.newOutputLocation, JavaModelStatus.VERIFIED_OK/*format is ok*/); > > // if needed, generate delta, update project ref, create markers, ... > classpathChanged(classpathChange); >#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.207 >diff -u -r1.207 ClasspathTests.java >--- src/org/eclipse/jdt/core/tests/model/ClasspathTests.java 22 Feb 2010 07:50:08 -0000 1.207 >+++ src/org/eclipse/jdt/core/tests/model/ClasspathTests.java 26 Feb 2010 19:38:01 -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 = "testBug252341c"; >+// TESTS_NAMES = new String[] {"testClasspathWithNonExistentLibraryEntry"}; > // TESTS_NUMBERS = new int[] { 23, 28, 38 }; > // TESTS_RANGE = new int[] { 21, 38 }; > } >@@ -6116,5 +6116,316 @@ > deleteExternalResource("lib.jar"); > } > } >+/** >+ * @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. >+ * 5) referenced libraries and their attributes are persisted in the .classpath file >+ * >+ * @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", ""); >+ >+ // Test referenced entries are included in the right order in the resolved classpath >+ 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]"); >+ >+ // Test referenced entries for a particular entry appear in the right order and the referencingEntry >+ // attribute has the correct value >+ IClasspathEntry[] chains = JavaCore.getReferencedClasspathEntries(rawClasspath[2], p); >+ assertClasspathEquals(chains, >+ "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + >+ "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); >+ >+ assertSame("Referencing Entry", rawClasspath[2], chains[0].getReferencingEntry()); >+ assertSame("Referencing Entry", rawClasspath[2], chains[1].getReferencingEntry()); >+ >+ // Test a newly created library entry with similar attributes but without any referencing entry is equal to >+ // the original referenced entry >+ IClasspathEntry tempLibEntry = JavaCore.newLibraryEntry(chains[0].getPath(), chains[0].getSourceAttachmentPath(), chains[0].getSourceAttachmentRootPath(), true); >+ assertEquals("Library Entry", tempLibEntry, chains[0]); >+ >+ // Test the source attachment and other attributes added to the referenced entries are stored and retrieved properly >+ 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, chains, p.getOutputLocation(), null); >+ >+ // Test the .classpath file contains all the referenced entries and their attributes >+ String contents = new String (org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath"))); >+ assertSourceEquals( >+ "Unexpected content", >+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + >+ "<classpath>\n" + >+ " <classpathentry kind=\"src\" path=\"\"/>\n" + >+ " <classpathentry kind=\"var\" path=\"JCL_LIB\"/>\n" + >+ " <classpathentry exported=\"true\" kind=\"lib\" path=\"lib1.jar\" sourcepath=\"abc.zip\"/>\n" + >+ " <classpathentry kind=\"output\" path=\"\"/>\n" + >+ " <referencedentry exported=\"true\" kind=\"lib\" path=\"lib2.jar\" rootpath=\"/src2\" sourcepath=\"efg.zip\">\n" + >+ " <attributes>\n" + >+ " <attribute name=\"javadoc_location\" value=\"/P/efg.zip\"/>\n" + >+ " </attributes>\n" + >+ " </referencedentry>\n" + >+ " <referencedentry exported=\"true\" kind=\"lib\" path=\"lib3.jar\" rootpath=\"/src3\" sourcepath=\"xyz.zip\"/>\n" + >+ "</classpath>\n", >+ contents); >+ >+ p.close(); >+ p.open(null); >+ rawClasspath = p.getRawClasspath(); >+ resolvedClasspath = p.getResolvedClasspath(true); >+ >+ 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]"); >+ >+ 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 >+ * 2) Removing one of the top-level library from the raw classpath doesn't remove the referenced >+ * entry that was commonly referenced by another entry and the referenced entry's source >+ * attachment and other attributes are retained. >+ * 3) Passing a NULL referencedEntries array retains the referenced entries >+ * 4) Passing an empty array as referencedEntries clears the earlier referenced entries >+ * >+ * @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", ""); >+ >+ // Test that the referenced entries are not included in the raw classpath >+ 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[] rawEntries = new IClasspathEntry[2]; >+ rawEntries[0] = JavaCore.newLibraryEntry(new Path("/P/lib1.jar"), null, null, true); >+ rawEntries[1] = JavaCore.newLibraryEntry(new Path("/P/lib2.jar"), null, null, true); >+ >+ // Test that the referenced entries are included in the raw classpath and in the right order >+ 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]"); >+ >+ // Test that the referenced classpath entries has the appropriate referencingEntry value >+ IClasspathEntry[] chains = JavaCore.getReferencedClasspathEntries(rawEntries[0], p); >+ assertClasspathEquals( >+ chains, >+ "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + >+ "/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); >+ assertEquals("Referencing Entry" , rawEntries[0], chains[0].getReferencingEntry()); >+ assertEquals("Referencing Entry" , rawEntries[0], chains[1].getReferencingEntry()); >+ >+ chains = JavaCore.getReferencedClasspathEntries(rawEntries[1], p); >+ assertClasspathEquals( >+ chains, >+ "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + >+ "/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); >+ >+ assertEquals("Referencing Entry" , rawEntries[0], chains[0].getReferencingEntry()); >+ assertEquals("Referencing Entry" , rawEntries[1], chains[1].getReferencingEntry()); >+ >+// // Test IPackageFragmentRoot#getResolvedClasspathEntry >+ IPackageFragmentRoot[] roots = p.getPackageFragmentRoots(); >+ assertEquals("Package fragment root", roots[2].getResolvedClasspathEntry(), resolvedClasspath[2]); >+ assertEquals("Package fragment root", roots[3].getResolvedClasspathEntry(), resolvedClasspath[3]); >+ assertEquals("Package fragment root", roots[4].getResolvedClasspathEntry(), resolvedClasspath[4]); >+ assertEquals("Package fragment root", roots[5].getResolvedClasspathEntry(), resolvedClasspath[5]); >+ assertEquals("Package fragment root", roots[6].getResolvedClasspathEntry(), resolvedClasspath[6]); >+ >+ // Test the attributes added to the referenced classpath entries are stored and retrieved properly >+ ((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, chains, p.getOutputLocation(), 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][sourcePath:/P/efg.zip][rootPath:/src2][isExported:true][attributes:javadoc_location=/P/efg.zip]\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][sourcePath:/P/xyz.zip][rootPath:/src3][isExported:true]\n" + >+ "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); >+ >+ // Test that removing any of the referencing entry from the raw classpath has the correct effect >+ // on the resolved classpath. Also test passing referencedEntries = null retains the existing >+ // referenced entries >+ 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, p.getOutputLocation(), 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][sourcePath:/P/efg.zip][rootPath:/src2][isExported:true][attributes:javadoc_location=/P/efg.zip]\n" + >+ "/P/lib5.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/xyz.zip][rootPath:/src3][isExported:true]\n" + >+ "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); >+ >+ // Test that passing empty array of referencedEntries clears all the earlier ones. >+ p.setRawClasspath(newRawClasspath, new IClasspathEntry[]{}, p.getOutputLocation(), 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 duplicate referenced entries or entries that are already present in the raw classpath >+ * are excluded from the referenced entries when invoking >+ * {@link IJavaProject#setRawClasspath(IClasspathEntry[], IClasspathEntry[], IPath, IProgressMonitor)} >+ * >+ * @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: 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(); >+ >+ IClasspathEntry[] rawEntries = new IClasspathEntry[2]; >+ rawEntries[0] = JavaCore.newLibraryEntry(new Path("/P/lib1.jar"), null, null, true); >+ rawEntries[1] = JavaCore.newLibraryEntry(new Path("/P/lib2.jar"), null, null, true); >+ >+ // Test that the referenced classpath entries has the appropriate referencingEntry value >+ IClasspathEntry[] chains = JavaCore.getReferencedClasspathEntries(rawEntries[0], p); >+ >+ IClasspathEntry[] referencedEntries = new IClasspathEntry[5]; >+ referencedEntries[0] = chains[0]; >+ referencedEntries[1] = chains[1]; >+ >+ chains = JavaCore.getReferencedClasspathEntries(rawEntries[1], p); >+ >+ referencedEntries[2] = chains[0]; >+ referencedEntries[3] = chains[1]; >+ referencedEntries[4] = chains[1]; >+ >+ p.setRawClasspath(rawClasspath, referencedEntries, p.getOutputLocation(), null); >+ >+ p.close(); >+ p.open(null); >+ >+ IClasspathEntry[] storedReferencedEnties = p.getReferencedClasspathEntries(); >+ assertClasspathEquals(storedReferencedEnties, >+ "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + >+ "/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + >+ "/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); >+ } >+ finally { >+ deleteProject("P"); >+ } >+} > > }
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 281551
:
140203
|
140271
|
140280
|
150497
|
160194
|
160304
| 160356