From ce70973121bc4e38f9e15fa2ee516b4bdc5fd4de Mon Sep 17 00:00:00 2001 From: Marc-Andre Laperle Date: Thu, 7 Apr 2016 23:45:48 -0400 Subject: [PATCH] lttng: Add schema for LTTng MI 3.0 (LTTng 2.8) This makes it possible to use the LTTng Control view with schema validation enabled and LTTng 2.8. The MI service is modified to be able to handle a different schema depending on the LTTng version. Change-Id: I85ec15edc3f0ce942d8df8637eadba3968fef1ca Signed-off-by: Marc-Andre Laperle Reviewed-on: https://git.eclipse.org/r/70188 Reviewed-by: Hudson CI Reviewed-by: Bernd Hufmann Tested-by: Bernd Hufmann --- .../component/TraceControlComponentTest.java | 3 +- .../service/LTTngControlServiceMiTest.java | 6 +- .../ui/views/service/LTTngControlService.java | 4 +- .../service/LTTngControlServiceConstants.java | 7 +- .../service/LTTngControlServiceFactory.java | 5 +- .../views/service/LTTngControlServiceMI.java | 137 +++-- .../control/ui/views/service/mi-lttng-3.0.xsd | 579 ++++++++++++++++++ 7 files changed, 669 insertions(+), 72 deletions(-) create mode 100644 lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/mi-lttng-3.0.xsd diff --git a/lttng/org.eclipse.tracecompass.lttng2.control.ui.tests/src/org/eclipse/tracecompass/lttng2/control/ui/tests/model/component/TraceControlComponentTest.java b/lttng/org.eclipse.tracecompass.lttng2.control.ui.tests/src/org/eclipse/tracecompass/lttng2/control/ui/tests/model/component/TraceControlComponentTest.java index 2ddb6e988b..e9910dfb8f 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.control.ui.tests/src/org/eclipse/tracecompass/lttng2/control/ui/tests/model/component/TraceControlComponentTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.control.ui.tests/src/org/eclipse/tracecompass/lttng2/control/ui/tests/model/component/TraceControlComponentTest.java @@ -33,7 +33,6 @@ import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.Trac import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.TraceControlRoot; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.ILttngControlService; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.LTTngControlService; -import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.LTTngControlServiceConstants; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.LTTngControlServiceMI; import org.eclipse.tracecompass.tmf.remote.core.proxy.TmfRemoteConnectionFactory; import org.eclipse.ui.ISharedImages; @@ -277,7 +276,7 @@ public class TraceControlComponentTest { assertNotNull(service); assertEquals(service, result); - service = new LTTngControlServiceMI(proxy.createCommandShell(), LTTngControlServiceMI.class.getResource(LTTngControlServiceConstants.MI_XSD_FILENAME)); + service = new LTTngControlServiceMI(proxy.createCommandShell(), null); fixture.setControlService(service); result = fixture.getControlService(); assertNotNull(service); diff --git a/lttng/org.eclipse.tracecompass.lttng2.control.ui.tests/src/org/eclipse/tracecompass/lttng2/control/ui/tests/service/LTTngControlServiceMiTest.java b/lttng/org.eclipse.tracecompass.lttng2.control.ui.tests/src/org/eclipse/tracecompass/lttng2/control/ui/tests/service/LTTngControlServiceMiTest.java index 06f479036a..01abe38254 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.control.ui.tests/src/org/eclipse/tracecompass/lttng2/control/ui/tests/service/LTTngControlServiceMiTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.control.ui.tests/src/org/eclipse/tracecompass/lttng2/control/ui/tests/service/LTTngControlServiceMiTest.java @@ -17,7 +17,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.net.URL; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -37,8 +36,8 @@ import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceSessionS import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.SessionInfo; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.ILttngControlService; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.LTTngControlService; -import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.LTTngControlServiceConstants; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.LTTngControlServiceMI; +import org.eclipse.tracecompass.internal.lttng2.control.ui.views.service.LttngVersion; import org.junit.Ignore; import org.junit.Test; @@ -59,8 +58,7 @@ public class LTTngControlServiceMiTest extends LTTngControlServiceTest { @Override protected ILttngControlService getControlService() { try { - URL resource = LTTngControlServiceMI.class.getResource(LTTngControlServiceConstants.MI_XSD_FILENAME); - return new LTTngControlServiceMI(getShell(), resource); + return new LTTngControlServiceMI(getShell(), new LttngVersion("2.7.0")); } catch (ExecutionException e) { return null; } diff --git a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlService.java b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlService.java index 378504ed51..4e60b2c8e5 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlService.java +++ b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlService.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2012, 2015 Ericsson + * Copyright (c) 2012, 2016 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -128,7 +128,7 @@ public class LTTngControlService implements ILttngControlService { * @param version * - a version to set */ - public void setVersion(LttngVersion version) { + protected void setVersion(LttngVersion version) { if (version != null) { fVersion = version; } diff --git a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceConstants.java b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceConstants.java index 934c1de7a2..09df0bf9b1 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceConstants.java +++ b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceConstants.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2012, 2015 Ericsson + * Copyright (c) 2012, 2016 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -60,6 +60,11 @@ public interface LTTngControlServiceConstants { * output from LTTng */ String MI_XSD_FILENAME = "mi_lttng.xsd"; //$NON-NLS-1$ + /** + * Name of the XSD to validate against the xml machine interface + * output from LTTng, version 3.0 + */ + String MI3_XSD_FILENAME = "mi-lttng-3.0.xsd"; //$NON-NLS-1$ // ------------------------------------------------------------------------ // Command constants // ------------------------------------------------------------------------ diff --git a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceFactory.java b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceFactory.java index 6d9407725e..ed42397426 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceFactory.java +++ b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceFactory.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2012, 2015 Ericsson + * Copyright (c) 2012, 2016 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -80,8 +80,7 @@ public final class LTTngControlServiceFactory { if ((result.getResult() == 0) && (!result.getOutput().isEmpty())) { if (machineInterfaceMode) { - LTTngControlServiceMI service = new LTTngControlServiceMI(shell, LTTngControlService.class.getResource(LTTngControlServiceConstants.MI_XSD_FILENAME)); - service.setVersion(result.getOutput()); + LTTngControlServiceMI service = new LTTngControlServiceMI(shell, LTTngControlServiceMI.parseVersion(result)); return service; } diff --git a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceMI.java b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceMI.java index 4fadc2f2f0..f026bef5e1 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceMI.java +++ b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/LTTngControlServiceMI.java @@ -100,23 +100,29 @@ public class LTTngControlServiceMI extends LTTngControlService { * * @param shell * the command shell implementation to use - * @param xsdUrl - * the xsd schema file for validation + * @param version + * the lttng version * @throws ExecutionException * if the creation of the Schema and DocumentBuilder objects * fails */ - public LTTngControlServiceMI(@NonNull ICommandShell shell, @Nullable URL xsdUrl) throws ExecutionException { + public LTTngControlServiceMI(@NonNull ICommandShell shell, @Nullable LttngVersion version) throws ExecutionException { super(shell); + setVersion(version); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilderFactory.setValidating(false); if (isSchemaValidationEnabled()) { - // Validate XSD schema - if (xsdUrl != null) { + if (version != null) { SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); try { + URL xsdUrl = LTTngControlService.class.getResource(LTTngControlServiceConstants.MI_XSD_FILENAME); + if (version.compareTo(new LttngVersion(2, 8, 0, null, null, null, null, null, null)) >= 0) { + xsdUrl = LTTngControlService.class.getResource(LTTngControlServiceConstants.MI3_XSD_FILENAME); + // MI 3.0 added name spaces. It will fail to validate if this is not set to true. + docBuilderFactory.setNamespaceAware(true); + } docBuilderFactory.setSchema(schemaFactory.newSchema(xsdUrl)); } catch (SAXException e) { throw new ExecutionException(Messages.TraceControl_InvalidSchemaError, e); @@ -145,11 +151,13 @@ public class LTTngControlServiceMI extends LTTngControlService { * * @param xmlStrings * list of strings representing an xml input + * @param documentBuilder + * the builder used to get the document * @return Document generated from strings input * @throws ExecutionException * when parsing has failed */ - private Document getDocumentFromStrings(List xmlStrings) throws ExecutionException { + private static Document getDocumentFromStrings(List xmlStrings, DocumentBuilder documentBuilder) throws ExecutionException { StringBuilder concatenedString = new StringBuilder(); for (String string : xmlStrings) { concatenedString.append(string); @@ -158,7 +166,7 @@ public class LTTngControlServiceMI extends LTTngControlService { Document document; try { - document = fDocumentBuilder.parse(stream); + document = documentBuilder.parse(stream); } catch (SAXException | IOException e) { throw new ExecutionException(Messages.TraceControl_XmlParsingError + ':' + e.toString(), e); } @@ -167,16 +175,29 @@ public class LTTngControlServiceMI extends LTTngControlService { } /** - * Parse, populate and set the internal LTTngVersion variable - * - * @param xmlOutput - * the mi xml output of lttng version + * Parse LTTng version from a MI command result + * + * @param commandResult + * the result obtained from a MI command + * @return the LTTng version * @throws ExecutionException * when xml extraction fail */ - public void setVersion(List xmlOutput) throws ExecutionException { - Document doc = getDocumentFromStrings(xmlOutput); + public static LttngVersion parseVersion(ICommandResult commandResult) throws ExecutionException { + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder; + try { + documentBuilder = docBuilderFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new ExecutionException(Messages.TraceControl_XmlDocumentBuilderError, e); + } + + Document doc = getDocumentFromStrings(commandResult.getOutput(), documentBuilder); NodeList element = doc.getElementsByTagName(MIStrings.VERSION); + if (element.getLength() != 1) { + throw new ExecutionException(Messages.TraceControl_UnsupportedVersionError); + } + int major = 0; int minor = 0; int patchLevel = 0; @@ -186,47 +207,43 @@ public class LTTngControlServiceMI extends LTTngControlService { String description = ""; //$NON-NLS-1$ String url = ""; //$NON-NLS-1$ String fullVersion = ""; //$NON-NLS-1$ - if (element.getLength() == 1) { - NodeList child = element.item(0).getChildNodes(); - // Get basic information - for (int i = 0; i < child.getLength(); i++) { - Node node = child.item(i); - switch (node.getNodeName()) { - case MIStrings.VERSION_MAJOR: - major = Integer.parseInt(node.getTextContent()); - break; - case MIStrings.VERSION_MINOR: - minor = Integer.parseInt(node.getTextContent()); - break; - case MIStrings.VERSION_PATCH_LEVEL: - patchLevel = Integer.parseInt(node.getTextContent()); - break; - case MIStrings.VERSION_COMMIT: - commit = node.getTextContent(); - break; - case MIStrings.VERSION_DESCRIPTION: - description = node.getTextContent(); - break; - case MIStrings.VERSION_LICENSE: - license = node.getTextContent(); - break; - case MIStrings.VERSION_NAME: - name = node.getTextContent(); - break; - case MIStrings.VERSION_STR: - fullVersion = node.getTextContent(); - break; - case MIStrings.VERSION_WEB: - url = node.getTextContent(); - break; - default: - break; - } + NodeList child = element.item(0).getChildNodes(); + // Get basic information + for (int i = 0; i < child.getLength(); i++) { + Node node = child.item(i); + switch (node.getNodeName()) { + case MIStrings.VERSION_MAJOR: + major = Integer.parseInt(node.getTextContent()); + break; + case MIStrings.VERSION_MINOR: + minor = Integer.parseInt(node.getTextContent()); + break; + case MIStrings.VERSION_PATCH_LEVEL: + patchLevel = Integer.parseInt(node.getTextContent()); + break; + case MIStrings.VERSION_COMMIT: + commit = node.getTextContent(); + break; + case MIStrings.VERSION_DESCRIPTION: + description = node.getTextContent(); + break; + case MIStrings.VERSION_LICENSE: + license = node.getTextContent(); + break; + case MIStrings.VERSION_NAME: + name = node.getTextContent(); + break; + case MIStrings.VERSION_STR: + fullVersion = node.getTextContent(); + break; + case MIStrings.VERSION_WEB: + url = node.getTextContent(); + break; + default: + break; } - setVersion(new LttngVersion(major, minor, patchLevel, license, commit, name, description, url, fullVersion)); - } else { - throw new ExecutionException(Messages.TraceControl_UnsupportedVersionError); } + return new LttngVersion(major, minor, patchLevel, license, commit, name, description, url, fullVersion); } @Override @@ -234,7 +251,7 @@ public class LTTngControlServiceMI extends LTTngControlService { ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST); ICommandResult result = executeCommand(command, monitor); - Document doc = getDocumentFromStrings(result.getOutput()); + Document doc = getDocumentFromStrings(result.getOutput(), fDocumentBuilder); NodeList elements = doc.getElementsByTagName(MIStrings.NAME); @@ -254,7 +271,7 @@ public class LTTngControlServiceMI extends LTTngControlService { ICommandResult result = executeCommand(command, monitor); ISessionInfo sessionInfo = new SessionInfo(sessionName); - Document document = getDocumentFromStrings(result.getOutput()); + Document document = getDocumentFromStrings(result.getOutput(), fDocumentBuilder); NodeList sessionsNode = document.getElementsByTagName(MIStrings.SESSION); // There should be only one session @@ -494,7 +511,7 @@ public class LTTngControlServiceMI extends LTTngControlService { // For now only keep the last one. ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_SNAPSHOT, LTTngControlServiceConstants.COMMAND_LIST_SNAPSHOT_OUTPUT, LTTngControlServiceConstants.OPTION_SESSION, sessionName); ICommandResult result = executeCommand(command, monitor); - Document doc = getDocumentFromStrings(result.getOutput()); + Document doc = getDocumentFromStrings(result.getOutput(), fDocumentBuilder); NodeList rawSnapshotsOutputs = doc.getElementsByTagName(MIStrings.SNAPSHOT_OUTPUTS); ISnapshotInfo snapshotInfo = new SnapshotInfo(""); //$NON-NLS-1$ @@ -551,7 +568,7 @@ public class LTTngControlServiceMI extends LTTngControlService { throw new ExecutionException(Messages.TraceControl_CommandError + command.toString()); } - Document document = getDocumentFromStrings(result.getOutput()); + Document document = getDocumentFromStrings(result.getOutput(), fDocumentBuilder); NodeList rawEvents = document.getElementsByTagName(MIStrings.EVENT); getBaseEventInfo(rawEvents, events); return events; @@ -579,7 +596,7 @@ public class LTTngControlServiceMI extends LTTngControlService { throw new ExecutionException(Messages.TraceControl_CommandError + command.toString()); } - Document document = getDocumentFromStrings(result.getOutput()); + Document document = getDocumentFromStrings(result.getOutput(), fDocumentBuilder); NodeList rawProviders = document.getElementsByTagName(MIStrings.PID); IUstProviderInfo providerInfo = null; @@ -625,7 +642,7 @@ public class LTTngControlServiceMI extends LTTngControlService { ICommandInput command = prepareSessionCreationCommand(sessionInfo); ICommandResult result = executeCommand(command, monitor); - Document document = getDocumentFromStrings(result.getOutput()); + Document document = getDocumentFromStrings(result.getOutput(), fDocumentBuilder); NodeList sessions = document.getElementsByTagName(MIStrings.SESSION); // Number of session should be equal to 1 @@ -668,7 +685,7 @@ public class LTTngControlServiceMI extends LTTngControlService { ICommandResult result = executeCommand(command, monitor); - Document document = getDocumentFromStrings(result.getOutput()); + Document document = getDocumentFromStrings(result.getOutput(), fDocumentBuilder); NodeList sessions = document.getElementsByTagName(MIStrings.SESSION); // Number of session should be equal to 1 @@ -734,7 +751,7 @@ public class LTTngControlServiceMI extends LTTngControlService { } // Check for action effect - Document doc = getDocumentFromStrings(result.getOutput()); + Document doc = getDocumentFromStrings(result.getOutput(), fDocumentBuilder); NodeList sessions = doc.getElementsByTagName(MIStrings.SESSION); if (sessions.getLength() != 1) { throw new ExecutionException(NLS.bind(Messages.TraceControl_MiInvalidNumberOfElementError, MIStrings.SESSION)); diff --git a/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/mi-lttng-3.0.xsd b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/mi-lttng-3.0.xsd new file mode 100644 index 0000000000..436a9893b3 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/service/mi-lttng-3.0.xsd @@ -0,0 +1,579 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.34.1