Use local copy of latest bndlib code for pre-release testing purposes
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1347815 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/libg/command/Command.java b/bundleplugin/src/main/java/aQute/libg/command/Command.java
new file mode 100644
index 0000000..0a79a58
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/command/Command.java
@@ -0,0 +1,259 @@
+package aQute.libg.command;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.*;
+
+import aQute.libg.reporter.*;
+
+public class Command {
+
+ boolean trace;
+ Reporter reporter;
+ List<String> arguments = new ArrayList<String>();
+ Map<String, String> variables = new LinkedHashMap<String, String>();
+ long timeout = 0;
+ File cwd = new File("").getAbsoluteFile();
+ static Timer timer = new Timer(Command.class.getName(), true);
+ Process process;
+ volatile boolean timedout;
+ String fullCommand;
+
+ public Command(String fullCommand) {
+ this.fullCommand = fullCommand;
+ }
+
+ public Command() {
+ }
+
+ public int execute(Appendable stdout, Appendable stderr) throws Exception {
+ return execute((InputStream) null, stdout, stderr);
+ }
+
+ public int execute(String input, Appendable stdout, Appendable stderr) throws Exception {
+ InputStream in = new ByteArrayInputStream(input.getBytes("UTF-8"));
+ return execute(in, stdout, stderr);
+ }
+
+ public int execute(InputStream in, Appendable stdout, Appendable stderr) throws Exception {
+ int result;
+ if (reporter != null) {
+ reporter.trace("executing cmd: %s", arguments);
+ }
+
+ String args[] = arguments.toArray(new String[arguments.size()]);
+ String vars[] = new String[variables.size()];
+ int i = 0;
+ for (Entry<String, String> s : variables.entrySet()) {
+ vars[i++] = s.getKey() + "=" + s.getValue();
+ }
+
+ if (fullCommand == null)
+ process = Runtime.getRuntime().exec(args, vars.length == 0 ? null : vars, cwd);
+ else
+ process = Runtime.getRuntime().exec(fullCommand, vars.length == 0 ? null : vars, cwd);
+
+
+ // Make sure the command will not linger when we go
+ Runnable r = new Runnable() {
+ public void run() {
+ process.destroy();
+ }
+ };
+ Thread hook = new Thread(r, arguments.toString());
+ Runtime.getRuntime().addShutdownHook(hook);
+ TimerTask timer = null;
+ OutputStream stdin = process.getOutputStream();
+ final InputStreamHandler handler = in != null ? new InputStreamHandler(in, stdin) : null;
+
+ if (timeout != 0) {
+ timer = new TimerTask() {
+ public void run() {
+ timedout = true;
+ process.destroy();
+ if (handler != null)
+ handler.interrupt();
+ }
+ };
+ Command.timer.schedule(timer, timeout);
+ }
+
+ InputStream out = process.getInputStream();
+ try {
+ InputStream err = process.getErrorStream();
+ try {
+ new Collector(out, stdout).start();
+ new Collector(err, stderr).start();
+ if (handler != null)
+ handler.start();
+
+ result = process.waitFor();
+ if (reporter != null)
+ reporter.trace("exited process.waitFor, %s", result);
+
+ }
+ finally {
+ err.close();
+ }
+ }
+ finally {
+ out.close();
+ if (timer != null)
+ timer.cancel();
+ Runtime.getRuntime().removeShutdownHook(hook);
+ if (handler != null)
+ handler.interrupt();
+ }
+ if (reporter != null)
+ reporter.trace("cmd %s executed with result=%d, result: %s/%s", arguments, result,
+ stdout, stderr);
+
+ if (timedout)
+ return Integer.MIN_VALUE;
+ byte exitValue = (byte) process.exitValue();
+ return exitValue;
+ }
+
+ public void add(String... args) {
+ for (String arg : args)
+ arguments.add(arg);
+ }
+
+ public void addAll(Collection<String> args) {
+ arguments.addAll(args);
+ }
+
+ public void setTimeout(long duration, TimeUnit unit) {
+ timeout = unit.toMillis(duration);
+ }
+
+ public void setTrace() {
+ this.trace = true;
+ }
+
+ public void setReporter(Reporter reporter) {
+ this.reporter = reporter;
+ }
+
+ public void setCwd(File dir) {
+ if (!dir.isDirectory())
+ throw new IllegalArgumentException("Working directory must be a directory: " + dir);
+
+ this.cwd = dir;
+ }
+
+ public void cancel() {
+ process.destroy();
+ }
+
+ class Collector extends Thread {
+ final InputStream in;
+ final Appendable sb;
+
+ Collector(InputStream inputStream, Appendable sb) {
+ this.in = inputStream;
+ this.sb = sb;
+ setDaemon(true);
+ }
+
+ public void run() {
+ try {
+ int c = in.read();
+ while (c >= 0) {
+ sb.append((char) c);
+ c = in.read();
+ }
+ }
+ catch( IOException e) {
+ // We assume the socket is closed
+ }
+ catch (Exception e) {
+ try {
+ sb.append("\n**************************************\n");
+ sb.append(e.toString());
+ sb.append("\n**************************************\n");
+ }
+ catch (IOException e1) {
+ }
+ if (reporter != null) {
+ reporter.trace("cmd exec: %s", e);
+ }
+ }
+ }
+ }
+
+ static class InputStreamHandler extends Thread {
+ final InputStream in;
+ final OutputStream stdin;
+
+ InputStreamHandler(InputStream in, OutputStream stdin) {
+ this.stdin = stdin;
+ this.in = in;
+ setDaemon(true);
+ }
+
+ public void run() {
+ try {
+ int c = in.read();
+ while (c >= 0) {
+ stdin.write(c);
+ stdin.flush();
+ c = in.read();
+ }
+ }
+ catch (InterruptedIOException e) {
+ // Ignore here
+ }
+ catch (Exception e) {
+ // Who cares?
+ }
+ finally {
+ try {
+ stdin.close();
+ }
+ catch (IOException e) {
+ // Who cares?
+ }
+ }
+ }
+ }
+
+ public Command var(String name, String value) {
+ variables.put(name, value);
+ return this;
+ }
+
+ public Command arg(String... args) {
+ add(args);
+ return this;
+ }
+
+ public Command full(String full) {
+ fullCommand = full;
+ return this;
+ }
+
+ public void inherit() {
+ ProcessBuilder pb = new ProcessBuilder();
+ for (Entry<String, String> e : pb.environment().entrySet()) {
+ var(e.getKey(), e.getValue());
+ }
+ }
+
+ public String var(String name) {
+ return variables.get(name);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ String del = "";
+
+ for (String argument : arguments) {
+ sb.append(del);
+ sb.append(argument);
+ del = " ";
+ }
+ return sb.toString();
+ }
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/command/packageinfo b/bundleplugin/src/main/java/aQute/libg/command/packageinfo
new file mode 100644
index 0000000..a2afe57
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/command/packageinfo
@@ -0,0 +1 @@
+version 2.1.0