blob: 061ada238b938d292f76d2446c9e8c770d3c8037 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Xored Software Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.ecl.interop.internal.commands;
import static org.eclipse.rcptt.ecl.interop.internal.EclInteropPlugin.error;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.rcptt.ecl.core.Command;
import org.eclipse.rcptt.ecl.interop.ExecProcess;
import org.eclipse.rcptt.ecl.interop.ExecProcessResult;
import org.eclipse.rcptt.ecl.interop.InteropFactory;
import org.eclipse.rcptt.ecl.runtime.ICommandService;
import org.eclipse.rcptt.ecl.runtime.IProcess;
public class ExecProcessService implements ICommandService {
public IStatus service(Command command, IProcess context)
throws InterruptedException, CoreException {
ExecProcess cmd = (ExecProcess) command;
List<String> cmdArray = new ArrayList<String>();
cmdArray.add(cmd.getCommand());
for (String arg : cmd.getArgs())
cmdArray.add(arg);
Runtime runtime = Runtime.getRuntime();
ExecProcessResult result = InteropFactory.eINSTANCE
.createExecProcessResult();
try {
Process process = runtime.exec(
cmdArray.toArray(new String[cmdArray.size()]), null, null);
if (cmd.getStdin() != null && cmd.getStdin().length() > 0) {
Writer stdin = new BufferedWriter(new OutputStreamWriter(
process.getOutputStream()));
stdin.write(cmd.getStdin());
stdin.flush();
}
process.getOutputStream().close();
Executor executor = new Executor(process);
executor.start();
try {
if (cmd.getTimeout() > 0) {
executor.join(cmd.getTimeout() * 1000);
executor.interrupt(); // To sync exitCode and output streams
executor.join();
} else
executor.join();
if (executor.exitCode == null)
return error("Timeout period elapsed. Terminating.");
else {
result.setExitCode(process.exitValue());
result.setStdout(executor.stdout);
result.setStderr(executor.stderr);
if (!cmd.isIgnoreExitCode() && result.getExitCode() != 0)
return error("Execution failed, exit code: %s. stderr:\n %s",
result.getExitCode(), result.getStderr());
if (!cmd.isIgnoreStderr()
&& result.getStderr().length() > 0)
return error("Execution failed, stderr:\n%s.",
result.getStderr());
}
} catch (InterruptedException e) {
executor.interrupt();
return error(e.getMessage());
} finally {
process.destroy();
}
} catch (IOException e) {
return error(e.getMessage());
}
context.getOutput().write(result);
return Status.OK_STATUS;
}
private static class ReaderReader extends Thread {
private Reader reader;
private StringBuffer buffer;
private ReaderReader(Reader reader, StringBuffer buffer) {
this.reader = reader;
this.buffer = buffer;
}
@Override
public void run() {
char[] chars = new char[4 * 1024];
while (!isInterrupted()) {
try {
int read = reader.read(chars);
if (read == -1)
break;
buffer.append(chars, 0, read);
} catch (IOException e) {
break;
}
}
}
}
private static class Executor extends Thread {
private final Process process;
public Integer exitCode = null;
public String stdout = "";
public String stderr = "";
private Executor(Process process) {
this.process = process;
}
@Override
public void run() {
StringBuffer stdoutBuffer = new StringBuffer();
ReaderReader stdoutReader = new ReaderReader(new BufferedReader(
new InputStreamReader(process.getInputStream())),
stdoutBuffer);
StringBuffer stderrBuffer = new StringBuffer();
ReaderReader stderrReader = new ReaderReader(new BufferedReader(
new InputStreamReader(process.getErrorStream())),
stderrBuffer);
try {
stdoutReader.start();
stderrReader.start();
exitCode = process.waitFor();
stdoutReader.join();
stderrReader.join();
} catch (InterruptedException ignore) {
return;
} finally {
stdoutReader.interrupt();
stderrReader.interrupt();
stdout = stdoutBuffer.toString();
stderr = stderrBuffer.toString();
}
}
}
}