/*
* Copyright 2012-2014 eBay Software Foundation and selendroid committers.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package io.selendroid.standalone.io;
import io.selendroid.standalone.exceptions.DeviceOfflineException;
import io.selendroid.standalone.exceptions.ShellCommandException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.exec.*;
import org.apache.commons.exec.environment.EnvironmentUtils;
public class ShellCommand {
private static final Logger log = Logger.getLogger(ShellCommand.class.getName());
public static String exec(CommandLine commandLine) throws ShellCommandException {
return exec(commandLine, 20000);
}
public static String exec(CommandLine commandline, long timeoutInMillies)
throws ShellCommandException {
log.info("Executing shell command: " + commandline);
PrintingLogOutputStream outputStream = new PrintingLogOutputStream();
DefaultExecutor exec = new DefaultExecutor();
exec.setWatchdog(new ExecuteWatchdog(timeoutInMillies));
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
exec.setStreamHandler(streamHandler);
try {
exec.execute(commandline);
} catch (Exception e) {
log.log(Level.SEVERE, "Error executing command: " + commandline, e);
if (e.getMessage().contains("device offline")) {
throw new DeviceOfflineException(e);
}
throw new ShellCommandException(
"Error executing shell command: " + commandline, new ShellCommandException(outputStream.getOutput()));
}
String result = outputStream.getOutput().trim();
log.info("Shell command output\n-->\n" + result + "\n<--");
return result;
}
public static void execAsync(CommandLine commandline) throws ShellCommandException {
execAsync(null, commandline);
}
public static void execAsync(String display, CommandLine commandline)
throws ShellCommandException {
execAsync(display, commandline, null, null);
}
public static void execAsync(String display,
CommandLine commandline,
ExecuteStreamHandler streamHandler,
ExecuteResultHandler resultHandler)
throws ShellCommandException {
log.info("executing async command: " + commandline);
DefaultExecutor exec = new DefaultExecutor();
if (resultHandler == null) {
resultHandler = new DefaultExecuteResultHandler();
}
if (streamHandler == null) {
streamHandler = new PumpStreamHandler(new PrintingLogOutputStream());
}
exec.setStreamHandler(streamHandler);
try {
if (display == null || display.isEmpty()) {
exec.execute(commandline, resultHandler);
} else {
Map env = EnvironmentUtils.getProcEnvironment();
EnvironmentUtils.addVariableToEnvironment(env, "DISPLAY=:" + display);
exec.execute(commandline, env, resultHandler);
}
} catch (Exception e) {
log.log(Level.SEVERE, "Error executing command: " + commandline, e);
throw new ShellCommandException("Error executing shell command: " + commandline, e);
}
}
public static class PrintingLogOutputStream extends LogOutputStream {
private StringBuilder output = new StringBuilder();
@Override
protected void processLine(String line, int level) {
log.fine("OUTPUT FROM PROCESS: " + line);
output.append(line).append("\n");
}
public String getOutput() {
return output.toString();
}
}
}