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