Sync with latest bnd code for testing purposes

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1354104 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/libg/cafs/CAFS.java b/bundleplugin/src/main/java/aQute/libg/cafs/CAFS.java
index db2a175..b97babc 100644
--- a/bundleplugin/src/main/java/aQute/libg/cafs/CAFS.java
+++ b/bundleplugin/src/main/java/aQute/libg/cafs/CAFS.java
@@ -23,8 +23,8 @@
  * underlying idea in Git.
  */
 public class CAFS implements Closeable, Iterable<SHA1> {
-	final static byte[]	CAFS			= "CAFS".getBytes();
-	final static byte[]	CAFE			= "CAFE".getBytes();
+	final static byte[]	CAFS;
+	final static byte[]	CAFE;
 	final static String	INDEXFILE		= "index.idx";
 	final static String	STOREFILE		= "store.cafs";
 	final static String	ALGORITHM		= "SHA-1";
@@ -42,6 +42,15 @@
 	RandomAccessFile	store;
 	FileChannel			channel;
 
+	static {
+		try {
+		CAFS = "CAFS".getBytes("UTF-8");
+		CAFE = "CAFE".getBytes("UTF-8");
+		} catch (Throwable e) {
+			throw new ExceptionInInitializerError(e);
+		}
+	}
+
 	/**
 	 * Constructor for a Content Addressable File Store
 	 * 
diff --git a/bundleplugin/src/main/java/aQute/libg/command/Command.java b/bundleplugin/src/main/java/aQute/libg/command/Command.java
index 3feb702..6bb24c3 100644
--- a/bundleplugin/src/main/java/aQute/libg/command/Command.java
+++ b/bundleplugin/src/main/java/aQute/libg/command/Command.java
@@ -4,7 +4,9 @@
 import java.util.*;
 import java.util.Map.Entry;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 
+import aQute.lib.io.*;
 import aQute.libg.reporter.*;
 
 public class Command {
@@ -35,7 +37,7 @@
 		return execute(in, stdout, stderr);
 	}
 
-	public int execute(InputStream in, Appendable stdout, Appendable stderr) throws Exception {
+	public int execute(final InputStream in, Appendable stdout, Appendable stderr) throws Exception {
 		if (reporter != null) {
 			reporter.trace("executing cmd: %s", arguments);
 		}
@@ -61,7 +63,8 @@
 		Thread hook = new Thread(r, arguments.toString());
 		Runtime.getRuntime().addShutdownHook(hook);
 		TimerTask timer = null;
-		OutputStream stdin = process.getOutputStream();
+		final OutputStream stdin = process.getOutputStream();
+		Thread rdInThread = null;
 
 		if (timeout != 0) {
 			timer = new TimerTask() {
@@ -73,6 +76,7 @@
 			Command.timer.schedule(timer, timeout);
 		}
 
+		final AtomicBoolean finished = new AtomicBoolean(false);
 		InputStream out = process.getInputStream();
 		try {
 			InputStream err = process.getErrorStream();
@@ -82,25 +86,45 @@
 				Collector cerr = new Collector(err, stderr);
 				cerr.start();
 
-				try {
-					int c = in.read();
-					while (c >= 0) {
-						stdin.write(c);
-						if (c == '\n')
-							stdin.flush();
-						c = in.read();
+				if (in != null) {
+					if (in == System.in) {
+						rdInThread = new Thread("Read Input Thread") {
+							public void run() {
+								try {
+									while (!finished.get()) {
+										int n = in.available();
+										if (n == 0) {
+											sleep(100);
+										} else {
+											int c = in.read();
+											if (c < 0) {
+												stdin.close();
+												return;
+											}
+											stdin.write(c);
+											if (c == '\n')
+												stdin.flush();
+										}
+									}
+								}
+								catch (InterruptedIOException e) {
+									// Ignore here
+								}
+								catch (Exception e) {
+									// Who cares?
+								}
+								finally {
+									IO.close(stdin);
+								}
+							}
+						};
+						rdInThread.setDaemon(true);
+						rdInThread.start();
+					} else {
+						IO.copy(in, stdin);
+						stdin.close();
 					}
 				}
-				catch (InterruptedIOException e) {
-					// Ignore here
-				}
-				catch (Exception e) {
-					// Who cares?
-				}
-				finally {
-					stdin.close();
-				}
-
 				if (reporter != null)
 					reporter.trace("exited process");
 
@@ -121,6 +145,13 @@
 		}
 
 		byte exitValue = (byte) process.waitFor();
+		finished.set(true);
+		if (rdInThread != null) {
+			if (in != null)
+				IO.close(in);
+			rdInThread.interrupt();
+		}
+
 		if (reporter != null)
 			reporter.trace("cmd %s executed with result=%d, result: %s/%s, timedout=%s", arguments, exitValue, stdout,
 					stderr, timedout);
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/Crypto.java b/bundleplugin/src/main/java/aQute/libg/cryptography/Crypto.java
index 22eac45..3d27188 100644
--- a/bundleplugin/src/main/java/aQute/libg/cryptography/Crypto.java
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/Crypto.java
@@ -16,7 +16,6 @@
 	 * @return
 	 * @throws Exception
 	 */
-	@SuppressWarnings("unchecked")
 	public static <T> T fromString(String spec, Class<T> c) throws Exception {
 		if (PrivateKey.class.isAssignableFrom(c)) {
 			Matcher m = RSA_PRIVATE.matcher(spec);
diff --git a/bundleplugin/src/main/java/aQute/libg/filters/AndFilter.java b/bundleplugin/src/main/java/aQute/libg/filters/AndFilter.java
new file mode 100644
index 0000000..2561d77
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/filters/AndFilter.java
@@ -0,0 +1,30 @@
+package aQute.libg.filters;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public final class AndFilter extends Filter {
+	
+	private final List<Filter> children = new LinkedList<Filter>();
+	
+	public AndFilter addChild(Filter child) {
+		if (child instanceof AndFilter)
+			children.addAll(((AndFilter) child).children);
+		else
+			children.add(child);
+		return this;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		if (children.isEmpty())
+			return;
+		
+		builder.append("(&");
+		for (Filter child : children) {
+			child.append(builder);
+		}
+		builder.append(")");
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/filters/Filter.java b/bundleplugin/src/main/java/aQute/libg/filters/Filter.java
new file mode 100644
index 0000000..e0a4555
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/filters/Filter.java
@@ -0,0 +1,14 @@
+package aQute.libg.filters;
+
+public abstract class Filter {
+
+	public abstract void append(StringBuilder builder);
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		append(builder);
+		return builder.toString();
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/filters/NotFilter.java b/bundleplugin/src/main/java/aQute/libg/filters/NotFilter.java
new file mode 100644
index 0000000..0f1061c
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/filters/NotFilter.java
@@ -0,0 +1,19 @@
+package aQute.libg.filters;
+
+public final class NotFilter extends Filter {
+
+	private final Filter	child;
+
+	public NotFilter(Filter child) {
+		this.child = child;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		builder.append("(!");
+		child.append(builder);
+		builder.append(")");
+	}
+	
+	
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/filters/Operator.java b/bundleplugin/src/main/java/aQute/libg/filters/Operator.java
new file mode 100644
index 0000000..b17aaff
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/filters/Operator.java
@@ -0,0 +1,17 @@
+package aQute.libg.filters;
+
+public enum Operator {
+
+	Equals("="), LessThanOrEqual("<="), GreaterThanOrEqual(">="), ApproxEqual("~=");
+
+	private final String	symbol;
+
+	Operator(String symbol) {
+		this.symbol = symbol;
+	}
+
+	public String getSymbol() {
+		return symbol;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/filters/OrFilter.java b/bundleplugin/src/main/java/aQute/libg/filters/OrFilter.java
new file mode 100644
index 0000000..b3332bd
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/filters/OrFilter.java
@@ -0,0 +1,30 @@
+package aQute.libg.filters;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public final class OrFilter extends Filter {
+	
+	private final List<Filter> children = new LinkedList<Filter>();
+	
+	public OrFilter addChild(Filter child) {
+		if (child instanceof OrFilter)
+			children.addAll(((OrFilter) child).children);
+		else
+			children.add(child);
+		return this;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		if (children.isEmpty())
+			return;
+		
+		builder.append("(|");
+		for (Filter child : children) {
+			child.append(builder);
+		}
+		builder.append(")");
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/filters/SimpleFilter.java b/bundleplugin/src/main/java/aQute/libg/filters/SimpleFilter.java
new file mode 100644
index 0000000..f0dea65
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/filters/SimpleFilter.java
@@ -0,0 +1,33 @@
+package aQute.libg.filters;
+
+public final class SimpleFilter extends Filter {
+
+	private final String	name;
+	private final Operator	operator;
+	private final String	value;
+
+	/**
+	 * Construct a simple filter with the default "equals" operator, i.e.
+	 * {@code (name=value)}.
+	 */
+	public SimpleFilter(String name, String value) {
+		this(name, Operator.Equals, value);
+	}
+
+	/**
+	 * Construct a simple filter with any of the comparison operators.
+	 */
+	public SimpleFilter(String name, Operator operator, String value) {
+		this.name = name;
+		this.operator = operator;
+		this.value = value;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		builder.append('(');
+		builder.append(name).append(operator.getSymbol()).append(value);
+		builder.append(')');
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/filters/packageinfo b/bundleplugin/src/main/java/aQute/libg/filters/packageinfo
new file mode 100644
index 0000000..a4f1546
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/filters/packageinfo
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/Messages.java b/bundleplugin/src/main/java/aQute/libg/reporter/Messages.java
index 504c10a..033df00 100644
--- a/bundleplugin/src/main/java/aQute/libg/reporter/Messages.java
+++ b/bundleplugin/src/main/java/aQute/libg/reporter/Messages.java
@@ -16,14 +16,13 @@
 
 package aQute.libg.reporter;
 
-import java.io.*;
 
 public interface Messages {
 	static public class ERROR {}
 
 	static public class WARNING {}
 
-	ERROR NoSuchFile_(File f);
+	ERROR NoSuchFile_(Object r);
 
 	ERROR Unexpected_Error_(String context, Exception e);
 
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java b/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
index 90da59b..eaf363c 100644
--- a/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
+++ b/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
@@ -24,7 +24,6 @@
 
 public class ReporterMessages {
 
-	@SuppressWarnings("unchecked")
 	public static <T> T base(final Reporter reporter, Class<T> messages) {
 		return (T) Proxy.newProxyInstance(messages.getClassLoader(), new Class[] {
 			messages
diff --git a/bundleplugin/src/main/java/aQute/libg/tuple/ComparablePair.java b/bundleplugin/src/main/java/aQute/libg/tuple/ComparablePair.java
new file mode 100644
index 0000000..36f0242
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/tuple/ComparablePair.java
@@ -0,0 +1,14 @@
+package aQute.libg.tuple;
+
+public class ComparablePair<A extends Comparable<A>, B> extends Pair<A,B> implements Comparable<Pair<A, ? >> {
+
+	private static final long	serialVersionUID	= 1L;
+
+	public ComparablePair(A first, B second) {
+		super(first, second);
+	}
+
+	public int compareTo(Pair<A, ? > o) {
+		return getFirst().compareTo(o.getFirst());
+	}
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java b/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java
index d86d6c8..f8f7afb 100644
--- a/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java
+++ b/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java
@@ -1,11 +1,71 @@
 package aQute.libg.tuple;
 
-public class Pair<A, B> {
-	final public A	a;
-	final public B	b;
+import java.io.Serializable;
 
-	public Pair(A a, B b) {
-		this.a = a;
-		this.b = b;
+public class Pair<A, B> implements Serializable {
+
+	private static final long	serialVersionUID	= 1L;
+
+	private final A				first;
+	private final B				second;
+
+	public Pair(A first, B second) {
+		assert first != null && second != null : "both parameters must be non-null";
+		this.first = first;
+		this.second = second;
 	}
-}
+
+	public static <A, B> Pair<A,B> newInstance(A first, B second) {
+		return new Pair<A,B>(first, second);
+	}
+
+	public A getFirst() {
+		return first;
+	}
+
+	public B getSecond() {
+		return second;
+	}
+
+	@Override
+	public String toString() {
+		return "Pair [" + first + ", " + second + "]";
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((first == null) ? 0 : first.hashCode());
+		result = prime * result + ((second == null) ? 0 : second.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		@SuppressWarnings("unchecked")
+		Pair<A,B> other = (Pair<A,B>) obj;
+		if (first == null) {
+			if (other.first != null)
+				return false;
+		} else if (!first.equals(other.first))
+			return false;
+		if (second == null) {
+			if (other.second != null)
+				return false;
+		} else if (!second.equals(other.second))
+			return false;
+		return true;
+	}
+
+	@Override
+	public Pair<A,B> clone() {
+		return new Pair<A,B>(first, second);
+	}
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java b/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java
index 4d5835b..a505c4b 100644
--- a/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java
+++ b/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java
@@ -11,20 +11,20 @@
 public class Transform {
 	static TransformerFactory	transformerFactory	= TransformerFactory.newInstance();
 
-	static Map<URL,Templates>	cache				= new ConcurrentHashMap<URL,Templates>();
+	static Map<URI,Templates>	cache				= new ConcurrentHashMap<URI,Templates>();
 
 	public static void transform(TransformerFactory transformerFactory, URL xslt, InputStream in, OutputStream out)
 			throws Exception {
 		if (xslt == null)
 			throw new IllegalArgumentException("No source template specified");
 
-		Templates templates = cache.get(xslt);
+		Templates templates = cache.get(xslt.toURI());
 		if (templates == null) {
 			InputStream xsltIn = xslt.openStream();
 			try {
 				templates = transformerFactory.newTemplates(new StreamSource(xsltIn));
 
-				cache.put(xslt, templates);
+				cache.put(xslt.toURI(), templates);
 			}
 			finally {
 				in.close();