package org.eclipse.buckminster.jdt.internal; import org.eclipse.buckminster.sax.ISaxable; import org.eclipse.buckminster.sax.ISaxableElement; import org.eclipse.buckminster.sax.Utils; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IAccessRule; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.internal.core.ClasspathEntry; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; @SuppressWarnings("restriction") public class SaxableClasspath implements ISaxable { private static void emitAccessRule(IAccessRule accessRule, ContentHandler receiver) throws SAXException { AttributesImpl attrs = new AttributesImpl(); Utils.addAttribute(attrs, ClasspathEntry.TAG_PATTERN, accessRule.getPattern().toString()); String kindString; switch (accessRule.getKind()) { case IAccessRule.K_NON_ACCESSIBLE: kindString = ClasspathEntry.TAG_NON_ACCESSIBLE; break; case IAccessRule.K_DISCOURAGED: kindString = ClasspathEntry.TAG_DISCOURAGED; break; default: kindString = ClasspathEntry.TAG_ACCESSIBLE; } Utils.addAttribute(attrs, ClasspathEntry.TAG_KIND, kindString); if (accessRule.ignoreIfBetter()) Utils.addAttribute(attrs, ClasspathEntry.TAG_IGNORE_IF_BETTER, "true"); //$NON-NLS-1$ receiver.startElement("", "", ClasspathEntry.TAG_ACCESS_RULE, attrs); //$NON-NLS-1$ //$NON-NLS-2$ receiver.endElement("", "", ClasspathEntry.TAG_ACCESS_RULE); //$NON-NLS-1$ //$NON-NLS-2$ } private static void emitAttribute(IClasspathAttribute attribute, ContentHandler receiver) throws SAXException { AttributesImpl attrs = new AttributesImpl(); Utils.addAttribute(attrs, ClasspathEntry.TAG_ATTRIBUTE_NAME, attribute.getName()); Utils.addAttribute(attrs, ClasspathEntry.TAG_ATTRIBUTE_VALUE, attribute.getValue()); receiver.startElement("", "", ClasspathEntry.TAG_ATTRIBUTE, attrs); //$NON-NLS-1$ //$NON-NLS-2$ receiver.endElement("", "", ClasspathEntry.TAG_ATTRIBUTE); //$NON-NLS-1$ //$NON-NLS-2$ } private static void encodePatterns(IPath[] patterns, String tag, AttributesImpl attrs) { if (patterns != null) { int top = patterns.length; if (top > 0) { StringBuilder rule = new StringBuilder(10); rule.append(patterns[0]); for (int idx = 1; idx < top; ++idx) { rule.append('|'); rule.append(patterns[idx]); } Utils.addAttribute(attrs, tag, rule.toString()); } } } private static String kindToString(int kind) { String kindStr; switch (kind) { case IClasspathEntry.CPE_PROJECT: case IClasspathEntry.CPE_SOURCE: kindStr = "src"; //$NON-NLS-1$ break; case IClasspathEntry.CPE_LIBRARY: kindStr = "lib"; //$NON-NLS-1$ break; case IClasspathEntry.CPE_VARIABLE: kindStr = "var"; //$NON-NLS-1$ break; case IClasspathEntry.CPE_CONTAINER: kindStr = "con"; //$NON-NLS-1$ break; case ClasspathEntry.K_OUTPUT: kindStr = "output"; //$NON-NLS-1$ break; default: kindStr = "unknown"; //$NON-NLS-1$ } return kindStr; } private final IClasspathEntry[] entries; private final IPath projectPath; public SaxableClasspath(IPath projectPath, IClasspathEntry[] entries) { this.projectPath = projectPath; this.entries = entries; } @Override public void toSax(ContentHandler receiver) throws SAXException { receiver.startDocument(); receiver.startElement("", "", ClasspathEntry.TAG_CLASSPATH, ISaxableElement.EMPTY_ATTRIBUTES); //$NON-NLS-1$ //$NON-NLS-2$ for (IClasspathEntry entry : entries) emitEntry(entry, receiver); receiver.endElement("", "", ClasspathEntry.TAG_CLASSPATH); //$NON-NLS-1$ //$NON-NLS-2$ receiver.endDocument(); } private void emitEntry(IClasspathEntry entry, ContentHandler receiver) throws SAXException { AttributesImpl attrs = new AttributesImpl(); int entryKind = entry.getEntryKind(); Utils.addAttribute(attrs, ClasspathEntry.TAG_KIND, kindToString(entryKind)); IPath xmlPath = makeProjectRelative(entry.getPath(), entryKind); if (xmlPath != null) Utils.addAttribute(attrs, ClasspathEntry.TAG_PATH, xmlPath.toString()); xmlPath = makeProjectRelative(entry.getSourceAttachmentPath(), entryKind); if (xmlPath != null) Utils.addAttribute(attrs, ClasspathEntry.TAG_SOURCEPATH, xmlPath.toString()); xmlPath = entry.getSourceAttachmentRootPath(); if (xmlPath != null) Utils.addAttribute(attrs, ClasspathEntry.TAG_ROOTPATH, xmlPath.toString()); if (entry.isExported()) Utils.addAttribute(attrs, ClasspathEntry.TAG_EXPORTED, "true");//$NON-NLS-1$ encodePatterns(entry.getInclusionPatterns(), ClasspathEntry.TAG_INCLUDING, attrs); encodePatterns(entry.getExclusionPatterns(), ClasspathEntry.TAG_EXCLUDING, attrs); if (entryKind == IClasspathEntry.CPE_PROJECT && !entry.combineAccessRules()) Utils.addAttribute(attrs, ClasspathEntry.TAG_COMBINE_ACCESS_RULES, "false"); //$NON-NLS-1$ IPath outputLocation = entry.getOutputLocation(); if (outputLocation != null) { outputLocation = outputLocation.removeFirstSegments(1); Utils.addAttribute(attrs, ClasspathEntry.TAG_OUTPUT, String.valueOf(outputLocation)); } receiver.startElement("", "", ClasspathEntry.TAG_CLASSPATHENTRY, attrs); //$NON-NLS-1$ //$NON-NLS-2$ IClasspathAttribute[] attributes = entry.getExtraAttributes(); if (attributes.length > 0) { receiver.startElement("", "", ClasspathEntry.TAG_ATTRIBUTES, ISaxableElement.EMPTY_ATTRIBUTES); //$NON-NLS-1$ //$NON-NLS-2$ for (IClasspathAttribute attribute : attributes) emitAttribute(attribute, receiver); receiver.endElement("", "", ClasspathEntry.TAG_ATTRIBUTES); //$NON-NLS-1$ //$NON-NLS-2$ } IAccessRule accessRules[] = entry.getAccessRules(); if (accessRules.length > 0) { receiver.startElement("", "", ClasspathEntry.TAG_ACCESS_RULES, ISaxableElement.EMPTY_ATTRIBUTES); //$NON-NLS-1$ //$NON-NLS-2$ for (IAccessRule accessRule : accessRules) emitAccessRule(accessRule, receiver); receiver.endElement("", "", ClasspathEntry.TAG_ACCESS_RULES); //$NON-NLS-1$ //$NON-NLS-2$ } receiver.endElement("", "", ClasspathEntry.TAG_CLASSPATHENTRY); //$NON-NLS-1$ //$NON-NLS-2$ } private IPath makeProjectRelative(IPath path, int entryKind) { if (path == null || !path.isAbsolute()) return path; if (entryKind == IClasspathEntry.CPE_VARIABLE || entryKind == IClasspathEntry.CPE_CONTAINER) return path; // translate to project relative from absolute (unless a device path) // if (projectPath == null || !projectPath.isPrefixOf(path)) return path; return path.removeFirstSegments(projectPath.segmentCount()).setDevice(null); } }