/******************************************************************************* * 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrew Gvozdev (Quoin Inc.) - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.errorparsers; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.ErrorParserManager; import org.eclipse.cdt.core.IErrorParser; import org.eclipse.cdt.core.IErrorParserNamed; 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.internal.core.XmlUtil; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; 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.Platform; 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.Node; import org.w3c.dom.NodeList; /** * ErrorParserExtensionManager manages error parser extensions, serialization and preferences * */ public class ErrorParserExtensionManager { private static final String STORAGE_ERRORPARSER_EXTENSIONS = "model.extensions.xml"; //$NON-NLS-1$ private static final String PREFERENCE_ERRORPARSER_DEFAULT_IDS = "errorparser.default.ids"; //$NON-NLS-1$ private static final String NONE = ""; //$NON-NLS-1$ private static final String EXTENSION_POINT_ERROR_PARSER = "org.eclipse.cdt.core.ErrorParser"; //$NON-NLS-1$ private static final String ELEM_PLUGIN = "plugin"; //$NON-NLS-1$ private static final String ELEM_EXTENSION = "extension"; //$NON-NLS-1$ private static final String ELEM_ERRORPARSER = "errorparser"; //$NON-NLS-1$ private static final String ELEM_PATTERN = "pattern"; //$NON-NLS-1$ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$ private static final String ATTR_ID = "id"; //$NON-NLS-1$ private static final String ATTR_NAME = "name"; //$NON-NLS-1$ private static final String ATTR_POINT = "point"; //$NON-NLS-1$ private static final String ATTR_REGEX = "regex"; //$NON-NLS-1$ private static final String ATTR_SEVERITY = "severity"; //$NON-NLS-1$ private static final String ATTR_FILE = "file-expr"; //$NON-NLS-1$ private static final String ATTR_LINE = "line-expr"; //$NON-NLS-1$ private static final String ATTR_DESCRIPTION = "description-expr"; //$NON-NLS-1$ private static final String ATTR_VARIABLE = "variable-expr"; //$NON-NLS-1$ private static final String ATTR_EAT_LINE = "eat-processed-line"; //$NON-NLS-1$ private static final String ATTR_VALUE_WARNING = "Warning"; //$NON-NLS-1$ private static final String ATTR_VALUE_ERROR = "Error"; //$NON-NLS-1$ private static final String ATTR_VALUE_INFO = "Info"; //$NON-NLS-1$ private static final String ATTR_VALUE_IGNORE = "Ignore"; //$NON-NLS-1$ private static final LinkedHashMap<String, IErrorParserNamed> fExtensionErrorParsers = new LinkedHashMap<String, IErrorParserNamed>(); private static final LinkedHashMap<String, IErrorParserNamed> fAvailableErrorParsers = new LinkedHashMap<String, IErrorParserNamed>(); private static LinkedHashMap<String, IErrorParserNamed> fUserDefinedErrorParsers = null; private static List<String> fDefaultErrorParserIds = null; private static class ErrorParserComparator implements Comparator<IErrorParserNamed> { // For the error parsers taken from platform extensions following sorting order applies: // - first regular error parsers // - then deprecated ones // - then contributed by test plugin // inside the same category sort by parser name public int compare(IErrorParserNamed errorParser1, IErrorParserNamed errorParser2) { final String TEST_PLUGIN_ID="org.eclipse.cdt.core.tests"; //$NON-NLS-1$ final String DEPRECATED=CCorePlugin.getResourceString("CCorePlugin.Deprecated"); //$NON-NLS-1$ boolean isTestPlugin1 = errorParser1.getId().startsWith(TEST_PLUGIN_ID); boolean isTestPlugin2 = errorParser2.getId().startsWith(TEST_PLUGIN_ID); if (isTestPlugin1==true && isTestPlugin2==false) return 1; if (isTestPlugin1==false && isTestPlugin2==true) return -1; boolean isDeprecated1 = errorParser1.getName().contains(DEPRECATED); boolean isDeprecated2 = errorParser2.getName().contains(DEPRECATED); if (isDeprecated1==true && isDeprecated2==false) return 1; if (isDeprecated1==false && isDeprecated2==true) return -1; return errorParser1.getName().compareTo(errorParser2.getName()); } } static { loadUserDefinedErrorParsers(); loadDefaultErrorParserIds(); loadErrorParserExtensions(); } /** * Load user defined error parsers from workspace preference storage. * * @noreference This method is not intended to be referenced by clients. */ synchronized public static void loadUserDefinedErrorParsers() { fUserDefinedErrorParsers = null; Document doc = null; try { doc = XmlUtil.loadXml(getStoreURI(STORAGE_ERRORPARSER_EXTENSIONS)); } catch (Exception e) { CCorePlugin.log("Can't load preferences from "+STORAGE_ERRORPARSER_EXTENSIONS, e); //$NON-NLS-1$ } if (doc!=null) { Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new ErrorParserComparator()); loadErrorParserExtensions(doc, sortedErrorParsers); if (sortedErrorParsers.size()>0) { fUserDefinedErrorParsers = new LinkedHashMap<String, IErrorParserNamed>(); for (IErrorParserNamed errorParser : sortedErrorParsers) { fUserDefinedErrorParsers.put(errorParser.getId(), errorParser); } } } recalculateAvailableErrorParsers(); } /** * Parse error parser contributed extensions from XML document. * * @param doc - source XML * @param errorParsers - resulting list of error parsers */ private static void loadErrorParserExtensions(Document doc, Set<IErrorParserNamed> errorParsers) { errorParsers.clear(); NodeList extensionNodes = doc.getElementsByTagName(ELEM_EXTENSION); for (int iext=0;iext<extensionNodes.getLength();iext++) { Node extensionNode = extensionNodes.item(iext); if(extensionNode.getNodeType() != Node.ELEMENT_NODE) continue; NodeList errorparserNodes = extensionNode.getChildNodes(); for (int ierp=0;ierp<errorparserNodes.getLength();ierp++) { Node errorparserNode = errorparserNodes.item(ierp); if(errorparserNode.getNodeType() != Node.ELEMENT_NODE || ! ELEM_ERRORPARSER.equals(errorparserNode.getNodeName())) continue; String className = XmlUtil.determineAttributeValue(errorparserNode, ATTR_CLASS); try { IErrorParserNamed errorParser = createErrorParserCarcass(className, Platform.getExtensionRegistry()); if (errorParser!=null) { configureErrorParser(errorParser, errorparserNode); errorParsers.add(errorParser); } } catch (Exception e) { CCorePlugin.log("Can't create class ["+className+"] while trying to load error parser extension", e); //$NON-NLS-1$ //$NON-NLS-2$ } } } } /** * Load workspace default error parser IDs to be used if no error parsers specified. * * @noreference This method is not intended to be referenced by clients. */ synchronized public static void loadDefaultErrorParserIds() { fDefaultErrorParserIds = null; IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID); String ids = preferences.get(PREFERENCE_ERRORPARSER_DEFAULT_IDS, NONE); if (ids.equals(NONE)) { return; } fDefaultErrorParserIds = Arrays.asList(ids.split(String.valueOf(ErrorParserManager.ERROR_PARSER_DELIMITER))); } /** * Load error parser contributed extensions. * * @noreference This method is not intended to be referenced by clients. */ synchronized public static void loadErrorParserExtensions() { Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new ErrorParserComparator()); loadErrorParserExtensions(Platform.getExtensionRegistry(), sortedErrorParsers); fExtensionErrorParsers.clear(); for (IErrorParserNamed errorParser : sortedErrorParsers) { fExtensionErrorParsers.put(errorParser.getId(), errorParser); } recalculateAvailableErrorParsers(); } /** * Load error parser contributed extensions from extension registry. * * @param registry - extension registry * @param errorParsers - resulting set of error parsers */ private static void loadErrorParserExtensions(IExtensionRegistry registry, Set<IErrorParserNamed> errorParsers) { errorParsers.clear(); IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.ERROR_PARSER_SIMPLE_ID); if (extension != null) { IExtension[] extensions = extension.getExtensions(); for (IExtension ext : extensions) { try { String extensionID = ext.getUniqueIdentifier(); String oldStyleId = extensionID; String oldStyleName = ext.getLabel(); for (IConfigurationElement cfgEl : ext.getConfigurationElements()) { if (cfgEl.getName().equals(ELEM_ERRORPARSER)) { IErrorParserNamed errorParser = createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl); if (errorParser!=null) { configureErrorParser(errorParser, cfgEl); errorParsers.add(errorParser); } } } } catch (Exception e) { CCorePlugin.log("Cannot load ErrorParser extension " + ext.getUniqueIdentifier(), e); //$NON-NLS-1$ } } } } /** * Populate the list of available error parsers where workspace level user defined parsers * overwrite contributed through error parser extension point. */ private static void recalculateAvailableErrorParsers() { fAvailableErrorParsers.clear(); // put default parsers on top of the list List<String> ids = new ArrayList<String>(); if (fDefaultErrorParserIds!=null) { for (String id : fDefaultErrorParserIds) { IErrorParserNamed errorParser = null; if (fUserDefinedErrorParsers!=null) { errorParser = fUserDefinedErrorParsers.get(id); } if (errorParser==null) { errorParser = fExtensionErrorParsers.get(id); } if (errorParser!=null) { fAvailableErrorParsers.put(id, errorParser); ids.add(id); } } } // then the rest in the order defined by comparator Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new ErrorParserComparator()); if (fUserDefinedErrorParsers!=null) { for (String id : fUserDefinedErrorParsers.keySet()) { if (!ids.contains(id)) { IErrorParserNamed errorParser = fUserDefinedErrorParsers.get(id); sortedErrorParsers.add(errorParser); } } } for (String id : fExtensionErrorParsers.keySet()) { if (!ids.contains(id)) { IErrorParserNamed errorParser = fExtensionErrorParsers.get(id); sortedErrorParsers.add(errorParser); } } for (IErrorParserNamed errorParser : sortedErrorParsers) { fAvailableErrorParsers.put(errorParser.getId(), errorParser); } } /** * Serialize error parsers in workspace level storage. * * @throws CoreException if something goes wrong */ public static void serializeUserDefinedErrorParsers() throws CoreException { try { Document doc = XmlUtil.newDocument(); Element elementPlugin = XmlUtil.appendElement(doc, ELEM_PLUGIN); if (fUserDefinedErrorParsers!=null) { for (Entry<String, IErrorParserNamed> entry: fUserDefinedErrorParsers.entrySet()) { IErrorParserNamed errorParser = entry.getValue(); addErrorParserExtension(elementPlugin, errorParser); } } XmlUtil.serializeXml(doc, getStoreURI(STORAGE_ERRORPARSER_EXTENSIONS)); } catch (Exception e) { throw new CoreException(CCorePlugin.createStatus("Failed serializing to file " + STORAGE_ERRORPARSER_EXTENSIONS, e)); //$NON-NLS-1$ } } /** * Utility method to convert severity to string for the purpose of serializing in XML. * * @param severity - severity * @return string representation */ private static String severityToString(int severity) { switch (severity) { case IMarkerGenerator.SEVERITY_INFO: return ATTR_VALUE_INFO; case IMarkerGenerator.SEVERITY_WARNING: return ATTR_VALUE_WARNING; case IMarkerGenerator.SEVERITY_ERROR_BUILD: case IMarkerGenerator.SEVERITY_ERROR_RESOURCE: return ATTR_VALUE_ERROR; } return ATTR_VALUE_IGNORE; } /** * Utility method to de-serialize severity from XML. * * @param attrSeverity - string representation of the severity * @return severity */ private static int stringToSeverity(String attrSeverity) { if (ATTR_VALUE_ERROR.equals(attrSeverity)) return IMarkerGenerator.SEVERITY_ERROR_RESOURCE; if (ATTR_VALUE_WARNING.equals(attrSeverity)) return IMarkerGenerator.SEVERITY_WARNING; if (ATTR_VALUE_INFO.equals(attrSeverity)) return IMarkerGenerator.SEVERITY_INFO; return RegexErrorPattern.SEVERITY_SKIP; } /** * Add error parser extension to XML fragment, normally under <plugin/> element. * * @param elementPlugin - element where to add error parser extension * @param errorParserNamed - error parser to add */ private static void addErrorParserExtension(Element elementPlugin, IErrorParserNamed errorParserNamed) { String id = errorParserNamed.getId(); String name = errorParserNamed.getName(); String simpleId = getSimpleId(id); IErrorParser errorParser = errorParserNamed; if (errorParser instanceof ErrorParserNamedWrapper) errorParser = ((ErrorParserNamedWrapper)errorParser).getErrorParser(); // <extension/> Element elementExtension = XmlUtil.appendElement(elementPlugin, ELEM_EXTENSION, new String[] { ATTR_ID, simpleId, ATTR_NAME, name, ATTR_POINT, EXTENSION_POINT_ERROR_PARSER, }); // <errorparser/> 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; RegexErrorPattern[] patterns = regexErrorParser.getPatterns(); for (RegexErrorPattern pattern : patterns) { // <pattern/> @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()), }); } } } /** * Determine simple ID of error parser as last segment of full or unique ID. * * @param uniqueId - full ID of error parser * @return simple ID of error parser */ private static String getSimpleId(String uniqueId) { String simpleId = uniqueId; int dot = uniqueId.lastIndexOf('.'); if (dot>=0) { simpleId = uniqueId.substring(dot+1); } return simpleId; } /** * Save the list of default error parsers in preferences. * * @throws BackingStoreException in case of problem storing */ public static void serializeDefaultErrorParserIds() throws BackingStoreException { IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID); String ids = NONE; if (fDefaultErrorParserIds!=null) { ids = ErrorParserManager.toDelimitedString(fDefaultErrorParserIds.toArray(new String[0])); } preferences.put(PREFERENCE_ERRORPARSER_DEFAULT_IDS, ids); preferences.flush(); } /** * @param store - name of the store * @return URI of the store in the plug-in state area to keep plug-in specific data. */ private static URI getStoreURI(String store) { IPath location = CCorePlugin.getDefault().getStateLocation().append(store); URI uri = URIUtil.toURI(location); return uri; } /** * Creates empty non-configured error parser from extension point definition looking at "class" attribute. * ID and name of error parser are assigned from first extension point encountered. * * @param className - full qualified class name of error parser. * @param registry - extension registry * @return new non-configured error parser */ private static IErrorParserNamed createErrorParserCarcass(String className, IExtensionRegistry registry) { if (className==null || className.length()==0 || className.equals(RegexErrorParser.class.getName())) return new RegexErrorParser(); try { IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.ERROR_PARSER_SIMPLE_ID); if (extension != null) { IExtension[] extensions = extension.getExtensions(); for (IExtension ext : extensions) { String extensionID = ext.getUniqueIdentifier(); String oldStyleId = extensionID; String oldStyleName = ext.getLabel(); for (IConfigurationElement cfgEl : ext.getConfigurationElements()) { if (cfgEl.getName().equals(ELEM_ERRORPARSER) && className.equals(cfgEl.getAttribute(ATTR_CLASS))) { return createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl); } } } } } catch (Exception e) { CCorePlugin.log("Error creating error parser", e); //$NON-NLS-1$ } return null; } /** * Creates empty non-configured error parser as executable extension from extension point definition. * If "class" attribute is empty RegexErrorParser is created. * * @param initialId - nominal ID of error parser * @param initialName - nominal name of error parser * @param ce - configuration element with error parser definition * @return new non-configured error parser * @throws CoreException in case of failure */ private static IErrorParserNamed createErrorParserCarcass(String initialId, String initialName, IConfigurationElement ce) throws CoreException { IErrorParserNamed errorParser = null; if (ce.getAttribute(ATTR_CLASS)!=null) { IErrorParser ep = (IErrorParser)ce.createExecutableExtension(ATTR_CLASS); if (ep instanceof IErrorParserNamed) { errorParser = (IErrorParserNamed)ep; errorParser.setId(initialId); errorParser.setName(initialName); } else if (ep!=null) { errorParser = new ErrorParserNamedWrapper(initialId, initialName, ep); } } if (errorParser==null) { errorParser = new RegexErrorParser(initialId, initialName); } return errorParser; } /** * Configure error parser from XML error parser node. * * @param errorParser - error parser to configure * @param errorparserNode - XML error parser node */ private static void configureErrorParser(IErrorParserNamed errorParser, Node errorparserNode) { String id = XmlUtil.determineAttributeValue(errorparserNode, ATTR_ID); String name = XmlUtil.determineAttributeValue(errorparserNode, ATTR_NAME); errorParser.setId(id); errorParser.setName(name); if (errorParser instanceof RegexErrorParser) { RegexErrorParser regexErrorParser = (RegexErrorParser)errorParser; NodeList patternNodes = errorparserNode.getChildNodes(); for (int ipat=0;ipat<patternNodes.getLength();ipat++) { Node patternNode = patternNodes.item(ipat); if(patternNode.getNodeType() != Node.ELEMENT_NODE || ! ELEM_PATTERN.equals(patternNode.getNodeName())) continue; 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); boolean eatLine = ! Boolean.FALSE.toString().equals(attrEatLine); // if null default to true regexErrorParser.addPattern(new RegexErrorPattern(regex, fileExpr, lineExpr, DescExpr, null, severity, eatLine)); } } } /** * Configure error parser from extension configuration element. * * @param errorParser - error parser to configure * @param cfgEl - extension configuration element * @throws CoreException */ private static void configureErrorParser(IErrorParserNamed errorParser, IConfigurationElement cfgEl) throws CoreException { String id = cfgEl.getAttribute(ATTR_ID); if (id!=null && id.length()>0) errorParser.setId(id); String name = cfgEl.getAttribute(ATTR_NAME); if (name!=null && name.length()>0) errorParser.setName(name); if (errorParser instanceof RegexErrorParser) { RegexErrorParser regexErrorParser = (RegexErrorParser)errorParser; for (IConfigurationElement cepat : cfgEl.getChildren()) { if (cepat.getName().equals(ELEM_PATTERN)) { boolean eat = ! Boolean.FALSE.toString().equals(cepat.getAttribute(ATTR_EAT_LINE)); regexErrorParser.addPattern(new RegexErrorPattern(cepat.getAttribute(ATTR_REGEX), cepat.getAttribute(ATTR_FILE), cepat.getAttribute(ATTR_LINE), cepat.getAttribute(ATTR_DESCRIPTION), cepat.getAttribute(ATTR_VARIABLE), stringToSeverity(cepat.getAttribute(ATTR_SEVERITY)), eat)); } } } } /** * Return error parser as stored in internal list. * * @noreference This method is not intended to be referenced by clients. * Use {@link #getErrorParserCopy(String, boolean)} instead. * * @param id - ID of error parser * @return internal instance of error parser */ public static IErrorParser getErrorParserInternal(String id) { IErrorParserNamed errorParser = fAvailableErrorParsers.get(id); if (errorParser instanceof ErrorParserNamedWrapper) return ((ErrorParserNamedWrapper)errorParser).getErrorParser(); return errorParser; } /** * Set and store in workspace area user defined error parsers. * * @param errorParsers - array of user defined error parsers * @throws CoreException in case of problems */ public static void setUserDefinedErrorParsers(IErrorParserNamed[] errorParsers) throws CoreException { setUserDefinedErrorParsersInternal(errorParsers); serializeUserDefinedErrorParsers(); } /** * Internal method to set user defined error parsers in memory. * * @noreference This method is not intended to be referenced by clients. * Use {@link #setUserDefinedErrorParsers(IErrorParserNamed[])}. * * @param errorParsers - array of user defined error parsers */ public static void setUserDefinedErrorParsersInternal(IErrorParserNamed[] errorParsers) { if (errorParsers==null) { fUserDefinedErrorParsers = null; } else { Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new ErrorParserComparator()); sortedErrorParsers.addAll(Arrays.asList(errorParsers)); fUserDefinedErrorParsers= new LinkedHashMap<String, IErrorParserNamed>(); // set customized list for (IErrorParserNamed errorParser : sortedErrorParsers) { fUserDefinedErrorParsers.put(errorParser.getId(), errorParser); } } recalculateAvailableErrorParsers(); } /** * @return available error parsers IDs which include contributed through extension + user defined ones * from workspace */ public static String[] getErrorParserAvailableIds() { return fAvailableErrorParsers.keySet().toArray(new String[0]); } /** * @return IDs of error parsers contributed through error parser extension point. */ public static String[] getErrorParserExtensionIds() { return fExtensionErrorParsers.keySet().toArray(new String[0]); } /** * @return default error parsers IDs to be used if error parser list is empty. */ public static String[] getUserDefinedErrorParserIds() { if (fUserDefinedErrorParsers!=null) return fUserDefinedErrorParsers.keySet().toArray(new String[0]); return null; } /** * Set and store default error parsers IDs to be used if error parser list is empty. * * @param ids - default error parsers IDs * @throws BackingStoreException in case of problem with storing */ public static void setDefaultErrorParserIds(String[] ids) throws BackingStoreException { setDefaultErrorParserIdsInternal(ids); serializeDefaultErrorParserIds(); } /** * Set default error parsers IDs in internal list. * * @noreference This method is not intended to be referenced by clients. * Use {@link #setDefaultErrorParserIds(String[])}. * * @param ids - default error parsers IDs */ public static void setDefaultErrorParserIdsInternal(String[] ids) { if (ids==null) { fDefaultErrorParserIds = null; } else { fDefaultErrorParserIds = new ArrayList<String>(Arrays.asList(ids)); } recalculateAvailableErrorParsers(); } /** * @return default error parsers IDs to be used if error parser list is empty. */ public static String[] getDefaultErrorParserIds() { if (fDefaultErrorParserIds==null) { return fAvailableErrorParsers.keySet().toArray(new String[0]); } return fDefaultErrorParserIds.toArray(new String[0]); } /** * @param id - ID of error parser * @param isExtension - if {@code true} get unmodified copy of error parser defined as extension * @return cloned copy of error parser. Note that {@link ErrorParserNamedWrapper} returns * shallow copy with the same instance of underlying error parser. */ public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension) { IErrorParserNamed errorParser = isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id); try { if (errorParser instanceof RegexErrorParser) { return (RegexErrorParser) ((RegexErrorParser)errorParser).clone(); } else if (errorParser instanceof ErrorParserNamedWrapper) { return (ErrorParserNamedWrapper) ((ErrorParserNamedWrapper)errorParser).clone(); } } catch (CloneNotSupportedException e) { CCorePlugin.log(e); } return errorParser; } }