From bc785ee83d728311eb3c2c77649837996ad46ee8 Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Thu, 14 Sep 2023 15:27:18 -0400 Subject: [PATCH] xml: Implement configuration extension for xml analysis This patch uses the recently added extension point for configuration source `org.eclipse.tracecompass.tmf.core.config.xmlsourcetype` for XML analysis. The purpose of the extension point is to standardize how configurations are managed in Trace Compass. This commit includes JUnit tests for the XmlConfigurationSource class. [Added] Implementation of a configuration extension for xml analysis Change-Id: I9b035f25eaef9dd98250801040f4fa6bf1d60f4b Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/c/tracecompass/org.eclipse.tracecompass/+/204456 Tested-by: Patrick Tasse Tested-by: Trace Compass Bot Reviewed-by: Patrick Tasse --- .../config/XmlConfigurationSourceTest.java | 305 ++++++++++++++++++ .../META-INF/MANIFEST.MF | 1 + .../plugin.xml | 7 + .../analysis/xml/core/config/Messages.java | 38 +++ .../core/config/XmlConfigurationSource.java | 196 +++++++++++ .../xml/core/config/messages.properties | 15 + .../xml/core/config/package-info.java | 13 + .../analysis/xml/core/module/XmlUtils.java | 1 + 8 files changed, 576 insertions(+) create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core.tests/src/org/eclipse/tracecompass/tmf/analysis/xml/core/tests/config/XmlConfigurationSourceTest.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/Messages.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/XmlConfigurationSource.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/messages.properties create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/package-info.java diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core.tests/src/org/eclipse/tracecompass/tmf/analysis/xml/core/tests/config/XmlConfigurationSourceTest.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core.tests/src/org/eclipse/tracecompass/tmf/analysis/xml/core/tests/config/XmlConfigurationSourceTest.java new file mode 100644 index 0000000000..ad9da5a1f3 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core.tests/src/org/eclipse/tracecompass/tmf/analysis/xml/core/tests/config/XmlConfigurationSourceTest.java @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright (c) 2023 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +package org.eclipse.tracecompass.tmf.analysis.xml.core.tests.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.config.XmlConfigurationSource; +import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils; +import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.Activator; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfigParamDescriptor; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfiguration; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfigurationSource; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfigurationSourceType; +import org.eclipse.tracecompass.tmf.core.config.TmfConfigurationSourceManager; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.ImmutableMap; + +/** + * Tests for the {@link XmlConfigurationSource} class + * + * @author Bernd Hufmann + */ +@SuppressWarnings("null") +public class XmlConfigurationSourceTest { + + private static final String UNKNOWN_TYPE = "test-test-test"; + private static final String XML_ANALYSIS_TYPE_ID = "org.eclipse.tracecompass.tmf.core.config.xmlsourcetype"; //$NON-NLS-1$ + private static final Path PATH_INVALID = new Path("test_xml_files/test_invalid"); + private static final Path PATH_VALID = new Path("test_xml_files/test_valid"); + + private static String VALID_NAME = "kvm_exits"; + private static String VALID_XML_FILE = VALID_NAME + ".xml"; + private static String INVALID_XML_FILE = "invalid_condition_operators.xml"; + private static String PATH_TO_INVALID_FILE = getPath(PATH_INVALID, INVALID_XML_FILE); + private static String PATH_TO_VALID_FILE = getPath(PATH_VALID, VALID_XML_FILE); + private static String PATH_TO_VALID_FILE2 = getPath(PATH_VALID, "state_provider_placement.xml"); //$NON-NLS-1$ + private static final String EXPECTED_TYPE_NAME = "XML Data-driven analyses"; //$NON-NLS-1$ + private static final String EXPECTED_TYPE_DESCRIPTION = "Data-driven analyses described in XML"; //$NON-NLS-1$ + private static final String EXPECTED_KEY_NAME = "path"; + private static final String EXPECTED_PARAM_DESCRIPTION = "URI to XML analysis file"; + private static final String EXPECTED_DATA_TYPE = "STRING"; + private static final String EXPECTED_CONFIG_NAME = VALID_NAME; + private static final String EXPECTED_CONFIG_ID = VALID_XML_FILE; + private static final String EXPECTED_CONFIG_DESCRIPTION = "XML Data-driven analysis: " + VALID_NAME; + private static Map VALID_PARAM = ImmutableMap.of(EXPECTED_KEY_NAME, PATH_TO_VALID_FILE); + private static Map VALID_PARAM2 = ImmutableMap.of(EXPECTED_KEY_NAME, PATH_TO_VALID_FILE2); + private static Map INVALID_PARAM = ImmutableMap.of(EXPECTED_KEY_NAME, PATH_TO_INVALID_FILE); + private static final String EXPECTED_MESSAGE_NO_PATH = "Missing path"; //$NON-NLS-1$ + private static final String EXPECTED_MESSAGE_FILE_NOT_FOUND = "An error occurred while validating the XML file."; //$NON-NLS-1$ + private static final String EXPECTED_MESSAGE_INVALID_CONFIG = "No such configuration with ID: " + UNKNOWN_TYPE; //$NON-NLS-1$ + private static final String EXPECTED_MESSAGE_FILE_MISMATCH = "File mismatch"; //$NON-NLS-1$ + + private static ITmfConfigurationSource sfXmlConfigSource; + private static TmfConfigurationSourceManager sfInstance; + /** + * Test setup + */ + @BeforeClass + public static void init() { + sfInstance = TmfConfigurationSourceManager.getInstance(); + assertNotNull(sfInstance); + sfXmlConfigSource = sfInstance.getConfigurationSource(XML_ANALYSIS_TYPE_ID); + assertNotNull(sfXmlConfigSource); + } + + /** + * Empty the XML directory after the test + */ + @After + public void emptyXmlFolder() { + // Clean-up config source + Iterator iter = sfXmlConfigSource.getConfigurations().iterator(); + while (iter.hasNext()) { + sfXmlConfigSource.remove(iter.next().getId()); + } + + // Delete any remaining xml files, if any + File fFolder = XmlUtils.getXmlFilesPath().toFile(); + if (!(fFolder.isDirectory() && fFolder.exists())) { + return; + } + for (File xmlFile : fFolder.listFiles()) { + xmlFile.delete(); + } + } + + /** + * Test the constructor of the XML configuration source + * + * @throws TmfConfigurationException + * If an error occurred + */ + @Test + public void testConstructor() throws TmfConfigurationException { + // Make sure that an xml file is loaded + ITmfConfiguration config = sfXmlConfigSource.create(VALID_PARAM); + + XmlConfigurationSource instance = new XmlConfigurationSource(); + List configurations = instance.getConfigurations(); + assertTrue(configurations.contains(config)); + } + + /** + * Test the ITmfConfigurationSourceType for this XML configuration source + */ + @Test + public void testSourceType() { + ITmfConfigurationSourceType type = sfXmlConfigSource.getConfigurationSourceType(); + assertEquals(XML_ANALYSIS_TYPE_ID, type.getId()); + assertEquals(EXPECTED_TYPE_NAME, type.getName()); + assertEquals(EXPECTED_TYPE_DESCRIPTION, type.getDescription()); + List descriptors = type.getConfigParamDescriptors(); + assertNotNull(descriptors); + assertEquals(1, descriptors.size()); + ITmfConfigParamDescriptor desc = descriptors.get(0); + assertEquals(EXPECTED_KEY_NAME, desc.getKeyName()); + assertEquals(EXPECTED_DATA_TYPE, desc.getDataType()); + assertEquals(EXPECTED_PARAM_DESCRIPTION, desc.getDescription()); + assertTrue(desc.isRequired()); + } + + /** + * Test the creation of a configuration instance + */ + @Test + public void testCreation() { + // Test missing path + Map param = Collections.emptyMap(); + try { + sfXmlConfigSource.create(param); + } catch (TmfConfigurationException e) { + // success + assertEquals(EXPECTED_MESSAGE_NO_PATH, e.getMessage()); + } + + // Test XML file doesn't exist + param = ImmutableMap.of(EXPECTED_KEY_NAME, XmlUtils.getXmlFilesPath().append(UNKNOWN_TYPE).toOSString()); + try { + sfXmlConfigSource.create(param); + } catch (TmfConfigurationException e) { + // success + assertEquals(EXPECTED_MESSAGE_FILE_NOT_FOUND, e.getMessage()); + } + + // Test invalid XML file + try { + sfXmlConfigSource.create(INVALID_PARAM); + } catch (TmfConfigurationException e) { + // success + } + + try { + ITmfConfiguration config = sfXmlConfigSource.create(VALID_PARAM); + validateConfig(PATH_TO_VALID_FILE, config); + } catch (TmfConfigurationException e) { + fail(); + } + } + + /** + * Test the update of a configuration instance + */ + @Test + public void testUpdate() { + ITmfConfiguration config = createConfig(PATH_TO_VALID_FILE); + assertNotNull(config); + + // Test missing path + Map param = Collections.emptyMap(); + try { + sfXmlConfigSource.update(config.getId(), param); + } catch (TmfConfigurationException e) { + // success + assertEquals(EXPECTED_MESSAGE_NO_PATH, e.getMessage()); + } + + // Test config doesn't exist + try { + sfXmlConfigSource.update(UNKNOWN_TYPE, param); + } catch (TmfConfigurationException e) { + // success + assertEquals(EXPECTED_MESSAGE_INVALID_CONFIG, e.getMessage()); + } + + // Test XML file doesn't exist + param = ImmutableMap.of(EXPECTED_KEY_NAME, XmlUtils.getXmlFilesPath().append(UNKNOWN_TYPE).toOSString()); + try { + sfXmlConfigSource.update(config.getId(), param); + } catch (TmfConfigurationException e) { + // success + assertEquals(EXPECTED_MESSAGE_FILE_NOT_FOUND, e.getMessage()); + } + + // Test invalid XML file + try { + sfXmlConfigSource.update(EXPECTED_CONFIG_ID, INVALID_PARAM); + } catch (TmfConfigurationException e) { + // success + + } + + // Test file name mismatch... not allowed to use different xmlfile name + try { + sfXmlConfigSource.update(config.getId(), VALID_PARAM2); + } catch (TmfConfigurationException e) { + assertEquals(EXPECTED_MESSAGE_FILE_MISMATCH, e.getMessage()); + } + + try { + ITmfConfiguration configUpdated = sfXmlConfigSource.update(config.getId(), VALID_PARAM); + validateConfig(PATH_TO_VALID_FILE, configUpdated); + } catch (TmfConfigurationException e) { + fail(); + } + } + + /** + * Test contains + */ + @Test + public void testContains() { + createConfig(PATH_TO_VALID_FILE); + assertTrue(sfXmlConfigSource.contains(EXPECTED_CONFIG_ID)); + assertFalse(sfXmlConfigSource.contains(UNKNOWN_TYPE)); + } + + /** + * Test the removal + */ + @Test + public void testRemove() { + createConfig(PATH_TO_VALID_FILE); + ITmfConfiguration config = sfXmlConfigSource.remove(UNKNOWN_TYPE); + assertNull(config); + config = sfXmlConfigSource.remove(EXPECTED_CONFIG_ID); + validateConfig(PATH_TO_VALID_FILE, config); + } + + /** + * Test list configuration + */ + @Test + public void testGetConfiguration() { + List configurations = sfXmlConfigSource.getConfigurations(); + assertTrue(configurations.isEmpty()); + ITmfConfiguration config = createConfig(PATH_TO_VALID_FILE); + assertNotNull(config); + configurations = sfXmlConfigSource.getConfigurations(); + assertFalse(configurations.isEmpty()); + assertTrue(configurations.contains(config)); + } + + private static ITmfConfiguration createConfig(String path) { + Map param = ImmutableMap.of("path", path); + try { + return sfXmlConfigSource.create(param); + } catch (TmfConfigurationException e) { + // Nothing to do + } + return null; + } + + private static void validateConfig(String path, ITmfConfiguration config) { + assertNotNull(config); + assertEquals(EXPECTED_CONFIG_NAME, config.getName()); + assertEquals(EXPECTED_CONFIG_ID, config.getId()); + assertEquals(XML_ANALYSIS_TYPE_ID, config.getSourceTypeId()); + assertEquals(EXPECTED_CONFIG_DESCRIPTION, config.getDescription()); + assertTrue(config.getParameters().isEmpty()); + } + + private static String getPath(Path folder, String name) { + IPath path = Activator.getAbsolutePath(folder).append(name); + File file = path.toFile(); + assertTrue(file.exists()); + return Objects.requireNonNull(file.getAbsolutePath()); + } +} diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF index cf7b12ab87..d385c0cb36 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF @@ -19,6 +19,7 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.jdt.annotation;bundle-version="[2.0.0,3.0.0)";resolution:=optional, org.mozilla.javascript;bundle-version="1.7.10" Export-Package: org.eclipse.tracecompass.internal.tmf.analysis.xml.core;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests", + org.eclipse.tracecompass.internal.tmf.analysis.xml.core.config;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests", org.eclipse.tracecompass.internal.tmf.analysis.xml.core.fsm.compile;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests,org.eclipse.tracecompass.tmf.analysis.xml.ui", org.eclipse.tracecompass.internal.tmf.analysis.xml.core.fsm.model;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests,org.eclipse.tracecompass.tmf.analysis.xml.ui", org.eclipse.tracecompass.internal.tmf.analysis.xml.core.fsm.model.runtime;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests,org.eclipse.tracecompass.tmf.analysis.xml.ui", diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/plugin.xml b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/plugin.xml index b405184b0a..a9887a6b85 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/plugin.xml +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/plugin.xml @@ -9,4 +9,11 @@ class="org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlAnalysisModuleSource"> + + + + diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/Messages.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/Messages.java new file mode 100644 index 0000000000..d85d4693ab --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/Messages.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2023 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.osgi.util.NLS; + +/** + * XML Configuration message bundle + */ +@NonNullByDefault({}) +public class Messages extends NLS { + + private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$ + /** The name of XML analysis configuration source */ + public static String XmlConfigurationSource_Name; + /** The description of XML analysis configuration source */ + public static String XmlConfigurationSource_Description; + /** The name of XML analysis configuration description */ + public static String XmlConfigurationSource_ConfigDescription; + /** The description of the path parameter*/ + public static String XmlConfigurationSource_PathDescription; + + static { + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() {} +} diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/XmlConfigurationSource.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/XmlConfigurationSource.java new file mode 100644 index 0000000000..72e40d6578 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/XmlConfigurationSource.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2023 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.config; + +import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlAnalysisModuleSource; +import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfiguration; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfigurationSource; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfigurationSourceType; +import org.eclipse.tracecompass.tmf.core.config.TmfConfigParamDescriptor; +import org.eclipse.tracecompass.tmf.core.config.TmfConfiguration; +import org.eclipse.tracecompass.tmf.core.config.TmfConfigurationSourceType; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException; + +import com.google.common.collect.ImmutableList; + +/** + * Implementation of {@link ITmfConfigurationSource} for managing data + * driven-analysis in XML files. + * + * @author Bernd Hufmann + */ +public class XmlConfigurationSource implements ITmfConfigurationSource { + + private static final ITmfConfigurationSourceType fType; + + private static final String XML_ANALYSIS_TYPE_ID = "org.eclipse.tracecompass.tmf.core.config.xmlsourcetype"; //$NON-NLS-1$ + private static final String NAME = nullToEmptyString(Messages.XmlConfigurationSource_Name); + private static final String DESCRIPTION = nullToEmptyString(Messages.XmlConfigurationSource_Description); + private static final String PATH_KEY = "path"; //$NON-NLS-1$ + private static final String PATH_DESCRIPTION = nullToEmptyString(Messages.XmlConfigurationSource_PathDescription); + private static final boolean IS_WINDOWS = System.getProperty("os.name").contains("Windows"); //$NON-NLS-1$ //$NON-NLS-2$ + private Map fConfigurations = new ConcurrentHashMap<>(); + + static { + TmfConfigParamDescriptor.Builder descriptorBuilder = new TmfConfigParamDescriptor.Builder() + .setKeyName(PATH_KEY) + .setDescription(PATH_DESCRIPTION); + + fType = new TmfConfigurationSourceType.Builder() + .setId(XML_ANALYSIS_TYPE_ID) + .setDescription(DESCRIPTION) + .setName(NAME) + .setConfigParamDescriptors(ImmutableList.of(descriptorBuilder.build())).build(); + } + + /** + * Default Constructor + */ + @SuppressWarnings("null") + public XmlConfigurationSource() { + for (Entry<@NonNull String, @NonNull File> entry : XmlUtils.listFiles().entrySet()) { + ITmfConfiguration config = createConfiguration(entry.getValue()); + fConfigurations.put(config.getId(), config); + } + } + + @Override + public ITmfConfigurationSourceType getConfigurationSourceType() { + return fType; + } + + @Override + public ITmfConfiguration create(Map parameters) throws TmfConfigurationException { + return createOrUpdateXml(null, parameters); + } + + @Override + public @Nullable ITmfConfiguration get(String id) { + return fConfigurations.get(id); + } + + @Override + public ITmfConfiguration update(String id, Map parameters) throws TmfConfigurationException { + ITmfConfiguration config = fConfigurations.get(id); + if (config == null) { + throw new TmfConfigurationException("No such configuration with ID: " + id); //$NON-NLS-1$ + } + return createOrUpdateXml(config, parameters); + } + + @Override + public @Nullable ITmfConfiguration remove(String id) { + if (fConfigurations.get(id) == null) { + return null; + } + + if (!XmlUtils.listFiles().containsKey(id)) { + return null; + } + + XmlUtils.deleteFiles(ImmutableList.of(id)); + XmlUtils.saveFilesStatus(); + XmlAnalysisModuleSource.notifyModuleChange(); + return fConfigurations.remove(id); + } + + @Override + public List getConfigurations() { + return ImmutableList.copyOf(fConfigurations.values()); + } + + @Override + public boolean contains(String id) { + return fConfigurations.containsKey(id); + } + + private static @Nullable File getFile(Map parameters) { + String path = (String) parameters.get(PATH_KEY); + if (IS_WINDOWS && path != null && path.startsWith("/")) { //$NON-NLS-1$ + /* + * Workaround for path created by the theia-trace-extension, see + * https://github.com/theia-ide/theia-trace-extension/issues/545. + * This is caused by + * https://github.com/eclipse-theia/theia/issues/8098. Once issue + * #8098 is resolved this workaround can be removed. + */ + path = path.substring(1); + } + if (path == null) { + return null; + } + return new File(path); + } + + private ITmfConfiguration createOrUpdateXml(@Nullable ITmfConfiguration existingConfig, Map parameters) throws TmfConfigurationException { + File file = getFile(parameters); + if (file == null) { + throw new TmfConfigurationException("Missing path"); //$NON-NLS-1$ + } + + ITmfConfiguration config = createConfiguration(file); + + IStatus status = XmlUtils.xmlValidate(file); + if (status.isOK()) { + if (existingConfig == null) { + status = XmlUtils.addXmlFile(file); + } else { + if (!existingConfig.getId().equals(config.getId())) { + throw new TmfConfigurationException("File mismatch"); //$NON-NLS-1$ + } + XmlUtils.updateXmlFile(file); + } + if (status.isOK()) { + XmlAnalysisModuleSource.notifyModuleChange(); + XmlUtils.saveFilesStatus(); + fConfigurations.put(config.getId(), config); + return config; + } + } + String statusMessage = status.getMessage(); + String message = statusMessage != null? statusMessage : "Failed to update xml analysis configuration"; //$NON-NLS-1$ + if (status.getException() != null) { + throw new TmfConfigurationException(message, status.getException()); + } + throw new TmfConfigurationException(message); + } + + @SuppressWarnings("null") + private static String getName(String file) { + return new Path(file).removeFileExtension().toString(); + } + + private static ITmfConfiguration createConfiguration(File file) { + String id = file.getName(); + String name = getName(file.getName()); + String description = NLS.bind(Messages.XmlConfigurationSource_ConfigDescription, name); + TmfConfiguration.Builder builder = new TmfConfiguration.Builder() + .setName(name) + .setId(id) + .setDescription(description.toString()) + .setSourceTypeId(XML_ANALYSIS_TYPE_ID); + return builder.build(); + } +} diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/messages.properties b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/messages.properties new file mode 100644 index 0000000000..da416cd0aa --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/messages.properties @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2023 Ericsson +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +############################################################################### + +XmlConfigurationSource_Name=XML Data-driven analyses +XmlConfigurationSource_Description=Data-driven analyses described in XML +XmlConfigurationSource_ConfigDescription=XML Data-driven analysis: {0} +XmlConfigurationSource_PathDescription=URI to XML analysis file diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/package-info.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/package-info.java new file mode 100644 index 0000000000..189e22de43 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/package-info.java @@ -0,0 +1,13 @@ +/******************************************************************************* + * Copyright (c) 2023 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.config; diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/module/XmlUtils.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/module/XmlUtils.java index 2b8b218cbf..e5d3b3675d 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/module/XmlUtils.java +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/module/XmlUtils.java @@ -410,6 +410,7 @@ public static void deleteFiles(Iterable names) { } } } + updateCachedOuputElements(); } /**