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