Copyright header update, 2015 edition
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / internal / tmf / ui / project / wizards / tracepkg / importexport / TracePackageImportOperation.java
CommitLineData
6e651d8b 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2013, 2015 Ericsson
6e651d8b
MAL
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 * Marc-Andre Laperle - Initial API and implementation
89730b51 11 * Patrick Tasse - Add support for source location
6e651d8b
MAL
12 *******************************************************************************/
13
2bdf0193 14package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
6e651d8b 15
e2659565
AM
16import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17
89730b51 18import java.io.File;
6e651d8b
MAL
19import java.io.IOException;
20import java.io.InputStream;
21import java.lang.reflect.InvocationTargetException;
89730b51 22import java.net.URI;
6e651d8b
MAL
23import java.text.MessageFormat;
24import java.util.ArrayList;
25import java.util.Enumeration;
26import java.util.List;
27import java.util.Map;
28
29import org.eclipse.core.resources.IFile;
89730b51 30import org.eclipse.core.resources.IFolder;
6e651d8b
MAL
31import org.eclipse.core.resources.IMarker;
32import org.eclipse.core.resources.IResource;
33import org.eclipse.core.runtime.CoreException;
34import org.eclipse.core.runtime.IPath;
35import org.eclipse.core.runtime.IProgressMonitor;
36import org.eclipse.core.runtime.IStatus;
37import org.eclipse.core.runtime.Path;
38import org.eclipse.core.runtime.Status;
39import org.eclipse.core.runtime.SubProgressMonitor;
89730b51 40import org.eclipse.core.runtime.URIUtil;
6e651d8b 41import org.eclipse.jface.operation.ModalContext;
2bdf0193
AM
42import org.eclipse.tracecompass.internal.tmf.ui.Activator;
43import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageOperation;
44import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageBookmarkElement;
45import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
46import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
47import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFileElement;
48import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFilesElement;
49import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
50import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
51import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
52import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
53import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
54import org.eclipse.tracecompass.tmf.core.util.Pair;
55import org.eclipse.tracecompass.tmf.ui.editors.TmfEventsEditor;
56import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
57import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
58import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
6e651d8b
MAL
59import org.eclipse.ui.dialogs.IOverwriteQuery;
60import org.eclipse.ui.ide.IDE;
61import org.eclipse.ui.internal.wizards.datatransfer.TarException;
62import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
63import org.eclipse.ui.wizards.datatransfer.ImportOperation;
64
65/**
66 * An operation that imports a trace package from an archive
67 *
68 * @author Marc-Andre Laperle
69 */
70@SuppressWarnings("restriction")
71public class TracePackageImportOperation extends AbstractTracePackageOperation implements IOverwriteQuery {
72
195355a9 73 private final TracePackageElement[] fImportTraceElements;
6e651d8b
MAL
74 private final TmfTraceFolder fTmfTraceFolder;
75
6e651d8b
MAL
76 /**
77 * Constructs a new import operation
78 *
195355a9 79 * @param importTraceElements
6e651d8b
MAL
80 * the trace element to be imported
81 * @param fileName
82 * the output file name
83 * @param tmfTraceFolder
84 * the destination folder
85 */
195355a9 86 public TracePackageImportOperation(String fileName, TracePackageElement[] importTraceElements, TmfTraceFolder tmfTraceFolder) {
6e651d8b 87 super(fileName);
195355a9 88 fImportTraceElements = importTraceElements;
6e651d8b
MAL
89 fTmfTraceFolder = tmfTraceFolder;
90 }
91
92 private class ImportProvider implements IImportStructureProvider {
93
94 private Exception fException;
95
96 @Override
97 public List getChildren(Object element) {
98 return null;
99 }
100
101 @Override
102 public InputStream getContents(Object element) {
103 InputStream inputStream = null;
104 // We can add throws
105 try {
106 inputStream = ((ArchiveProviderElement) element).getContents();
107 } catch (IOException e) {
108 fException = e;
109 } catch (TarException e) {
110 fException = e;
111 }
112 return inputStream;
113 }
114
115 @Override
116 public String getFullPath(Object element) {
117 return ((ArchiveProviderElement) element).getFullPath();
118 }
119
120 @Override
121 public String getLabel(Object element) {
122 return ((ArchiveProviderElement) element).getLabel();
123 }
124
125 @Override
126 public boolean isFolder(Object element) {
127 return ((ArchiveProviderElement) element).isFolder();
128 }
129
130 public Exception getException() {
131 return fException;
132 }
133 }
134
135 private class ArchiveProviderElement {
136
137 private final String fPath;
138 private final String fLabel;
139
140 private ArchiveFile fArchiveFile;
141 private ArchiveEntry fEntry;
142
143 public ArchiveProviderElement(String destinationPath, String label, ArchiveFile archiveFile, ArchiveEntry entry) {
144 fPath = destinationPath;
145 fLabel = label;
146 this.fArchiveFile = archiveFile;
147 this.fEntry = entry;
148 }
149
150 public InputStream getContents() throws TarException, IOException {
151 return fArchiveFile.getInputStream(fEntry);
152 }
153
154 public String getFullPath() {
155 return fPath;
156 }
157
158 public String getLabel() {
159 return fLabel;
160 }
161
162 public boolean isFolder() {
163 return false;
164 }
165 }
166
167 /**
168 * Run the operation. The status (result) of the operation can be obtained
169 * with {@link #getStatus}
170 *
171 * @param progressMonitor
172 * the progress monitor to use to display progress and receive
173 * requests for cancellation
174 */
175 @Override
176 public void run(IProgressMonitor progressMonitor) {
195355a9 177 int totalWork = getNbCheckedElements(fImportTraceElements) * 2;
6e651d8b
MAL
178 progressMonitor.beginTask(Messages.TracePackageImportOperation_ImportingPackage, totalWork);
179 doRun(progressMonitor);
180 progressMonitor.done();
181 }
182
183 private void doRun(IProgressMonitor progressMonitor) {
184 try {
195355a9 185 setStatus(deleteExistingTraces(progressMonitor));
6e651d8b
MAL
186 if (getStatus().getSeverity() != IStatus.OK) {
187 return;
188 }
189
89730b51 190 TracePackageFilesElement traceFilesElement = null;
195355a9
MAL
191 for (TracePackageElement packageElement : fImportTraceElements) {
192 TracePackageTraceElement traceElement = (TracePackageTraceElement) packageElement;
193 if (!isFilesChecked(packageElement)) {
194 continue;
195 }
196
197 TracePackageElement[] children = traceElement.getChildren();
198 for (TracePackageElement element : children) {
199 ModalContext.checkCanceled(progressMonitor);
200
201 if (element instanceof TracePackageFilesElement) {
89730b51 202 traceFilesElement = (TracePackageFilesElement) element;
a6ee485c 203 setStatus(importTraceFiles(traceFilesElement, traceElement, progressMonitor));
6e651d8b 204
195355a9
MAL
205 } else if (element instanceof TracePackageSupplFilesElement) {
206 TracePackageSupplFilesElement suppFilesElement = (TracePackageSupplFilesElement) element;
207 setStatus(importSupplFiles(suppFilesElement, traceElement, progressMonitor));
208 }
6e651d8b 209
195355a9
MAL
210 if (getStatus().getSeverity() != IStatus.OK) {
211 return;
212 }
6e651d8b 213 }
89730b51 214 }
6e651d8b
MAL
215
216 } catch (InterruptedException e) {
217 setStatus(Status.CANCEL_STATUS);
218 }
219 }
220
a6ee485c
MAL
221 /**
222 * Returns whether or not the Files element is checked under the given trace
223 * package element
224 *
225 * @param tracePackageElement
226 * the trace package element
227 * @return whether or not the Files element is checked under the given trace
228 * package element
229 */
230 public static boolean isFilesChecked(TracePackageElement tracePackageElement) {
231 for (TracePackageElement element : tracePackageElement.getChildren()) {
232 if (element instanceof TracePackageFilesElement) {
233 return element.isChecked();
234 }
235 }
236
237 return false;
238 }
239
240 /**
241 * Return the matching TmfTraceElement for a given trace element.
242 */
243 private TmfTraceElement getMatchingTraceElement(TracePackageTraceElement tracePackageElement) {
244 IPath tracePath = fTmfTraceFolder.getPath().append(tracePackageElement.getDestinationElementPath());
6e651d8b 245 List<TmfTraceElement> traces = fTmfTraceFolder.getTraces();
a6ee485c
MAL
246 for (TmfTraceElement t : traces) {
247 if (t.getPath().equals(tracePath)) {
248 return t;
249 }
250 }
251
252 return null;
253 }
6e651d8b 254
a6ee485c 255 private IStatus deleteExistingTraces(IProgressMonitor progressMonitor) {
195355a9
MAL
256 for (TracePackageElement packageElement : fImportTraceElements) {
257 TracePackageTraceElement traceElement = (TracePackageTraceElement) packageElement;
258 if (!isFilesChecked(traceElement)) {
259 continue;
6e651d8b 260 }
6e651d8b 261
a6ee485c 262 TmfTraceElement existingTrace = getMatchingTraceElement(traceElement);
195355a9
MAL
263 if (existingTrace != null) {
264 try {
265 existingTrace.delete(new SubProgressMonitor(progressMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
266 } catch (CoreException e) {
2bdf0193 267 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e);
195355a9 268 }
6e651d8b
MAL
269 }
270 }
271
272 return Status.OK_STATUS;
273 }
274
195355a9
MAL
275 private void importBookmarks(IResource traceRes, TracePackageTraceElement traceElement, IProgressMonitor monitor) {
276 for (TracePackageElement o : traceElement.getChildren()) {
6e651d8b
MAL
277 if (o instanceof TracePackageBookmarkElement && o.isChecked()) {
278
279 // Get element
280 IFile bookmarksFile = null;
a6ee485c
MAL
281 TmfTraceElement tmfTraceElement = getMatchingTraceElement(traceElement);
282 if (tmfTraceElement != null) {
283 try {
284 bookmarksFile = tmfTraceElement.createBookmarksFile();
6e651d8b 285
a6ee485c
MAL
286 // Make sure that if a bookmark is double-clicked first
287 // before opening the trace, it opens the right editor
6e651d8b 288
a6ee485c
MAL
289 // Get the editor id from the extension point
290 String traceEditorId = tmfTraceElement.getEditorId();
291 final String editorId = (traceEditorId != null) ? traceEditorId : TmfEventsEditor.ID;
292 IDE.setDefaultEditor(bookmarksFile, editorId);
6e651d8b 293
a6ee485c
MAL
294 } catch (CoreException e) {
295 Activator.getDefault().logError(MessageFormat.format(Messages.TracePackageImportOperation_ErrorCreatingBookmarkFile, traceRes.getName()), e);
6e651d8b
MAL
296 }
297 }
298
299 if (bookmarksFile == null) {
300 break;
301 }
302
303 TracePackageBookmarkElement bookmarkElement = (TracePackageBookmarkElement) o;
304
305 List<Map<String, String>> bookmarks = bookmarkElement.getBookmarks();
306 for (Map<String, String> attrs : bookmarks) {
307 IMarker createMarker = null;
308 try {
309 createMarker = bookmarksFile.createMarker(IMarker.BOOKMARK);
310 } catch (CoreException e) {
311 Activator.getDefault().logError(MessageFormat.format(Messages.TracePackageImportOperation_ErrorCreatingBookmark, traceRes.getName()), e);
312 }
313 if (createMarker != null && createMarker.exists()) {
314 try {
315 for (String key : attrs.keySet()) {
316 String value = attrs.get(key);
317 if (key.equals(IMarker.LOCATION)) {
318 createMarker.setAttribute(IMarker.LOCATION, Integer.valueOf(value).intValue());
319 } else {
320 createMarker.setAttribute(key, value);
321 }
322 }
323 } catch (CoreException e) {
324 Activator.getDefault().logError(MessageFormat.format(Messages.TracePackageImportOperation_ErrorCreatingBookmark, traceRes.getName()), e);
325 }
326 }
327 }
328 }
329 }
330
331 monitor.worked(1);
332 }
333
a6ee485c 334 private IStatus importTraceFiles(TracePackageFilesElement traceFilesElement, TracePackageTraceElement traceElement, IProgressMonitor monitor) {
7441221c
MAL
335 List<Pair<String, String>> fileNameAndLabelPairs = new ArrayList<>();
336
e2659565
AM
337 String sourceName = checkNotNull(traceFilesElement.getFileName());
338 String destinationName = checkNotNull(traceElement.getImportName());
7441221c
MAL
339
340 fileNameAndLabelPairs.add(new Pair<>(sourceName, destinationName));
341
6e651d8b 342 IPath containerPath = fTmfTraceFolder.getPath();
a6ee485c
MAL
343 IStatus status = importFiles(getSpecifiedArchiveFile(), fileNameAndLabelPairs, containerPath, Path.EMPTY, monitor);
344 if (getStatus().getSeverity() != IStatus.OK) {
345 return status;
346 }
347
348 // We need to set the trace type before importing the supplementary files so we do it here
349 IResource traceRes = fTmfTraceFolder.getResource().findMember(traceElement.getDestinationElementPath());
350 if (traceRes == null || !traceRes.exists()) {
351 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format(Messages.ImportTracePackageWizardPage_ErrorFindingImportedTrace, destinationName));
352 }
353
354 TraceTypeHelper traceType = null;
355 String traceTypeStr = traceElement.getTraceType();
356 if (traceTypeStr != null) {
a4a116c3 357 traceType = TmfTraceType.getTraceType(traceTypeStr);
a6ee485c
MAL
358 if (traceType == null) {
359 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format(Messages.ImportTracePackageWizardPage_ErrorSettingTraceType, traceElement.getTraceType(), destinationName));
360 }
361 } else {
362 try {
363 monitor.subTask(MessageFormat.format(Messages.TracePackageImportOperation_DetectingTraceType, destinationName));
364 traceType = TmfTraceTypeUIUtils.selectTraceType(traceRes.getLocation().toOSString(), null, null);
365 } catch (TmfTraceImportException e) {
366 // Could not figure out the type
367 }
368 }
369
370 if (traceType != null) {
371 try {
372 TmfTraceTypeUIUtils.setTraceType(traceRes, traceType);
373 } catch (CoreException e) {
374 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format(Messages.ImportTracePackageWizardPage_ErrorSettingTraceType, traceElement.getTraceType(), destinationName), e);
375 }
376 }
377
378 importBookmarks(traceRes, traceElement, monitor);
379
380 try {
381 URI uri = new File(getFileName()).toURI();
382 IPath entryPath = new Path(traceFilesElement.getFileName());
383 if (traceRes instanceof IFolder) {
384 entryPath = entryPath.addTrailingSeparator();
385 }
386 String sourceLocation = URIUtil.toUnencodedString(URIUtil.toJarURI(uri, entryPath));
387 traceRes.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
388 } catch (CoreException e) {
389 }
390
6e651d8b
MAL
391 return status;
392 }
393
195355a9 394 private IStatus importSupplFiles(TracePackageSupplFilesElement suppFilesElement, TracePackageTraceElement traceElement, IProgressMonitor monitor) {
7441221c 395 List<Pair<String, String>> fileNameAndLabelPairs = new ArrayList<>();
6e651d8b 396 for (TracePackageElement child : suppFilesElement.getChildren()) {
4d40b148
MAL
397 if (child.isChecked()) {
398 TracePackageSupplFileElement supplFile = (TracePackageSupplFileElement) child;
e2659565 399 fileNameAndLabelPairs.add(new Pair<>(checkNotNull(supplFile.getText()), checkNotNull(new Path(supplFile.getText()).lastSegment())));
4d40b148 400 }
6e651d8b
MAL
401 }
402
7441221c 403 if (!fileNameAndLabelPairs.isEmpty()) {
a6ee485c
MAL
404 TmfTraceElement existingTrace = getMatchingTraceElement(traceElement);
405 if (existingTrace != null) {
6e651d8b 406 ArchiveFile archiveFile = getSpecifiedArchiveFile();
a6ee485c
MAL
407 existingTrace.refreshSupplementaryFolder();
408 // Project/Traces/A/B -> A/B
409 IPath traceFolderRelativePath = fTmfTraceFolder.getPath().makeRelativeTo(fTmfTraceFolder.getProject().getTracesFolder().getPath());
410 // Project/.tracing/A/B/
411 IFolder traceSupplementaryFolder = fTmfTraceFolder.getTraceSupplementaryFolder(traceFolderRelativePath.toString());
412 IPath destinationContainerPath = traceSupplementaryFolder.getFullPath();
413 // Remove the .tracing segment at the beginnin so that a file in folder .tracing/A/B/ imports destinationContainerPath/A/B/
414 Path baseSourcePath = new Path(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER_NAME);
415 return importFiles(archiveFile, fileNameAndLabelPairs, destinationContainerPath, baseSourcePath, monitor);
6e651d8b
MAL
416 }
417 }
418
419 return Status.OK_STATUS;
420 }
421
a6ee485c 422 private IStatus importFiles(ArchiveFile archiveFile, List<Pair<String, String>> fileNameAndLabelPairs, IPath destinationContainerPath, IPath baseSourcePath, IProgressMonitor monitor) {
507b1336 423 List<ArchiveProviderElement> objects = new ArrayList<>();
6e651d8b
MAL
424 Enumeration<?> entries = archiveFile.entries();
425 while (entries.hasMoreElements()) {
426 ArchiveEntry entry = (ArchiveEntry) entries.nextElement();
427 String entryName = entry.getName();
428 IPath fullArchivePath = new Path(entryName);
429 if (fullArchivePath.hasTrailingSeparator()) {
430 // We only care about file entries as the folders will get created by the ImportOperation
431 continue;
432 }
433
7441221c 434 for (Pair<String, String> fileNameAndLabel : fileNameAndLabelPairs) {
f7885d6d 435
a6ee485c 436 // Examples: Traces/aaa/kernel/ .tracing/aaa/testtexttrace.txt/statistics.ht
7441221c 437 IPath searchedArchivePath = new Path(fileNameAndLabel.getFirst());
f7885d6d 438
6e651d8b 439 // Check if this archive entry matches the searched file name at this archive location
7441221c 440 boolean fileMatch = entryName.equalsIgnoreCase(searchedArchivePath.toString());
a6ee485c 441 // For example Traces/aaa/kernel/metadata matches Traces/aaa/kernel/
7441221c
MAL
442 boolean folderMatch = entryName.startsWith(searchedArchivePath + "/"); //$NON-NLS-1$
443
444 if (fileMatch || folderMatch) {
a6ee485c
MAL
445 // .tracing/aaa/testtexttrace.txt/statistics.ht -> aaa/testtexttrace.txt/statistics.ht
446 IPath destinationPath = fullArchivePath.makeRelativeTo(baseSourcePath);
7441221c 447
f7885d6d 448 // metadata statistics.ht
7441221c
MAL
449 // We don't use the label when the entry is a folder match because the labels for individual files
450 // under the folder are not specified in the manifest so just use the last segment.
451 String resourceLabel = folderMatch ? fullArchivePath.lastSegment() : fileNameAndLabel.getSecond();
6e651d8b
MAL
452
453 ArchiveProviderElement pe = new ArchiveProviderElement(destinationPath.toString(), resourceLabel, archiveFile, entry);
454 objects.add(pe);
455 break;
456 }
457 }
458 }
459
460 ImportProvider provider = new ImportProvider();
461
462 ImportOperation operation = new ImportOperation(destinationContainerPath,
463 null, provider, this,
464 objects);
465 operation.setCreateContainerStructure(true);
466 operation.setOverwriteResources(true);
467
468 try {
7441221c 469 operation.run(new SubProgressMonitor(monitor, fileNameAndLabelPairs.size(), SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
6e651d8b
MAL
470 archiveFile.close();
471 } catch (InvocationTargetException e) {
2bdf0193 472 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e);
6e651d8b
MAL
473 } catch (InterruptedException e) {
474 return Status.CANCEL_STATUS;
475 } catch (IOException e) {
2bdf0193 476 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e);
6e651d8b
MAL
477 }
478
479 if (provider.getException() != null) {
2bdf0193 480 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, provider.getException());
6e651d8b
MAL
481 }
482
483 return operation.getStatus();
484 }
485
486 @Override
487 public String queryOverwrite(String pathString) {
488 // We always overwrite once we reach this point
489 return null;
490 }
6e651d8b 491}
This page took 0.071546 seconds and 5 git commands to generate.