1 /*******************************************************************************
2 * Copyright (c) 2013 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
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.importexport
;
15 import java
.io
.ByteArrayInputStream
;
16 import java
.io
.StringWriter
;
17 import java
.lang
.reflect
.InvocationTargetException
;
18 import java
.util
.ArrayList
;
19 import java
.util
.HashSet
;
22 import javax
.xml
.parsers
.DocumentBuilderFactory
;
23 import javax
.xml
.transform
.OutputKeys
;
24 import javax
.xml
.transform
.Transformer
;
25 import javax
.xml
.transform
.TransformerFactory
;
26 import javax
.xml
.transform
.dom
.DOMSource
;
27 import javax
.xml
.transform
.stream
.StreamResult
;
29 import org
.eclipse
.core
.resources
.IFile
;
30 import org
.eclipse
.core
.resources
.IFolder
;
31 import org
.eclipse
.core
.resources
.IMarker
;
32 import org
.eclipse
.core
.resources
.IResource
;
33 import org
.eclipse
.core
.runtime
.CoreException
;
34 import org
.eclipse
.core
.runtime
.IPath
;
35 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
36 import org
.eclipse
.core
.runtime
.IStatus
;
37 import org
.eclipse
.core
.runtime
.Status
;
38 import org
.eclipse
.core
.runtime
.SubProgressMonitor
;
39 import org
.eclipse
.jface
.operation
.ModalContext
;
40 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Activator
;
41 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.AbstractTracePackageOperation
;
42 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.ITracePackageConstants
;
43 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageBookmarkElement
;
44 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageElement
;
45 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageFilesElement
;
46 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageSupplFileElement
;
47 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageSupplFilesElement
;
48 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.TracePackageTraceElement
;
49 import org
.eclipse
.linuxtools
.tmf
.core
.TmfCommonConstants
;
50 import org
.eclipse
.linuxtools
.tmf
.ui
.project
.model
.TmfTraceElement
;
51 import org
.eclipse
.linuxtools
.tmf
.ui
.project
.model
.TmfTraceFolder
;
52 import org
.eclipse
.ui
.internal
.wizards
.datatransfer
.ArchiveFileExportOperation
;
53 import org
.w3c
.dom
.Document
;
54 import org
.w3c
.dom
.Element
;
55 import org
.w3c
.dom
.Node
;
58 * An operation that exports a trace package to an archive
60 * @author Marc-Andre Laperle
62 @SuppressWarnings("restriction")
63 public class TracePackageExportOperation
extends AbstractTracePackageOperation
{
65 private static final String TRACE_EXPORT_TEMP_FOLDER
= ".traceExport"; //$NON-NLS-1$
67 private final TracePackageTraceElement
[] fTraceExportElements
;
68 private final boolean fUseCompression
;
69 private final boolean fUseTar
;
70 private final Set
<IResource
> fResources
;
71 private IFolder fExportFolder
;
74 * Constructs a new export operation
76 * @param traceExportElements
77 * the trace elements to be exported
78 * @param useCompression
79 * whether or not to use compression
81 * use tar format or zip
83 * the output file name
85 public TracePackageExportOperation(TracePackageTraceElement
[] traceExportElements
, boolean useCompression
, boolean useTar
, String fileName
) {
87 fTraceExportElements
= traceExportElements
;
88 fUseCompression
= useCompression
;
90 fResources
= new HashSet
<>();
94 * Run the operation. The status (result) of the operation can be obtained
95 * with {@link #getStatus}
97 * @param progressMonitor
98 * the progress monitor to use to display progress and receive
99 * requests for cancellation
102 public void run(IProgressMonitor progressMonitor
) {
105 int totalWork
= getNbCheckedElements(fTraceExportElements
) * 2;
106 progressMonitor
.beginTask(Messages
.TracePackageExportOperation_GeneratingPackage
, totalWork
);
108 fExportFolder
= createExportFolder(progressMonitor
);
110 Document doc
= DocumentBuilderFactory
.newInstance().newDocumentBuilder().newDocument();
111 Element createElement
= doc
.createElement(ITracePackageConstants
.TMF_EXPORT_ELEMENT
);
112 Node tmfNode
= doc
.appendChild(createElement
);
114 for (TracePackageTraceElement tracePackageElement
: fTraceExportElements
) {
115 if (!isFilesChecked(tracePackageElement
)) {
119 exportTrace(progressMonitor
, tmfNode
, tracePackageElement
);
122 Transformer transformer
= TransformerFactory
.newInstance().newTransformer();
123 transformer
.setOutputProperty(OutputKeys
.INDENT
, "yes"); //$NON-NLS-1$
124 transformer
.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
125 DOMSource source
= new DOMSource(doc
);
126 StringWriter buffer
= new StringWriter();
127 StreamResult result
= new StreamResult(buffer
);
128 transformer
.transform(source
, result
);
129 String content
= buffer
.getBuffer().toString();
131 ModalContext
.checkCanceled(progressMonitor
);
133 exportManifest(content
);
135 setStatus(exportToArchive(progressMonitor
, totalWork
));
137 fExportFolder
.delete(true, new SubProgressMonitor(progressMonitor
, 1, SubProgressMonitor
.PREPEND_MAIN_LABEL_TO_SUBTASK
));
139 progressMonitor
.done();
141 } catch (Exception e
) {
142 if (e
instanceof InterruptedException
) {
143 setStatus(Status
.CANCEL_STATUS
);
145 setStatus(new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, org
.eclipse
.linuxtools
.internal
.tmf
.ui
.project
.wizards
.tracepkg
.Messages
.TracePackage_ErrorOperation
, e
));
150 private IFolder
createExportFolder(IProgressMonitor monitor
) throws CoreException
{
151 IFolder folder
= fTraceExportElements
[0].getTraceElement().getProject().getResource().getFolder(TRACE_EXPORT_TEMP_FOLDER
);
152 if (folder
.exists()) {
153 folder
.delete(true, null);
155 folder
.create(IResource
.FORCE
| IResource
.HIDDEN
, true, new SubProgressMonitor(monitor
, 1, SubProgressMonitor
.PREPEND_MAIN_LABEL_TO_SUBTASK
));
159 private void exportTrace(IProgressMonitor monitor
, Node tmfNode
, TracePackageTraceElement tracePackageElement
) throws InterruptedException
, CoreException
{
160 TmfTraceElement traceElement
= tracePackageElement
.getTraceElement();
161 Element traceXmlElement
= tmfNode
.getOwnerDocument().createElement(ITracePackageConstants
.TRACE_ELEMENT
);
162 traceXmlElement
.setAttribute(ITracePackageConstants
.TRACE_NAME_ATTRIB
, traceElement
.getResource().getName());
163 traceXmlElement
.setAttribute(ITracePackageConstants
.TRACE_TYPE_ATTRIB
, traceElement
.getTraceType());
164 Node traceNode
= tmfNode
.appendChild(traceXmlElement
);
166 for (TracePackageElement element
: tracePackageElement
.getChildren()) {
167 ModalContext
.checkCanceled(monitor
);
168 if (!element
.isChecked()) {
172 if (element
instanceof TracePackageSupplFilesElement
) {
173 exportSupplementaryFiles(monitor
, traceNode
, traceElement
, (TracePackageSupplFilesElement
) element
);
174 } else if (element
instanceof TracePackageBookmarkElement
) {
175 exportBookmarks(monitor
, traceNode
, (TracePackageBookmarkElement
) element
);
176 } else if (element
instanceof TracePackageFilesElement
) {
177 exportTraceFiles(monitor
, traceNode
, (TracePackageFilesElement
) element
);
184 private void exportSupplementaryFiles(IProgressMonitor monitor
, Node traceNode
, TmfTraceElement traceElement
, TracePackageSupplFilesElement element
) throws InterruptedException
, CoreException
{
185 Document doc
= traceNode
.getOwnerDocument();
186 if (element
.getChildren().length
> 0) {
187 IFolder suppFilesFolder
= fExportFolder
.getFolder(TmfCommonConstants
.TRACE_SUPPLEMENTARY_FOLDER_NAME
);
188 if (!suppFilesFolder
.exists()) {
189 suppFilesFolder
.create(IResource
.FORCE
, true, new SubProgressMonitor(monitor
, 1, SubProgressMonitor
.PREPEND_MAIN_LABEL_TO_SUBTASK
));
191 IFolder traceSuppFilesFolder
= suppFilesFolder
.getFolder(traceElement
.getResource().getName());
192 traceSuppFilesFolder
.create(IResource
.FORCE
, true, new SubProgressMonitor(monitor
, 1, SubProgressMonitor
.PREPEND_MAIN_LABEL_TO_SUBTASK
));
194 for (TracePackageElement child
: element
.getChildren()) {
195 TracePackageSupplFileElement supplFile
= (TracePackageSupplFileElement
) child
;
196 ModalContext
.checkCanceled(monitor
);
197 IResource res
= supplFile
.getResource();
198 res
.refreshLocal(0, new SubProgressMonitor(monitor
, 1, SubProgressMonitor
.PREPEND_MAIN_LABEL_TO_SUBTASK
));
199 IResource link
= createExportResource(traceSuppFilesFolder
, res
);
200 Element suppFileElement
= doc
.createElement(ITracePackageConstants
.SUPPLEMENTARY_FILE_ELEMENT
);
202 // project/.traceExport/.tracing/kernel/statistics.ht -> .tracing/kernel/statistics.ht
203 IPath archiveRelativePath
= link
.getFullPath().makeRelativeTo(fExportFolder
.getFullPath());
205 suppFileElement
.setAttribute(ITracePackageConstants
.SUPPLEMENTARY_FILE_NAME_ATTRIB
, archiveRelativePath
.toString());
206 traceNode
.appendChild(suppFileElement
);
209 fResources
.add(suppFilesFolder
);
213 private void exportTraceFiles(IProgressMonitor monitor
, Node traceNode
, TracePackageFilesElement element
) throws CoreException
{
214 Document doc
= traceNode
.getOwnerDocument();
215 IResource resource
= ((TracePackageTraceElement
) element
.getParent()).getTraceElement().getResource();
216 IFolder folder
= fExportFolder
.getFolder(TmfTraceFolder
.TRACE_FOLDER_NAME
);
217 if (!folder
.exists()) {
218 folder
.create(IResource
.FORCE
, true, new SubProgressMonitor(monitor
, 1, SubProgressMonitor
.PREPEND_MAIN_LABEL_TO_SUBTASK
));
221 IResource link
= createExportResource(folder
, resource
);
222 Element fileElement
= doc
.createElement(ITracePackageConstants
.TRACE_FILE_ELEMENT
);
223 // project/.traceExport/Traces/kernel -> Traces/kernel
224 IPath archiveRelativePath
= link
.getFullPath().makeRelativeTo(fExportFolder
.getFullPath());
225 fileElement
.setAttribute(ITracePackageConstants
.TRACE_FILE_NAME_ATTRIB
, archiveRelativePath
.toString());
226 traceNode
.appendChild(fileElement
);
227 fResources
.add(folder
);
231 * Creates a linked resource in the specified folder
233 * @param exportFolder the folder that will contain the linked resource
234 * @param res the resource to export
235 * @throws CoreException when createLink fails
236 * @return the created linked resource
238 private static IResource
createExportResource(IFolder exportFolder
, IResource res
) throws CoreException
{
239 IResource ret
= null;
240 // Note: The resources cannot be HIDDEN or else they are ignored by ArchiveFileExportOperation
241 if (res
instanceof IFolder
) {
242 IFolder folder
= exportFolder
.getFolder(res
.getName());
243 folder
.createLink(res
.getLocationURI(), IResource
.NONE
, null);
245 } else if (res
instanceof IFile
) {
246 IFile file
= exportFolder
.getFile(res
.getName());
247 file
.createLink(res
.getLocationURI(), IResource
.NONE
, null);
253 private static void exportBookmarks(IProgressMonitor monitor
, Node traceNode
, TracePackageBookmarkElement element
) throws CoreException
, InterruptedException
{
254 Document doc
= traceNode
.getOwnerDocument();
255 IFile bookmarksFile
= ((TracePackageTraceElement
) element
.getParent()).getTraceElement().getBookmarksFile();
256 if (bookmarksFile
!= null && bookmarksFile
.exists()) {
257 IMarker
[] findMarkers
= bookmarksFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
258 if (findMarkers
.length
> 0) {
259 Element bookmarksXmlElement
= doc
.createElement(ITracePackageConstants
.BOOKMARKS_ELEMENT
);
260 Node bookmarksNode
= traceNode
.appendChild(bookmarksXmlElement
);
262 for (IMarker marker
: findMarkers
) {
263 ModalContext
.checkCanceled(monitor
);
265 Element singleBookmarkXmlElement
= doc
.createElement(ITracePackageConstants
.BOOKMARK_ELEMENT
);
266 for (String key
: marker
.getAttributes().keySet()) {
267 singleBookmarkXmlElement
.setAttribute(key
, marker
.getAttribute(key
).toString());
270 bookmarksNode
.appendChild(singleBookmarkXmlElement
);
276 private void exportManifest(String content
) throws CoreException
{
277 IFile file
= fExportFolder
.getFile(ITracePackageConstants
.MANIFEST_FILENAME
);
278 ByteArrayInputStream inputStream
= new ByteArrayInputStream(content
.getBytes());
280 file
.setContents(inputStream
, IResource
.FORCE
, null);
282 file
.create(inputStream
, IResource
.FORCE
| IResource
.HIDDEN
, null);
284 fResources
.add(file
);
287 private IStatus
exportToArchive(IProgressMonitor monitor
, int totalWork
) throws InvocationTargetException
, InterruptedException
{
288 ArchiveFileExportOperation op
= new ArchiveFileExportOperation(new ArrayList
<>(fResources
), getFileName());
289 op
.setCreateLeadupStructure(false);
290 op
.setUseCompression(fUseCompression
);
291 op
.setUseTarFormat(fUseTar
);
292 op
.run(new SubProgressMonitor(monitor
, totalWork
/ 2, SubProgressMonitor
.PREPEND_MAIN_LABEL_TO_SUBTASK
));
294 return op
.getStatus();