/*******************************************************************************
* Copyright (c) 2013 Zend Technologies.
* All rights reserved. This program and the accompanying materials
* are the copyright of Zend Technologies and is protected under
* copyright laws of the United States.
* You must not copy, adapt or redistribute this document for
* any use.
*******************************************************************************/
package org.zend.sdklib.internal.utils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.zend.sdklib.logger.ILogger;
import org.zend.sdklib.logger.Log;
/**
*
*/
public class CommandExecutor {
protected class MonitorCanceledJob extends Job {
private IProgressMonitor toMonitor;
private CommandExecutor cmd;
public MonitorCanceledJob(CommandExecutor cmd,
IProgressMonitor toMonitor) {
super("Cancel Process Job"); //$NON-NLS-1$
this.toMonitor = toMonitor;
this.cmd = cmd;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
while (cmd.process != null) {
if (toMonitor.isCanceled()) {
cmd.process.destroy();
break;
} else {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
cmd.log.error(e);
}
}
}
return org.eclipse.core.runtime.Status.OK_STATUS;
}
}
protected Process process;
protected ILogDevice ouputLogDevice;
protected ILogDevice errorLogDevice;
protected String workingDirectory;
protected Map<String, String> environmentVars;
protected StringBuffer commandOutput;
protected StringBuffer commandError;
protected AsyncStreamReader commandOutThread;
protected AsyncStreamReader commandErrorThread;
protected String[] command;
protected ILogger log;
public CommandExecutor() {
this.environmentVars = new HashMap<String, String>();
this.log = Log.getInstance().getLogger(this.getClass().getName());
}
public void setCommand(List<String> command) {
setCommand(command.toArray(new String[command.size()]));
}
public void setCommand(String... command) {
this.command = command;
}
public void setOutputLogDevice(ILogDevice logDevice) {
ouputLogDevice = logDevice;
}
public void setErrorLogDevice(ILogDevice logDevice) {
errorLogDevice = logDevice;
}
public void setWorkingDirectory(String workingDirectory) {
this.workingDirectory = workingDirectory;
}
public void setEnvironmentVar(String name, String value) {
if (environmentVars == null) {
environmentVars = new HashMap<String, String>();
}
environmentVars.put(name, value);
}
public String getCommandOutput() {
return commandOutput.toString();
}
public String getCommandError() {
return commandError.toString();
}
public int run() throws IOException {
return run(new NullProgressMonitor());
}
public int run(IProgressMonitor monitor) throws IOException {
process = runCommandHelper();
MonitorCanceledJob cancelJob = new MonitorCanceledJob(this, monitor);
cancelJob.setSystem(true);
cancelJob.schedule();
startOutputAndErrorReadThreads(process.getInputStream(),
process.getErrorStream());
updateLogDeviceOutputStream(process.getOutputStream());
int exitStatus = -1;
try {
exitStatus = process.waitFor();
} catch (InterruptedException e) {
log.error(e);
} finally {
process = null;
notifyOutputAndErrorReadThreadsToStopReading();
}
return exitStatus;
}
protected Process runCommandHelper() throws IOException {
ProcessBuilder pBuilder = new ProcessBuilder(command);
pBuilder.environment().putAll(getEnvTokens());
if (workingDirectory != null) {
pBuilder.directory(new File(workingDirectory));
}
return pBuilder.start();
}
protected void startOutputAndErrorReadThreads(InputStream processOut,
InputStream processErr) {
commandOutput = new StringBuffer();
commandOutThread = new AsyncStreamReader(processOut, commandOutput,
ouputLogDevice);
commandOutThread.start();
commandError = new StringBuffer();
commandErrorThread = new ErrorAsyncStreamReader(processErr,
commandError, errorLogDevice);
commandErrorThread.start();
}
protected void updateLogDeviceOutputStream(OutputStream outputStream) {
if (ouputLogDevice != null) {
ouputLogDevice.updateOutputStream(outputStream);
}
}
protected void notifyOutputAndErrorReadThreadsToStopReading() {
commandOutThread.stopReading();
commandErrorThread.stopReading();
}
protected Map<String, String> getEnvTokens() {
Map<String, String> currentVars = System.getenv();
Set<String> currentKeys = currentVars.keySet();
for (String key : currentKeys) {
if (!environmentVars.containsKey(key)) {
environmentVars.put(key, currentVars.get(key));
}
}
return environmentVars;
}
}