tmf: Fix TestImportExportPackageWizard on Eclipse 4.6M5
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / internal / tmf / ui / project / wizards / tracepkg / importexport / TracePackageExportOperation.java
1 /*******************************************************************************
2 * Copyright (c) 2013, 2014 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.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
14
15 import java.io.ByteArrayInputStream;
16 import java.io.StringWriter;
17 import java.lang.reflect.InvocationTargetException;
18 import java.lang.reflect.Method;
19 import java.util.ArrayList;
20 import java.util.HashSet;
21 import java.util.Set;
22
23 import javax.xml.parsers.DocumentBuilderFactory;
24 import javax.xml.transform.OutputKeys;
25 import javax.xml.transform.Transformer;
26 import javax.xml.transform.TransformerFactory;
27 import javax.xml.transform.dom.DOMSource;
28 import javax.xml.transform.stream.StreamResult;
29
30 import org.eclipse.core.resources.IFile;
31 import org.eclipse.core.resources.IFolder;
32 import org.eclipse.core.resources.IMarker;
33 import org.eclipse.core.resources.IResource;
34 import org.eclipse.core.runtime.CoreException;
35 import org.eclipse.core.runtime.IPath;
36 import org.eclipse.core.runtime.IProgressMonitor;
37 import org.eclipse.core.runtime.IStatus;
38 import org.eclipse.core.runtime.Status;
39 import org.eclipse.core.runtime.SubMonitor;
40 import org.eclipse.jface.operation.ModalContext;
41 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
42 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageOperation;
43 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.ITracePackageConstants;
44 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageBookmarkElement;
45 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
46 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
47 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFileElement;
48 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFilesElement;
49 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
50 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
51 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
52 import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
53 import org.eclipse.ui.internal.wizards.datatransfer.ArchiveFileExportOperation;
54 import org.w3c.dom.Document;
55 import org.w3c.dom.Element;
56 import org.w3c.dom.Node;
57
58 /**
59 * An operation that exports a trace package to an archive
60 *
61 * @author Marc-Andre Laperle
62 */
63 @SuppressWarnings("restriction")
64 public class TracePackageExportOperation extends AbstractTracePackageOperation {
65
66 private static final String TRACE_EXPORT_TEMP_FOLDER = ".traceExport"; //$NON-NLS-1$
67
68 private final TracePackageTraceElement[] fTraceExportElements;
69 private final boolean fUseCompression;
70 private final boolean fUseTar;
71 private final Set<IResource> fResources;
72 private IFolder fExportFolder;
73
74 /**
75 * Constructs a new export operation
76 *
77 * @param traceExportElements
78 * the trace elements to be exported
79 * @param useCompression
80 * whether or not to use compression
81 * @param useTar
82 * use tar format or zip
83 * @param fileName
84 * the output file name
85 */
86 public TracePackageExportOperation(TracePackageTraceElement[] traceExportElements, boolean useCompression, boolean useTar, String fileName) {
87 super(fileName);
88 fTraceExportElements = traceExportElements;
89 fUseCompression = useCompression;
90 fUseTar = useTar;
91 fResources = new HashSet<>();
92 }
93
94 /**
95 * Run the operation. The status (result) of the operation can be obtained
96 * with {@link #getStatus}
97 *
98 * @param progressMonitor
99 * the progress monitor to use to display progress and receive
100 * requests for cancellation
101 */
102 @Override
103 public void run(IProgressMonitor progressMonitor) {
104
105 try {
106 int totalWork = getNbCheckedElements(fTraceExportElements) * 2;
107 progressMonitor.beginTask(Messages.TracePackageExportOperation_GeneratingPackage, totalWork);
108
109 fExportFolder = createExportFolder(progressMonitor);
110
111 Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
112 Element createElement = doc.createElement(ITracePackageConstants.TMF_EXPORT_ELEMENT);
113 Node tmfNode = doc.appendChild(createElement);
114
115 for (TracePackageTraceElement tracePackageElement : fTraceExportElements) {
116 if (!isFilesChecked(tracePackageElement)) {
117 continue;
118 }
119
120 exportTrace(progressMonitor, tmfNode, tracePackageElement);
121 }
122
123 Transformer transformer = TransformerFactory.newInstance().newTransformer();
124 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
125 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
126 DOMSource source = new DOMSource(doc);
127 StringWriter buffer = new StringWriter();
128 StreamResult result = new StreamResult(buffer);
129 transformer.transform(source, result);
130 String content = buffer.getBuffer().toString();
131
132 ModalContext.checkCanceled(progressMonitor);
133
134 exportManifest(content);
135
136 setStatus(exportToArchive(progressMonitor, totalWork));
137
138 fExportFolder.delete(true, SubMonitor.convert(progressMonitor));
139
140 progressMonitor.done();
141
142 } catch (InterruptedException e) {
143 setStatus(Status.CANCEL_STATUS);
144 } catch (Exception e) {
145 setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e));
146 }
147 }
148
149 private IFolder createExportFolder(IProgressMonitor monitor) throws CoreException {
150 IFolder folder = fTraceExportElements[0].getTraceElement().getProject().getResource().getFolder(TRACE_EXPORT_TEMP_FOLDER);
151 if (folder.exists()) {
152 folder.delete(true, null);
153 }
154 folder.create(IResource.FORCE | IResource.HIDDEN, true, SubMonitor.convert(monitor));
155 return folder;
156 }
157
158 private void exportTrace(IProgressMonitor monitor, Node tmfNode, TracePackageTraceElement tracePackageElement) throws InterruptedException, CoreException {
159 TmfTraceElement traceElement = tracePackageElement.getTraceElement();
160 Element traceXmlElement = tmfNode.getOwnerDocument().createElement(ITracePackageConstants.TRACE_ELEMENT);
161 traceXmlElement.setAttribute(ITracePackageConstants.TRACE_NAME_ATTRIB, traceElement.getResource().getName());
162 traceXmlElement.setAttribute(ITracePackageConstants.TRACE_TYPE_ATTRIB, traceElement.getTraceType());
163 Node traceNode = tmfNode.appendChild(traceXmlElement);
164
165 for (TracePackageElement element : tracePackageElement.getChildren()) {
166 ModalContext.checkCanceled(monitor);
167 if (!element.isChecked()) {
168 continue;
169 }
170
171 if (element instanceof TracePackageSupplFilesElement) {
172 exportSupplementaryFiles(monitor, traceNode, traceElement, (TracePackageSupplFilesElement) element);
173 } else if (element instanceof TracePackageBookmarkElement) {
174 exportBookmarks(monitor, traceNode, (TracePackageBookmarkElement) element);
175 } else if (element instanceof TracePackageFilesElement) {
176 exportTraceFiles(monitor, traceNode, (TracePackageFilesElement) element);
177 }
178
179 monitor.worked(1);
180 }
181 }
182
183 private void exportSupplementaryFiles(IProgressMonitor monitor, Node traceNode, TmfTraceElement traceElement, TracePackageSupplFilesElement element) throws InterruptedException, CoreException {
184 Document doc = traceNode.getOwnerDocument();
185 if (element.getChildren().length > 0) {
186
187 IPath projectPath = traceElement.getProject().getPath();
188
189 for (TracePackageElement child : element.getChildren()) {
190 TracePackageSupplFileElement supplFile = (TracePackageSupplFileElement) child;
191 ModalContext.checkCanceled(monitor);
192 IResource res = supplFile.getResource();
193 // project/.tracing/A/B/statistics.ht -> .tracing/A/B/statistics.ht
194 IPath relativeToExportFolder = res.getFullPath().makeRelativeTo(projectPath);
195
196 // project/.traceExport/.tracing/A/B
197 IFolder folder = fExportFolder.getFolder(relativeToExportFolder.removeLastSegments(1));
198 TraceUtils.createFolder(folder, SubMonitor.convert(monitor));
199
200 res.refreshLocal(0, SubMonitor.convert(monitor));
201 createExportResource(folder, res);
202 Element suppFileElement = doc.createElement(ITracePackageConstants.SUPPLEMENTARY_FILE_ELEMENT);
203
204 suppFileElement.setAttribute(ITracePackageConstants.SUPPLEMENTARY_FILE_NAME_ATTRIB, relativeToExportFolder.toString());
205 traceNode.appendChild(suppFileElement);
206 }
207
208 IFolder suppFilesFolder = fExportFolder.getFolder(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER_NAME);
209 fResources.add(suppFilesFolder);
210 }
211 }
212
213 private void exportTraceFiles(IProgressMonitor monitor, Node traceNode, TracePackageFilesElement element) throws CoreException {
214 Document doc = traceNode.getOwnerDocument();
215 TmfTraceElement traceElement = ((TracePackageTraceElement) element.getParent()).getTraceElement();
216 IResource resource = traceElement.getResource();
217 IPath traceFolderPath = traceElement.getProject().getTracesFolder().getPath();
218
219 // project/Traces/A/B/Kernel -> A/B/Kernel
220 IPath relativeToExportFolder = resource.getFullPath().makeRelativeTo(traceFolderPath);
221
222 // project/.traceExport/A/B
223 IFolder folder = fExportFolder.getFolder(relativeToExportFolder.removeLastSegments(1));
224 TraceUtils.createFolder(folder, SubMonitor.convert(monitor));
225
226 createExportResource(folder, resource);
227 Element fileElement = doc.createElement(ITracePackageConstants.TRACE_FILE_ELEMENT);
228
229 fileElement.setAttribute(ITracePackageConstants.TRACE_FILE_NAME_ATTRIB, relativeToExportFolder.toString());
230 traceNode.appendChild(fileElement);
231
232 // Always export the top-most folder containing the trace or the trace itself
233 IResource exportedResource = fExportFolder.findMember(relativeToExportFolder.segment(0));
234 fResources.add(exportedResource);
235 }
236
237 /**
238 * Creates a linked resource in the specified folder
239 *
240 * @param exportFolder the folder that will contain the linked resource
241 * @param res the resource to export
242 * @throws CoreException when createLink fails
243 * @return the created linked resource
244 */
245 private static IResource createExportResource(IFolder exportFolder, IResource res) throws CoreException {
246 IResource ret = null;
247 // Note: The resources cannot be HIDDEN or else they are ignored by ArchiveFileExportOperation
248 if (res instanceof IFolder) {
249 IFolder folder = exportFolder.getFolder(res.getName());
250 folder.createLink(res.getLocationURI(), IResource.NONE, null);
251 ret = folder;
252 } else if (res instanceof IFile) {
253 IFile file = exportFolder.getFile(res.getName());
254 file.createLink(res.getLocationURI(), IResource.NONE, null);
255 ret = file;
256 }
257 return ret;
258 }
259
260 private static void exportBookmarks(IProgressMonitor monitor, Node traceNode, TracePackageBookmarkElement element) throws CoreException, InterruptedException {
261 Document doc = traceNode.getOwnerDocument();
262 IFile bookmarksFile = ((TracePackageTraceElement) element.getParent()).getTraceElement().getBookmarksFile();
263 if (bookmarksFile != null && bookmarksFile.exists()) {
264 IMarker[] findMarkers = bookmarksFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
265 if (findMarkers.length > 0) {
266 Element bookmarksXmlElement = doc.createElement(ITracePackageConstants.BOOKMARKS_ELEMENT);
267 Node bookmarksNode = traceNode.appendChild(bookmarksXmlElement);
268
269 for (IMarker marker : findMarkers) {
270 ModalContext.checkCanceled(monitor);
271
272 Element singleBookmarkXmlElement = doc.createElement(ITracePackageConstants.BOOKMARK_ELEMENT);
273 for (String key : marker.getAttributes().keySet()) {
274 singleBookmarkXmlElement.setAttribute(key, marker.getAttribute(key).toString());
275 }
276
277 bookmarksNode.appendChild(singleBookmarkXmlElement);
278 }
279 }
280 }
281 }
282
283 private void exportManifest(String content) throws CoreException {
284 IFile file = fExportFolder.getFile(ITracePackageConstants.MANIFEST_FILENAME);
285 ByteArrayInputStream inputStream = new ByteArrayInputStream(content.getBytes());
286 if (file.exists()) {
287 file.setContents(inputStream, IResource.FORCE, null);
288 } else {
289 file.create(inputStream, IResource.FORCE | IResource.HIDDEN, null);
290 }
291 fResources.add(file);
292 }
293
294 private IStatus exportToArchive(IProgressMonitor monitor, int totalWork) throws InvocationTargetException, InterruptedException {
295 ArchiveFileExportOperation op = new ArchiveFileExportOperation(new ArrayList<>(fResources), getFileName());
296 op.setCreateLeadupStructure(false);
297 //FIXME: Remove use of reflection when support for Eclipse 4.5 is dropped
298 try {
299 Method method = op.getClass().getMethod("setIncludeLinkedResources", boolean.class); //$NON-NLS-1$
300 method.invoke(op, true);
301 } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException e) {
302 // Ignored, setIncludeLinkedResources doesn't exist in Eclipse < 4.6
303 }
304 op.setUseCompression(fUseCompression);
305 op.setUseTarFormat(fUseTar);
306 op.run(SubMonitor.convert(monitor).newChild(totalWork / 2));
307
308 return op.getStatus();
309 }
310 }
This page took 0.039887 seconds and 5 git commands to generate.