9562d06ebc4edf2817b657e12172eceb30e879b5
[deliverable/tracecompass.git] / org.eclipse.tracecompass.lttng2.control.ui / src / org / eclipse / tracecompass / internal / lttng2 / control / ui / views / dialogs / ImportDialog.java
1 /**********************************************************************
2 * Copyright (c) 2012, 2015 Ericsson
3 *
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
8 *
9 * Contributors:
10 * Bernd Hufmann - Initial API and implementation
11 * Bernd Hufmann - Added handling of streamed traces
12 * Marc-Andre Laperle - Use common method to get opened tmf projects
13 * Markus Schorn - Bug 448058: Use org.eclipse.remote in favor of RSE
14 **********************************************************************/
15 package org.eclipse.tracecompass.internal.lttng2.control.ui.views.dialogs;
16
17 import java.util.ArrayList;
18 import java.util.List;
19
20 import org.eclipse.core.filesystem.EFS;
21 import org.eclipse.core.filesystem.IFileInfo;
22 import org.eclipse.core.filesystem.IFileStore;
23 import org.eclipse.core.resources.IFolder;
24 import org.eclipse.core.resources.IProject;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IPath;
27 import org.eclipse.core.runtime.NullProgressMonitor;
28 import org.eclipse.core.runtime.Path;
29 import org.eclipse.jface.dialogs.Dialog;
30 import org.eclipse.jface.dialogs.IDialogConstants;
31 import org.eclipse.jface.dialogs.MessageDialog;
32 import org.eclipse.jface.viewers.CheckStateChangedEvent;
33 import org.eclipse.jface.viewers.CheckboxTreeViewer;
34 import org.eclipse.jface.viewers.ICheckStateListener;
35 import org.eclipse.jface.viewers.ITreeContentProvider;
36 import org.eclipse.jface.viewers.LabelProvider;
37 import org.eclipse.jface.viewers.Viewer;
38 import org.eclipse.jface.window.Window;
39 import org.eclipse.remote.core.IRemoteFileService;
40 import org.eclipse.swt.SWT;
41 import org.eclipse.swt.custom.CCombo;
42 import org.eclipse.swt.events.SelectionAdapter;
43 import org.eclipse.swt.events.SelectionEvent;
44 import org.eclipse.swt.graphics.Image;
45 import org.eclipse.swt.graphics.Point;
46 import org.eclipse.swt.layout.GridData;
47 import org.eclipse.swt.layout.GridLayout;
48 import org.eclipse.swt.widgets.Button;
49 import org.eclipse.swt.widgets.Composite;
50 import org.eclipse.swt.widgets.Control;
51 import org.eclipse.swt.widgets.Group;
52 import org.eclipse.swt.widgets.Shell;
53 import org.eclipse.swt.widgets.Text;
54 import org.eclipse.swt.widgets.Tree;
55 import org.eclipse.tracecompass.internal.lttng2.control.ui.Activator;
56 import org.eclipse.tracecompass.internal.lttng2.control.ui.views.messages.Messages;
57 import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.TraceSessionComponent;
58 import org.eclipse.tracecompass.tmf.remote.core.proxy.RemoteSystemProxy;
59 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder;
60 import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
61 import org.eclipse.ui.ISharedImages;
62 import org.eclipse.ui.PlatformUI;
63
64 /**
65 * <p>
66 * Dialog box for collecting trace import information.
67 * </p>
68 *
69 * @author Bernd Hufmann
70 */
71 public class ImportDialog extends Dialog implements IImportDialog {
72
73 // ------------------------------------------------------------------------
74 // Constants
75 // ------------------------------------------------------------------------
76 /** The icon file for this dialog box. */
77 public static final String IMPORT_ICON_FILE = "icons/elcl16/import_trace.gif"; //$NON-NLS-1$
78
79 /** Parent directory for UST traces */
80 public static final String UST_PARENT_DIRECTORY = "ust"; //$NON-NLS-1$
81
82 /** Name of metadata file of trace */
83 public static final String METADATA_FILE_NAME = "metadata"; //$NON-NLS-1$
84
85 // ------------------------------------------------------------------------
86 // Attributes
87 // ------------------------------------------------------------------------
88 /**
89 * The dialog composite.
90 */
91 private Composite fDialogComposite = null;
92 /**
93 * The checkbox tree viewer for selecting available traces
94 */
95 private CheckboxTreeViewer fFolderViewer;
96 /**
97 * The combo box for selecting a project.
98 */
99 private CCombo fCombo;
100 /**
101 * The overwrite button
102 */
103 private Button fOverwriteButton;
104 /**
105 * List of available LTTng 2.0 projects
106 */
107 private List<IProject> fProjects;
108 /**
109 * The parent where the new node should be added.
110 */
111 private TraceSessionComponent fSession = null;
112 /**
113 * The name of the default project name
114 */
115 private String fDefaultProjectName = null;
116 /**
117 * List of traces to import
118 */
119 private final List<ImportFileInfo> fTraces = new ArrayList<>();
120 /**
121 * Selection index in project combo box.
122 */
123 private int fProjectIndex;
124 /**
125 * Flag to indicate that something went wrong when creating the dialog box.
126 */
127 private boolean fIsError = false;
128 /**
129 * Children of the remote folder (can be null)
130 */
131 private Object[] fFolderChildren = null;
132
133 // ------------------------------------------------------------------------
134 // Constructors
135 // ------------------------------------------------------------------------
136 /**
137 * Constructor
138 *
139 * @param shell
140 * - a shell for the display of the dialog
141 */
142 public ImportDialog(Shell shell) {
143 super(shell);
144 setShellStyle(SWT.RESIZE | getShellStyle());
145 }
146
147 // ------------------------------------------------------------------------
148 // Accessors
149 // ------------------------------------------------------------------------
150
151 @Override
152 public List<ImportFileInfo> getTracePathes() {
153 List<ImportFileInfo> retList = new ArrayList<>();
154 retList.addAll(fTraces);
155 return retList;
156 }
157
158 @Override
159 public IProject getProject() {
160 return fProjects.get(fProjectIndex);
161 }
162
163 @Override
164 public void setSession(TraceSessionComponent session) {
165 fSession = session;
166 }
167
168 @Override
169 public void setDefaultProject(String defaultProject) {
170 fDefaultProjectName = defaultProject;
171 }
172
173 // ------------------------------------------------------------------------
174 // Operations
175 // ------------------------------------------------------------------------
176
177 @Override
178 protected void configureShell(Shell newShell) {
179 super.configureShell(newShell);
180 newShell.setText(Messages.TraceControl_ImportDialogTitle);
181 newShell.setImage(Activator.getDefault().loadIcon(IMPORT_ICON_FILE));
182 }
183
184 @Override
185 protected Control createDialogArea(Composite parent) {
186
187 // Main dialog panel
188 fDialogComposite = new Composite(parent, SWT.NONE);
189 GridLayout layout = new GridLayout(1, true);
190 fDialogComposite.setLayout(layout);
191 fDialogComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
192
193 try {
194 createRemoteComposite();
195 } catch (CoreException e) {
196 createErrorComposite(parent, e.fillInStackTrace());
197 return fDialogComposite;
198 }
199 return fDialogComposite;
200 }
201
202 @Override
203 protected void createButtonsForButtonBar(Composite parent) {
204 Button selectAllButton = createButton(parent, IDialogConstants.SELECT_ALL_ID, Messages.TraceControl_ImportDialog_SelectAll, true);
205 selectAllButton.addSelectionListener(new SelectionAdapter() {
206 @Override
207 public void widgetSelected(SelectionEvent e) {
208 setFolderChildrenChecked(true);
209 }
210 });
211
212 Button deselectAllButton = createButton(parent, IDialogConstants.DESELECT_ALL_ID, Messages.TraceControl_ImportDialog_DeselectAll, true);
213 deselectAllButton.addSelectionListener(new SelectionAdapter() {
214 @Override
215 public void widgetSelected(SelectionEvent e) {
216 setFolderChildrenChecked(false);
217 }
218 });
219 createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true);
220 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
221 updateOKButtonEnablement();
222 }
223
224 @Override
225 protected void okPressed() {
226 if (!fIsError) {
227
228 // Validate input data
229 fTraces.clear();
230
231 fProjectIndex = fCombo.getSelectionIndex();
232
233 if (fProjectIndex < 0) {
234 MessageDialog.openError(getShell(),
235 Messages.TraceControl_ImportDialogTitle,
236 Messages.TraceControl_ImportDialogNoProjectSelectedError);
237 return;
238 }
239
240 IProject project = fProjects.get(fProjectIndex);
241 IFolder traceFolder = project.getFolder(TmfTracesFolder.TRACES_FOLDER_NAME);
242
243 if (!traceFolder.exists()) {
244 // Invalid LTTng 2.0 project
245 MessageDialog.openError(getShell(),
246 Messages.TraceControl_ImportDialogTitle,
247 Messages.TraceControl_ImportDialogInvalidTracingProject + " (" + TmfTracesFolder.TRACES_FOLDER_NAME + ")"); //$NON-NLS-1$//$NON-NLS-2$
248 return;
249 }
250
251 boolean overwriteAll = fOverwriteButton.getSelection();
252
253 Object[] checked = fFolderViewer.getCheckedElements();
254 for (int i = 0; i < checked.length; i++) {
255 IFileStore file = (IFileStore) checked[i];
256 if (!file.fetchInfo().isDirectory() && file.getName().equals(METADATA_FILE_NAME)) {
257 IFileStore trace = file.getParent();
258 IFileStore parent = trace.getParent();
259
260 String path = fSession.isSnapshotSession() ? fSession.getSnapshotInfo().getSnapshotPath() : fSession.getSessionPath();
261 path = getUnifiedPath(path);
262 IPath sessionParentPath = new Path(path).removeLastSegments(1);
263 IPath traceParentPath = new Path(parent.toURI().getPath());
264
265 IPath relativeTracePath = traceParentPath.makeRelativeTo(sessionParentPath);
266
267 IFolder destinationFolder = traceFolder.getFolder(new Path(relativeTracePath.toOSString()));
268
269 ImportFileInfo info = new ImportFileInfo(trace, trace.getName(), destinationFolder, overwriteAll);
270 IFolder folder = destinationFolder.getFolder(trace.getName());
271
272 // Verify if trace directory already exists (and not
273 // overwrite)
274 if (folder.exists() && !overwriteAll) {
275
276 // Ask user for overwrite or new name
277 IImportConfirmationDialog conf = TraceControlDialogFactory.getInstance().getImportConfirmationDialog();
278 conf.setTraceName(trace.getName());
279
280 // Don't add trace to list if dialog was cancelled.
281 if (conf.open() == Window.OK) {
282 info.setOverwrite(conf.isOverwrite());
283 if (!conf.isOverwrite()) {
284 info.setLocalTraceName(conf.getNewTraceName());
285 }
286 fTraces.add(info);
287 }
288 } else {
289 fTraces.add(info);
290 }
291 }
292 }
293
294 if (fTraces.isEmpty()) {
295 MessageDialog.openError(getShell(),
296 Messages.TraceControl_ImportDialogTitle,
297 Messages.TraceControl_ImportDialogNoTraceSelectedError);
298 return;
299 }
300 }
301
302 // validation successful -> call super.okPressed()
303 super.okPressed();
304 }
305
306 // ------------------------------------------------------------------------
307 // Helper methods and classes
308 // ------------------------------------------------------------------------
309
310 private final class FolderCheckStateListener implements ICheckStateListener {
311 @Override
312 public void checkStateChanged(CheckStateChangedEvent event) {
313 Object elem = event.getElement();
314 if (elem instanceof IFileStore) {
315 IFileStore element = (IFileStore) elem;
316 IFileInfo info = element.fetchInfo();
317 if (!info.isDirectory()) {
318 // A trick to keep selection of a file in sync with the
319 // directory
320 boolean p = fFolderViewer.getChecked((element.getParent()));
321 fFolderViewer.setChecked(element, p);
322 } else {
323 fFolderViewer.setSubtreeChecked(event.getElement(), event.getChecked());
324 if (!event.getChecked()) {
325 fFolderViewer.setChecked(element.getParent(), false);
326 }
327 }
328 updateOKButtonEnablement();
329 }
330 }
331 }
332
333 /**
334 * Helper class for the contents of a folder in a tracing project
335 *
336 * @author Bernd Hufmann
337 */
338 public static class FolderContentProvider implements ITreeContentProvider {
339 @Override
340 public Object[] getChildren(Object o) {
341 try {
342 IFileStore store = (IFileStore) o;
343 if (store.fetchInfo().isDirectory()) {
344 return store.childStores(EFS.NONE, new NullProgressMonitor());
345 }
346 } catch (CoreException e) {
347 Activator.getDefault().logError(e.getMessage(), e);
348 }
349 return new Object[0];
350 }
351
352 @Override
353 public Object getParent(Object element) {
354 return ((IFileStore) element).getParent();
355 }
356
357 @Override
358 public void dispose() {
359 }
360
361 @Override
362 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
363 }
364
365 @Override
366 public Object[] getElements(Object inputElement) {
367 return getChildren(inputElement);
368 }
369
370 @Override
371 public boolean hasChildren(Object element) {
372 return ((IFileStore) element).fetchInfo().isDirectory();
373 }
374 }
375
376 /**
377 * Creates a dialog composite with an error message which can be used when
378 * an exception occurred during creation time of the dialog box.
379 *
380 * @param parent
381 * - a parent composite
382 * @param e
383 * - a error causing exception
384 */
385 private void createErrorComposite(Composite parent, Throwable e) {
386 fIsError = true;
387 fDialogComposite.dispose();
388
389 fDialogComposite = new Composite(parent, SWT.NONE);
390 GridLayout layout = new GridLayout(1, true);
391 fDialogComposite.setLayout(layout);
392 fDialogComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
393
394 Text errorText = new Text(fDialogComposite, SWT.MULTI);
395 StringBuffer error = new StringBuffer();
396 error.append(Messages.TraceControl_ImportDialogCreationError);
397 error.append(System.getProperty("line.separator")); //$NON-NLS-1$
398 error.append(System.getProperty("line.separator")); //$NON-NLS-1$
399 error.append(e.toString());
400 errorText.setText(error.toString());
401 errorText.setLayoutData(new GridData(GridData.FILL_BOTH));
402 }
403
404 private void createRemoteComposite() throws CoreException {
405 Group contextGroup = new Group(fDialogComposite, SWT.SHADOW_NONE);
406 contextGroup.setText(Messages.TraceControl_ImportDialogTracesGroupName);
407 GridLayout layout = new GridLayout(1, true);
408 contextGroup.setLayout(layout);
409 contextGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
410
411 RemoteSystemProxy proxy = fSession.getTargetNode().getRemoteSystemProxy();
412
413 IRemoteFileService fsss = proxy.getRemoteConnection().getService(IRemoteFileService.class);
414
415 if (fsss == null) {
416 return;
417 }
418
419 final String path = fSession.isSnapshotSession() ? fSession.getSnapshotInfo().getSnapshotPath() : fSession.getSessionPath();
420 final IFileStore remoteFolder = fsss.getResource(path);
421
422 fFolderViewer = new CheckboxTreeViewer(contextGroup, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
423 GridData data = new GridData(GridData.FILL_BOTH);
424 Tree tree = fFolderViewer.getTree();
425 tree.setLayoutData(data);
426 tree.setFont(fDialogComposite.getFont());
427 tree.setToolTipText(Messages.TraceControl_ImportDialogTracesTooltip);
428
429 fFolderViewer.setContentProvider(new FolderContentProvider());
430 fFolderViewer.setLabelProvider(new LabelProvider() {
431 @Override
432 public String getText(Object element) {
433 return ((IFileStore) element).getName();
434 }
435
436 @Override
437 public Image getImage(Object element) {
438 if (((IFileStore) element).fetchInfo().isDirectory()) {
439 return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
440 }
441 return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
442 }
443 });
444
445 fFolderViewer.addCheckStateListener(new FolderCheckStateListener());
446 fFolderViewer.setInput(remoteFolder);
447
448 fFolderChildren = remoteFolder.childStores(EFS.NONE, new NullProgressMonitor());
449 // children can be null if there the path doesn't exist. This happens
450 // when a trace
451 // session hadn't been started and no output was created.
452 setFolderChildrenChecked(true);
453
454 Group projectGroup = new Group(fDialogComposite, SWT.SHADOW_NONE);
455 projectGroup.setText(Messages.TraceControl_ImportDialogProjectsGroupName);
456 layout = new GridLayout(1, true);
457 projectGroup.setLayout(layout);
458 projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
459
460 fProjects = new ArrayList<>();
461 List<String> projectNames = new ArrayList<>();
462
463 for (IProject project : TraceUtils.getOpenedTmfProjects()) {
464 fProjects.add(project);
465 projectNames.add(project.getName());
466 }
467
468 fCombo = new CCombo(projectGroup, SWT.READ_ONLY);
469 fCombo.setToolTipText(Messages.TraceControl_ImportDialogProjectsTooltip);
470 fCombo.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 1, 1));
471 fCombo.setItems(projectNames.toArray(new String[projectNames.size()]));
472
473 if (fDefaultProjectName != null) {
474 int select = projectNames.indexOf(fDefaultProjectName);
475 fCombo.select(select);
476 }
477
478 Group overrideGroup = new Group(fDialogComposite, SWT.SHADOW_NONE);
479 layout = new GridLayout(1, true);
480 overrideGroup.setLayout(layout);
481 overrideGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
482
483 fOverwriteButton = new Button(overrideGroup, SWT.CHECK);
484 fOverwriteButton.setText(Messages.TraceControl_ImportDialogOverwriteButtonText);
485 getShell().setMinimumSize(new Point(500, 400));
486 }
487
488 private void setFolderChildrenChecked(boolean isChecked) {
489 if (fFolderChildren != null) {
490 for (Object child : fFolderChildren) {
491 fFolderViewer.setSubtreeChecked(child, isChecked);
492 }
493 }
494 updateOKButtonEnablement();
495 }
496
497 private void updateOKButtonEnablement() {
498 Object[] checked = fFolderViewer.getCheckedElements();
499 Button okButton = getButton(IDialogConstants.OK_ID);
500 if (okButton != null) {
501 okButton.setEnabled(checked.length > 0);
502 }
503 }
504
505 private static String getUnifiedPath(String path) {
506 // Use Path class to remove unnecessary slashes
507 return new Path(path).removeTrailingSeparator().toString();
508 }
509 }
This page took 0.083723 seconds and 4 git commands to generate.