Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2000, 2012 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: IBM Corporation - initial API and implementation Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425 /
  
  package org.eclipse.jdt.internal.core;
  
  import java.io.File;
  import java.net.URL;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  
  import  org.eclipse.core.resources.IContainer;
  import  org.eclipse.core.resources.IFile;
  import  org.eclipse.core.resources.IProject;
  import  org.eclipse.core.resources.IResource;
  import  org.eclipse.core.resources.IWorkspaceRoot;
  import  org.eclipse.core.resources.ResourcesPlugin;
  import  org.eclipse.core.runtime.CoreException;
  import  org.eclipse.core.runtime.IPath;
  import  org.eclipse.core.runtime.IStatus;
  import  org.eclipse.core.runtime.Path;
  import org.w3c.dom.Node;
  import org.w3c.dom.Text;

See also:
IClasspathEntry
  
  public class ClasspathEntry implements IClasspathEntry {
  	
  	public static class AssertionFailedException extends RuntimeException {
  		
  		private static final long serialVersionUID = -171699380721189572L;
  
  		public AssertionFailedException(String message) {
  			super(message);
  		}
  	}
  
  	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$
  	public static final String TAG_SOURCEPATH = "sourcepath"//$NON-NLS-1$
  	public static final String TAG_ROOTPATH = "rootpath"//$NON-NLS-1$
  	public static final String TAG_EXPORTED = "exported"//$NON-NLS-1$
  	public static final String TAG_INCLUDING = "including"//$NON-NLS-1$
  	public static final String TAG_EXCLUDING = "excluding"//$NON-NLS-1$
  	public static final String TAG_ATTRIBUTES = "attributes"//$NON-NLS-1$
  	public static final String TAG_ATTRIBUTE = "attribute"//$NON-NLS-1$
  	public static final String TAG_ATTRIBUTE_NAME = "name"//$NON-NLS-1$
  	public static final String TAG_ATTRIBUTE_VALUE = "value"//$NON-NLS-1$
  	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_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$
 
Describes the kind of classpath entry - one of CPE_PROJECT, CPE_LIBRARY, CPE_SOURCE, CPE_VARIABLE or CPE_CONTAINER
 
 	public int entryKind;

Describes the kind of package fragment roots found on this classpath entry - either K_BINARY or K_SOURCE or K_OUTPUT.
 
 	public int contentKind;

The meaning of the path of a classpath entry depends on its entry kind:
  • Source code in the current project (CPE_SOURCE) - The path associated with this entry is the absolute path to the root folder.
  • A binary library in the current project (CPE_LIBRARY) - the path associated with this entry is the absolute path to the JAR (or root folder), and in case it refers to an external JAR, then there is no associated resource in the workbench.
  • A required project (CPE_PROJECT) - the path of the entry denotes the path to the corresponding project resource.
  • A variable entry (CPE_VARIABLE) - the first segment of the path is the name of a classpath variable. If this classpath variable is bound to the path <it>P</it>, the path of the corresponding classpath entry is computed by appending to <it>P</it> the segments of the returned path without the variable.
  • A container entry (CPE_CONTAINER) - the first segment of the path is denoting the unique container identifier (for which a ClasspathContainerInitializer could be registered), and the remaining segments are used as additional hints for resolving the container entry to an actual IClasspathContainer.
 
 	public IPath path;

Patterns allowing to include/exclude portions of the resource tree denoted by this entry path.
 
 	private IPath[] inclusionPatterns;
 	private char[][] fullInclusionPatternChars;
 	private IPath[] exclusionPatterns;
 	private char[][] fullExclusionPatternChars;
 	private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
 	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();
 
 	private boolean combineAccessRules;
 
 	private String rootID;
 
 
 	static class UnknownXmlElements {
 	}
 
 	/*
 	 * Default inclusion pattern set
 	 */
 	public final static IPath[] INCLUDE_ALL = {};
 
 	/*
 	 * Default exclusion pattern set
 	 */
 	public final static IPath[] EXCLUDE_NONE = {};
 
 	/*
 	 * Default extra attributes
 	 */
 	public final static IClasspathAttribute[] NO_EXTRA_ATTRIBUTES = {};
 
 	/*
 	 * Default access rules
 	 */
 	public final static IAccessRule[] NO_ACCESS_RULES = {};

Describes the path to the source archive associated with this classpath entry, or null if this classpath entry has no source attachment.

Only library and variable classpath entries may have source attachments. For library classpath entries, the result path (if present) locates a source archive. For variable classpath entries, the result path (if present) has an analogous form and meaning as the variable path, namely the first segment is the name of a classpath variable.

 
 	public IPath sourceAttachmentPath;

Describes the path within the source archive where package fragments are located. An empty path indicates that packages are located at the root of the source archive. Returns a non-null value if and only if getSourceAttachmentPath returns a non-null value.
 
 	public IPath sourceAttachmentRootPath;

See IClasspathEntry.getReferencingEntry()
 
Specific output location (for this source entry)
 
 	public IPath specificOutputLocation;

A constant indicating an output location.
 
 	public static final int K_OUTPUT = 10;
 	
 	public static final String DOT_DOT = ".."//$NON-NLS-1$
 
The export flag
 
 	public boolean isExported;

The extra attributes
 
 
 	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.
 
 	public ClasspathEntry(
 		int contentKind,
 		int entryKind,
 		IPath path,
 		IPath[] inclusionPatterns,
 		IPath[] exclusionPatterns,
 		IPath sourceAttachmentPath,
 		IPath sourceAttachmentRootPath,
 		IPath specificOutputLocation,
 		IClasspathEntry referencingEntry,
 		boolean isExported,
 		IAccessRule[] accessRules,
 		boolean combineAccessRules,
 		IClasspathAttribute[] extraAttributes) {
 
 		this. = contentKind;
 		this. = entryKind;
 		this. = path;
 		this. = inclusionPatterns;
 		this. = exclusionPatterns;
 		this. = referencingEntry;
 		
 		int length;
 		if (accessRules != null && (length = accessRules.length) > 0) {
 			AccessRule[] rules = new AccessRule[length];
 			System.arraycopy(accessRules, 0, rules, 0, length);
 			byte classpathEntryType;
 			String classpathEntryName;
 			JavaModelManager manager = JavaModelManager.getJavaModelManager();
 			if (this. ==  || this. == ) { // can be remote source entry when reconciling
 				classpathEntryType = .;
 				classpathEntryName = manager.intern(getPath().segment(0));
 			} else {
 				classpathEntryType = .;
 				Object target = JavaModel.getWorkspaceTarget(path);
 				if (target == null) {
 					classpathEntryName = manager.intern(path.toOSString());
 				} else {
 					classpathEntryName = manager.intern(path.makeRelative().toString());
 				}
 			}
 			this. = new AccessRuleSet(rulesclasspathEntryTypeclasspathEntryName);
 		}
 //		else { -- implicit!
 //			this.accessRuleSet = null;
 //		}
 
 		this. = combineAccessRules;
 		this. = extraAttributes;
 
 	    if (inclusionPatterns !=  && inclusionPatterns.length > 0) {
 	    }
 	    if (exclusionPatterns.length > 0) {
 	    }
 		this. = sourceAttachmentPath;
 		this. = sourceAttachmentRootPath;
 		this. = specificOutputLocation;
 		this. = isExported;
 	}
 
 	public boolean combineAccessRules() {
 		return this.;
 	}

Used to perform export/restriction propagation across referring projects/containers
 
 	public ClasspathEntry combineWith(ClasspathEntry referringEntry) {
 		if (referringEntry == nullreturn this;
 		if (referringEntry.isExported() || referringEntry.getAccessRuleSet() != null ) {
 			boolean combine = this. ==  || referringEntry.combineAccessRules();
 			return new ClasspathEntry(
 								referringEntry.isExported() || this.// duplicate container entry for tagging it as exported
 								combine(referringEntry.getAccessRules(), getAccessRules(), combine),
 		}
 		// no need to clone
 		return this;
 	}
 
 	private IAccessRule[] combine(IAccessRule[] referringRulesIAccessRule[] rulesboolean combine) {
 		if (!combinereturn rules;
 		if (rules == null || rules.length == 0) return referringRules;
 
 		// concat access rules
 		int referringRulesLength = referringRules.length;
 		int accessRulesLength = rules.length;
 		int rulesLength = referringRulesLength + accessRulesLength;
 		IAccessRule[] result = new IAccessRule[rulesLength];
 		System.arraycopy(referringRules, 0, result, 0, referringRulesLength);
 		System.arraycopy(rules, 0, resultreferringRulesLengthaccessRulesLength);
 
 		return result;
 	}
 
 		if (attributes == nullreturn ;
 		int length = attributes.getLength();
 		if (length == 0) return ;
 		IClasspathAttribute[] result = new IClasspathAttribute[length];
 		int index = 0;
 		for (int i = 0; i < length; ++i) {
 			Node node = attributes.item(i);
 			if (node.getNodeType() == .) {
 				Element attribute = (Element)node;
 				String name = attribute.getAttribute();
 				if (name == nullcontinue;
 				String value = attribute.getAttribute();
 				if (value == nullcontinue;
 				result[index++] = new ClasspathAttribute(namevalue);
 			}
 		}
 		if (index != length)
 			System.arraycopy(result, 0, result = new IClasspathAttribute[index], 0, index);
 		return result;
 	}
 
 	static IAccessRule[] decodeAccessRules(NodeList list) {
 		if (list == nullreturn null;
 		int length = list.getLength();
 		if (length == 0) return null;
 		IAccessRule[] result = new IAccessRule[length];
 		int index = 0;
 		for (int i = 0; i < lengthi++) {
 			Node accessRule = list.item(i);
 			if (accessRule.getNodeType() == .) {
 				Element elementAccessRule = (ElementaccessRule;
 				String pattern = elementAccessRule.getAttribute();
 				if (pattern == nullcontinue;
 				String tagKind =  elementAccessRule.getAttribute();
 				int kind;
 				if (.equals(tagKind))
 				else if (.equals(tagKind))
 				else if (.equals(tagKind))
 				else
 					continue;
 				boolean ignoreIfBetter = "true".equals(elementAccessRule.getAttribute()); //$NON-NLS-1$
 				result[index++] = new ClasspathAccessRule(new Path(pattern), ignoreIfBetter ? kind | . : kind);
 			}
 		}
 		if (index != length)
 			System.arraycopy(result, 0, result = new IAccessRule[index], 0, index);
 		return result;
 	}

Decode some element tag containing a sequence of patterns into IPath[]
 
 	private static IPath[] decodePatterns(NamedNodeMap nodeMapString tag) {
 		String sequence = removeAttribute(tagnodeMap);
 		if (!sequence.equals("")) { //$NON-NLS-1$
 			char[][] patterns = CharOperation.splitOn('|'sequence.toCharArray());
 			int patternCount;
 			if ((patternCount = patterns.length) > 0) {
 				IPath[] paths = new IPath[patternCount];
 				int index = 0;
 				for (int j = 0; j < patternCountj++) {
 					char[] pattern = patterns[j];
 					if (pattern.length == 0) continue// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=105581
 					paths[index++] = new Path(new String(pattern));
 				}
 				if (index < patternCount)
 					System.arraycopy(paths, 0, paths = new IPath[index], 0, index);
 				return paths;
 			}
 		}
 		return null;
 	}
 
 	private static void decodeUnknownNode(Node nodeStringBuffer bufferIJavaProject project) {
 		try {
 			writer = new OutputStreamWriter(s"UTF8"); //$NON-NLS-1$
 			XMLWriter xmlWriter = new XMLWriter(writerprojectfalse/*don't print XML version*/);
 			decodeUnknownNode(nodexmlWritertrue/*insert new line*/);
 			xmlWriter.flush();
 			xmlWriter.close();
 			buffer.append(s.toString("UTF8")); //$NON-NLS-1$
 		} catch (UnsupportedEncodingException e) {
 			// ignore (UTF8 is always supported)
 		}
 	}
 
 	private static void decodeUnknownNode(Node nodeXMLWriter xmlWriterboolean insertNewLine) {
 		switch (node.getNodeType()) {
 			NamedNodeMap attributes;
 			HashMap parameters = null;
 			if ((attributes = node.getAttributes()) != null) {
 				int length = attributes.getLength();
 				if (length > 0) {
 					parameters = new HashMap();
 					for (int i = 0; i < lengthi++) {
 						Node attribute = attributes.item(i);
 						parameters.put(attribute.getNodeName(), attribute.getNodeValue());
 					}
 				}
 			}
 			NodeList children = node.getChildNodes();
 			int childrenLength = children.getLength();
 			String nodeName = node.getNodeName();
 			xmlWriter.printTag(nodeNameparametersfalse/*don't insert tab*/false/*don't insert new line*/childrenLength == 0/*close tag if no children*/);
 			if (childrenLength > 0) {
 				for (int i = 0; i < childrenLengthi++) {
 					decodeUnknownNode(children.item(i), xmlWriterfalse/*don't insert new line*/);
 				}
 				xmlWriter.endTag(nodeNamefalse/*don't insert tab*/insertNewLine);
 			}
 			break;
 		case .:
 			String data = ((Textnode).getData();
 			xmlWriter.printString(datafalse/*don't insert tab*/false/*don't insert new line*/);
 			break;
 		}
 	}
 
 	/*
 	 * Returns a char based representation of the exclusions patterns full path.
 	 */
 	public char[][] fullExclusionPatternChars() {
 
 			int length = this..length;
 			this. = new char[length][];
 			IPath prefixPath = this..removeTrailingSeparator();
 			for (int i = 0; i < lengthi++) {
 					prefixPath.append(this.[i]).toString().toCharArray();
 			}
 		}
 	}
 
 	/*
 	 * Returns a char based representation of the exclusions patterns full path.
 	 */
 	public char[][] fullInclusionPatternChars() {
 
 			int length = this..length;
 			this. = new char[length][];
 			IPath prefixPath = this..removeTrailingSeparator();
 			for (int i = 0; i < lengthi++) {
 					prefixPath.append(this.[i]).toString().toCharArray();
 			}
 		}
 	}

Returns the XML encoding of the class path.
 
 	public void elementEncode(XMLWriter writer, IPath projectPathboolean indentboolean newLineMap unknownElementsboolean isReferencedEntry) {
 		HashMap parameters = new HashMap();
 
 		parameters.put(, ClasspathEntry.kindToString(this.));
 
 		IPath xmlPath = this.;
 			// 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(, String.valueOf(xmlPath));
 
 		if (this. != null) {
 			xmlPath = this.;
 			// translate to project relative from absolute
 			if (this. != . && projectPath != null && projectPath.isPrefixOf(xmlPath)) {
 				if (xmlPath.segment(0).equals(projectPath.segment(0))) {
 					xmlPath = xmlPath.removeFirstSegments(1);
 					xmlPath = xmlPath.makeRelative();
 				}
 			}
 			parameters.put(, String.valueOf(xmlPath));
 		}
 		if (this. != null) {
 			parameters.put(, String.valueOf(this.));
 		}
 		if (this.) {
 			parameters.put("true");//$NON-NLS-1$
 		}
 		if (this. ==  && !this.)
 			parameters.put("false"); //$NON-NLS-1$
 
 
 		// unknown attributes
 		UnknownXmlElements unknownXmlElements = unknownElements == null ? null : (UnknownXmlElementsunknownElements.get(this.);
 		String[] unknownAttributes;
 		if (unknownXmlElements != null && (unknownAttributes = unknownXmlElements.attributes) != null)
 			for (int i = 0, length = unknownAttributes.lengthi < lengthi+=2) {
 				String tagName = unknownAttributes[i];
 				String tagValue = unknownAttributes[i+1];
 				parameters.put(tagNametagValue);
 			}
 
 		if (this. != null) {
 			IPath outputLocation = this..removeFirstSegments(1);
 			outputLocation = outputLocation.makeRelative();
 			parameters.put(, String.valueOf(outputLocation));
 		}
 
 		boolean hasExtraAttributes = this..length != 0;
 		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 ?  : 
 		writer.printTag(
 			tagName,
 			parameters,
 			indent,
 			newLine,
 			!hasExtraAttributes && !hasRestrictions && !hasUnknownChildren);
 
 		if (hasExtraAttributes)
 			encodeExtraAttributes(writerindentnewLine);
 
 		if (hasRestrictions)
 			encodeAccessRules(writerindentnewLine);
 
 		if (hasUnknownChildren)
 			encodeUnknownChildren(writerindentnewLineunknownChildren);
 
 		if (hasExtraAttributes || hasRestrictions || hasUnknownChildren)
 			writer.endTag(tagNameindenttrue/*insert new line*/);
 	}
 
 	void encodeExtraAttributes(XMLWriter writerboolean indentboolean newLine) {
 		writer.startTag(indent);
 		for (int i = 0; i < this..lengthi++) {
 			IClasspathAttribute attribute = this.[i];
 			HashMap parameters = new HashMap();
 	    	parameters.put(attribute.getName());
 			parameters.put(attribute.getValue());
 			writer.printTag(parametersindentnewLinetrue);
 		}
 		writer.endTag(indenttrue/*insert new line*/);
 	}
 
 	void encodeAccessRules(XMLWriter writerboolean indentboolean newLine) {
 
 		writer.startTag(indent);
 		for (int i = 0, length = rules.lengthi < lengthi++) {
 			encodeAccessRule(rules[i], writerindentnewLine);
 		}
 		writer.endTag(indenttrue/*insert new line*/);
 	}
 
 	private void encodeAccessRule(AccessRule accessRuleXMLWriter writerboolean indentboolean newLine) {
 
 		HashMap parameters = new HashMap();
 		parameters.put(new String(accessRule.pattern));
 
 		switch (accessRule.getProblemId()) {
 				break;
 				parameters.put();
 				break;
 			default:
 				parameters.put();
 				break;
 		}
 		if (accessRule.ignoreIfBetter())
 			parameters.put("true"); //$NON-NLS-1$
 
 		writer.printTag(parametersindentnewLinetrue);
 
 	}
 
 	private void encodeUnknownChildren(XMLWriter writerboolean indentboolean newLineArrayList unknownChildren) {
 		for (int i = 0, length = unknownChildren.size(); i < lengthi++) {
 			String child = (StringunknownChildren.get(i);
 			writer.printString(childindentfalse/*don't insert new line*/);
 		}
 	}
 
 	public static IClasspathEntry elementDecode(Element elementIJavaProject projectMap unknownElements) {
 
 		IPath projectPath = project.getProject().getFullPath();
 		NamedNodeMap attributes = element.getAttributes();
 		NodeList children = element.getChildNodes();
 		boolean[] foundChildren = new boolean[children.getLength()];
 		String kindAttr = removeAttribute(attributes);
 		String pathAttr = removeAttribute(attributes);
 
 		// ensure path is absolute
 		IPath path = new Path(pathAttr);
 		int kind = kindFromString(kindAttr);
 		if (kind != . && kind != . && !path.isAbsolute()) {
 			if (!(path.segmentCount() > 0 && path.segment(0).equals(.))) {
 				path = projectPath.append(path);
 			}
 		}
 		// source attachment info (optional)
 		IPath sourceAttachmentPath =
 			? new Path(removeAttribute(attributes))
 			: null;
 		if (kind != . && sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) {
 			sourceAttachmentPath = projectPath.append(sourceAttachmentPath);
 		}
 		IPath sourceAttachmentRootPath =
 			? new Path(removeAttribute(attributes))
 			: null;
 
 		// exported flag (optional)
 		boolean isExported = removeAttribute(attributes).equals("true"); //$NON-NLS-1$
 
 		// inclusion patterns (optional)
 		IPath[] inclusionPatterns = decodePatterns(attributes);
 		if (inclusionPatterns == nullinclusionPatterns = ;
 
 		// exclusion patterns (optional)
 		IPath[] exclusionPatterns = decodePatterns(attributes);
 		if (exclusionPatterns == nullexclusionPatterns = ;
 
 		// access rules (optional)
 		NodeList attributeList = getChildAttributes(childrenfoundChildren);
 		IAccessRule[] accessRules = decodeAccessRules(attributeList);
 
 		// backward compatibility
 		if (accessRules == null) {
 			accessRules = getAccessRules(inclusionPatternsexclusionPatterns);
 		}
 
 		// combine access rules (optional)
 		boolean combineAccessRestrictions = !removeAttribute(attributes).equals("false"); //$NON-NLS-1$
 
 		// extra attributes (optional)
 		attributeList = getChildAttributes(childrenfoundChildren);
 		IClasspathAttribute[] extraAttributes = decodeExtraAttributes(attributeList);
 
 		// custom output location
 		IPath outputLocation = element.hasAttribute() ? projectPath.append(removeAttribute(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 < unknownAttributeLengthi++) {
 					Node attribute = attributes.item(i);
 					unknownAttributes[i*2] = attribute.getNodeName();
 					unknownAttributes[i*2 + 1] = attribute.getNodeValue();
 				}
 			}
 
 			// unknown children
 			for (int i = 0, length = foundChildren.lengthi < lengthi++) {
 				if (!foundChildren[i]) {
 					Node node = children.item(i);
 					if (node.getNodeType() != .continue;
 					if (unknownChildren == null)
 						unknownChildren = new ArrayList();
 					StringBuffer buffer = new StringBuffer();
 					decodeUnknownNode(nodebufferproject);
 					unknownChildren.add(buffer.toString());
 				}
 			}
 		}
 
 		// recreate the CP entry
 		IClasspathEntry entry = null;
 		switch (kind) {
 
 				entry = new ClasspathEntry(
 												path,
 												.// inclusion patterns
 												.// exclusion patterns
 												null// source attachment
 												null// source attachment root
 												null// specific output folder
 												isExported,
 												accessRules,
 												combineAccessRestrictions,
 												extraAttributes);
 				break;
 				entry = JavaCore.newLibraryEntry(
 												path,
 												sourceAttachmentPath,
 												sourceAttachmentRootPath,
 												accessRules,
 												extraAttributes,
 												isExported);
 				break;
 				// must be an entry in this project or specify another project
 				String projSegment = path.segment(0);
 				if (projSegment != null && projSegment.equals(project.getElementName())) { // this project
 					entry = JavaCore.newSourceEntry(
 												path
 												inclusionPatterns
 												exclusionPatterns
 												outputLocation
 												extraAttributes);
 				} else {
 					if (path.segmentCount() == 1) {
 						// another project
 						entry = JavaCore.newProjectEntry(
 												path,
 												accessRules,
 												combineAccessRestrictions,
 												extraAttributes,
 												isExported);
 					} else {
 						// an invalid source folder
 						entry = JavaCore.newSourceEntry(
 												path
 												inclusionPatterns
 												exclusionPatterns
 												outputLocation
 												extraAttributes);
 					}
 				}
 				break;
 				entry = JavaCore.newVariableEntry(
 												path,
 												sourceAttachmentPath,
 												sourceAttachmentRootPath,
 												accessRules,
 												extraAttributes,
 												isExported);
 				break;
 				entry = JavaCore.newContainerEntry(
 												path,
 												accessRules,
 												extraAttributes,
 												isExported);
 				break;
 				if (!path.isAbsolute()) return null;
 				entry = new ClasspathEntry(
 												path,
 												null// source attachment
 												null// source attachment root
 												null// custom output location
 												false,
 												null// no access rules
 												false// no accessible files to combine
 				break;
 			default :
 				throw new AssertionFailedException(Messages.bind(.kindAttr));
 		}
 
 		if (unknownAttributes != null || unknownChildren != null) {
 			UnknownXmlElements unknownXmlElements = new UnknownXmlElements();
 			unknownXmlElements.attributes = unknownAttributes;
 			unknownXmlElements.children = unknownChildren;
 			unknownElements.put(pathunknownXmlElements);
 		}
 
 		return entry;
 	}
 	
 	/*
 	 * Returns whether the given path as a ".." segment
 	 */
 	public static boolean hasDotDot(IPath path) {
 		for (int i = 0, length = path.segmentCount(); i < lengthi++) {
 			if (.equals(path.segment(i)))
 				return true;
 		}
 		return false;
 	}
 
 	public static NodeList getChildAttributes(String childNameNodeList childrenboolean[] foundChildren) {
 		for (int i = 0, length = foundChildren.lengthi < lengthi++) {
 			Node node = children.item(i);
 			if (childName.equals(node.getNodeName())) {
 				foundChildren[i] = true;
 				return node.getChildNodes();
 			}
 		}
 		return null;
 	}
 
 
 	private static String removeAttribute(String nodeNameNamedNodeMap nodeMap) {
 		Node node = removeNode(nodeNamenodeMap);
 		if (node == null)
 			return ""// //$NON-NLS-1$
 		return node.getNodeValue();
 	}
 
 	private static Node removeNode(String nodeNameNamedNodeMap nodeMap) {
 		try {
 			return nodeMap.removeNamedItem(nodeName);
 		} catch (DOMException e) {
 			if (e.code != .)
 				throw e;
 			return null;
 		}
 	}
 
 	/*
 	 * Read the Class-Path clause of the manifest of the jar pointed by this path, and return
 	 * the corresponding paths.
 	 */
 	public static IPath[] resolvedChainedLibraries(IPath jarPath) {
 		ArrayList result = new ArrayList();
 		resolvedChainedLibraries(jarPathnew HashSet(), result);
 		if (result.size() == 0)
 			return ;
 		return (IPath[]) result.toArray(new IPath[result.size()]);
 	}
 	
 	private static void resolvedChainedLibraries(IPath jarPathHashSet visitedArrayList result) {
 		if (visited.containsjarPath))
 			return;
 		visited.add(jarPath);
 		JavaModelManager manager = JavaModelManager.getJavaModelManager();
 		if (manager.isNonChainingJar(jarPath))
 			return;
 		List calledFileNames = getCalledFileNames(jarPath);
 		if (calledFileNames == null) {
 			manager.addNonChainingJar(jarPath);
 		} else {
 			Iterator calledFilesIterator = calledFileNames.iterator();
 			IPath directoryPath = jarPath.removeLastSegments(1);
 			while (calledFilesIterator.hasNext()) {
 				String calledFileName = (StringcalledFilesIterator.next();
 				if (!directoryPath.isValidPath(calledFileName)) {
 						Util.verbose("Invalid Class-Path entry " + calledFileName + " in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
 					}
 				} else {
 					IPath calledJar = directoryPath.append(new Path(calledFileName));
 					// Ignore if segment count is Zero (https://bugs.eclipse.org/bugs/show_bug.cgi?id=308150)
 					if (calledJar.segmentCount() == 0) {
 							Util.verbose("Invalid Class-Path entry " + calledFileName + " in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
 						}
 						continue;
 					}
 					resolvedChainedLibraries(calledJarvisitedresult);
 					result.add(calledJar);
 				}
 			}
 		}
 	}
 
 	private static List getCalledFileNames(IPath jarPath) {
 		Object target = JavaModel.getTarget(jarPathtrue/*check existence, otherwise the manifest cannot be read*/);
 		if (!(target instanceof IFile || target instanceof File))
 			return null;
 		JavaModelManager manager = JavaModelManager.getJavaModelManager();
 		ZipFile zip = null;
 		InputStream inputStream = null;
 		List calledFileNames = null;
 		try {
 			zip = manager.getZipFile(jarPath);
 			ZipEntry manifest = zip.getEntry("META-INF/MANIFEST.MF"); //$NON-NLS-1$
 			if (manifest == null
 				return null;
 			// non-null implies regular file
 			ManifestAnalyzer analyzer = new ManifestAnalyzer();
 			inputStream = zip.getInputStream(manifest);
 			boolean success = analyzer.analyzeManifestContents(inputStream);
 			calledFileNames = analyzer.getCalledFileNames();
 			if (!success || analyzer.getClasspathSectionsCount() == 1 && calledFileNames == null) {
 					Util.verbose("Invalid Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
 				}
 				return null;
 			} else if (analyzer.getClasspathSectionsCount() > 1) {
 					Util.verbose("Multiple Class-Path headers in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
 				}
 				return null;
 			}
 		} catch (CoreException e) {
 			// not a zip file
 				Util.verbose("Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
 				e.printStackTrace();
 			}
 		} catch (IOException e) {
 			// not a zip file
 				Util.verbose("Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
 			}
 		} finally {
 			if (inputStream != null) {
 				try {
 					inputStream.close();
 				} catch (IOException e) {
 					// best effort
 				}
 			}
			manager.closeZipFile(zip);
		return calledFileNames;
	/*
	 * Resolves the ".." in the given path. Returns the given path if it contains no ".." segment.
	 */
	public static IPath resolveDotDot(IPath reference, IPath path) {
		IPath newPath = null;
		IPath workspaceLocation = .getLocation();
		if (reference == null || workspaceLocation.isPrefixOf(reference)) {
			for (int i = 0, length = path.segmentCount(); i < lengthi++) {
				String segment = path.segment(i);
				if (.equals(segment)) {
					if (newPath == null) {
						if (i == 0) {
							newPath = workspaceLocation;
else {
							newPath = path.removeFirstSegments(i);
else {
						if (newPath.segmentCount() > 0) {
							newPath = newPath.removeLastSegments(1);
else {
							newPath = workspaceLocation;
else if (newPath != null) {
					if (newPath.equals(workspaceLocation) && .getProject(segment).isAccessible()) {
						newPath = new Path(segment).makeAbsolute();
else {
						newPath = newPath.append(segment);
		else {
			for (int i = 0, length = path.segmentCount(); i < lengthi++) {
				String segment = path.segment(i);
				if (.equals(segment)) {
					if (newPath == null){
						newPath = reference;
					if (newPath.segmentCount() > 0) {
						newPath = newPath.removeLastSegments(1);
	 				}
else if (newPath != null) {
					newPath = newPath.append(segment);
	 			}
		if (newPath == null)
			return path;
		return newPath;
	}

Encode some patterns into XML parameter tag
	private static void encodePatterns(IPath[] patternsString tagMap parameters) {
		if (patterns != null && patterns.length > 0) {
			StringBuffer rule = new StringBuffer(10);
			for (int i = 0, max = patterns.length; i < maxi++){
				if (i > 0) rule.append('|');
				rule.append(patterns[i]);
			parameters.put(tag, String.valueOf(rule));
	}

Returns true if the given object is a classpath entry with equivalent attributes.
	public boolean equals(Object object) {
		if (this == object)
			return true;
		if (object instanceof ClasspathEntry) {
			ClasspathEntry otherEntry = (ClasspathEntryobject;
			if (this. != otherEntry.getContentKind())
				return false;
			if (this. != otherEntry.getEntryKind())
				return false;
			if (this. != otherEntry.isExported())
				return false;
			if (!this..equals(otherEntry.getPath()))
				return false;
			IPath otherPath = otherEntry.getSourceAttachmentPath();
			if (this. == null) {
				if (otherPath != null)
					return false;
else {
				if (!this..equals(otherPath))
					return false;
			otherPath = otherEntry.getSourceAttachmentRootPath();
			if (this. == null) {
				if (otherPath != null)
					return false;
else {
				if (!this..equals(otherPath))
					return false;
				return false;
				return false;
			AccessRuleSet otherRuleSet = otherEntry.getAccessRuleSet();
			if (getAccessRuleSet() != null) {
				if (!getAccessRuleSet().equals(otherRuleSet))
					return false;
else if (otherRuleSet != null)
				return false;
			if (this. != otherEntry.combineAccessRules())
				return false;
			otherPath = otherEntry.getOutputLocation();
			if (this. == null) {
				if (otherPath != null)
					return false;
else {
				if (!this..equals(otherPath))
					return false;
				return false;
			return true;
else {
			return false;
	private static boolean equalAttributes(IClasspathAttribute[] firstAttributesIClasspathAttribute[] secondAttributes) {
		if (firstAttributes != secondAttributes){
		    if (firstAttributes == nullreturn false;
			int length = firstAttributes.length;
			if (secondAttributes == null || secondAttributes.length != length)
				return false;
			for (int i = 0; i < lengthi++) {
				if (!firstAttributes[i].equals(secondAttributes[i]))
					return false;
		return true;
	private static boolean equalPatterns(IPath[] firstPatterns, IPath[] secondPatterns) {
		if (firstPatterns != secondPatterns){
		    if (firstPatterns == nullreturn false;
			int length = firstPatterns.length;
			if (secondPatterns == null || secondPatterns.length != length)
				return false;
			for (int i = 0; i < lengthi++) {
				// compare toStrings instead of IPaths
				// since IPath.equals is specified to ignore trailing separators
				if (!firstPatterns[i].toString().equals(secondPatterns[i].toString()))
					return false;
		return true;