ctf: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / org.eclipse.tracecompass.lttng2.control.ui / src / org / eclipse / tracecompass / internal / lttng2 / control / ui / views / handlers / ImportHandler.java
CommitLineData
291cbdbf 1/**********************************************************************
60ae41e1 2 * Copyright (c) 2012, 2014 Ericsson
cfdb727a 3 *
291cbdbf
BH
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
cfdb727a
AM
8 *
9 * Contributors:
291cbdbf 10 * Bernd Hufmann - Initial API and implementation
ba3a9bd2 11 * Bernd Hufmann - Updated for support of streamed traces
89730b51 12 * Patrick Tasse - Add support for source location
b732adaa 13 * Markus Schorn - Bug 448058: Use org.eclipse.remote in favor of RSE
291cbdbf 14 **********************************************************************/
9bc60be7 15package org.eclipse.tracecompass.internal.lttng2.control.ui.views.handlers;
291cbdbf 16
b732adaa
MS
17import java.io.FileOutputStream;
18import java.io.IOException;
19import java.io.InputStream;
20import java.io.OutputStream;
89730b51 21import java.net.URI;
291cbdbf
BH
22import java.util.Iterator;
23import java.util.List;
24
25import org.eclipse.core.commands.ExecutionEvent;
26import org.eclipse.core.commands.ExecutionException;
b732adaa
MS
27import org.eclipse.core.filesystem.EFS;
28import org.eclipse.core.filesystem.IFileInfo;
29import org.eclipse.core.filesystem.IFileStore;
291cbdbf
BH
30import org.eclipse.core.resources.IFolder;
31import org.eclipse.core.resources.IProject;
a6e37e4c 32import org.eclipse.core.resources.IResource;
6fd3c6e9 33import org.eclipse.core.resources.ResourcesPlugin;
291cbdbf 34import org.eclipse.core.runtime.CoreException;
89730b51 35import org.eclipse.core.runtime.IPath;
291cbdbf
BH
36import org.eclipse.core.runtime.IProgressMonitor;
37import org.eclipse.core.runtime.IStatus;
cd9821de 38import org.eclipse.core.runtime.MultiStatus;
291cbdbf 39import org.eclipse.core.runtime.NullProgressMonitor;
6fd3c6e9 40import org.eclipse.core.runtime.Path;
291cbdbf 41import org.eclipse.core.runtime.Status;
374565c6 42import org.eclipse.core.runtime.SubMonitor;
89730b51 43import org.eclipse.core.runtime.URIUtil;
291cbdbf 44import org.eclipse.core.runtime.jobs.Job;
81d5dc3a
MAL
45import org.eclipse.jface.dialogs.MessageDialogWithToggle;
46import org.eclipse.jface.preference.IPreferenceStore;
291cbdbf
BH
47import org.eclipse.jface.viewers.ISelection;
48import org.eclipse.jface.viewers.StructuredSelection;
49import org.eclipse.jface.window.Window;
cd9821de 50import org.eclipse.jface.wizard.WizardDialog;
6fd3c6e9 51import org.eclipse.swt.widgets.Display;
9bc60be7
AM
52import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceSessionState;
53import org.eclipse.tracecompass.internal.lttng2.control.ui.Activator;
54import org.eclipse.tracecompass.internal.lttng2.control.ui.relayd.LttngRelaydConnectionInfo;
55import org.eclipse.tracecompass.internal.lttng2.control.ui.relayd.LttngRelaydConnectionManager;
56import org.eclipse.tracecompass.internal.lttng2.control.ui.relayd.LttngRelaydConsumer;
57import org.eclipse.tracecompass.internal.lttng2.control.ui.views.ControlView;
58import org.eclipse.tracecompass.internal.lttng2.control.ui.views.dialogs.IImportDialog;
59import org.eclipse.tracecompass.internal.lttng2.control.ui.views.dialogs.ImportFileInfo;
60import org.eclipse.tracecompass.internal.lttng2.control.ui.views.dialogs.TraceControlDialogFactory;
61import org.eclipse.tracecompass.internal.lttng2.control.ui.views.messages.Messages;
62import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.TraceSessionComponent;
2bdf0193
AM
63import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.ImportTraceWizard;
64import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
65import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
66import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
67import org.eclipse.tracecompass.tmf.ctf.core.CtfConstants;
68import org.eclipse.tracecompass.tmf.ui.project.model.TmfOpenTraceHelper;
69import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
70import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
71import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
72import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
73import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
74import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder;
75import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
291cbdbf
BH
76import org.eclipse.ui.IWorkbenchPage;
77import org.eclipse.ui.IWorkbenchWindow;
78import org.eclipse.ui.PlatformUI;
79
80/**
291cbdbf 81 * <p>
6fd3c6e9
MAL
82 * Command handler implementation to import traces from a (remote) session to a
83 * tracing project.
291cbdbf 84 * </p>
cfdb727a 85 *
dbd4432d 86 * @author Bernd Hufmann
291cbdbf
BH
87 */
88public class ImportHandler extends BaseControlViewHandler {
89
65e28a02
MK
90 private static final int BUFFER_IN_KB = 16;
91
92 private static final int BYTES_PER_KB = 1024;
93
cd9821de
BH
94 // ------------------------------------------------------------------------
95 // Constants
96 // ------------------------------------------------------------------------
cd9821de
BH
97 /** Name of default project to import traces to */
98 public static final String DEFAULT_REMOTE_PROJECT_NAME = "Remote"; //$NON-NLS-1$
99
81d5dc3a
MAL
100 /** The preference key to remeber whether or not the user wants the notification shown next time **/
101 private static final String NOTIFY_IMPORT_STREAMED_PREF_KEY = "NOTIFY_IMPORT_STREAMED"; //$NON-NLS-1$
102
291cbdbf
BH
103 // ------------------------------------------------------------------------
104 // Attributes
105 // ------------------------------------------------------------------------
6f4e8ec0
AM
106
107 /**
108 * The command parameter
109 */
291cbdbf 110 protected CommandParameter fParam;
cfdb727a 111
291cbdbf
BH
112 // ------------------------------------------------------------------------
113 // Operations
114 // ------------------------------------------------------------------------
cfdb727a 115
291cbdbf
BH
116 @Override
117 public Object execute(ExecutionEvent event) throws ExecutionException {
118
119 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
120
121 if (window == null) {
122 return false;
123 }
124
125 fLock.lock();
126 try {
127 final CommandParameter param = fParam.clone();
cfdb727a 128
cd9821de
BH
129 // create default project
130 IProject project = TmfProjectRegistry.createProject(DEFAULT_REMOTE_PROJECT_NAME, null, null);
cd9821de 131
6fd3c6e9
MAL
132 if (param.getSession().isLiveTrace()) {
133 importLiveTrace(new LttngRelaydConnectionInfo(param.getSession().getLiveUrl(), param.getSession().getLivePort(), param.getSession().getName()), project);
134 return null;
135 } else if (param.getSession().isStreamedTrace()) {
81d5dc3a
MAL
136
137 IPreferenceStore store = Activator.getDefault().getPreferenceStore();
138 String notify = store.getString(NOTIFY_IMPORT_STREAMED_PREF_KEY);
139 if (!MessageDialogWithToggle.ALWAYS.equals(notify)) {
140 MessageDialogWithToggle.openInformation(window.getShell(), null, Messages.TraceControl_ImportDialogStreamedTraceNotification, Messages.TraceControl_ImportDialogStreamedTraceNotificationToggle, false, store, NOTIFY_IMPORT_STREAMED_PREF_KEY);
141 }
142
cd9821de 143 // Streamed trace
f537c959 144 TmfProjectElement projectElement = TmfProjectRegistry.getProject(project, true);
cd9821de
BH
145 TmfTraceFolder traceFolder = projectElement.getTracesFolder();
146
10a4498a 147 ImportTraceWizard wizard = new ImportTraceWizard();
cd9821de
BH
148 wizard.init(PlatformUI.getWorkbench(), new StructuredSelection(traceFolder));
149 WizardDialog dialog = new WizardDialog(window.getShell(), wizard);
150 dialog.open();
cd9821de
BH
151 return null;
152 }
153
154 // Remote trace
291cbdbf
BH
155 final IImportDialog dialog = TraceControlDialogFactory.getInstance().getImportDialog();
156 dialog.setSession(param.getSession());
cd9821de 157 dialog.setDefaultProject(DEFAULT_REMOTE_PROJECT_NAME);
291cbdbf 158
cd9821de 159 if (dialog.open() != Window.OK) {
291cbdbf
BH
160 return null;
161 }
162
163 Job job = new Job(Messages.TraceControl_ImportJob) {
164 @Override
165 protected IStatus run(IProgressMonitor monitor) {
cfdb727a 166
cd9821de
BH
167 MultiStatus status = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, Messages.TraceControl_ImportFailure, null);
168 List<ImportFileInfo> traces = dialog.getTracePathes();
169 IProject selectedProject = dialog.getProject();
170 for (Iterator<ImportFileInfo> iterator = traces.iterator(); iterator.hasNext();) {
171 try {
374565c6 172
f537c959 173 if (monitor.isCanceled()) {
374565c6
BH
174 status.add(Status.CANCEL_STATUS);
175 break;
176 }
177
67c7236e
BH
178 ImportFileInfo remoteFile = iterator.next();
179
180 downloadTrace(remoteFile, selectedProject, monitor);
181
182 // Set trace type
183 IFolder traceFolder = remoteFile.getDestinationFolder();
184
a6e37e4c 185 IResource file = traceFolder.findMember(remoteFile.getLocalTraceName());
cd9821de 186
67c7236e
BH
187 if (file != null) {
188 TraceTypeHelper helper = null;
cd9821de 189
80c7ca57 190 try {
4b677ea9 191 helper = TmfTraceTypeUIUtils.selectTraceType(file.getLocation().toOSString(), null, null);
80c7ca57
BH
192 } catch (TmfTraceImportException e) {
193 // the trace did not match any trace type
67c7236e 194 }
cd9821de 195
67c7236e
BH
196 if (helper != null) {
197 status.add(TmfTraceTypeUIUtils.setTraceType(file, helper));
198 }
89730b51 199
b732adaa
MS
200 URI uri = remoteFile.getImportFile().toURI();
201 String sourceLocation = URIUtil.toUnencodedString(uri);
202 file.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
89730b51 203 }
cd9821de
BH
204 } catch (ExecutionException e) {
205 status.add(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.TraceControl_ImportFailure, e));
206 } catch (CoreException e) {
207 status.add(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.TraceControl_ImportFailure, e));
208 }
cfdb727a 209 }
cd9821de 210 return status;
291cbdbf
BH
211 }
212 };
213 job.setUser(true);
214 job.schedule();
215 } finally {
216 fLock.unlock();
217 }
218 return null;
219 }
220
291cbdbf
BH
221 @Override
222 public boolean isEnabled() {
223 // Get workbench page for the Control View
224 IWorkbenchPage page = getWorkbenchPage();
225 if (page == null) {
226 return false;
227 }
228
229 // Check if one or more session are selected
230 ISelection selection = page.getSelection(ControlView.ID);
231 TraceSessionComponent session = null;
232 if (selection instanceof StructuredSelection) {
233 StructuredSelection structered = ((StructuredSelection) selection);
234 for (Iterator<?> iterator = structered.iterator(); iterator.hasNext();) {
cfdb727a 235 Object element = iterator.next();
291cbdbf 236 if (element instanceof TraceSessionComponent) {
6fd3c6e9
MAL
237 // Add only TraceSessionComponents that are inactive and not
238 // destroyed
291cbdbf 239 TraceSessionComponent tmpSession = (TraceSessionComponent) element;
6fd3c6e9 240 if ((tmpSession.isSnapshotSession() || tmpSession.isLiveTrace() || (tmpSession.getSessionState() == TraceSessionState.INACTIVE)) && (!tmpSession.isDestroyed())) {
291cbdbf
BH
241 session = tmpSession;
242 }
243 }
244 }
245 }
246 boolean isEnabled = session != null;
247
248 fLock.lock();
249 try {
250 fParam = null;
251 if (isEnabled) {
252 fParam = new CommandParameter(session);
253 }
254 } finally {
255 fLock.unlock();
256 }
257 return isEnabled;
258 }
cfdb727a 259
291cbdbf
BH
260 // ------------------------------------------------------------------------
261 // Helper methods
262 // ------------------------------------------------------------------------
11252342 263
291cbdbf
BH
264 /**
265 * Downloads a trace from the remote host to the given project.
cfdb727a
AM
266 *
267 * @param trace
268 * - trace information of trace to import
269 * @param project
270 * - project to import to
374565c6
BH
271 * @param monitor
272 * - a progress monitor
291cbdbf
BH
273 * @throws ExecutionException
274 */
374565c6 275 private static void downloadTrace(ImportFileInfo trace, IProject project, IProgressMonitor monitor)
0a78d11a 276 throws ExecutionException {
291cbdbf 277 try {
b732adaa 278 IFileStore importRoot = trace.getImportFile();
cfdb727a 279
339d539c 280 IFolder traceFolder = project.getFolder(TmfTracesFolder.TRACES_FOLDER_NAME);
291cbdbf 281 if (!traceFolder.exists()) {
6fd3c6e9 282 throw new ExecutionException(Messages.TraceControl_ImportDialogInvalidTracingProject + " (" + TmfTracesFolder.TRACES_FOLDER_NAME + ")"); //$NON-NLS-1$//$NON-NLS-2$
291cbdbf
BH
283 }
284
67c7236e
BH
285 IFolder destinationFolder = trace.getDestinationFolder();
286 TraceUtils.createFolder(destinationFolder, monitor);
287
291cbdbf 288 String traceName = trace.getLocalTraceName();
67c7236e 289 IFolder folder = destinationFolder.getFolder(traceName);
291cbdbf 290 if (folder.exists()) {
6fd3c6e9 291 if (!trace.isOverwrite()) {
291cbdbf
BH
292 throw new ExecutionException(Messages.TraceControl_ImportDialogTraceAlreadyExistError + ": " + traceName); //$NON-NLS-1$
293 }
294 } else {
295 folder.create(true, true, null);
296 }
297
b732adaa 298 IFileStore[] sources = importRoot.childStores(EFS.NONE, new NullProgressMonitor());
374565c6
BH
299 SubMonitor subMonitor = SubMonitor.convert(monitor, sources.length);
300 subMonitor.beginTask(Messages.TraceControl_DownloadTask, sources.length);
291cbdbf 301
b732adaa 302 for (IFileStore source : sources) {
374565c6
BH
303 if (subMonitor.isCanceled()) {
304 monitor.setCanceled(true);
305 return;
306 }
b732adaa
MS
307 SubMonitor childMonitor = subMonitor.newChild(1);
308 IFileInfo info = source.fetchInfo();
309 if (!info.isDirectory()) {
310 IPath destination = folder.getLocation().addTrailingSeparator().append(source.getName());
311 subMonitor.setTaskName(Messages.TraceControl_DownloadTask + ' ' + traceName + '/' + source.getName());
312 try (InputStream in = source.openInputStream(EFS.NONE, new NullProgressMonitor())) {
313 copy(in, destination, childMonitor, info.getLength());
314 }
315 }
291cbdbf 316 }
b732adaa 317 } catch (IOException e) {
9fa32496 318 throw new ExecutionException(e.toString(), e);
291cbdbf 319 } catch (CoreException e) {
9fa32496 320 throw new ExecutionException(e.toString(), e);
291cbdbf
BH
321 }
322 }
6fd3c6e9 323
b732adaa
MS
324 private static void copy(InputStream in, IPath destination, SubMonitor monitor, long length) throws IOException {
325 try (OutputStream out = new FileOutputStream(destination.toFile())) {
65e28a02
MK
326 monitor.setWorkRemaining((int) (length / BYTES_PER_KB));
327 byte[] buf = new byte[BYTES_PER_KB * BUFFER_IN_KB];
b732adaa
MS
328 int counter = 0;
329 for (;;) {
330 int n = in.read(buf);
331 if (n <= 0) {
332 return;
333 }
334 out.write(buf, 0, n);
65e28a02
MK
335 counter = (counter % BYTES_PER_KB) + n;
336 monitor.worked(counter / BYTES_PER_KB);
b732adaa
MS
337 }
338 }
339 }
340
6fd3c6e9
MAL
341 private static void importLiveTrace(final LttngRelaydConnectionInfo connectionInfo, final IProject project) {
342 Job job = new Job(Messages.TraceControl_ImportJob) {
343
344 @Override
345 protected IStatus run(final IProgressMonitor monitor) {
346 try {
347 // We initiate the connection first so that we can retrieve the trace path
348 LttngRelaydConsumer lttngRelaydConsumer = LttngRelaydConnectionManager.getInstance().getConsumer(connectionInfo);
349 try {
350 lttngRelaydConsumer.connect();
351 } catch (CoreException e) {
92fe6900 352 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.lttng2.control.ui.relayd.Messages.LttngRelaydConnectionManager_ConnectionError, e);
6fd3c6e9
MAL
353 }
354 initializeTraceResource(connectionInfo, lttngRelaydConsumer.getTracePath(), project);
355 return Status.OK_STATUS;
356 } catch (CoreException | TmfTraceImportException e) {
357 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.ImportHandler_LiveTraceInitError, e);
358 }
359 }
360
361 };
362 job.setSystem(true);
363 job.schedule();
364 }
365
366
367 private static void initializeTraceResource(final LttngRelaydConnectionInfo connectionInfo, final String tracePath, final IProject project) throws CoreException, TmfTraceImportException {
368 IFolder folder = project.getFolder(TmfTracesFolder.TRACES_FOLDER_NAME);
369 IFolder traceFolder = folder.getFolder(connectionInfo.getSessionName());
370 Path location = new Path(tracePath);
371 IStatus result = ResourcesPlugin.getWorkspace().validateLinkLocation(folder, location);
372 if (result.isOK()) {
373 traceFolder.createLink(location, IResource.REPLACE, new NullProgressMonitor());
374 } else {
375 throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, result.getMessage()));
376 }
377
378 TraceTypeHelper selectedTraceType = TmfTraceTypeUIUtils.selectTraceType(location.toOSString(), null, null);
379 // No trace type was determined.
380 TmfTraceTypeUIUtils.setTraceType(traceFolder, selectedTraceType);
381
382 final TmfProjectElement projectElement = TmfProjectRegistry.getProject(project, true);
383 final TmfTraceFolder tracesFolder = projectElement.getTracesFolder();
384 final List<TmfTraceElement> traces = tracesFolder.getTraces();
385 TmfTraceElement found = null;
386 for (TmfTraceElement candidate : traces) {
387 if (candidate.getName().equals(connectionInfo.getSessionName())) {
388 found = candidate;
389 }
390 }
391
392 if (found == null) {
393 throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.ImportHandler_LiveTraceElementError));
394 }
395
396 // Properties used to be able to reopen a trace in live mode
397 traceFolder.setPersistentProperty(CtfConstants.LIVE_HOST, connectionInfo.getHost());
398 traceFolder.setPersistentProperty(CtfConstants.LIVE_PORT, Integer.toString(connectionInfo.getPort()));
399 traceFolder.setPersistentProperty(CtfConstants.LIVE_SESSION_NAME, connectionInfo.getSessionName());
400
401 final TmfTraceElement finalTrace = found;
402 Display.getDefault().syncExec(new Runnable() {
403
404 @Override
405 public void run() {
406 TmfOpenTraceHelper.openTraceFromElement(finalTrace);
407 }
408 });
409 }
291cbdbf 410}
This page took 0.084957 seconds and 5 git commands to generate.