Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: org.eclipse.osgi,
org.eclipse.core.runtime,
+ org.eclipse.ui,
org.eclipse.ui.workbench,
- org.eclipse.tracecompass.common.core
-Export-Package: org.eclipse.tracecompass.internal.tmf.ctf.ui;x-internal:=true
+ org.eclipse.tracecompass.common.core,
+ org.eclipse.core.commands,
+ org.eclipse.jface,
+ org.eclipse.tracecompass.tmf.ui,
+ org.eclipse.tracecompass.tmf.core,
+ org.eclipse.tracecompass.tmf.ctf.core,
+ org.eclipse.core.expressions
+Export-Package: org.eclipse.tracecompass.internal.tmf.ctf.ui;x-internal:=true,
+ org.eclipse.tracecompass.internal.tmf.ctf.ui.streamintersection;x-internal:=true
+Import-Package: com.google.common.collect
bin.includes = META-INF/,\
.,\
about.html,\
- plugin.properties
+ plugin.properties,\
+ plugin.xml
src.includes = about.html
additional.bundles = org.eclipse.jdt.annotation
Bundle-Vendor = Eclipse Trace Compass
Bundle-Name = CTF support for TMF UI Plug-in
+command.stream_intersection = Perform Stream Intersection...
+command.stream_intersection.description = Trim the trace to the time range intersecting all CTF streams
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ locationURI="popup:org.eclipse.ui.popup.any?after=additions">
+ <command
+ commandId="org.eclipse.tracecompass.tmf.ctf.ui.command.stream_intersection"
+ label="%command.stream_intersection"
+ style="push"
+ tooltip="%command.stream_intersection.description">
+ <visibleWhen
+ checkEnabled="false">
+ <with
+ variable="selection">
+ <and>
+ <iterate>
+ <instanceof
+ value="org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement">
+ </instanceof>
+ </iterate>
+ <iterate>
+ <test
+ forcePluginActivation="true"
+ property="org.eclipse.tracecompass.tmf.ctf.ui.elementIsCtfTrace">
+ </test>
+ </iterate>
+ </and>
+ </with>
+ </visibleWhen>
+ </command>
+ </menuContribution>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ description="%command.stream_intersection.description"
+ id="org.eclipse.tracecompass.tmf.ctf.ui.command.stream_intersection"
+ name="%command.stream_intersection">
+ </command>
+ </extension>
+ <extension
+ point="org.eclipse.ui.handlers">
+ <handler
+ class="org.eclipse.tracecompass.internal.tmf.ctf.ui.streamintersection.StreamIntersectionHandler"
+ commandId="org.eclipse.tracecompass.tmf.ctf.ui.command.stream_intersection">
+ </handler>
+ </extension>
+ <extension
+ point="org.eclipse.core.expressions.propertyTesters">
+ <propertyTester
+ class="org.eclipse.tracecompass.internal.tmf.ctf.ui.streamintersection.CtfTmfTracePropertyTester"
+ id="org.eclipse.tracecompass.tmf.ctf.ui.elementIsCtfTraceTester"
+ namespace="org.eclipse.tracecompass.tmf.ctf.ui"
+ properties="elementIsCtfTrace"
+ type="org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement">
+ </propertyTester>
+ </extension>
+
+</plugin>
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ctf.ui.streamintersection;
+
+import java.util.Set;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfTmfTrace;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Property tester to check if a right-clicked trace element represents a CTF
+ * trace.
+ *
+ * @author Alexandre Montplaisir
+ */
+public class CtfTmfTracePropertyTester extends PropertyTester {
+
+ private static final String ELEMENT_IS_CTF_PROPERTY = "elementIsCtfTrace"; //$NON-NLS-1$
+
+ /**
+ * Known trace IDs of CTF traces.
+ *
+ * Not great to have to define this statically, but there doesn't seem to be
+ * a way to get the trace type class without the trace being necessarily
+ * opened.
+ */
+ private static final Set<String> MATCHING_TRACE_TYPES = ImmutableSet.of(
+ "org.eclipse.linuxtools.tmf.ui.type.ctf", //$NON-NLS-1$
+ "org.eclipse.linuxtools.lttng2.kernel.tracetype", //$NON-NLS-1$
+ "org.eclipse.linuxtools.lttng2.ust.tracetype"); //$NON-NLS-1$
+
+ @Override
+ public boolean test(@Nullable Object receiver, @Nullable String property,
+ Object @Nullable [] args, @Nullable Object expectedValue) {
+
+ if (ELEMENT_IS_CTF_PROPERTY.equals(property)
+ && receiver instanceof TmfTraceElement) {
+ TmfTraceElement traceElem = (TmfTraceElement) receiver;
+
+ /*
+ * If the trace is opened, check the trace class, it should catch
+ * all CTF traces.
+ */
+ if (traceElem.getTrace() instanceof CtfTmfTrace) {
+ return true;
+ }
+
+ /* If not, defer to checking the trace type among known ones. */
+ if (MATCHING_TRACE_TYPES.contains(traceElem.getTraceType())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ctf.ui.streamintersection;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Package messages
+ *
+ * @author Alexandre Montplaisir
+ * @noreference Messages class
+ */
+@SuppressWarnings("javadoc")
+@NonNullByDefault({})
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$
+
+ public static String StreamIntersection_JobName;
+ public static String StreamIntersection_DirectoryChooser_DialogTitle;
+ public static String StreamIntersection_InvalidDirectory_DialogTitle;
+ public static String StreamIntersection_InvalidDirectory_DialogText;
+ public static String StreamIntersection_NoWriteAccess_DialogText;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ctf.ui.streamintersection;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfTmfTrace;
+import org.eclipse.tracecompass.tmf.ui.project.handlers.HandlerUtils;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfOpenTraceHelper;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
+import org.eclipse.tracecompass.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Handler for the "Stream Intersection" action for CTF traces.
+ *
+ * @author Alexandre Montplaisir
+ */
+public class StreamIntersectionHandler extends AbstractHandler {
+
+ /**
+ * Suffix for new traces with stream intersection, added to the original
+ * trace name.
+ */
+ private static final String TRACE_NAME_SUFFIX = "-stream-intersect"; //$NON-NLS-1$
+
+ @Override
+ public boolean isEnabled() {
+ final Object element = HandlerUtils.getSelectedModelElement();
+ if (element == null) {
+ return false;
+ }
+
+ /*
+ * Only available for CTF (ctf.tmf) traces.
+ *
+ * plugin.xml should have done element type/count verification already.
+ */
+ TmfTraceElement traceElem = (TmfTraceElement) element;
+ return (traceElem.getTrace() instanceof CtfTmfTrace);
+ }
+
+ @Override
+ public @Nullable Object execute(@Nullable ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
+ Object element = ((IStructuredSelection) selection).getFirstElement();
+ final TmfTraceElement traceElem = (TmfTraceElement) element;
+
+ ITmfTrace trace = traceElem.getTrace();
+ if (trace == null) {
+ /* That trace is not currently opened */
+ return null;
+ }
+ /* plugin.xml should have already verified the trace type */
+ CtfTmfTrace ctfTmfTrace = (CtfTmfTrace) trace;
+
+ /*
+ * Pop a dialog asking the user to select a parent directory for the new
+ * trace.
+ */
+ final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ DirectoryDialog dialog = new DirectoryDialog(shell);
+ dialog.setText(Messages.StreamIntersection_DirectoryChooser_DialogTitle);
+ String result = dialog.open();
+ if (result == null) {
+ /* Dialog was cancelled, take no further action. */
+ return null;
+ }
+
+ /* Verify that the selected path is valid and writeable */
+ final Path parentPath = checkNotNull(Paths.get(result));
+ if (!Files.isDirectory(parentPath)) {
+ MessageDialog.openError(shell, Messages.StreamIntersection_InvalidDirectory_DialogTitle, Messages.StreamIntersection_InvalidDirectory_DialogText);
+ return null;
+ }
+ if (!Files.isWritable(parentPath)) {
+ MessageDialog.openError(shell, Messages.StreamIntersection_InvalidDirectory_DialogTitle, Messages.StreamIntersection_NoWriteAccess_DialogText);
+ return null;
+ }
+
+ /*
+ * Create a directory for the new trace. We will pick the next available
+ * name, adding -2, -3, etc. as needed.
+ */
+ String newTraceName = trace.getName() + TRACE_NAME_SUFFIX;
+ Path potentialPath = parentPath.resolve(newTraceName);
+ for (int i = 2; Files.exists(potentialPath); i++) {
+ newTraceName = trace.getName() + TRACE_NAME_SUFFIX + '-' + String.valueOf(i);
+ potentialPath = parentPath.resolve(newTraceName);
+ }
+
+ final Path tracePath = checkNotNull(potentialPath);
+ try {
+ Files.createDirectory(tracePath);
+ } catch (IOException e) {
+ /* Should not happen since we have checked permissions, etc. */
+ throw new IllegalStateException(e);
+ }
+
+ TmfWorkspaceModifyOperation streamIntersectionOperation = new TmfWorkspaceModifyOperation() {
+ @Override
+ public void execute(@Nullable IProgressMonitor monitor) throws CoreException {
+ IProgressMonitor mon = (monitor == null ? new NullProgressMonitor() : monitor);
+
+ ctfTmfTrace.streamIntersection(tracePath, mon);
+
+ /* Import the new trace into the current project. */
+ TmfProjectElement currentProjectElement = traceElem.getProject();
+ TmfTraceFolder traceFolder = currentProjectElement.getTracesFolder();
+ TmfOpenTraceHelper.openTraceFromPath(traceFolder, tracePath.toString(), shell);
+ }
+ };
+
+ try {
+ PlatformUI.getWorkbench().getProgressService().run(true, true, streamIntersectionOperation);
+ } catch (InterruptedException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ TraceUtils.displayErrorMsg(e.toString(), e.getTargetException().toString());
+ return null;
+ }
+
+ return null;
+ }
+
+}
--- /dev/null
+###############################################################################
+# Copyright (c) 2016 EfficiOS 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
+###############################################################################
+
+StreamIntersection_JobName = Performing stream intersection
+StreamIntersection_DirectoryChooser_DialogTitle = Choose a parent directory for the new trace
+StreamIntersection_InvalidDirectory_DialogTitle = Invalid directory
+StreamIntersection_InvalidDirectory_DialogText = Selected directory is invalid
+StreamIntersection_NoWriteAccess_DialogText = No write access to the selected directory
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.tmf.ctf.ui.streamintersection;
\ No newline at end of file