analysis: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.remote.core / src / org / eclipse / tracecompass / internal / tmf / remote / core / shell / CommandShell.java
1 /**********************************************************************
2 * Copyright (c) 2012, 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 * Patrick Tasse - Initial API and implementation
11 * Bernd Hufmann - Updated using Executor Framework
12 * Markus Schorn - Bug 448058: Use org.eclipse.remote in favor of RSE
13 * Bernd Hufmann - Update to org.eclipse.remote API 2.0
14 **********************************************************************/
15 package org.eclipse.tracecompass.internal.tmf.remote.core.shell;
16
17 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
18
19 import java.io.IOException;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.ExecutorService;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.FutureTask;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.TimeoutException;
26
27 import org.eclipse.core.commands.ExecutionException;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.core.runtime.NullProgressMonitor;
30 import org.eclipse.core.runtime.OperationCanceledException;
31 import org.eclipse.jdt.annotation.NonNull;
32 import org.eclipse.remote.core.IRemoteConnection;
33 import org.eclipse.remote.core.IRemoteProcess;
34 import org.eclipse.remote.core.IRemoteProcessService;
35 import org.eclipse.tracecompass.internal.tmf.remote.core.messages.Messages;
36 import org.eclipse.tracecompass.internal.tmf.remote.core.preferences.TmfRemotePreferences;
37 import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandInput;
38 import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandResult;
39 import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandShell;
40
41 /**
42 * <p>
43 * Implementation of remote command execution using IRemoteConnection.
44 * </p>
45 *
46 * @author Patrick Tasse
47 * @author Bernd Hufmann
48 */
49 public class CommandShell implements ICommandShell {
50
51 // ------------------------------------------------------------------------
52 // Attributes
53 // ------------------------------------------------------------------------
54 private final IRemoteConnection fConnection;
55 private final ExecutorService fExecutor = checkNotNull(Executors.newFixedThreadPool(1));
56
57 // ------------------------------------------------------------------------
58 // Constructors
59 // ------------------------------------------------------------------------
60
61 /**
62 * Create a new command shell
63 *
64 * @param connection the remote connection for this shell
65 */
66 public CommandShell(IRemoteConnection connection) {
67 fConnection = connection;
68 }
69
70 // ------------------------------------------------------------------------
71 // Operations
72 // ------------------------------------------------------------------------
73
74 @Override
75 public void dispose() {
76 fExecutor.shutdown();
77 }
78
79 @Override
80 public ICommandInput createCommand() {
81 return new CommandInput();
82 }
83
84 @Override
85 public ICommandResult executeCommand(final ICommandInput command, final IProgressMonitor aMonitor) throws ExecutionException {
86 if (fConnection.isOpen()) {
87 FutureTask<CommandResult> future = new FutureTask<>(new Callable<CommandResult>() {
88 @Override
89 public CommandResult call() throws IOException, InterruptedException {
90 IProgressMonitor monitor = aMonitor;
91 if (monitor == null) {
92 monitor = new NullProgressMonitor();
93 }
94 if (!monitor.isCanceled()) {
95 IRemoteProcess process = fConnection.getService(IRemoteProcessService.class).getProcessBuilder(command.getInput()).start();
96 InputReader stdout = new InputReader(checkNotNull(process.getInputStream()));
97 InputReader stderr = new InputReader(checkNotNull(process.getErrorStream()));
98
99 try {
100 stdout.waitFor(monitor);
101 stderr.waitFor(monitor);
102 if (!monitor.isCanceled()) {
103 return createResult(process.waitFor(), stdout.toString(), stderr.toString());
104 }
105 } catch (OperationCanceledException e) {
106 } catch (InterruptedException e) {
107 return new CommandResult(1, new String[0], new String[] {e.getMessage()});
108 } finally {
109 stdout.stop();
110 stderr.stop();
111 process.destroy();
112 }
113 }
114 return new CommandResult(1, new String[0], new String[] {"cancelled"}); //$NON-NLS-1$
115 }
116 });
117
118 fExecutor.execute(future);
119
120 try {
121 return checkNotNull(future.get(TmfRemotePreferences.getCommandTimeout(), TimeUnit.SECONDS));
122 } catch (InterruptedException ex) {
123 throw new ExecutionException(Messages.RemoteConnection_ExecutionCancelled, ex);
124 } catch (TimeoutException ex) {
125 throw new ExecutionException(Messages.RemoteConnection_ExecutionTimeout, ex);
126 } catch (Exception ex) {
127 throw new ExecutionException(Messages.RemoteConnection_ExecutionFailure, ex);
128 }
129 finally {
130 future.cancel(true);
131 }
132 }
133 throw new ExecutionException(Messages.RemoteConnection_ShellNotConnected, null);
134 }
135
136 // ------------------------------------------------------------------------
137 // Helper methods
138 // ------------------------------------------------------------------------
139
140 private static CommandResult createResult(int origResult, String origStdout, String origStderr) {
141 final int result;
142 final String stdout, stderr;
143 result = origResult;
144 stdout = origStdout;
145 stderr = origStderr;
146 String[] output = splitLines(stdout);
147 String[] error = splitLines(stderr);
148 return new CommandResult(result, output, error);
149 }
150
151 private static @NonNull String[] splitLines(String output) {
152 return checkNotNull(output.split("\\r?\\n")); //$NON-NLS-1$
153 }
154 }
This page took 0.034651 seconds and 5 git commands to generate.