Removed dependency on 'org.apache.commons.exec' (#1359)

* Removed dependency on 'org.apache.commons.exec'
* Use StringBuilder

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2020-02-12 13:20:06 +01:00 committed by GitHub
parent 2cf5931de2
commit 11fa4fad4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 121 additions and 99 deletions

View File

@ -58,12 +58,6 @@
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.commons-httpclient</artifactId>

View File

@ -348,12 +348,6 @@
<!-- END: logging -->
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>

View File

@ -12,18 +12,14 @@
*/
package org.openhab.core.io.net.exec;
import java.io.ByteArrayOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecuteResultHandler;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.Executor;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -34,7 +30,9 @@ import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - added exception logging
*/
public class ExecUtil {
private static Logger logger = LoggerFactory.getLogger(ExecUtil.class);
/**
* Use this to separate between command and parameter, and also between parameters.
*/
@ -43,98 +41,73 @@ public class ExecUtil {
/**
* <p>
* Executes <code>commandLine</code>. Sometimes (especially observed on MacOS) the commandLine isn't executed
* properly. In that cases another exec-method is to be used. To accomplish this please use the special delimiter '
* <code>@@</code>'. If <code>commandLine</code> contains this delimiter it is split into a String[] array and the
* properly. In that cases another exec-method is to be used. To accomplish this please use the special delimiter
* '<code>@@</code>'. If <code>commandLine</code> contains this delimiter it is split into a String list and the
* special exec-method is used.
*
* <p>
* A possible {@link IOException} gets logged but no further processing is done.
*
* @param commandLine the command line to execute
* @see http://www.peterfriese.de/running-applescript-from-java/
*/
public static void executeCommandLine(String commandLine) {
try {
if (commandLine.contains(CMD_LINE_DELIMITER)) {
String[] cmdArray = commandLine.split(CMD_LINE_DELIMITER);
Runtime.getRuntime().exec(cmdArray);
logger.info("executed commandLine '{}'", Arrays.asList(cmdArray));
} else {
Runtime.getRuntime().exec(commandLine);
logger.info("executed commandLine '{}'", commandLine);
}
} catch (IOException e) {
logger.error("couldn't execute commandLine '{}'", commandLine, e);
}
internalExecute(commandLine);
}
/**
* <p>
* Executes <code>commandLine</code>. Sometimes (especially observed on MacOS) the commandLine isn't executed
* properly. In that cases another exec-method is to be used. To accomplish this please use the special delimiter '
* <code>@@</code>'. If <code>commandLine</code> contains this delimiter it is split into a String[] array and the
* special exec-method is used.
* Executes <code>commandLine</code> and return its result. Sometimes (especially observed on MacOS) the commandLine
* isn't executed properly. In that cases another exec-method is to be used. To accomplish this please use the
* special delimiter '<code>@@</code>'. If <code>commandLine</code> contains this delimiter it is split into a
* String list and the special exec-method is used.
*
* <p>
* A possible {@link IOException} gets logged but no further processing is done.
*
* @param commandLine the command line to execute
* @param timeout timeout for execution in milliseconds
* @return response data from executed command line
* @return response data from executed command line or <code>null</code> if an error occurred
*/
public static String executeCommandLineAndWaitResponse(String commandLine, int timeout) {
String retval = null;
CommandLine cmdLine = null;
if (commandLine.contains(CMD_LINE_DELIMITER)) {
String[] cmdArray = commandLine.split(CMD_LINE_DELIMITER);
cmdLine = new CommandLine(cmdArray[0]);
for (int i = 1; i < cmdArray.length; i++) {
cmdLine.addArgument(cmdArray[i], false);
final Process process = internalExecute(commandLine);
if (process != null) {
try {
process.waitFor(timeout, TimeUnit.MILLISECONDS);
int exitCode = process.exitValue();
final StringBuilder result = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line = "";
while ((line = reader.readLine()) != null) {
result.append(line).append("\n");
}
}
logger.debug("exit code '{}', result '{}'", exitCode, result);
return result.toString();
} catch (IOException e) {
logger.warn("I/O exception occurred when executing commandLine '{}'", commandLine, e);
} catch (InterruptedException e) {
logger.warn("Timeout occurred when executing commandLine '{}'", commandLine, e);
}
} else {
cmdLine = CommandLine.parse(commandLine);
}
return null;
}
DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout);
Executor executor = new DefaultExecutor();
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(stdout);
executor.setExitValues(null);
executor.setStreamHandler(streamHandler);
executor.setWatchdog(watchdog);
private static @Nullable Process internalExecute(String commandLine) {
final Process process;
try {
executor.execute(cmdLine, resultHandler);
logger.debug("executed commandLine '{}'", commandLine);
} catch (ExecuteException e) {
logger.warn("couldn't execute commandLine '{}'", commandLine, e);
} catch (IOException e) {
logger.warn("couldn't execute commandLine '{}'", commandLine, e);
}
// some time later the result handler callback was invoked so we
// can safely request the exit code
try {
resultHandler.waitFor();
int exitCode = resultHandler.getExitValue();
retval = StringUtils.chomp(stdout.toString());
if (resultHandler.getException() != null) {
logger.warn("{}", resultHandler.getException().getMessage());
if (commandLine.contains(CMD_LINE_DELIMITER)) {
final List<String> cmdArray = Arrays.asList(commandLine.split(CMD_LINE_DELIMITER));
process = new ProcessBuilder(cmdArray).start();
logger.info("executed commandLine '{}'", cmdArray);
} else {
logger.debug("exit code '{}', result '{}'", exitCode, retval);
process = new ProcessBuilder(commandLine).start();
logger.info("executed commandLine '{}'", commandLine);
}
} catch (InterruptedException e) {
logger.warn("Timeout occurred when executing commandLine '{}'", commandLine, e);
} catch (IOException e) {
logger.error("couldn't execute commandLine '{}'", commandLine, e);
return null;
}
return retval;
return process;
}
}

View File

@ -0,0 +1,64 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.io.net.exec;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Tests for the ExecUtil
*
* @author Christoph Weitkamp - Initial contribution
*/
public class ExecUtilTest {
@Test
public void testBasicExecuteCommandLine() {
if (isWindowsSystem()) {
ExecUtil.executeCommandLine("dir");
} else {
ExecUtil.executeCommandLine("ls");
}
}
@Test
public void testBasicExecuteCommandLineAndWaitResponse() {
final String result;
if (isWindowsSystem()) {
result = ExecUtil.executeCommandLineAndWaitResponse("dir", 1000);
} else {
result = ExecUtil.executeCommandLineAndWaitResponse("ls", 1000);
}
assertNotNull(result);
assertNotEquals("", result);
}
@Test
public void testExecuteCommandLineAndWaitResponseWithArguments() {
final String result;
if (isWindowsSystem()) {
result = ExecUtil.executeCommandLineAndWaitResponse("echo@@test", 1000);
} else {
result = ExecUtil.executeCommandLineAndWaitResponse("echo@@'test'", 1000);
}
assertNotNull(result);
assertNotEquals("test", result);
}
private boolean isWindowsSystem() {
String osName = System.getProperty("os.name").toLowerCase();
return osName.indexOf("windows") >= 0;
}
}

View File

@ -23,7 +23,6 @@
<!-- Apache Commons -->
<bundle dependency="true">mvn:commons-codec/commons-codec/1.6</bundle>
<bundle dependency="true">mvn:org.apache.commons/commons-exec/1.1</bundle>
<bundle dependency="true">mvn:commons-io/commons-io/2.2</bundle>
<bundle dependency="true">mvn:commons-lang/commons-lang/2.6</bundle>

View File

@ -10,7 +10,6 @@ Fragment-Host: org.openhab.core.auth.oauth2client
#
-runbundles: \
javax.measure.unit-api;version='[1.0.0,1.0.1)',\
org.apache.commons.exec;version='[1.1.0,1.1.1)',\
org.apache.commons.lang;version='[2.6.0,2.6.1)',\
org.apache.felix.configadmin;version='[1.9.8,1.9.9)',\
org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\

View File

@ -53,7 +53,6 @@ Fragment-Host: org.openhab.core.model.core
org.eclipse.xtext.common.types;version='[2.19.0,2.19.1)',\
org.objectweb.asm;version='[7.1.0,7.1.1)',\
jollyday;version='[0.5.8,0.5.9)',\
org.apache.commons.exec;version='[1.1.0,1.1.1)',\
org.apache.xbean.bundleutils;version='[4.12.0,4.12.1)',\
org.apache.xbean.finder;version='[4.12.0,4.12.1)',\
org.eclipse.xtext.xbase;version='[2.19.0,2.19.1)',\
@ -97,4 +96,5 @@ Fragment-Host: org.openhab.core.model.core
org.openhab.core.test;version='[3.0.0,3.0.1)',\
org.openhab.core.thing;version='[3.0.0,3.0.1)',\
org.openhab.core.transform;version='[3.0.0,3.0.1)',\
org.openhab.core.voice;version='[3.0.0,3.0.1)'
org.openhab.core.voice;version='[3.0.0,3.0.1)',\
org.openhab.core.model.sitemap.runtime;version='[3.0.0,3.0.1)'

View File

@ -51,7 +51,6 @@ Fragment-Host: org.openhab.core.model.item
org.eclipse.xtext.xbase.lib;version='[2.19.0,2.19.1)',\
org.objectweb.asm;version='[7.1.0,7.1.1)',\
jollyday;version='[0.5.8,0.5.9)',\
org.apache.commons.exec;version='[1.1.0,1.1.1)',\
org.apache.xbean.bundleutils;version='[4.12.0,4.12.1)',\
org.apache.xbean.finder;version='[4.12.0,4.12.1)',\
org.eclipse.xtext.xbase;version='[2.19.0,2.19.1)',\
@ -96,4 +95,5 @@ Fragment-Host: org.openhab.core.model.item
org.openhab.core.test;version='[3.0.0,3.0.1)',\
org.openhab.core.thing;version='[3.0.0,3.0.1)',\
org.openhab.core.transform;version='[3.0.0,3.0.1)',\
org.openhab.core.voice;version='[3.0.0,3.0.1)'
org.openhab.core.voice;version='[3.0.0,3.0.1)',\
org.openhab.core.model.sitemap.runtime;version='[3.0.0,3.0.1)'

View File

@ -50,7 +50,6 @@ Fragment-Host: org.openhab.core.model.persistence
org.eclipse.xtext.xbase.lib;version='[2.19.0,2.19.1)',\
org.objectweb.asm;version='[7.1.0,7.1.1)',\
jollyday;version='[0.5.8,0.5.9)',\
org.apache.commons.exec;version='[1.1.0,1.1.1)',\
org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
org.apache.xbean.bundleutils;version='[4.12.0,4.12.1)',\
org.apache.xbean.finder;version='[4.12.0,4.12.1)',\
@ -112,4 +111,5 @@ Fragment-Host: org.openhab.core.model.persistence
org.openhab.core.test;version='[3.0.0,3.0.1)',\
org.openhab.core.thing;version='[3.0.0,3.0.1)',\
org.openhab.core.transform;version='[3.0.0,3.0.1)',\
org.openhab.core.voice;version='[3.0.0,3.0.1)'
org.openhab.core.voice;version='[3.0.0,3.0.1)',\
org.openhab.core.model.sitemap.runtime;version='[3.0.0,3.0.1)'

View File

@ -15,7 +15,6 @@ Fragment-Host: org.openhab.core.model.rule.runtime
javax.measure.unit-api;version='[1.0.0,1.0.1)',\
log4j;version='[1.2.17,1.2.18)',\
org.antlr.runtime;version='[3.2.0,3.2.1)',\
org.apache.commons.exec;version='[1.1.0,1.1.1)',\
org.apache.commons.io;version='[2.2.0,2.2.1)',\
org.apache.commons.lang;version='[2.6.0,2.6.1)',\
org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
@ -96,4 +95,5 @@ Fragment-Host: org.openhab.core.model.rule.runtime
org.openhab.core.test;version='[3.0.0,3.0.1)',\
org.openhab.core.thing;version='[3.0.0,3.0.1)',\
org.openhab.core.transform;version='[3.0.0,3.0.1)',\
org.openhab.core.voice;version='[3.0.0,3.0.1)'
org.openhab.core.voice;version='[3.0.0,3.0.1)',\
org.openhab.core.model.sitemap.runtime;version='[3.0.0,3.0.1)'

View File

@ -15,7 +15,6 @@ Fragment-Host: org.openhab.core.model.script
javax.measure.unit-api;version='[1.0.0,1.0.1)',\
log4j;version='[1.2.17,1.2.18)',\
org.antlr.runtime;version='[3.2.0,3.2.1)',\
org.apache.commons.exec;version='[1.1.0,1.1.1)',\
org.apache.commons.io;version='[2.2.0,2.2.1)',\
org.apache.commons.lang;version='[2.6.0,2.6.1)',\
org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
@ -95,5 +94,6 @@ Fragment-Host: org.openhab.core.model.script
org.openhab.core.test;version='[3.0.0,3.0.1)',\
org.openhab.core.thing;version='[3.0.0,3.0.1)',\
org.openhab.core.transform;version='[3.0.0,3.0.1)',\
org.openhab.core.voice;version='[3.0.0,3.0.1)'
org.openhab.core.voice;version='[3.0.0,3.0.1)',\
org.openhab.core.model.sitemap.runtime;version='[3.0.0,3.0.1)'

View File

@ -17,7 +17,6 @@ Fragment-Host: org.openhab.core.model.thing
javax.measure.unit-api;version='[1.0.0,1.0.1)',\
log4j;version='[1.2.17,1.2.18)',\
org.antlr.runtime;version='[3.2.0,3.2.1)',\
org.apache.commons.exec;version='[1.1.0,1.1.1)',\
org.apache.commons.io;version='[2.2.0,2.2.1)',\
org.apache.commons.lang;version='[2.6.0,2.6.1)',\
org.apache.felix.configadmin;version='[1.9.8,1.9.9)',\