Index: model/org/eclipse/jdt/internal/core/ClasspathEntry.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java,v retrieving revision 1.81 diff -u -r1.81 ClasspathEntry.java --- model/org/eclipse/jdt/internal/core/ClasspathEntry.java 1 Jun 2005 18:56:14 -0000 1.81 +++ model/org/eclipse/jdt/internal/core/ClasspathEntry.java 30 Aug 2005 09:48:04 -0000 @@ -10,11 +10,16 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core; +import java.io.CharArrayWriter; import java.io.File; +import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import org.apache.crimson.tree.XmlWritable; +import org.apache.crimson.tree.XmlWriteContext; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; @@ -39,7 +44,9 @@ import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; +import org.w3c.dom.DOMException; import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -119,6 +126,9 @@ private String rootID; private AccessRuleSet accessRuleSet; + private String[] unknownAttributes; + private ArrayList unknownChildren; + /* * Default inclusion pattern set */ @@ -278,10 +288,7 @@ return result; } - static IClasspathAttribute[] decodeExtraAttributes(Element element) { - Node extra = element.getElementsByTagName(TAG_ATTRIBUTES).item(0); - if (extra == null) return NO_EXTRA_ATTRIBUTES; - NodeList attributes = element.getElementsByTagName(TAG_ATTRIBUTE); + static IClasspathAttribute[] decodeExtraAttributes(NodeList attributes) { if (attributes == null) return NO_EXTRA_ATTRIBUTES; int length = attributes.getLength(); if (length == 0) return NO_EXTRA_ATTRIBUTES; @@ -303,31 +310,30 @@ return result; } - static IAccessRule[] decodeAccessRules(Element element) { - Node accessRules = element.getElementsByTagName(TAG_ACCESS_RULES).item(0); - if (accessRules == null || accessRules.getNodeType() != Node.ELEMENT_NODE) return null; - NodeList list = ((Element) accessRules).getElementsByTagName(TAG_ACCESS_RULE); + static IAccessRule[] decodeAccessRules(NodeList list) { + if (list == null) return null; int length = list.getLength(); if (length == 0) return null; IAccessRule[] result = new IAccessRule[length]; int index = 0; for (int i = 0; i < length; i++) { Node accessRule = list.item(i); - if (accessRule == null || accessRule.getNodeType() != Node.ELEMENT_NODE) return null; - Element elementAccessRule = (Element) accessRule; - String pattern = elementAccessRule.getAttribute(TAG_PATTERN); - if (pattern == null) continue; - String tagKind = elementAccessRule.getAttribute(TAG_KIND); - int kind; - if (TAG_ACCESSIBLE.equals(tagKind)) - kind = IAccessRule.K_ACCESSIBLE; - else if (TAG_NON_ACCESSIBLE.equals(tagKind)) - kind = IAccessRule.K_NON_ACCESSIBLE; - else if (TAG_DISCOURAGED.equals(tagKind)) - kind = IAccessRule.K_DISCOURAGED; - else - continue; - result[index++] = new ClasspathAccessRule(new Path(pattern), kind); + if (accessRule.getNodeType() == Node.ELEMENT_NODE) { + Element elementAccessRule = (Element) accessRule; + String pattern = elementAccessRule.getAttribute(TAG_PATTERN); + if (pattern == null) continue; + String tagKind = elementAccessRule.getAttribute(TAG_KIND); + int kind; + if (TAG_ACCESSIBLE.equals(tagKind)) + kind = IAccessRule.K_ACCESSIBLE; + else if (TAG_NON_ACCESSIBLE.equals(tagKind)) + kind = IAccessRule.K_NON_ACCESSIBLE; + else if (TAG_DISCOURAGED.equals(tagKind)) + kind = IAccessRule.K_DISCOURAGED; + else + continue; + result[index++] = new ClasspathAccessRule(new Path(pattern), kind); + } } if (index != length) System.arraycopy(result, 0, result = new IAccessRule[index], 0, index); @@ -337,8 +343,8 @@ /** * Decode some element tag containing a sequence of patterns into IPath[] */ - private static IPath[] decodePatterns(Element element, String tag) { - String sequence = element.getAttribute(tag); + private static IPath[] decodePatterns(NamedNodeMap nodeMap, String tag) { + String sequence = removeAttribute(tag, nodeMap); if (!sequence.equals("")) { //$NON-NLS-1$ char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray()); int patternCount; @@ -352,6 +358,22 @@ } return null; } + + private static void decodeUnknownChild(Node child, StringBuffer buffer) { + if (child instanceof XmlWritable) { + CharArrayWriter writer = new CharArrayWriter(); + XmlWriteContext context = new XmlWriteContext(writer); + try { + ((XmlWritable) child).writeXml(context); + buffer.append(writer.toString()); + } catch (IOException e) { + buffer.append(""); //$NON-NLS-1$ + } + } else { + buffer.append(""); //$NON-NLS-1$ + } + } + /* * Returns a char based representation of the exclusions patterns full path. */ @@ -432,6 +454,13 @@ if (this.entryKind == CPE_PROJECT && !this.combineAccessRules) parameters.put(TAG_COMBINE_ACCESS_RULES, "false"); //$NON-NLS-1$ + // unknown attributes + if (this.unknownAttributes != null) + for (int i = 0, length = this.unknownAttributes.length; i < length; i+=2) { + String tagName = this.unknownAttributes[i]; + String tagValue = this.unknownAttributes[i+1]; + parameters.put(tagName, tagValue); + } if (this.specificOutputLocation != null) { IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1); @@ -441,15 +470,24 @@ boolean hasExtraAttributes = this.extraAttributes.length != 0; boolean hasRestrictions = getAccessRuleSet() != null; // access rule set is null if no access rules - writer.printTag(TAG_CLASSPATHENTRY, parameters, indent, newLine, !hasExtraAttributes && !hasRestrictions /*close tag if no extra attributes and no restriction*/); + boolean hasUnknownChildren = this.unknownChildren != null; + writer.printTag( + TAG_CLASSPATHENTRY, + parameters, + indent, + newLine, + !hasExtraAttributes && !hasRestrictions && !hasUnknownChildren/*close tag if no extra attributes, no restriction and no unknown children*/); if (hasExtraAttributes) encodeExtraAttributes(writer, indent, newLine); if (hasRestrictions) encodeAccessRules(writer, indent, newLine); + + if (hasUnknownChildren) + encodeUnknownChildren(writer, indent, newLine); - if (hasExtraAttributes || hasRestrictions) + if (hasExtraAttributes || hasRestrictions || hasUnknownChildren) writer.endTag(TAG_CLASSPATHENTRY, indent); } @@ -496,11 +534,21 @@ } + private void encodeUnknownChildren(XMLWriter writer, boolean indent, boolean newLine) { + for (int i = 0, length = this.unknownChildren.size(); i < length; i++) { + String child = (String) this.unknownChildren.get(i); + writer.printString(child, indent, newLine); + } + } + public static IClasspathEntry elementDecode(Element element, IJavaProject project) { IPath projectPath = project.getProject().getFullPath(); - String kindAttr = element.getAttribute(TAG_KIND); - String pathAttr = element.getAttribute(TAG_PATH); + NamedNodeMap attributes = element.getAttributes(); + NodeList children = element.getChildNodes(); + boolean[] foundChildren = new boolean[children.getLength()]; + String kindAttr = removeAttribute(TAG_KIND, attributes); + String pathAttr = removeAttribute(TAG_PATH, attributes); // ensure path is absolute IPath path = new Path(pathAttr); @@ -511,29 +559,30 @@ // source attachment info (optional) IPath sourceAttachmentPath = element.hasAttribute(TAG_SOURCEPATH) - ? new Path(element.getAttribute(TAG_SOURCEPATH)) + ? new Path(removeAttribute(TAG_SOURCEPATH, attributes)) : null; if (kind != IClasspathEntry.CPE_VARIABLE && sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) { sourceAttachmentPath = projectPath.append(sourceAttachmentPath); } IPath sourceAttachmentRootPath = element.hasAttribute(TAG_ROOTPATH) - ? new Path(element.getAttribute(TAG_ROOTPATH)) + ? new Path(removeAttribute(TAG_ROOTPATH, attributes)) : null; // exported flag (optional) - boolean isExported = element.getAttribute(TAG_EXPORTED).equals("true"); //$NON-NLS-1$ + boolean isExported = removeAttribute(TAG_EXPORTED, attributes).equals("true"); //$NON-NLS-1$ // inclusion patterns (optional) - IPath[] inclusionPatterns = decodePatterns(element, TAG_INCLUDING); + IPath[] inclusionPatterns = decodePatterns(attributes, TAG_INCLUDING); if (inclusionPatterns == null) inclusionPatterns = INCLUDE_ALL; // exclusion patterns (optional) - IPath[] exclusionPatterns = decodePatterns(element, TAG_EXCLUDING); + IPath[] exclusionPatterns = decodePatterns(attributes, TAG_EXCLUDING); if (exclusionPatterns == null) exclusionPatterns = EXCLUDE_NONE; // access rules (optional) - IAccessRule[] accessRules = decodeAccessRules(element); + NodeList attributeList = getChildAttributes(TAG_ACCESS_RULES, children, foundChildren); + IAccessRule[] accessRules = decodeAccessRules(attributeList); // backward compatibility if (accessRules == null) { @@ -541,13 +590,40 @@ } // combine access rules (optional) - boolean combineAccessRestrictions = !element.getAttribute(TAG_COMBINE_ACCESS_RULES).equals("false"); //$NON-NLS-1$ + boolean combineAccessRestrictions = !removeAttribute(TAG_COMBINE_ACCESS_RULES, attributes).equals("false"); //$NON-NLS-1$ // extra attributes (optional) - IClasspathAttribute[] extraAttributes = decodeExtraAttributes(element); + attributeList = getChildAttributes(TAG_ATTRIBUTES, children, foundChildren); + IClasspathAttribute[] extraAttributes = decodeExtraAttributes(attributeList); // custom output location - IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(element.getAttribute(TAG_OUTPUT)) : null; + IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(removeAttribute(TAG_OUTPUT, attributes)) : null; + + // unknown attributes + String[] unknownAttributes = null; + 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 + ArrayList unknownChildren = null; + 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(); + decodeUnknownChild(node, buffer); + unknownChildren.add(buffer.toString()); + } + } // recreate the CP entry IClasspathEntry entry = null; @@ -574,7 +650,7 @@ // 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 - return JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes); + entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes); } else { if (path.segmentCount() == 1) { // another project @@ -586,7 +662,7 @@ isExported); } else { // an invalid source folder - return JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes); + entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes); } } break; @@ -608,7 +684,7 @@ break; case ClasspathEntry.K_OUTPUT : if (!path.isAbsolute()) return null; - return new ClasspathEntry( + entry = new ClasspathEntry( ClasspathEntry.K_OUTPUT, IClasspathEntry.CPE_LIBRARY, path, @@ -621,11 +697,46 @@ null, // no access rules false, // no accessible files to combine NO_EXTRA_ATTRIBUTES); + break; default : throw new Assert.AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr)); } + + ClasspathEntry classpathEntry = (ClasspathEntry) entry; + classpathEntry.unknownAttributes = unknownAttributes; + classpathEntry.unknownChildren = unknownChildren; + return entry; } + + public static NodeList getChildAttributes(String childName, NodeList children, boolean[] foundChildren) { + for (int i = 0, length = foundChildren.length; i < length; i++) { + Node node = children.item(i); + if (childName.equals(node.getNodeName())) { + foundChildren[i] = true; + return node.getChildNodes(); + } + } + return null; + } + + + private static String removeAttribute(String nodeName, NamedNodeMap nodeMap) { + Node node = removeNode(nodeName, nodeMap); + if (node == null) + return ""; // //$NON-NLS-1$ + return node.getNodeValue(); + } + + private static Node removeNode(String nodeName, NamedNodeMap nodeMap) { + try { + return nodeMap.removeNamedItem(nodeName); + } catch (DOMException e) { + if (e.code != DOMException.NOT_FOUND_ERR) + throw e; + return null; + } + } /** * Encode some patterns into XML parameter tag Index: model/org/eclipse/jdt/internal/core/UserLibrary.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java,v retrieving revision 1.6 diff -u -r1.6 UserLibrary.java --- model/org/eclipse/jdt/internal/core/UserLibrary.java 23 May 2005 15:11:35 -0000 1.6 +++ model/org/eclipse/jdt/internal/core/UserLibrary.java 30 Aug 2005 09:48:04 -0000 @@ -177,8 +177,12 @@ String path = element.getAttribute(TAG_PATH); IPath sourceAttach= element.hasAttribute(TAG_SOURCEATTACHMENT) ? new Path(element.getAttribute(TAG_SOURCEATTACHMENT)) : null; IPath sourceAttachRoot= element.hasAttribute(TAG_SOURCEATTACHMENTROOT) ? new Path(element.getAttribute(TAG_SOURCEATTACHMENTROOT)) : null; - IClasspathAttribute[] extraAttributes = ClasspathEntry.decodeExtraAttributes(element); - IAccessRule[] accessRules = ClasspathEntry.decodeAccessRules(element); + NodeList children = element.getElementsByTagName("*"); //$NON-NLS-1$ + boolean[] foundChildren = new boolean[children.getLength()]; + NodeList attributeList = ClasspathEntry.getChildAttributes(ClasspathEntry.TAG_ATTRIBUTES, children, foundChildren); + IClasspathAttribute[] extraAttributes = ClasspathEntry.decodeExtraAttributes(attributeList); + attributeList = ClasspathEntry.getChildAttributes(ClasspathEntry.TAG_ACCESS_RULES, children, foundChildren); + IAccessRule[] accessRules = ClasspathEntry.decodeAccessRules(attributeList); IClasspathEntry entry = JavaCore.newLibraryEntry(new Path(path), sourceAttach, sourceAttachRoot, accessRules, extraAttributes, false/*not exported*/); res.add(entry); } Index: model/org/eclipse/jdt/internal/core/XMLWriter.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/XMLWriter.java,v retrieving revision 1.7 diff -u -r1.7 XMLWriter.java --- model/org/eclipse/jdt/internal/core/XMLWriter.java 23 May 2005 15:11:35 -0000 1.7 +++ model/org/eclipse/jdt/internal/core/XMLWriter.java 30 Aug 2005 09:48:05 -0000 @@ -92,16 +92,19 @@ } else { sb.append(">"); //$NON-NLS-1$ } + printString(sb.toString(), insertTab, insertNewLine); + if (parameters != null && !closeTag) + this.tab++; + + } + public void printString(String string, boolean insertTab, boolean insertNewLine) { if (insertTab) { printTabulation(); } - print(sb.toString()); + print(string); if (insertNewLine) { print(this.lineSeparator); } - if (parameters != null && !closeTag) - this.tab++; - } public void startTag(String name, boolean insertTab) { printTag(name, null/*no parameters*/, insertTab, true/*insert new line*/, false/*don't close tag*/);