| /******************************************************************************* |
| * 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; |
| } |
| } |