### 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 4 Feb 2010 07:36:02 -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 @@ -105,6 +105,7 @@ *

* * @see JavaCore#newLibraryEntry(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath) + * @see JavaCore#newLibraryEntry(IPath, IPath, IPath, IClasspathEntry, IClasspathEntry[], boolean, IAccessRule[], IClasspathAttribute[], boolean) * @see JavaCore#newProjectEntry(org.eclipse.core.runtime.IPath) * @see JavaCore#newSourceEntry(org.eclipse.core.runtime.IPath) * @see JavaCore#newVariableEntry(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath) @@ -418,6 +419,64 @@ */ IPath getSourceAttachmentRootPath(); + + /** + * Returns the library entry that is referencing this classpath entry. For CPE_LIBRARY, + * this is the classpath entry that is representing the jar that mentions this + * in the Class-Path clause of it's MANIFEST. For entry kinds other than CPE_LIBRARY, + * this returns null. + * + * @return the classpath entry that is referencing this entry. + * @since 3.6 + */ + IClasspathEntry getReferencingEntry(); + + /** + * Returns an array of classpath entries that are chained to 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 chained library is already part of the raw classpath of the project, that will not be + * included in the returned list. + *

+ * The chained 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 classpath of a project - when a same + * (chained) library is referenced in more than one library entry {@link #CPE_LIBRARY}, the + * chained 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 chained jars + * while the second gets none.
  • + *
  • If a chained library is also directly part of the raw classpath, it does not get added + * as chained library to any entry.
  • + *
  • {@link IClasspathEntry#excludeChainedJars()} - If this flag is turned on for this + * classpath entry, then no chained libraries get added to this. Apart from this, + * it could also affect the chained libraries of the other classpath entries in the project's + * raw classpath. + *

    + *

    + * The chained libraries themselves will not have any further chained entries. The order of the + * chained 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. + * @since 3.6 + */ + IClasspathEntry[] getChainedEntries(); + + /** + * Returns whether the chained Jars should be included as part of the resolved build path. + * For entry kinds other than library {@link #CPE_LIBRARY}, this flag does not affect the + * classpath in any way. Setting this flag off will detach all the chained entries from + * this entry at once. However, this does not always guarantee that these + * libraries will be removed from the resolved classpath. + *

    + * For more, refer to {@link IClasspathEntry#getChainedEntries()}

    + * + * @return whether or not the chained jars should be excluded from this classpath entry. + * @since 3.6 + */ + boolean excludeChainedJars(); + /** * Returns whether this entry is exported to dependent projects. * Always returns false 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 4 Feb 2010 07:36:03 -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 @@ -611,7 +611,10 @@ * The resulting resolved classpath is accurate for the given point in time. * If the project's raw classpath is later modified, or if classpath * variables are changed, the resolved classpath can become out of date. - * Because of this, hanging on resolved classpath is not recommended. + * Because of this, hanging on resolved classpath is not recommended. + * One such classpath attributes that can affect the resolved classpath is + * {@link IClasspathEntry#excludeChainedJars()}. This flag determines whether or + * not referenced (or chained) jars are included in the resolved classpath. *

    *

    * Note that if the resolution creates duplicate entries 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.647 diff -u -r1.647 JavaCore.java --- model/org/eclipse/jdt/core/JavaCore.java 13 Jan 2010 15:13:42 -0000 1.647 +++ model/org/eclipse/jdt/core/JavaCore.java 4 Feb 2010 07:36:10 -0000 @@ -3993,6 +3993,94 @@ * Creates and returns a new classpath entry of kind CPE_LIBRARY for the JAR or folder * identified by the given absolute path. This specifies that all package fragments within the root * will have children of type IClassFile. + * This method is fully equivalent to calling + * {@link #newLibraryEntry(IPath, IPath, IPath, IClasspathEntry[], boolean, IAccessRule[], IClasspathAttribute[], boolean) + * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, ClasspathEntry.NO_ENTRIES, false, new IAccessRule[0], new IClasspathAttribute[0], isExported)}. + * + * @param path the path to the library + * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, + * or null if none. Note, since 3.0, an empty path is allowed to denote no source attachment. + * and will be automatically converted to null. Since 3.4, this path can also denote a path external + * to the workspace. + * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder + * or null if this location should be automatically detected. + * @param accessRules the possibly empty list of access rules for this entry + * @param extraAttributes the possibly empty list of extra attributes to persist with this entry + * @param isExported indicates whether this entry is contributed to dependent + * projects in addition to the output location + * @return a new library classpath entry + * @since 3.1 + */ + public static IClasspathEntry newLibraryEntry( + IPath path, + IPath sourceAttachmentPath, + IPath sourceAttachmentRootPath, + IAccessRule[] accessRules, + IClasspathAttribute[] extraAttributes, + boolean isExported) { + + return newLibraryEntry( + path, + sourceAttachmentPath, + sourceAttachmentRootPath, + ClasspathEntry.NO_ENTRIES, + false, + accessRules, + extraAttributes, + isExported); + } + + + /** + * Creates and returns a new classpath entry of kind CPE_LIBRARY for the JAR or folder + * identified by the given absolute path. This specifies that all package fragments within the root + * will have children of type IClassFile. + * This method is fully equivalent to calling + * {@link #newLibraryEntry(IPath, IPath, IPath, IClasspathEntry, IClasspathEntry[], boolean, IAccessRule[], IClasspathAttribute[], boolean) + * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, null, chainedEntries, false, new IAccessRule[0], new IClasspathAttribute[0], isExported)}. + * + * @param path the path to the library + * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, + * or null if none. Note, since 3.0, an empty path is allowed to denote no source attachment. + * and will be automatically converted to null. Since 3.4, this path can also denote a path external + * to the workspace. + * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder + * or null if this location should be automatically detected. + * @param chainedEntries the libraries that are chained to this entry, e.g. via MANIFEST file + * @param excludeChained indicates whether the chained library entries need to be resolved or not. + * @param accessRules the possibly empty list of access rules for this entry + * @param extraAttributes the possibly empty list of extra attributes to persist with this entry + * @param isExported indicates whether this entry is contributed to dependent + * projects in addition to the output location + * @return a new library classpath entry + * @since 3.6 + */ + public static IClasspathEntry newLibraryEntry( + IPath path, + IPath sourceAttachmentPath, + IPath sourceAttachmentRootPath, + IClasspathEntry[] chainedEntries, + boolean excludeChained, + IAccessRule[] accessRules, + IClasspathAttribute[] extraAttributes, + boolean isExported) { + + return newLibraryEntry( + path, + sourceAttachmentPath, + sourceAttachmentRootPath, + null, + chainedEntries, + excludeChained, + accessRules, + extraAttributes, + isExported); + } + + /** + * Creates and returns a new classpath entry of kind CPE_LIBRARY for the JAR or folder + * identified by the given absolute path. This specifies that all package fragments within the root + * will have children of type IClassFile. *

    * A library entry is used to denote a prerequisite JAR or root folder containing binaries. * The target JAR can either be defined internally to the workspace (absolute path relative @@ -4038,8 +4126,7 @@ *

    * Since 3.5, if the libray is a ZIP archive, the "Class-Path" clause (if any) in the "META-INF/MANIFEST.MF" is read * and referenced ZIP archives are added to the {@link IJavaProject#getResolvedClasspath(boolean) resolved classpath}. - *

    - * + *

    * @param path the path to the library * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, * or null if none. Note, since 3.0, an empty path is allowed to denote no source attachment. @@ -4047,17 +4134,23 @@ * to the workspace. * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder * or null if this location should be automatically detected. + * @param referencingEntry the library entry that refers to this library entry, e.g. via MANIFEST file + * @param chainedEntries the libraries that are chained to this entry, e.g. via MANIFEST file + * @param excludeChained indicates whether the chained library entries need to be resolved or not. * @param accessRules the possibly empty list of access rules for this entry * @param extraAttributes the possibly empty list of extra attributes to persist with this entry * @param isExported indicates whether this entry is contributed to dependent * projects in addition to the output location * @return a new library classpath entry - * @since 3.1 + * @since 3.6 */ public static IClasspathEntry newLibraryEntry( IPath path, IPath sourceAttachmentPath, IPath sourceAttachmentRootPath, + IClasspathEntry referencingEntry, + IClasspathEntry[] chainedEntries, + boolean excludeChained, IAccessRule[] accessRules, IClasspathAttribute[] extraAttributes, boolean isExported) { @@ -4089,6 +4182,9 @@ sourceAttachmentPath, sourceAttachmentRootPath, null, // specific output folder + referencingEntry, + chainedEntries, + excludeChained, isExported, accessRules, false, // no access rules to combine 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 4 Feb 2010 07:36:12 -0000 @@ -92,11 +92,14 @@ 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$ public static final String TAG_DISCOURAGED = "discouraged"; //$NON-NLS-1$ public static final String TAG_IGNORE_IF_BETTER = "ignoreifbetter"; //$NON-NLS-1$ + public static final String TAG_EXCLUDE_CHAINED = "excludechained"; //$NON-NLS-1$ /** * Describes the kind of classpath entry - one of @@ -141,7 +144,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 +200,13 @@ * a non-null value. */ public IPath sourceAttachmentRootPath; + + public IClasspathEntry[] chainedEntries; + + public IClasspathEntry referencingEntry; + + public boolean excludeChainedJars = false; + /** * Specific output location (for this source entry) @@ -220,6 +230,37 @@ */ 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, + null, + false, + isExported, + accessRules, + combineAccessRules, + extraAttributes); + } + /** * Creates a class path entry of the specified kind with the given path. */ @@ -232,6 +273,9 @@ IPath sourceAttachmentPath, IPath sourceAttachmentRootPath, IPath specificOutputLocation, + IClasspathEntry referencingEntry, + IClasspathEntry[] chainedEntries, + boolean excludeChainedJars, boolean isExported, IAccessRule[] accessRules, boolean combineAccessRules, @@ -242,7 +286,10 @@ this.path = path; this.inclusionPatterns = inclusionPatterns; this.exclusionPatterns = exclusionPatterns; - + this.referencingEntry = referencingEntry; + this.excludeChainedJars = excludeChainedJars; + this.chainedEntries = chainedEntries; + int length; if (accessRules != null && (length = accessRules.length) > 0) { AccessRule[] rules = new AccessRule[length]; @@ -379,6 +426,43 @@ System.arraycopy(result, 0, result = new IAccessRule[index], 0, index); return result; } + + static IClasspathEntry[] decodeReferences(NodeList list, IClasspathEntry parent) { + 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; + String path = elementReference.getAttribute(TAG_PATH); + String sourceAttachment = elementReference.getAttribute(TAG_SOURCEPATH); + String sourceRoot = elementReference.getAttribute(TAG_ROOTPATH); + result[index++] = + new ClasspathEntry( + parent.getContentKind(), + parent.getEntryKind(), + new Path(path), + parent.getInclusionPatterns(), + parent.getExclusionPatterns(), + "".equals(sourceAttachment) ? null : new Path(sourceAttachment), //$NON-NLS-1$ + "".equals(sourceRoot) ? null : new Path(sourceRoot), //$NON-NLS-1$ + parent.getOutputLocation(), + parent, + new IClasspathEntry[0], + parent.excludeChainedJars(), + parent.isExported(), + parent.getAccessRules(), + parent.combineAccessRules(), + parent.getExtraAttributes()); + } + } + 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 +578,13 @@ 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(); - } - } + encodePathAttributes(projectPath, parameters); + + if (this.entryKind == IClasspathEntry.CPE_LIBRARY) { + if (this.excludeChainedJars) { + parameters.put(TAG_EXCLUDE_CHAINED, "true"); //$NON-NLS-1$ } } - 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)); - } if (this.isExported) { parameters.put(TAG_EXPORTED, "true");//$NON-NLS-1$ } @@ -553,12 +614,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 hasChainedEntries = getChainedEntries().length > 0 ? true : false; + + /* close tag if no extra attributes, no restriction, no unknown children and no chained 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 && !hasChainedEntries); if (hasExtraAttributes) encodeExtraAttributes(writer, indent, newLine); @@ -566,13 +630,49 @@ if (hasRestrictions) encodeAccessRules(writer, indent, newLine); + if (this.getChainedEntries().length > 0) { + encodeReferences(writer, projectPath, indent, newLine); + } if (hasUnknownChildren) encodeUnknownChildren(writer, indent, newLine, unknownChildren); - if (hasExtraAttributes || hasRestrictions || hasUnknownChildren) + if (hasExtraAttributes || hasRestrictions || hasUnknownChildren || hasChainedEntries) 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 +717,18 @@ 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 = getChainedEntries(); + for (int index = 0, length = references.length; index < length; index++) { + // Set the capacity to maximum possible + HashMap parameters = new HashMap(3); + ((ClasspathEntry)references[index]).encodePathAttributes(projectPath, parameters); + writer.printTag(TAG_REFERENCE, parameters, indent, newLine, true); + } + 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++) { @@ -657,7 +769,8 @@ // exported flag (optional) boolean isExported = removeAttribute(TAG_EXPORTED, attributes).equals("true"); //$NON-NLS-1$ - + boolean excludeChained = removeAttribute(TAG_EXCLUDE_CHAINED, attributes).equals("true"); //$NON-NLS-1$ + // inclusion patterns (optional) IPath[] inclusionPatterns = decodePatterns(attributes, TAG_INCLUDING); if (inclusionPatterns == null) inclusionPatterns = INCLUDE_ALL; @@ -685,35 +798,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) { @@ -738,9 +822,14 @@ path, sourceAttachmentPath, sourceAttachmentRootPath, + null, + excludeChained, accessRules, extraAttributes, isExported); + NodeList referencesList = getChildAttributes(TAG_REFERENCES, children, foundChildren); + IClasspathEntry[] references = decodeReferences(referencesList, entry); + ((ClasspathEntry)entry).setChainedEntries(references); break; case IClasspathEntry.CPE_SOURCE : // must be an entry in this project or specify another project @@ -807,6 +896,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(); @@ -1019,6 +1137,9 @@ if (this.entryKind != otherEntry.getEntryKind()) return false; + if (this.excludeChainedJars != otherEntry.excludeChainedJars()) + return false; + if (this.isExported != otherEntry.isExported()) return false; @@ -1178,6 +1299,26 @@ return this.sourceAttachmentRootPath; } + + public boolean excludeChainedJars() { + return this.excludeChainedJars; + } + + public IClasspathEntry getReferencingEntry() { + return this.referencingEntry; + } + + public IClasspathEntry[] getChainedEntries() { + if (this.chainedEntries == null) { + this.chainedEntries = new IClasspathEntry[0]; + } + return this.chainedEntries; + } + + public void setChainedEntries(IClasspathEntry[] entries) { + this.chainedEntries = entries; + } + /** * Returns the hash code for this classpath entry */ @@ -1380,6 +1521,9 @@ getSourceAttachmentPath(), getSourceAttachmentRootPath(), getOutputLocation(), + this.getReferencingEntry(), + this.getChainedEntries(), + this.excludeChainedJars(), this.isExported, getAccessRules(), this.combineAccessRules, @@ -1398,18 +1542,21 @@ ClasspathEntry[] result = new ClasspathEntry[length]; for (int i = 0; i < length; i++) { result[i] = new ClasspathEntry( - getContentKind(), - getEntryKind(), - paths[i], - this.inclusionPatterns, - this.exclusionPatterns, - getSourceAttachmentPath(), - getSourceAttachmentRootPath(), - getOutputLocation(), - this.isExported, - getAccessRules(), - this.combineAccessRules, - this.extraAttributes); + getContentKind(), + getEntryKind(), + paths[i], + this.inclusionPatterns, + this.exclusionPatterns, + null, + null, + getOutputLocation(), + this, + null, + false, + this.isExported, + getAccessRules(), + this.combineAccessRules, + this.extraAttributes); } 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 4 Feb 2010 07:36:14 -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 @@ -19,6 +19,7 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -2541,6 +2542,7 @@ ResolvedClasspath result = new ResolvedClasspath(); LinkedHashSet resolvedEntries = new LinkedHashSet(); + Set newChainedEntries = new LinkedHashSet(); int length = rawClasspath.length; for (int i = 0; i < length; i++) { @@ -2565,10 +2567,10 @@ // resolve Class-Path: in manifest ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries(); for (int j = 0, length2 = extraEntries.length; j < length2; j++) { - addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager, true); } } - addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, false); } break; @@ -2607,11 +2609,11 @@ // 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); + addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, true); } } } - addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager, false); } break; @@ -2620,30 +2622,96 @@ resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot(); if (resolveChainedLibraries) { - // 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 (rawEntry.excludeChainedJars()) { + ((ClasspathEntry)rawEntry).setChainedEntries(new IClasspathEntry[0]); + } else { + // resolve Class-Path: in manifest + ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries(); + for (int k = 0, length2 = extraEntries.length; k < length2; k++) { + newChainedEntries.add(extraEntries[k].getPath()); + addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, true); + } } } - - addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, false); break; default : - addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager); + addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, false); break; } } + + if (resolveChainedLibraries && newChainedEntries.size() > 0) { + populateChainedEntries(rawClasspath, result, newChainedEntries); + } result.resolvedClasspath = new IClasspathEntry[resolvedEntries.size()]; resolvedEntries.toArray(result.resolvedClasspath); return result; } - private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager) { + private void populateChainedEntries(IClasspathEntry[] rawClasspath, ResolvedClasspath result, Set newChainedEntries) { + // Collect the old chained entries before overwriting them as these potentially have + // the old attributes user added + Map oldChainedEntries = new HashMap(); + for (int index = 0; index < rawClasspath.length; index++) { + if (rawClasspath[index].getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + IClasspathEntry[] chainedEntries = ((ClasspathEntry)rawClasspath[index]).getChainedEntries(); + for (int chainIndex = 0; chainIndex < chainedEntries.length; chainIndex++) { + oldChainedEntries.put(chainedEntries[chainIndex].getPath(), chainedEntries[chainIndex]); + } + } + } + + Map rawEntryChainsMap = new HashMap(); + Iterator iter = newChainedEntries.iterator(); + while (iter.hasNext()) { + IPath chainedEntryPath = (IPath) iter.next(); + IClasspathEntry rawEntry = (IClasspathEntry)result.rawReverseMap.get(chainedEntryPath); + // Filter out the chained libraries that ended up with raw entry of kind other than CPE_LIBRARY + // For e.g. library xyz.jar is referenced in MANIFEST of abc.jar, which is in the raw classpath + // And if xyz.jar is part of a resolved container, then xyz.jar will not be considered as part of the container + // and not a chained library of abc.jar + if (rawEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + IClasspathEntry chainedEntry = (ClasspathEntry)oldChainedEntries.get(chainedEntryPath); + IClasspathEntry resolvedEntry = (IClasspathEntry)result.rootPathToResolvedEntries.get(chainedEntryPath); + if (chainedEntry != null) { + copyFromOldChainedEntry(resolvedEntry, chainedEntry); + } + Set chainsSet = (Set)rawEntryChainsMap.get(rawEntry); + if (chainsSet == null) { + chainsSet = new LinkedHashSet(); + rawEntryChainsMap.put(rawEntry, chainsSet); + } + chainsSet.add(resolvedEntry); + } + } + + iter = rawEntryChainsMap.keySet().iterator(); + while(iter.hasNext()) { + ClasspathEntry rawEntry = (ClasspathEntry) iter.next(); + Set chainsSet = (Set)rawEntryChainsMap.get(rawEntry); + IClasspathEntry[] chainedEntries = new IClasspathEntry[chainsSet.size()]; + rawEntry.setChainedEntries((IClasspathEntry[])chainsSet.toArray(chainedEntries)); + } + } + + private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, + LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager, boolean isChainedEntry) { + IPath resolvedPath; - if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) { + IClasspathEntry oldResolvedEntry = (IClasspathEntry)result.rootPathToResolvedEntries.get(resolvedPath = resolvedEntry.getPath()); + + if (oldResolvedEntry == null || (!isChainedEntry && oldResolvedEntry.getReferencingEntry() != null)) { + // If the entry has already been resolved, overwrite with the new one when: + // current resolvedEntry is a raw entry (!isChainedEntry) and previously resolved entry was a chained entry + // This ensures that preference is always given for a raw entry over a chained entry + + if (oldResolvedEntry != null) { + resolvedEntries.remove(result.rootPathToResolvedEntries.get(resolvedPath)); + } result.rawReverseMap.put(resolvedPath, rawEntry); result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry); + resolvedEntries.add(resolvedEntry); } resolvedEntries.add(resolvedEntry); if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) { @@ -2651,6 +2719,17 @@ } } + private void copyFromOldChainedEntry(IClasspathEntry resolvedEntry, IClasspathEntry chainedEntry) { + IPath path = chainedEntry.getSourceAttachmentPath(); + if ( path != null) { + ((ClasspathEntry) resolvedEntry).sourceAttachmentPath = path; + } + path = chainedEntry.getSourceAttachmentRootPath(); + if (path != null) { + ((ClasspathEntry) resolvedEntry).sourceAttachmentRootPath = path; + } + } + /* * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo. */ #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 4 Feb 2010 07:36:23 -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[] {"testBug252341a"}; // 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,191 @@ JavaCore.removeClasspathVariable("INVALID_LIB", null); } } +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]"); + + assertClasspathEquals(resolvedClasspath[4].getChainedEntries(), + "/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + assertEquals("source attachment", resolvedClasspath[4].getSourceAttachmentPath().toPortableString(), "/P/abc.zip"); + assertNull("source attachment", resolvedClasspath[2].getSourceAttachmentPath()); + assertNull("source attachment", resolvedClasspath[3].getSourceAttachmentPath()); + + ((ClasspathEntry)resolvedClasspath[2]).sourceAttachmentPath = new Path("/P/efg.zip"); + ((ClasspathEntry)resolvedClasspath[3]).sourceAttachmentPath = new Path("/P/xyz.zip"); + + p.setRawClasspath(rawClasspath, null); + + p.close(); + p.open(null); + 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][isExported:true]\n" + + "/P/lib3.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/xyz.zip][isExported:true]\n" + + "/P/lib1.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/abc.zip][isExported:true]"); + + } finally { + deleteProject("P"); + } +} +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[] 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( + resolvedClasspath[4].getChainedEntries(), + "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + assertClasspathEquals( + resolvedClasspath[6].getChainedEntries(), + "/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + } finally { + deleteProject("P"); + } +} +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(); + 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( + resolvedClasspath[4].getChainedEntries(), + "/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + + "/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + assertClasspathEquals( + resolvedClasspath[6].getChainedEntries(), + "/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]"); + + ((ClasspathEntry)rawClasspath[2]).excludeChainedJars = true; + 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/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\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]"); + + //Flip it back to false + ((ClasspathEntry)rawClasspath[2]).excludeChainedJars = false; + 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"); + } +} } #P org.eclipse.jdt.ui Index: ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java,v retrieving revision 1.79 diff -u -r1.79 CPListElement.java --- ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java 14 Feb 2009 07:57:06 -0000 1.79 +++ ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java 4 Feb 2010 07:36:27 -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 @@ -49,7 +49,8 @@ public static final String OUTPUT= "output"; //$NON-NLS-1$ public static final String EXCLUSION= "exclusion"; //$NON-NLS-1$ public static final String INCLUSION= "inclusion"; //$NON-NLS-1$ - + public static final String CHAINED_JARS= "chainedjars"; //$NON-NLS-1$ + public static final String EXCLUDE_CHAINS="exclude_chains"; //$NON-NLS-1$ public static final String ACCESSRULES= "accessrules"; //$NON-NLS-1$ public static final String COMBINE_ACCESSRULES= "combineaccessrules"; //$NON-NLS-1$ @@ -112,6 +113,9 @@ createAttributeElement(NATIVE_LIB_PATH, null, false); break; case IClasspathEntry.CPE_LIBRARY: + createAttributeElement(CHAINED_JARS, null, true); + createAttributeElement(EXCLUDE_CHAINS, Boolean.FALSE, true); + //$FALL-THROUGH$ case IClasspathEntry.CPE_VARIABLE: createAttributeElement(SOURCEATTACHMENT, null, true); createAttributeElement(JAVADOC, null, false); @@ -185,8 +189,10 @@ return JavaCore.newSourceEntry(fPath, inclusionPattern, exclusionPattern, outputLocation, extraAttributes); case IClasspathEntry.CPE_LIBRARY: { IPath attach= (IPath) getAttribute(SOURCEATTACHMENT); + IClasspathEntry[] referencedJars = (IClasspathEntry[]) getAttribute(CHAINED_JARS); + boolean excludeChainedJars = ((Boolean) getAttribute(EXCLUDE_CHAINS)).booleanValue(); IAccessRule[] accesRules= (IAccessRule[]) getAttribute(ACCESSRULES); - return JavaCore.newLibraryEntry(fPath, attach, null, accesRules, extraAttributes, isExported()); + return JavaCore.newLibraryEntry(fPath, attach, null, referencedJars, excludeChainedJars, accesRules, extraAttributes, isExported()); } case IClasspathEntry.CPE_PROJECT: { IAccessRule[] accesRules= (IAccessRule[]) getAttribute(ACCESSRULES); @@ -625,6 +631,8 @@ elem.setAttribute(INCLUSION, curr.getInclusionPatterns()); elem.setAttribute(ACCESSRULES, curr.getAccessRules()); elem.setAttribute(COMBINE_ACCESSRULES, new Boolean(curr.combineAccessRules())); + elem.setAttribute(CHAINED_JARS, curr.getChainedEntries()); + elem.setAttribute(EXCLUDE_CHAINS, new Boolean(curr.excludeChainedJars())); IClasspathAttribute[] extraAttributes= curr.getExtraAttributes(); for (int i= 0; i < extraAttributes.length; i++) { @@ -709,6 +717,8 @@ appendEncodedAccessRules((IAccessRule[]) elem.getValue(), buf).append(';'); } else if (COMBINE_ACCESSRULES.equals(key)) { buf.append(((Boolean) elem.getValue()).booleanValue()).append(';'); + } else if (EXCLUDE_CHAINS.equals(key)) { + buf.append(((Boolean) elem.getValue()).booleanValue()).append(';'); } } else { appendEncodedString((String) elem.getValue(), buf);