diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java index 45b6a9706f2..b64a2a3bc28 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Andrew Gvozdev (Quoin Inc.) and others. + * Copyright (c) 2009, 2011 Andrew Gvozdev (Quoin Inc.) 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 @@ -11,11 +11,7 @@ package org.eclipse.cdt.internal.errorparsers; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -25,16 +21,6 @@ import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.ErrorParserManager; import org.eclipse.cdt.core.IErrorParser; @@ -43,7 +29,6 @@ import org.eclipse.cdt.core.IMarkerGenerator; import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper; import org.eclipse.cdt.core.errorparsers.RegexErrorParser; import org.eclipse.cdt.core.errorparsers.RegexErrorPattern; -import org.eclipse.cdt.core.resources.ResourcesUtil; import org.eclipse.cdt.internal.core.XmlUtil; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.runtime.CoreException; @@ -52,18 +37,14 @@ import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.osgi.service.prefs.BackingStoreException; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; /** * ErrorParserExtensionManager manages error parser extensions, serialization and preferences @@ -145,9 +126,9 @@ public class ErrorParserExtensionManager { fUserDefinedErrorParsers = null; Document doc = null; try { - doc = loadXml(getStoreLocation(STORAGE_ERRORPARSER_EXTENSIONS)); + doc = XmlUtil.loadXml(getStoreURI(STORAGE_ERRORPARSER_EXTENSIONS)); } catch (Exception e) { - CCorePlugin.log("Can't load preferences from file "+STORAGE_ERRORPARSER_EXTENSIONS, e); //$NON-NLS-1$ + CCorePlugin.log("Can't load preferences from "+STORAGE_ERRORPARSER_EXTENSIONS, e); //$NON-NLS-1$ } if (doc!=null) { @@ -164,25 +145,6 @@ public class ErrorParserExtensionManager { recalculateAvailableErrorParsers(); } - /** - * Load XML from file to DOM Document. - * - * @param location - location of XML file - * @return new loaded XML Document or {@code null} if file does not exist - * @throws ParserConfigurationException - * @throws SAXException - * @throws IOException - */ - private static Document loadXml(IPath location) throws ParserConfigurationException, SAXException, IOException { - java.io.File storeFile = location.toFile(); - if (storeFile.exists()) { - InputStream xmlStream = new FileInputStream(storeFile); - DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - return builder.parse(xmlStream); - } - return null; - } - /** * Parse error parser contributed extensions from XML document. * @@ -191,21 +153,19 @@ public class ErrorParserExtensionManager { */ private static void loadErrorParserExtensions(Document doc, Set errorParsers) { errorParsers.clear(); - NodeList extentionNodes = doc.getElementsByTagName(ELEM_EXTENSION); - for (int iext=0;iext entry: fUserDefinedErrorParsers.entrySet()) { @@ -348,10 +306,10 @@ public class ErrorParserExtensionManager { } } - serializeXml(doc, getStoreLocation(STORAGE_ERRORPARSER_EXTENSIONS)); + XmlUtil.serializeXml(doc, getStoreURI(STORAGE_ERRORPARSER_EXTENSIONS)); } catch (Exception e) { - throw new CoreException(new Status(IStatus.ERROR, "Failed serializing to file " + STORAGE_ERRORPARSER_EXTENSIONS, CCorePlugin.PLUGIN_ID, e)); //$NON-NLS-1$ + throw new CoreException(CCorePlugin.createStatus("Failed serializing to file " + STORAGE_ERRORPARSER_EXTENSIONS, e)); //$NON-NLS-1$ } } @@ -406,23 +364,19 @@ public class ErrorParserExtensionManager { if (errorParser instanceof ErrorParserNamedWrapper) errorParser = ((ErrorParserNamedWrapper)errorParser).getErrorParser(); - Document doc = elementPlugin.getOwnerDocument(); - // - Element elementExtension = doc.createElement(ELEM_EXTENSION); - elementExtension.setAttribute(ATTR_ID, simpleId); - elementExtension.setAttribute(ATTR_NAME, name); - elementExtension.setAttribute(ATTR_POINT, EXTENSION_POINT_ERROR_PARSER); - - elementPlugin.appendChild(elementExtension); + Element elementExtension = XmlUtil.appendElement(elementPlugin, ELEM_EXTENSION, new String[] { + ATTR_ID, simpleId, + ATTR_NAME, name, + ATTR_POINT, EXTENSION_POINT_ERROR_PARSER, + }); // - Element elementErrorParser = doc.createElement(ELEM_ERRORPARSER); - elementErrorParser.setAttribute(ATTR_ID, id); - elementErrorParser.setAttribute(ATTR_NAME, name); - elementErrorParser.setAttribute(ATTR_CLASS, errorParser.getClass().getCanonicalName()); - - elementExtension.appendChild(elementErrorParser); + Element elementErrorParser = XmlUtil.appendElement(elementExtension, ELEM_ERRORPARSER, new String[] { + ATTR_ID, id, + ATTR_NAME, name, + ATTR_CLASS, errorParser.getClass().getCanonicalName(), + }); if (errorParserNamed instanceof RegexErrorParser) { RegexErrorParser regexErrorParser = (RegexErrorParser)errorParserNamed; @@ -430,15 +384,15 @@ public class ErrorParserExtensionManager { for (RegexErrorPattern pattern : patterns) { // - Element elementPattern = doc.createElement(ELEM_PATTERN); - elementPattern.setAttribute(ATTR_SEVERITY, severityToString(pattern.getSeverity())); - elementPattern.setAttribute(ATTR_REGEX, pattern.getPattern()); - elementPattern.setAttribute(ATTR_FILE, pattern.getFileExpression()); - elementPattern.setAttribute(ATTR_LINE, pattern.getLineExpression()); - elementPattern.setAttribute(ATTR_DESCRIPTION, pattern.getDescriptionExpression()); - elementPattern.setAttribute(ATTR_EAT_LINE, String.valueOf(pattern.isEatProcessedLine())); - - elementErrorParser.appendChild(elementPattern); + @SuppressWarnings("unused") + Element elementPattern = XmlUtil.appendElement(elementErrorParser, ELEM_PATTERN, new String[] { + ATTR_SEVERITY, severityToString(pattern.getSeverity()), + ATTR_REGEX, pattern.getPattern(), + ATTR_FILE, pattern.getFileExpression(), + ATTR_LINE, pattern.getLineExpression(), + ATTR_DESCRIPTION, pattern.getDescriptionExpression(), + ATTR_EAT_LINE, String.valueOf(pattern.isEatProcessedLine()), + }); } } @@ -459,37 +413,6 @@ public class ErrorParserExtensionManager { return simpleId; } - /** - * Serialize XML Document in a file. - * - * @param doc - XML to serialize - * @param location - location of the file - * @throws IOException in case of problems with file I/O - * @throws TransformerException in case of problems with XML output - */ - synchronized private static void serializeXml(Document doc, IPath location) throws IOException, TransformerException { - - java.io.File storeFile = location.toFile(); - if (!storeFile.exists()) { - storeFile.createNewFile(); - } - OutputStream fileStream = new FileOutputStream(storeFile); - - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ - transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ - - XmlUtil.prettyFormat(doc); - DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(new FileOutputStream(storeFile)); - transformer.transform(source, result); - - fileStream.close(); - ResourcesUtil.refreshWorkspaceFiles(URIUtil.toURI(location)); - } - /** * Save the list of default error parsers in preferences. * @@ -508,10 +431,12 @@ public class ErrorParserExtensionManager { /** * @param store - name of the store - * @return location of the store in the plug-in state area + * @return URI of the store in the plug-in state area to keep plug-in specific data. */ - private static IPath getStoreLocation(String store) { - return CCorePlugin.getDefault().getStateLocation().append(store); + private static URI getStoreURI(String store) { + IPath location = CCorePlugin.getDefault().getStateLocation().append(store); + URI uri = URIUtil.toURI(location); + return uri; } /** @@ -582,9 +507,8 @@ public class ErrorParserExtensionManager { * @param errorparserNode - XML error parser node */ private static void configureErrorParser(IErrorParserNamed errorParser, Node errorparserNode) { - NamedNodeMap errorParserAttributes = errorparserNode.getAttributes(); - String id = determineNodeValue(errorParserAttributes.getNamedItem(ATTR_ID)); - String name = determineNodeValue(errorParserAttributes.getNamedItem(ATTR_NAME)); + String id = XmlUtil.determineAttributeValue(errorparserNode, ATTR_ID); + String name = XmlUtil.determineAttributeValue(errorparserNode, ATTR_NAME); errorParser.setId(id); errorParser.setName(name); if (errorParser instanceof RegexErrorParser) { @@ -596,13 +520,12 @@ public class ErrorParserExtensionManager { if(patternNode.getNodeType() != Node.ELEMENT_NODE || ! ELEM_PATTERN.equals(patternNode.getNodeName())) continue; - NamedNodeMap patternAttributes = patternNode.getAttributes(); - String attrSeverity = determineNodeValue(patternAttributes.getNamedItem(ATTR_SEVERITY)); - String regex = determineNodeValue(patternAttributes.getNamedItem(ATTR_REGEX)); - String fileExpr = determineNodeValue(patternAttributes.getNamedItem(ATTR_FILE)); - String lineExpr = determineNodeValue(patternAttributes.getNamedItem(ATTR_LINE)); - String DescExpr = determineNodeValue(patternAttributes.getNamedItem(ATTR_DESCRIPTION)); - String attrEatLine = determineNodeValue(patternAttributes.getNamedItem(ATTR_EAT_LINE)); + String attrSeverity = XmlUtil.determineAttributeValue(patternNode, ATTR_SEVERITY); + String regex = XmlUtil.determineAttributeValue(patternNode, ATTR_REGEX); + String fileExpr = XmlUtil.determineAttributeValue(patternNode, ATTR_FILE); + String lineExpr = XmlUtil.determineAttributeValue(patternNode, ATTR_LINE); + String DescExpr = XmlUtil.determineAttributeValue(patternNode, ATTR_DESCRIPTION); + String attrEatLine = XmlUtil.determineAttributeValue(patternNode, ATTR_EAT_LINE); int severity = stringToSeverity(attrSeverity); @@ -613,14 +536,6 @@ public class ErrorParserExtensionManager { } } - /** - * @param node - * @return node value or {@code null} - */ - private static String determineNodeValue(Node node) { - return node!=null ? node.getNodeValue() : null; - } - /** * Configure error parser from extension configuration element. * diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Messages.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Messages.java index 65803d1b7d5..9b0291f2759 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Messages.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Messages.java @@ -49,6 +49,8 @@ public class Messages extends NLS { public static String convention_enum_leadingUnderscore; public static String convention_enum_lowercaseName; public static String convention_enum_invalidName; + public static String XmlUtil_InternalErrorLoading; + public static String XmlUtil_InternalErrorSerializing; static { // initialize resource bundle diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/XmlUtil.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/XmlUtil.java index 6936851af6f..60fc7e4b295 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/XmlUtil.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/XmlUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2009 Andrew Gvozdev (Quoin Inc.). + * Copyright (c) 2009, 2011 Andrew Gvozdev (Quoin Inc.). * 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 @@ -10,8 +10,33 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.resources.ResourcesUtil; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -23,6 +48,78 @@ public class XmlUtil { private static final String EOL_XML = "\n"; //$NON-NLS-1$ private static final String DEFAULT_IDENT = "\t"; //$NON-NLS-1$ + /** + * Convenience method to create new XML DOM Document. + * + * @return a new instance of a DOM {@link Document}. + * @throws ParserConfigurationException in case of a problem retrieving {@link DocumentBuilder}. + */ + public static Document newDocument() throws ParserConfigurationException { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + return builder.newDocument(); + } + + /** + * Convenience method to retrieve value of a node. + * @return node value or {@code null} + */ + public static String determineNodeValue(Node node) { + return node!=null ? node.getNodeValue() : null; + } + + /** + * Convenience method to retrieve an attribute of an element. + * Note that calling element.getAttributes() once may be more efficient when pulling several attributes. + * + * @param element - element to retrieve the attribute from. + * @param attr - attribute to get value. + * @return attribute value or {@code null} + */ + public static String determineAttributeValue(Node element, String attr) { + NamedNodeMap attributes = element.getAttributes(); + return attributes!=null ? determineNodeValue(attributes.getNamedItem(attr)) : null; + } + + /** + * The method creates an element with specified name and attributes and appends it to the parent element. + * This is a convenience method for often used sequence of calls. + * + * @param parent - the node where to append the new element. + * @param name - the name of the element type being created. + * @param attributes - string array of pairs attributes and their values. + * Each attribute must have a value, so the array must have even number of elements. + * @return the newly created element. + * + * @throws ArrayIndexOutOfBoundsException in case of odd number of elements of the attribute array + * (i.e. the last attribute is missing a value). + */ + public static Element appendElement(Node parent, String name, String[] attributes) { + Document doc = parent instanceof Document ? (Document)parent : parent.getOwnerDocument(); + Element element = doc.createElement(name); + if (attributes!=null) { + int attrLen = attributes.length; + for (int i=0;i + * Note: clients should synchronize access to this method. + * + * @param doc - DOM Document to serialize. + * @param uriLocation - URI of the file. + * @throws IOException in case of problems with file I/O + * @throws TransformerException in case of problems with XML output + */ + public static void serializeXml(Document doc, URI uriLocation) throws IOException, TransformerException { + XmlUtil.prettyFormat(doc); + + java.io.File storeFile = new java.io.File(uriLocation); + if (!storeFile.exists()) { + storeFile.createNewFile(); + } + OutputStream fileStream = new FileOutputStream(storeFile); + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ + + XmlUtil.prettyFormat(doc); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(new FileOutputStream(storeFile)); + transformer.transform(source, result); + + fileStream.close(); + ResourcesUtil.refreshWorkspaceFiles(uriLocation); + } + + /** + * Serialize XML Document into a byte array. + * @param doc - DOM Document to serialize. + * @return XML as a byte array. + * @throws CoreException if something goes wrong. + */ + private static byte[] toByteArray(Document doc) throws CoreException { + XmlUtil.prettyFormat(doc); + + try { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(stream); + transformer.transform(source, result); + + return stream.toByteArray(); + } catch (Exception e) { + throw new CoreException(CCorePlugin.createStatus(Messages.XmlUtil_InternalErrorSerializing, e)); + } + } + + /** + * Serialize XML Document into a workspace file.
+ * Note: clients should synchronize access to this method. + * + * @param doc - DOM Document to serialize. + * @param file - file where to write the XML. + * @throws CoreException if something goes wrong. + */ + public static void serializeXml(Document doc, IFile file) throws CoreException { + XmlUtil.prettyFormat(doc); + + InputStream input = new ByteArrayInputStream(toByteArray(doc)); + if (file.exists()) { + file.setContents(input, IResource.FORCE, null); + } else { + file.create(input, IResource.FORCE, null); + } + } + + /** + * Serialize XML Document into a string. + * + * @param doc - DOM Document to serialize. + * @return XML as a String. + * @throws CoreException if something goes wrong. + */ + public static String toString(Document doc) throws CoreException { + return new String(toByteArray(doc)); } } - - diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/messages.properties b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/messages.properties index 71c680770f1..5ba21c06acc 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/messages.properties +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/messages.properties @@ -46,4 +46,7 @@ convention_enum_lowercaseName= Enum name starts with lower case convention_enum_invalidName= Enum name is invalid Util_unexpectedError=Unexpected error -Addr_valueOutOfRange=Address is outside valid range. \ No newline at end of file +Addr_valueOutOfRange=Address is outside valid range. + +XmlUtil_InternalErrorLoading=Internal error while trying to load XML document +XmlUtil_InternalErrorSerializing=Internal error while trying to serialize XML Document.