tmf: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.remote.ui / src / org / eclipse / tracecompass / internal / tmf / remote / ui / wizards / fetch / model / RemoteImportTracesOperation.java
1 /*******************************************************************************
2 * Copyright (c) 2015 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 * Bernd Hufmann - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.internal.tmf.remote.ui.wizards.fetch.model;
14
15 import java.io.FileOutputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.lang.reflect.InvocationTargetException;
20 import java.net.URI;
21 import java.util.Arrays;
22
23 import org.eclipse.core.commands.ExecutionException;
24 import org.eclipse.core.filesystem.EFS;
25 import org.eclipse.core.filesystem.IFileInfo;
26 import org.eclipse.core.filesystem.IFileStore;
27 import org.eclipse.core.resources.IFolder;
28 import org.eclipse.core.resources.IResource;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.core.runtime.IPath;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.IStatus;
33 import org.eclipse.core.runtime.NullProgressMonitor;
34 import org.eclipse.core.runtime.Path;
35 import org.eclipse.core.runtime.Status;
36 import org.eclipse.core.runtime.SubMonitor;
37 import org.eclipse.core.runtime.URIUtil;
38 import org.eclipse.jface.operation.ModalContext;
39 import org.eclipse.osgi.util.NLS;
40 import org.eclipse.swt.widgets.Shell;
41 import org.eclipse.tracecompass.internal.tmf.remote.ui.Activator;
42 import org.eclipse.tracecompass.internal.tmf.remote.ui.messages.RemoteMessages;
43 import org.eclipse.tracecompass.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
44 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.ImportConfirmation;
45 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.ImportConflictHandler;
46 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
47 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
48 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
49 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceCoreUtils;
50 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
51 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
52 import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
53 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
54 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
55 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder;
56 import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
57
58 /**
59 * Operation to import a set of traces from a remote node into a tracing project.
60 *
61 * @author Bernd Hufmann
62 */
63 public class RemoteImportTracesOperation extends TmfWorkspaceModifyOperation {
64
65 // ------------------------------------------------------------------------
66 // Constants
67 // ------------------------------------------------------------------------
68 private static final int BUFFER_IN_KB = 16;
69 private static final int BYTES_PER_KB = 1024;
70
71 // ------------------------------------------------------------------------
72 // Attributes
73 // ------------------------------------------------------------------------
74 private IStatus fStatus;
75 private final Shell fShell;
76 private final TmfTraceFolder fDestination;
77 private final Object[] fTraceElements;
78 private final ImportConflictHandler fConflictHandler;
79
80 // ------------------------------------------------------------------------
81 // Constructor(s)
82 // ------------------------------------------------------------------------
83 /**
84 * Operation to import a set of traces from a remote node into a tracing project.
85 * @param shell
86 * shell to display confirmation dialog
87 * @param destination
88 * The destination traces folder
89 * @param elements
90 * The trace model elements describing the traces to import
91 * @param overwriteAll
92 * Flag to indicate to overwrite all existing traces
93 */
94 public RemoteImportTracesOperation(Shell shell, TmfTraceFolder destination, Object[] elements, boolean overwriteAll) {
95 super();
96 fShell = shell;
97 fDestination = destination;
98 fTraceElements = Arrays.copyOf(elements, elements.length);
99 if (overwriteAll) {
100 fConflictHandler = new ImportConflictHandler(fShell, destination, ImportConfirmation.OVERWRITE_ALL);
101 } else {
102 fConflictHandler = new ImportConflictHandler(fShell, destination, ImportConfirmation.SKIP);
103 }
104 }
105
106 // ------------------------------------------------------------------------
107 // Operations
108 // ------------------------------------------------------------------------
109 @Override
110 protected void execute(IProgressMonitor monitor) throws CoreException,
111 InvocationTargetException, InterruptedException {
112
113 try {
114 doRun(monitor);
115 setStatus(Status.OK_STATUS);
116 } catch (InterruptedException e) {
117 setStatus(Status.CANCEL_STATUS);
118 throw e;
119 } catch (Exception e) {
120 setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, RemoteMessages.RemoteImportTracesOperation_ImportFailure, e));
121 throw new InvocationTargetException(e);
122 }
123 }
124
125 // ------------------------------------------------------------------------
126 // Helper methods
127 // ------------------------------------------------------------------------
128 private void doRun(IProgressMonitor monitor) throws ExecutionException, CoreException, IOException, InterruptedException {
129
130 IFolder destinationFolder = fDestination.getResource();
131 if (!destinationFolder.exists()) {
132 throw new ExecutionException(RemoteMessages.RemoteImportTracesOperation_ImportDialogInvalidTracingProject + " (" + TmfTracesFolder.TRACES_FOLDER_NAME + ")"); //$NON-NLS-1$//$NON-NLS-2$
133 }
134
135 SubMonitor subMonitor = SubMonitor.convert(monitor, fTraceElements.length * 4);
136 subMonitor.beginTask(RemoteMessages.RemoteImportTracesOperation_DownloadTask, fTraceElements.length * 4);
137
138 for (Object packageElement : fTraceElements) {
139 if (!(packageElement instanceof TracePackageTraceElement)) {
140 continue;
141 }
142 TracePackageTraceElement traceElement = (TracePackageTraceElement) packageElement;
143 TracePackageElement parentElement = traceElement.getParent();
144 while (parentElement != null) {
145 if (parentElement instanceof RemoteImportTraceGroupElement) {
146 break;
147 }
148 parentElement = parentElement.getParent();
149 }
150
151 if (parentElement == null) {
152 continue;
153 }
154
155 RemoteImportTraceGroupElement traceGroup = (RemoteImportTraceGroupElement) parentElement;
156 String rootPath = traceGroup.getRootImportPath();
157
158 // Create folder with node name in destination folder
159 RemoteImportConnectionNodeElement nodeElement = (RemoteImportConnectionNodeElement) traceGroup.getParent();
160 String nodeName = nodeElement.getName();
161 IFolder nodeFolder = destinationFolder.getFolder(nodeName);
162
163 TracePackageElement[] children = traceElement.getChildren();
164 SubMonitor childMonitor = subMonitor.newChild(1);
165 TraceUtils.createFolder(nodeFolder, childMonitor);
166
167 for (TracePackageElement element : children) {
168 ModalContext.checkCanceled(monitor);
169
170 if (element instanceof RemoteImportTraceFilesElement) {
171 RemoteImportTraceFilesElement traceFilesElement = (RemoteImportTraceFilesElement) element;
172
173 IFileStore remoteFile = traceFilesElement.getRemoteFile();
174
175 // Preserve folder structure
176 IPath sessionParentPath = TmfTraceCoreUtils.newSafePath(rootPath);
177 IPath traceParentPath = TmfTraceCoreUtils.newSafePath(remoteFile.getParent().toURI().getPath());
178 IPath relativeTracePath = Path.EMPTY;
179 if (sessionParentPath.isPrefixOf(traceParentPath)) {
180 relativeTracePath = traceParentPath.makeRelativeTo(sessionParentPath);
181 }
182
183 String[] segments = relativeTracePath.segments();
184 for (int i = 0; i < segments.length; i++) {
185 String segment = TmfTraceCoreUtils.validateName(TmfTraceCoreUtils.safePathToString(segments[i]));
186 if (i == 0) {
187 relativeTracePath = new Path(segment);
188 } else {
189 relativeTracePath = relativeTracePath.append(segment);
190 }
191 }
192
193 IFolder traceFolder = nodeFolder.getFolder(new Path(relativeTracePath.toOSString()));
194 childMonitor = subMonitor.newChild(1);
195 TraceUtils.createFolder(traceFolder, childMonitor);
196 childMonitor.done();
197
198 // Import trace
199 IResource traceRes = null;
200 IFileInfo info = remoteFile.fetchInfo();
201 if (info.isDirectory()) {
202 traceRes = downloadDirectoryTrace(remoteFile, traceFolder, subMonitor.newChild(1));
203 } else {
204 traceRes = downloadFileTrace(remoteFile, traceFolder, subMonitor.newChild(1));
205 }
206
207 String traceName = traceElement.getText();
208 if (traceRes == null || !traceRes.exists()) {
209 continue;
210 }
211
212 // Select trace type
213 TraceTypeHelper traceTypeHelper = null;
214 String traceTypeStr = traceElement.getTraceType();
215 if (traceTypeStr != null) {
216 traceTypeHelper = TmfTraceType.getTraceType(traceTypeStr);
217 }
218
219 // no specific trace type found
220 if (traceTypeHelper == null) {
221 try {
222 // Try to auto-detect the trace typ
223 childMonitor = subMonitor.newChild(1);
224 childMonitor.setTaskName(NLS.bind(RemoteMessages.RemoteImportTracesOperation_DetectingTraceType, traceName));
225 childMonitor.done();
226 traceTypeHelper = TmfTraceTypeUIUtils.selectTraceType(traceRes.getLocation().toOSString(), null, null);
227 } catch (TmfTraceImportException e) {
228 //Could not figure out the type
229 }
230 }
231
232 if (traceTypeHelper != null) {
233 TmfTraceTypeUIUtils.setTraceType(traceRes, traceTypeHelper);
234 }
235
236 // Set source location
237 URI uri = remoteFile.toURI();
238 String sourceLocation = URIUtil.toUnencodedString(uri);
239 traceRes.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
240 }
241 }
242 }
243 }
244
245 // Download a directory trace
246 private IResource downloadDirectoryTrace(IFileStore trace, IFolder traceFolder, IProgressMonitor monitor) throws CoreException, IOException, InterruptedException {
247
248 IFileStore[] sources = trace.childStores(EFS.NONE, monitor);
249
250 // Don't import just the metadata file
251 if (sources.length > 1) {
252 String traceName = trace.getName();
253
254 traceName = TmfTraceCoreUtils.validateName(traceName);
255
256 IFolder folder = traceFolder.getFolder(traceName);
257 String newName = fConflictHandler.checkAndHandleNameClash(folder.getFullPath(), monitor);
258 if (newName == null) {
259 return null;
260 }
261
262 folder = traceFolder.getFolder(newName);
263 folder.create(true, true, null);
264
265 SubMonitor subMonitor = SubMonitor.convert(monitor, sources.length);
266 subMonitor.beginTask(RemoteMessages.RemoteImportTracesOperation_DownloadTask, sources.length);
267
268 for (IFileStore source : sources) {
269 if (subMonitor.isCanceled()) {
270 throw new InterruptedException();
271 }
272
273 IPath destination = folder.getLocation().addTrailingSeparator().append(source.getName());
274 IFileInfo info = source.fetchInfo();
275 // TODO allow for downloading index directory and files
276 if (!info.isDirectory()) {
277 SubMonitor childMonitor = subMonitor.newChild(1);
278 childMonitor.setTaskName(RemoteMessages.RemoteImportTracesOperation_DownloadTask + ' ' + trace.getName()+ '/' + source.getName());
279
280 try (InputStream in = source.openInputStream(EFS.NONE, new NullProgressMonitor())) {
281 copy(in, destination, childMonitor, info.getLength());
282 }
283 }
284 }
285 folder.refreshLocal(IResource.DEPTH_INFINITE, null);
286 return folder;
287 }
288 return null;
289 }
290
291 // Download file trace
292 private IResource downloadFileTrace(IFileStore trace, IFolder traceFolder, IProgressMonitor monitor) throws CoreException, IOException, InterruptedException {
293
294 IFolder folder = traceFolder;
295 String traceName = trace.getName();
296
297 traceName = TmfTraceCoreUtils.validateName(traceName);
298
299 IResource resource = folder.findMember(traceName);
300 if ((resource != null) && resource.exists()) {
301 String newName = fConflictHandler.checkAndHandleNameClash(resource.getFullPath(), monitor);
302 if (newName == null) {
303 return null;
304 }
305 traceName = newName;
306 }
307 SubMonitor subMonitor = SubMonitor.convert(monitor, 1);
308 subMonitor.beginTask(RemoteMessages.RemoteImportTracesOperation_DownloadTask, 1);
309
310 IPath destination = folder.getLocation().addTrailingSeparator().append(traceName);
311 IFileInfo info = trace.fetchInfo();
312 subMonitor.setTaskName(RemoteMessages.RemoteImportTracesOperation_DownloadTask + ' ' + trace.getName()+ '/' +trace.getName());
313 try (InputStream in = trace.openInputStream(EFS.NONE, new NullProgressMonitor())) {
314 copy(in, destination, subMonitor, info.getLength());
315 }
316 folder.refreshLocal(IResource.DEPTH_INFINITE, null);
317 return folder.findMember(traceName);
318 }
319
320
321 private static void copy(InputStream in, IPath destination, SubMonitor monitor, long length) throws IOException {
322 try (OutputStream out = new FileOutputStream(destination.toFile())) {
323 monitor.setWorkRemaining((int) (length / BYTES_PER_KB));
324 byte[] buf = new byte[BYTES_PER_KB * BUFFER_IN_KB];
325 int counter = 0;
326 for (;;) {
327 int n = in.read(buf);
328 if (n <= 0) {
329 return;
330 }
331 out.write(buf, 0, n);
332 counter = (counter % BYTES_PER_KB) + n;
333 monitor.worked(counter / BYTES_PER_KB);
334 }
335 }
336 }
337
338 /**
339 * Set the result status for this operation
340 *
341 * @param status
342 * the status
343 */
344 protected void setStatus(IStatus status) {
345 fStatus = status;
346 }
347
348 /**
349 * Gets the result of the operation.
350 *
351 * @return result status of operation
352 */
353 public IStatus getStatus() {
354 return fStatus;
355 }
356 }
This page took 0.039946 seconds and 6 git commands to generate.