blob: 93c6bd4cf342cc9f6520e36fcab47add49e03f63 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2018 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Marc-Andre Laperle - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageWizardPage;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageBookmarkElement;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageExperimentElement;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageLabelProvider;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFileElement;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFilesElement;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
import org.eclipse.tracecompass.tmf.ui.project.model.TmfCommonProjectElement;
import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
/**
* Wizard page for the export trace package wizard
*
* @author Marc-Andre Laperle
*/
public class ExportTracePackageWizardPage extends AbstractTracePackageWizardPage {
private static final int CONTENT_COL_WIDTH = 300;
private static final int SIZE_COL_WIDTH = 100;
private static final String ZIP_EXTENSION = ".zip"; //$NON-NLS-1$
private static final String TAR_EXTENSION = ".tar"; //$NON-NLS-1$
private static final String TAR_GZ_EXTENSION = ".tar.gz"; //$NON-NLS-1$
private static final String TGZ_EXTENSION = ".tgz"; //$NON-NLS-1$
private static final String ICON_PATH = "icons/wizban/export_wiz.png"; //$NON-NLS-1$
/**
* The page name, can be referenced from other pages
*/
public static final String PAGE_NAME = "ExportTracePackageWizardPage"; //$NON-NLS-1$
// dialog store id constants
private static final String STORE_COMPRESS_CONTENTS_ID = PAGE_NAME + ".STORE_COMPRESS_CONTENTS_ID"; //$NON-NLS-1$
private static final String STORE_FORMAT_ID = PAGE_NAME + ".STORE_FORMAT_ID"; //$NON-NLS-1$
private Button fCompressContentsCheckbox;
private Button fZipFormatButton;
private Button fTargzFormatButton;
private Label fApproximateSizeLabel;
private List<TmfCommonProjectElement> fSelectedTraces;
/**
* Constructor for the export trace package wizard page
*
* @param selection
* the current object selection
* @param selectedTraces
* the selected traces from the selection
*/
public ExportTracePackageWizardPage(IStructuredSelection selection, List<TmfCommonProjectElement> selectedTraces) {
super(PAGE_NAME, Messages.ExportTracePackageWizardPage_Title, Activator.getDefault().getImageDescripterFromPath(ICON_PATH), selection);
fSelectedTraces = new ArrayList<>(selectedTraces);
}
/**
* Set the selected trace from the previous page to be displayed in the
* element viewer
*
* @param selectedTraces
* the selected trace
*/
public void setSelectedTraces(List<TmfTraceElement> selectedTraces) {
if (!fSelectedTraces.containsAll(selectedTraces) || !selectedTraces.containsAll(fSelectedTraces)) {
fSelectedTraces = new ArrayList<>(selectedTraces);
CheckboxTreeViewer elementViewer = getElementViewer();
elementViewer.setInput(createElementViewerInput());
elementViewer.expandToLevel(2);
setAllChecked(elementViewer, false, true);
updateApproximateSelectedSize();
}
}
@Override
public void createControl(Composite parent) {
initializeDialogUnits(parent);
Composite composite = new Composite(parent, SWT.NULL);
composite.setLayout(new GridLayout());
composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
createElementViewer(composite);
createButtonsGroup(composite);
createFilePathGroup(composite, Messages.ExportTracePackageWizardPage_ToArchive, SWT.SAVE);
createOptionsGroup(composite);
restoreWidgetValues();
setMessage(Messages.ExportTracePackageWizardPage_ChooseContent);
updateApproximateSelectedSize();
updatePageCompletion();
setControl(composite);
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
updatePageCompletion();
} else {
setPageComplete(false);
}
}
/**
* Restore widget values to the values that they held last time this wizard
* was used to completion.
*/
@Override
protected void restoreWidgetValues() {
super.restoreWidgetValues();
IDialogSettings settings = getDialogSettings();
if (settings != null) {
if (getFilePathCombo().getItemCount() > 0) {
String item = getFilePathCombo().getItem(0);
setFilePathValue(item);
}
fCompressContentsCheckbox.setSelection(settings.getBoolean(STORE_COMPRESS_CONTENTS_ID));
fZipFormatButton.setSelection(settings.getBoolean(STORE_FORMAT_ID));
fTargzFormatButton.setSelection(!settings.getBoolean(STORE_FORMAT_ID));
updateWithFilePathSelection();
}
}
@Override
protected void createFilePathGroup(Composite parent, String label, int fileDialogStyle) {
super.createFilePathGroup(parent, label, fileDialogStyle);
getFilePathCombo().addModifyListener(e -> updatePageCompletion());
}
private void createOptionsGroup(Composite parent) {
Group optionsGroup = new Group(parent, SWT.NONE);
optionsGroup.setLayout(new RowLayout(SWT.VERTICAL));
optionsGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
| GridData.GRAB_HORIZONTAL));
optionsGroup.setText(Messages.ExportTracePackageWizardPage_Options);
SelectionAdapter listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
updateWithFilePathSelection();
}
};
fZipFormatButton = new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
fZipFormatButton.setText(Messages.ExportTracePackageWizardPage_SaveInZipFormat);
fZipFormatButton.setSelection(true);
fZipFormatButton.addSelectionListener(listener);
fTargzFormatButton = new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
fTargzFormatButton.setText(Messages.ExportTracePackageWizardPage_SaveInTarFormat);
fTargzFormatButton.setSelection(false);
fTargzFormatButton.addSelectionListener(listener);
fCompressContentsCheckbox = new Button(optionsGroup, SWT.CHECK | SWT.LEFT);
fCompressContentsCheckbox.setText(Messages.ExportTracePackageWizardPage_CompressContents);
fCompressContentsCheckbox.setSelection(true);
fCompressContentsCheckbox.addSelectionListener(listener);
}
@Override
protected void createElementViewer(Composite parent) {
super.createElementViewer(parent);
CheckboxTreeViewer elementViewer = getElementViewer();
elementViewer.getTree().setHeaderVisible(true);
// Content column
TreeViewerColumn column = new TreeViewerColumn(elementViewer, SWT.NONE);
column.getColumn().setWidth(CONTENT_COL_WIDTH);
column.getColumn().setText(Messages.ExportTracePackageWizardPage_ContentColumnName);
column.setLabelProvider(new TracePackageLabelProvider());
// Size column
column = new TreeViewerColumn(elementViewer, SWT.NONE);
column.getColumn().setWidth(SIZE_COL_WIDTH);
column.getColumn().setText(Messages.ExportTracePackageWizardPage_SizeColumnName);
column.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
TracePackageElement tracePackageElement = (TracePackageElement) element;
long size = tracePackageElement.getSize(false);
if (size == 0) {
return null;
}
int level = 0;
TracePackageElement curElement = tracePackageElement.getParent();
while (curElement != null) {
curElement = curElement.getParent();
++level;
}
return indent(getHumanReadable(size), level);
}
private String indent(String humanReadable, int level) {
StringBuilder s = new StringBuilder(humanReadable);
for (int i = 0; i < level; ++i) {
final String indentStr = " "; //$NON-NLS-1$
s.insert(0, indentStr);
}
return s.toString();
}
});
elementViewer.setInput(createElementViewerInput());
elementViewer.expandToLevel(2);
setAllChecked(elementViewer, false, true);
}
@Override
protected void updateApproximateSelectedSize() {
long checkedSize = 0;
TracePackageElement[] tracePackageElements = (TracePackageElement[]) getElementViewer().getInput();
for (TracePackageElement element : tracePackageElements) {
checkedSize += element.getSize(true);
}
checkedSize = Math.max(0, checkedSize);
fApproximateSizeLabel.setText(MessageFormat.format(Messages.ExportTracePackageWizardPage_ApproximateSizeLbl, getHumanReadable(checkedSize)));
}
/**
* Get the human readable string for a size in bytes. (KB, MB, etc).
*
* @param size
* the size to print in human readable,
* @return the human readable string
*/
private static String getHumanReadable(long size) {
String humanSuffix[] = { Messages.ExportTracePackageWizardPage_SizeByte, Messages.ExportTracePackageWizardPage_SizeKilobyte,
Messages.ExportTracePackageWizardPage_SizeMegabyte, Messages.ExportTracePackageWizardPage_SizeGigabyte,
Messages.ExportTracePackageWizardPage_SizeTerabyte };
long curSize = size;
int suffixIndex = 0;
while (curSize >= 1024) {
curSize /= 1024;
++suffixIndex;
}
return Long.toString(curSize) + " " + humanSuffix[suffixIndex]; //$NON-NLS-1$
}
@Override
protected Object createElementViewerInput() {
List<TracePackageTraceElement> traceElements = new ArrayList<>();
for (TmfCommonProjectElement projectElement : fSelectedTraces) {
TracePackageTraceElement traceElement;
if (projectElement instanceof TmfExperimentElement) {
TmfExperimentElement experimentElement = (TmfExperimentElement) projectElement;
traceElement = new TracePackageExperimentElement(null, experimentElement);
for (TmfTraceElement expTrace : experimentElement.getTraces()) {
((TracePackageExperimentElement) traceElement).addExpTrace(expTrace.getElementPath());
}
} else {
traceElement = new TracePackageTraceElement(null, projectElement);
}
// Trace files
TracePackageFilesElement filesElement = new TracePackageFilesElement(traceElement, projectElement.getResource());
filesElement.setChecked(true);
// Supplementary files
try {
String supplementaryFolder = projectElement.getResource().getPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
TracePackageSupplFilesElement suppFilesElement = new TracePackageSupplFilesElement(null);
IResource[] supplementaryResources = projectElement.getSupplementaryResources();
for (IResource res : supplementaryResources) {
String name = supplementaryFolder == null ? res.getName() : res.getLocation().makeRelativeTo(new Path(supplementaryFolder)).toString();
new TracePackageSupplFileElement(res, name, suppFilesElement);
}
if (supplementaryFolder != null) {
// If the supplementary folder path is in a shadow project,
// the resources must be taken from the parent project.
IFolder projectSupplementaryFolder = projectElement.getProject().getSupplementaryFolder();
IPath path = new Path(supplementaryFolder).append(TmfCommonConstants.TRACE_PROPERTIES_FOLDER);
IFolder propertiesFolder = projectSupplementaryFolder.getFolder(path.makeRelativeTo(projectSupplementaryFolder.getLocation()));
if (propertiesFolder.exists()) {
for (IResource res : propertiesFolder.members()) {
String name = res.getLocation().makeRelativeTo(new Path(supplementaryFolder)).toString();
new TracePackageSupplFileElement(res, name, suppFilesElement);
}
}
}
if (suppFilesElement.getChildren().length > 0) {
traceElement.addChild(suppFilesElement);
}
} catch (CoreException e) {
// Should not happen
Activator.getDefault().logError("Error finding supplementary files", e); //$NON-NLS-1$
}
// Bookmarks
IFile bookmarksFile = projectElement.getBookmarksFile();
if (bookmarksFile != null && bookmarksFile.exists()) {
IMarker[] findMarkers;
try {
findMarkers = bookmarksFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
if (findMarkers.length > 0) {
new TracePackageBookmarkElement(traceElement, null);
}
} catch (CoreException e) {
// Should not happen since we just checked bookmarksFile.exists() but log it just in case
Activator.getDefault().logError("Error finding bookmarks", e); //$NON-NLS-1$
}
}
traceElements.add(traceElement);
}
return traceElements.toArray(new TracePackageTraceElement[] {});
}
@Override
protected final Composite createButtonsGroup(Composite parent) {
Composite buttonGroup = super.createButtonsGroup(parent);
// Add the label on the same row of the select/deselect all buttons
fApproximateSizeLabel = new Label(buttonGroup, SWT.RIGHT);
GridData layoutData = new GridData(GridData.FILL_HORIZONTAL);
layoutData.grabExcessHorizontalSpace = true;
fApproximateSizeLabel.setLayoutData(layoutData);
return buttonGroup;
}
/**
* Save widget values to Dialog settings
*/
@Override
protected void saveWidgetValues() {
super.saveWidgetValues();
IDialogSettings settings = getDialogSettings();
if (settings != null) {
settings.put(STORE_COMPRESS_CONTENTS_ID, fCompressContentsCheckbox.getSelection());
settings.put(STORE_FORMAT_ID, fZipFormatButton.getSelection());
}
}
private String getOutputExtension() {
if (fZipFormatButton.getSelection()) {
return ZIP_EXTENSION;
} else if (fCompressContentsCheckbox.getSelection()) {
return TAR_GZ_EXTENSION;
} else {
return TAR_EXTENSION;
}
}
@Override
protected void updateWithFilePathSelection() {
String filePathValue = getFilePathValue();
if (filePathValue.isEmpty()) {
return;
}
filePathValue = stripKnownExtension(filePathValue);
filePathValue = filePathValue.concat(getOutputExtension());
setFilePathValue(filePathValue);
}
private static String stripKnownExtension(String str) {
String ret = str;
if (str.endsWith(TAR_GZ_EXTENSION)) {
ret = ret.substring(0, ret.lastIndexOf('.'));
}
if (ret.endsWith(ZIP_EXTENSION) || ret.endsWith(TAR_EXTENSION) || ret.endsWith(TGZ_EXTENSION)) {
ret = ret.substring(0, ret.lastIndexOf('.'));
}
return ret;
}
/**
* Finish the wizard page
*
* @return true on success
*/
public boolean finish() {
if (!checkForOverwrite()) {
return false;
}
saveWidgetValues();
TracePackageTraceElement[] traceExportElements = (TracePackageTraceElement[]) getElementViewer().getInput();
boolean useCompression = fCompressContentsCheckbox.getSelection();
boolean useTar = fTargzFormatButton.getSelection();
String fileName = getFilePathValue();
final TracePackageExportOperation exporter = new TracePackageExportOperation(traceExportElements, useCompression, useTar, fileName);
try {
getContainer().run(true, true, exporter::run);
IStatus status = exporter.getStatus();
if (status.getSeverity() == IStatus.ERROR) {
handleErrorStatus(status);
}
} catch (InvocationTargetException e) {
handleError(org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return exporter.getStatus().getSeverity() == IStatus.OK;
}
private boolean checkForOverwrite() {
File file = new File(getFilePathValue());
if (file.exists()) {
return MessageDialog.openQuestion(getContainer().getShell(), null, Messages.ExportTracePackageWizardPage_AlreadyExitst);
}
return true;
}
}