1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
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
10 * Marc-Andre Laperle - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.internal
.tmf
.remote
.ui
.wizards
.fetch
;
15 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import java
.lang
.reflect
.InvocationTargetException
;
18 import java
.text
.MessageFormat
;
19 import java
.util
.ArrayList
;
20 import java
.util
.HashSet
;
21 import java
.util
.List
;
24 import org
.eclipse
.core
.resources
.IFolder
;
25 import org
.eclipse
.core
.resources
.IProject
;
26 import org
.eclipse
.core
.resources
.IResource
;
27 import org
.eclipse
.core
.resources
.IWorkspace
;
28 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
29 import org
.eclipse
.core
.runtime
.CoreException
;
30 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
31 import org
.eclipse
.core
.runtime
.IStatus
;
32 import org
.eclipse
.core
.runtime
.Status
;
33 import org
.eclipse
.core
.runtime
.SubMonitor
;
34 import org
.eclipse
.jdt
.annotation
.Nullable
;
35 import org
.eclipse
.jface
.operation
.IRunnableWithProgress
;
36 import org
.eclipse
.jface
.viewers
.CheckboxTreeViewer
;
37 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
38 import org
.eclipse
.jface
.viewers
.ViewerComparator
;
39 import org
.eclipse
.osgi
.util
.NLS
;
40 import org
.eclipse
.swt
.SWT
;
41 import org
.eclipse
.swt
.custom
.CCombo
;
42 import org
.eclipse
.swt
.events
.ModifyEvent
;
43 import org
.eclipse
.swt
.events
.ModifyListener
;
44 import org
.eclipse
.swt
.events
.SelectionAdapter
;
45 import org
.eclipse
.swt
.events
.SelectionEvent
;
46 import org
.eclipse
.swt
.graphics
.Image
;
47 import org
.eclipse
.swt
.layout
.GridData
;
48 import org
.eclipse
.swt
.layout
.GridLayout
;
49 import org
.eclipse
.swt
.widgets
.Button
;
50 import org
.eclipse
.swt
.widgets
.Composite
;
51 import org
.eclipse
.swt
.widgets
.Group
;
52 import org
.eclipse
.swt
.widgets
.Text
;
53 import org
.eclipse
.swt
.widgets
.ToolBar
;
54 import org
.eclipse
.swt
.widgets
.ToolItem
;
55 import org
.eclipse
.tracecompass
.internal
.tmf
.remote
.ui
.Activator
;
56 import org
.eclipse
.tracecompass
.internal
.tmf
.remote
.ui
.messages
.RemoteMessages
;
57 import org
.eclipse
.tracecompass
.internal
.tmf
.remote
.ui
.wizards
.fetch
.model
.RemoteGenerateManifestOperation
;
58 import org
.eclipse
.tracecompass
.internal
.tmf
.remote
.ui
.wizards
.fetch
.model
.RemoteImportConnectionNodeElement
;
59 import org
.eclipse
.tracecompass
.internal
.tmf
.remote
.ui
.wizards
.fetch
.model
.RemoteImportProfileElement
;
60 import org
.eclipse
.tracecompass
.internal
.tmf
.remote
.ui
.wizards
.fetch
.model
.RemoteImportTracesOperation
;
61 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.operations
.NewExperimentOperation
;
62 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.operations
.SelectTracesOperation
;
63 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.AbstractTracePackageOperation
;
64 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.AbstractTracePackageWizardPage
;
65 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageElement
;
66 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageFilesElement
;
67 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageLabelProvider
;
68 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageTraceElement
;
69 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.importexport
.Messages
;
70 import org
.eclipse
.tracecompass
.tmf
.core
.TmfProjectNature
;
71 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfExperimentElement
;
72 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfExperimentFolder
;
73 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfProjectElement
;
74 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfProjectRegistry
;
75 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfTraceFolder
;
76 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfTracesFolder
;
77 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TraceUtils
;
78 import org
.eclipse
.ui
.ISharedImages
;
79 import org
.eclipse
.ui
.PlatformUI
;
80 import org
.eclipse
.ui
.plugin
.AbstractUIPlugin
;
83 * Wizard page that connects to a remote node, lists all traces according to
84 * a given remote profile and imports the selected traces.
86 * @author Marc-Andre Laperle
87 * @author Bernd Hufmann
89 public class RemoteFetchLogWizardRemotePage
extends AbstractTracePackageWizardPage
{
91 // ------------------------------------------------------------------------
93 // ------------------------------------------------------------------------
95 private static final String PAGE_NAME
= "org.eclipse.tracecompass.internal.tmf.remote.ui.wizards.fetch"; //$NON-NLS-1$
96 private static final String ICON_PATH
= "icons/elcl16/fetch_log_wiz.gif"; //$NON-NLS-1$
97 private static final Image COLLAPSE_ALL_IMAGE
= PlatformUI
.getWorkbench().getSharedImages().getImage(ISharedImages
.IMG_ELCL_COLLAPSEALL
);
98 private static final Image EXPAND_ALL_IMAGE
= Activator
.getDefault().getImageFromPath("icons/elcl16/expandall.png"); //$NON-NLS-1$
99 /** Name of default project to import traces to */
100 public static final String DEFAULT_REMOTE_PROJECT_NAME
= "Remote"; //$NON-NLS-1$
102 // ------------------------------------------------------------------------
104 // ------------------------------------------------------------------------
105 private TmfTraceFolder fTmfTraceFolder
;
107 private RemoteImportProfileElement fProfile
;
108 private final Set
<RemoteImportConnectionNodeElement
> fRemoteHosts
= new HashSet
<>();
109 private boolean fOverwriteAll
;
110 private boolean fIsVisible
= false;
111 private String fDefaultProjectName
= null;
112 private CCombo fCombo
;
113 private Button fCreateExperimentCheckbox
;
114 private Text fExperimentNameText
;
115 private List
<IProject
> fProjects
;
116 private @Nullable TmfExperimentFolder fExperimentFolderElement
;
117 private @Nullable String fExperimentName
;
119 // ------------------------------------------------------------------------
121 // ------------------------------------------------------------------------
128 * The current selection (trace folder element)
130 * A profile to use or null
131 * @param experimentName
132 * A name of an experiment to create and add traces to, or null
135 protected RemoteFetchLogWizardRemotePage(String title
, IStructuredSelection selection
, @Nullable RemoteImportProfileElement profile
, @Nullable String experimentName
) {
136 super(PAGE_NAME
, title
, null, selection
);
137 setImageDescriptor(AbstractUIPlugin
.imageDescriptorFromPlugin(Activator
.PLUGIN_ID
, ICON_PATH
));
139 if (selection
.getFirstElement() instanceof TmfTraceFolder
) {
140 fTmfTraceFolder
= (TmfTraceFolder
) selection
.getFirstElement();
143 if (fTmfTraceFolder
== null) {
144 // create default project
145 TmfProjectRegistry
.createProject(DEFAULT_REMOTE_PROJECT_NAME
, null, null);
146 fDefaultProjectName
= DEFAULT_REMOTE_PROJECT_NAME
;
150 fExperimentName
= experimentName
;
151 setDescription(RemoteMessages
.RemoteFetchLogWizardRemotePage_Description
);
154 // ------------------------------------------------------------------------
156 // ------------------------------------------------------------------------
158 public void createControl(Composite parent
) {
159 initializeDialogUnits(parent
);
161 Composite composite
= new Composite(parent
, SWT
.NULL
);
162 composite
.setLayout(new GridLayout());
163 composite
.setLayoutData(new GridData(GridData
.VERTICAL_ALIGN_FILL
164 | GridData
.HORIZONTAL_ALIGN_FILL
));
165 composite
.setFont(parent
.getFont());
167 createToolBar(composite
);
168 createElementViewer(composite
);
170 createButtonsGroup(composite
);
172 createProjectGroup(composite
);
174 createOptionGroup(composite
);
176 restoreWidgetValues();
177 updatePageCompletion();
179 setControl(composite
);
183 protected boolean determinePageCompletion() {
184 if (getElementViewer().getCheckedElements().length
<= 0) {
190 if ((fExperimentName
!= null) && (fCreateExperimentCheckbox
.getSelection())) {
191 String name
= fExperimentNameText
.getText().trim();
192 // verify if experiment name is empty
193 if (name
.isEmpty()) {
195 setErrorMessage(RemoteMessages
.RemoteFetchLogWizardRemotePage_ErrorEmptyExperimentName
);
199 // verify that name is a valid resource name
200 IWorkspace workspace
= ResourcesPlugin
.getWorkspace();
201 if ((workspace
!= null) && (!workspace
.validateName(name
, IResource
.FILE
).isOK())) {
203 setErrorMessage(NLS
.bind(RemoteMessages
.RemoteFetchLogWizardRemotePage_ErrorExperimentNameInvalid
, name
));
207 TmfExperimentFolder experimentFolder
= fExperimentFolderElement
;
208 if (experimentFolder
!= null) {
209 TmfExperimentElement element
=
210 experimentFolder
.getExperiment(name
);
211 // verify if experiment already exists
212 if (element
!= null) {
214 setErrorMessage(NLS
.bind(RemoteMessages
.RemoteFetchLogWizardRemotePage_ErrorExperimentAlreadyExists
, name
));
218 // verify if a resource already exists in the experiment folder
219 IFolder expResource
= experimentFolder
.getResource();
220 IResource res
= expResource
.findMember(name
);
223 setErrorMessage(NLS
.bind(RemoteMessages
.RemoteFetchLogWizardRemotePage_ErrorResourceAlreadyExists
, name
));
234 protected void updateWithFilePathSelection() {
238 public void setVisible(final boolean visible
) {
239 super.setVisible(visible
);
241 fIsVisible
= visible
;
244 getContainer().getShell().getDisplay().asyncExec(new Runnable() {
251 getElementViewer().setInput(null);
255 private void createToolBar(Composite parent
) {
256 ToolBar toolBar
= new ToolBar(parent
, SWT
.HORIZONTAL
);
257 toolBar
.setLayoutData(new GridData(SWT
.RIGHT
, SWT
.CENTER
, false, false));
259 ToolItem expandAll
= new ToolItem(toolBar
, SWT
.PUSH
);
260 expandAll
.setImage(EXPAND_ALL_IMAGE
);
261 expandAll
.setToolTipText(RemoteMessages
.RemoteFetchLogWizardRemotePage_ExpandAll
);
262 expandAll
.addSelectionListener(new SelectionAdapter() {
264 public void widgetSelected(SelectionEvent e
) {
265 getElementViewer().expandAll();
269 ToolItem collapseAll
= new ToolItem(toolBar
, SWT
.PUSH
);
270 collapseAll
.setImage(COLLAPSE_ALL_IMAGE
);
271 collapseAll
.setToolTipText(RemoteMessages
.RemoteFetchLogWizardRemotePage_CollapseAll
);
272 collapseAll
.addSelectionListener(new SelectionAdapter() {
274 public void widgetSelected(SelectionEvent e
) {
275 getElementViewer().collapseAll();
281 protected void createElementViewer(Composite compositeParent
) {
282 super.createElementViewer(compositeParent
);
284 CheckboxTreeViewer elementViewer
= getElementViewer();
285 elementViewer
.setLabelProvider(new TracePackageLabelProvider() {
287 public String
getText(Object element
) {
288 if (element
instanceof TracePackageTraceElement
) {
289 for (TracePackageElement files
: ((TracePackageTraceElement
) element
).getChildren()) {
290 if (files
instanceof TracePackageFilesElement
) {
291 return ((TracePackageFilesElement
) files
).getFileName();
295 return super.getText(element
);
298 public Image
getImage(Object element
) {
299 if (element
instanceof TracePackageTraceElement
) {
300 for (TracePackageElement files
: ((TracePackageTraceElement
) element
).getChildren()) {
301 return files
.getImage();
304 return super.getImage(element
);
307 elementViewer
.setComparator(new ViewerComparator() {
309 public int category(Object element
) {
310 if (element
instanceof TracePackageTraceElement
) {
318 private void createProjectGroup(Composite parent
) {
319 if (fDefaultProjectName
!= null) {
320 Group projectGroup
= new Group(parent
, SWT
.SHADOW_NONE
);
321 projectGroup
.setText(RemoteMessages
.RemoteFetchLogWizardRemotePage_ImportDialogProjectsGroupName
);
322 GridLayout layout
= new GridLayout(1, true);
323 projectGroup
.setLayout(layout
);
324 projectGroup
.setLayoutData(new GridData(GridData
.FILL_HORIZONTAL
));
326 fProjects
= new ArrayList
<>();
327 List
<String
> projectNames
= new ArrayList
<>();
329 for (IProject project
: TraceUtils
.getOpenedTmfProjects()) {
330 fProjects
.add(project
);
331 projectNames
.add(project
.getName());
334 fCombo
= new CCombo(projectGroup
, SWT
.READ_ONLY
);
335 fCombo
.setToolTipText(RemoteMessages
.RemoteFetchLogWizardRemotePage_ImportDialogProjectsGroupName
);
336 fCombo
.setLayoutData(new GridData(GridData
.FILL
, GridData
.CENTER
, true, false, 1, 1));
337 fCombo
.setItems(projectNames
.toArray(new String
[projectNames
.size()]));
338 int select
= projectNames
.indexOf(fDefaultProjectName
);
339 fCombo
.select(select
);
343 private void createOptionGroup(Composite parent
) {
344 if (fExperimentName
!= null) {
345 Group comp
= new Group(parent
, SWT
.SHADOW_NONE
);
346 comp
.setText(RemoteMessages
.RemoteFetchLogWizardRemotePage_OptionsGroupName
);
347 GridLayout layout
= new GridLayout(2, false);
348 comp
.setLayout(layout
);
349 GridData data
= new GridData(GridData
.FILL
, GridData
.CENTER
, true, false);
350 comp
.setLayoutData(data
);
352 fCreateExperimentCheckbox
= new Button(comp
, SWT
.CHECK
);
353 fCreateExperimentCheckbox
.setFont(comp
.getFont());
354 fCreateExperimentCheckbox
.setText(RemoteMessages
.RemoteFetchLogWizardRemotePage_CreateExperimentName
);
355 fCreateExperimentCheckbox
.setSelection(false);
356 data
= new GridData(GridData
.BEGINNING
, GridData
.CENTER
, false, false);
357 fCreateExperimentCheckbox
.setLayoutData(data
);
359 fExperimentNameText
= new Text(comp
, SWT
.BORDER
);
360 data
= new GridData(GridData
.FILL
, GridData
.CENTER
, true, false);
361 fExperimentNameText
.setLayoutData(data
);
362 fExperimentNameText
.setText(fExperimentName
);
363 fExperimentNameText
.setEnabled(fCreateExperimentCheckbox
.getSelection());
365 fExperimentNameText
.addModifyListener(new ModifyListener() {
367 public void modifyText(ModifyEvent e
) {
368 updatePageCompletion();
372 fCreateExperimentCheckbox
.addSelectionListener(new SelectionAdapter() {
374 public void widgetSelected(SelectionEvent e
) {
375 fExperimentNameText
.setEnabled(fCreateExperimentCheckbox
.getSelection());
376 updatePageCompletion();
383 protected Object
createElementViewerInput() {
384 if (fProfile
== null) {
387 final List
<RemoteImportConnectionNodeElement
> remoteHosts
= fProfile
.getConnectionNodeElements();
389 if (remoteHosts
.size() == 0) {
390 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, RemoteMessages
.RemoteFetchLogWizardRemotePage_MissingConnectionInformation
);
393 final IStatus status
[] = new IStatus
[1];
395 getContainer().run(true, true, new IRunnableWithProgress() {
397 public void run(IProgressMonitor monitor
) throws InvocationTargetException
, InterruptedException
{
398 SubMonitor subMonitor
= SubMonitor
.convert(monitor
, remoteHosts
.size());
399 for (final RemoteImportConnectionNodeElement remoteHost
: remoteHosts
) {
400 SubMonitor child
= subMonitor
.newChild(1);
401 child
.setTaskName(MessageFormat
.format(RemoteMessages
.RemoteFetchLogWizardRemotePage_OpeningConnectionTo
, remoteHost
.getURI()));
402 status
[0] = remoteHost
.connect(checkNotNull(subMonitor
.newChild(1)));
403 if (!status
[0].isOK()) {
408 fRemoteHosts
.add(remoteHost
);
413 } catch (InvocationTargetException e
) {
415 MessageFormat
.format(RemoteMessages
.RemoteFetchLogWizardRemotePage_ConnectionError
, fProfile
.getText()),
418 } catch (InterruptedException e
) {
420 status
[0] = Status
.CANCEL_STATUS
;
423 if (!status
[0].isOK()) {
424 handleErrorStatus(status
[0]);
429 final AbstractTracePackageOperation generateManifestOperation
= new RemoteGenerateManifestOperation(fProfile
);
431 getContainer().run(true, true, new IRunnableWithProgress() {
433 public void run(IProgressMonitor monitor
)
434 throws InvocationTargetException
, InterruptedException
{
436 Messages
.ImportTracePackageWizardPage_ReadingPackage
,
438 generateManifestOperation
.run(monitor
);
443 status
[0] = generateManifestOperation
.getStatus();
444 if (status
[0].getSeverity() == IStatus
.ERROR
) {
445 handleErrorStatus(status
[0]);
448 return generateManifestOperation
.getResultElements();
449 } catch (InvocationTargetException e1
) {
451 Messages
.TracePackageExtractManifestOperation_ErrorReadingManifest
,
453 } catch (InterruptedException e1
) {
460 * Method to set input data for this wizard
464 * @param overwriteAll
465 * Overwrite existing traces without confirmation
467 public void setPageData(RemoteImportProfileElement profile
, boolean overwriteAll
) {
469 fOverwriteAll
= overwriteAll
;
473 * Finishes the wizard page.
475 * @return <code>true</code> if successful else <code>false</code>
477 public boolean finish() {
481 result
= updateViewer();
487 result
= validateProject();
492 Object
[] elements
= getElementViewer().getCheckedElements();
493 final RemoteImportTracesOperation importOperation
= new RemoteImportTracesOperation(getContainer().getShell(), fTmfTraceFolder
, elements
, fOverwriteAll
);
495 final List
<IResource
> traceResources
= new ArrayList
<>();
497 getContainer().run(true, true, new IRunnableWithProgress() {
499 public void run(IProgressMonitor monitor
) throws InvocationTargetException
, InterruptedException
{
500 importOperation
.run(monitor
);
501 traceResources
.addAll(importOperation
.getImportedResources());
506 if ((fExperimentName
!= null) && fCreateExperimentCheckbox
.getSelection() && (traceResources
.size() > 0)) {
507 final IFolder
[] experimentFolders
= new IFolder
[1];
508 final TmfExperimentFolder root
= fExperimentFolderElement
;
509 final IStatus
[] operationStatus
= new IStatus
[1];
510 final String experimentName
= fExperimentNameText
.getText().trim();
512 // just safety guards
513 if ((root
== null) || (experimentName
== null)) {
516 getContainer().run(true, true, new IRunnableWithProgress() {
518 public void run(IProgressMonitor monitor
) throws InvocationTargetException
, InterruptedException
{
519 operationStatus
[0] = null;
520 final NewExperimentOperation operation
= new NewExperimentOperation(root
, experimentName
);
521 operation
.run(monitor
);
523 operationStatus
[0] = operation
.getStatus();
524 experimentFolders
[0] = operation
.getExperimentFolder();
528 final IFolder expFolder
= experimentFolders
[0];
529 final TmfTraceFolder parentTraceFolder
= fTmfTraceFolder
;
530 // just safety guards
531 if ((expFolder
== null) || (parentTraceFolder
== null)) {
535 if ((operationStatus
[0] != null) && (operationStatus
[0].isOK())) {
536 getContainer().run(true, true, new IRunnableWithProgress() {
538 public void run(IProgressMonitor monitor
) throws InvocationTargetException
, InterruptedException
{
539 operationStatus
[0] = null;
540 final SelectTracesOperation operation
= new SelectTracesOperation(root
, expFolder
, parentTraceFolder
, traceResources
);
541 operation
.run(monitor
);
543 operationStatus
[0] = operation
.getStatus();
548 } catch (InvocationTargetException e
) {
550 Messages
.TracePackageExtractManifestOperation_ErrorReadingManifest
,
553 } catch (InterruptedException e
) {
558 IStatus status
= importOperation
.getStatus();
559 if (status
.getSeverity() == IStatus
.ERROR
) {
560 handleErrorStatus(status
);
564 disconnectAllRemoteHosts();
569 * Cancels the the wizard and disconnects all open connections.
571 public void cancel() {
572 disconnectAllRemoteHosts();
575 // ------------------------------------------------------------------------
577 // ------------------------------------------------------------------------
578 private void disconnectAllRemoteHosts() {
579 for (RemoteImportConnectionNodeElement remoteHost
: fRemoteHosts
) {
580 remoteHost
.disconnect();
584 private boolean updateViewer() {
585 Object elementViewerInput
= createElementViewerInput();
586 if (elementViewerInput
== null) {
590 CheckboxTreeViewer elementViewer
= getElementViewer();
591 elementViewer
.setInput(elementViewerInput
);
592 elementViewer
.expandToLevel(3);
593 setAllChecked(elementViewer
, false, true);
594 updatePageCompletion();
599 private boolean validateProject() {
600 if (fCombo
!= null) {
601 int fProjectIndex
= fCombo
.getSelectionIndex();
602 if (fProjectIndex
< 0) {
603 handleError(RemoteMessages
.RemoteFetchLogWizardRemotePage_NoProjectSelectedError
, null);
607 IProject project
= fProjects
.get(fProjectIndex
);
608 IFolder traceFolder
= project
.getFolder(TmfTracesFolder
.TRACES_FOLDER_NAME
);
610 if (!traceFolder
.exists()) {
611 handleError(RemoteMessages
.RemoteFetchLogWizardRemotePage_InvalidTracingProject
, null);
616 if (project
.hasNature(TmfProjectNature
.ID
)) {
617 TmfProjectElement projectElement
= TmfProjectRegistry
.getProject(project
, true);
618 fTmfTraceFolder
= projectElement
.getTracesFolder();
619 fExperimentFolderElement
= projectElement
.getExperimentsFolder();
621 } catch (CoreException ex
) {
622 handleError(RemoteMessages
.RemoteFetchLogWizardRemotePage_InvalidTracingProject
, ex
);