You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by mc...@apache.org on 2012/06/07 23:57:43 UTC

svn commit: r1347815 [19/19] - in /felix/trunk/bundleplugin: ./ src/main/java/aQute/ src/main/java/aQute/bnd/ src/main/java/aQute/bnd/annotation/ src/main/java/aQute/bnd/annotation/component/ src/main/java/aQute/bnd/annotation/metatype/ src/main/java/a...

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/Forker.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/Forker.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/Forker.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/Forker.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,212 @@
+package aQute.libg.forker;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A Forker is good in parallel scheduling tasks with dependencies. You can add
+ * tasks with {@link #doWhen(Collection, Object, Runnable)}. The collection is
+ * the list of dependencies, the object is the target, and the runnable is run
+ * to update the target. The runnable will only run when all its dependencies
+ * have ran their associated runnable.
+ * 
+ * @author aqute
+ * 
+ * @param <T>
+ */
+public class Forker<T> {
+	final Executor		executor;
+	final Map<T, Job>	waiting		= new HashMap<T, Job>();
+	final Set<Job>		executing	= new HashSet<Job>();
+	final AtomicBoolean	canceled	= new AtomicBoolean();
+	private int			count;
+
+	/**
+	 * Helper class to model a Job
+	 */
+	class Job implements Runnable {
+		T						target;
+		Set<T>					dependencies;
+		Runnable				runnable;
+		Throwable				exception;
+		volatile Thread			t;
+		volatile AtomicBoolean	canceled	= new AtomicBoolean(false);
+
+		/**
+		 * Run when the job's dependencies are done.
+		 */
+		public void run() {
+			Thread.interrupted(); // clear the interrupt flag
+
+			try {
+				synchronized (this) {
+					// Check if we got canceled
+					if (canceled.get())
+						return;
+
+					t = Thread.currentThread();
+				}
+				runnable.run();
+			} catch (Exception e) {
+				exception = e;
+				e.printStackTrace();
+			} finally {
+				synchronized (this) {
+					t = null;
+				}
+				Thread.interrupted(); // clear the interrupt flag
+				done(this);
+			}
+		}
+
+		/**
+		 * Cancel this job
+		 */
+		private void cancel() {
+			if (!canceled.getAndSet(true)) {
+				synchronized (this) {
+					if (t != null)
+						t.interrupt();
+				}
+			}
+		}
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 * @param executor
+	 */
+	public Forker(Executor executor) {
+		this.executor = executor;
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 */
+	public Forker() {
+		this.executor = Executors.newFixedThreadPool(4);
+	}
+
+	/**
+	 * Schedule a job for execution when the dependencies are done of target are
+	 * done.
+	 * 
+	 * @param dependencies
+	 *            the dependencies that must have run
+	 * @param target
+	 *            the target, is removed from all the dependencies when it ran
+	 * @param runnable
+	 *            the runnable to run
+	 */
+	public synchronized void doWhen(Collection<? extends T> dependencies, T target,
+			Runnable runnable) {
+		if (waiting.containsKey(target))
+			throw new IllegalArgumentException("You can only add a target once to the forker");
+
+		System.err.println("doWhen " + dependencies + " " + target);
+		Job job = new Job();
+		job.dependencies = new HashSet<T>(dependencies);
+		job.target = target;
+		job.runnable = runnable;
+		waiting.put(target, job);
+	}
+
+	public void start(long ms) throws InterruptedException {
+		check();
+		count = waiting.size();
+		System.err.println("Count " + count);
+		schedule();
+		if (ms >= 0)
+			sync(ms);
+	}
+
+	private void check() {
+		Set<T> dependencies = new HashSet<T>();
+		for (Job job : waiting.values())
+			dependencies.addAll(job.dependencies);
+		dependencies.removeAll(waiting.keySet());
+		if (dependencies.size() > 0)
+			throw new IllegalArgumentException(
+					"There are dependencies in the jobs that are not present in the targets: "
+							+ dependencies);
+
+	}
+
+	public synchronized void sync(long ms) throws InterruptedException {
+		System.err.println("Waiting for sync");
+		while (count > 0) {
+			System.err.println("Waiting for sync " + count);
+			wait(ms);
+		}
+		System.err.println("Exiting sync " + count);
+	}
+
+	private void schedule() {
+		if (canceled.get())
+			return;
+
+		List<Runnable> torun = new ArrayList<Runnable>();
+		synchronized (this) {
+			for (Iterator<Job> e = waiting.values().iterator(); e.hasNext();) {
+				Job job = e.next();
+				if (job.dependencies.isEmpty()) {
+					torun.add(job);
+					executing.add(job);
+					e.remove();
+				}
+			}
+		}
+		for (Runnable r : torun)
+			executor.execute(r);
+	}
+
+	/**
+	 * Called when the target has ran by the Job.
+	 * 
+	 * @param done
+	 */
+	private void done(Job done) {
+		synchronized (this) {
+			System.err.println("count = " + count);
+			executing.remove(done);
+			count--;
+			if (count == 0) {
+				System.err.println("finished");
+				notifyAll();
+				return;
+			}
+
+			for (Job job : waiting.values()) {
+				// boolean x =
+					job.dependencies.remove(done.target);
+				//System.err.println( "Removing " + done.target + " from " + job.target + " ?" + x  + " " + job.dependencies.size());
+			}
+		}
+		schedule();
+	}
+
+	/**
+	 * Cancel the forker.
+	 * 
+	 * @throws InterruptedException
+	 */
+	public void cancel(long ms) throws InterruptedException {
+		System.err.println("canceled " + count);
+
+		if (!canceled.getAndSet(true)) {
+			synchronized (this) {
+				for (Job job : executing) {
+					job.cancel();
+				}
+			}
+		}
+		sync(ms);
+	}
+
+	public int getCount() {
+		return count;
+	}
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/Forker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/Forker.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/forker/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/Create.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/Create.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/Create.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/Create.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,54 @@
+package aQute.libg.generics;
+
+import java.util.*;
+
+public class Create {
+    
+    public static <K,V>  Map<K, V> map() {
+        return new LinkedHashMap<K,V>();
+    }
+
+    public static <K,V>  Map<K, V> map(Class<K> key, Class<V> value) {
+        return Collections.checkedMap(new LinkedHashMap<K,V>(), key,value);
+    }
+
+    public static <T>  List<T> list() {
+        return new ArrayList<T>();
+    }
+
+    public static <T>  List<T> list(Class<T> c) {
+        return Collections.checkedList(new ArrayList<T>(),c) ;
+    }
+
+    public static <T>  Set<T> set() {
+        return new HashSet<T>();
+    }
+
+    public static <T>  Set<T> set(Class<T> c) {
+        return Collections.checkedSet(new HashSet<T>(),c);
+    }
+
+    public static <T>  List<T> list(T[] source) {
+        return new ArrayList<T>(Arrays.asList(source));
+    }
+
+    public static <T>  Set<T> set(T[]source) {
+        return new HashSet<T>(Arrays.asList(source));
+    }
+
+    public static <K,V>  Map<K, V> copy(Map<K,V> source) {
+        return new LinkedHashMap<K,V>(source);
+    }
+
+    public static <T>  List<T> copy(List<T> source) {
+        return new ArrayList<T>(source);
+    }
+
+    public static <T>  Set<T> copy(Collection<T> source) {
+        if ( source == null )
+            return set();
+        return new HashSet<T>(source);
+    }
+
+    
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/Create.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/Create.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/generics/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/Glob.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/Glob.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/Glob.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/Glob.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,110 @@
+package aQute.libg.glob;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Glob {
+
+	private final String glob;
+	private final Pattern pattern;
+	
+	public Glob(String globString) {
+		this.glob = globString;
+		this.pattern = Pattern.compile(convertGlobToRegEx(globString));
+	}
+	
+	public Matcher matcher(CharSequence input) {
+		return pattern.matcher(input);
+	}
+	
+	@Override
+	public String toString() {
+		return glob;
+	}
+
+	private static String convertGlobToRegEx(String line) {
+		line = line.trim();
+		int strLen = line.length();
+		StringBuilder sb = new StringBuilder(strLen);
+		// Remove beginning and ending * globs because they're useless
+		if (line.startsWith("*")) {
+			line = line.substring(1);
+			strLen--;
+		}
+		if (line.endsWith("*")) {
+			line = line.substring(0, strLen - 1);
+			strLen--;
+		}
+		boolean escaping = false;
+		int inCurlies = 0;
+		for (char currentChar : line.toCharArray()) {
+			switch (currentChar) {
+			case '*':
+				if (escaping)
+					sb.append("\\*");
+				else
+					sb.append(".*");
+				escaping = false;
+				break;
+			case '?':
+				if (escaping)
+					sb.append("\\?");
+				else
+					sb.append('.');
+				escaping = false;
+				break;
+			case '.':
+			case '(':
+			case ')':
+			case '+':
+			case '|':
+			case '^':
+			case '$':
+			case '@':
+			case '%':
+				sb.append('\\');
+				sb.append(currentChar);
+				escaping = false;
+				break;
+			case '\\':
+				if (escaping) {
+					sb.append("\\\\");
+					escaping = false;
+				} else
+					escaping = true;
+				break;
+			case '{':
+				if (escaping) {
+					sb.append("\\{");
+				} else {
+					sb.append('(');
+					inCurlies++;
+				}
+				escaping = false;
+				break;
+			case '}':
+				if (inCurlies > 0 && !escaping) {
+					sb.append(')');
+					inCurlies--;
+				} else if (escaping)
+					sb.append("\\}");
+				else
+					sb.append("}");
+				escaping = false;
+				break;
+			case ',':
+				if (inCurlies > 0 && !escaping) {
+					sb.append('|');
+				} else if (escaping)
+					sb.append("\\,");
+				else
+					sb.append(",");
+				break;
+			default:
+				escaping = false;
+				sb.append(currentChar);
+			}
+		}
+		return sb.toString();
+	}
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/Glob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/Glob.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/glob/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/GZipUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/GZipUtils.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/GZipUtils.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/GZipUtils.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,60 @@
+package aQute.libg.gzip;
+
+import java.io.BufferedInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+
+public class GZipUtils {
+	
+	/**
+	 * Determines whether the specified stream contains gzipped data, by
+	 * checking for the GZIP magic number, and returns a stream capable of
+	 * reading those data.
+	 * 
+	 * @throws IOException
+	 */
+	public static InputStream detectCompression(InputStream stream) throws IOException {
+		InputStream buffered;
+		if (stream.markSupported())
+			buffered = stream;
+		else
+			buffered = new BufferedInputStream(stream);
+		
+		buffered.mark(2);
+		int magic = readUShort(buffered);
+		buffered.reset();
+		
+		InputStream result;
+		if (magic == GZIPInputStream.GZIP_MAGIC)
+			result = new GZIPInputStream(buffered);
+		else
+			result = buffered;
+		return result;
+	}
+
+    /*
+     * Reads unsigned short in Intel byte order.
+     */
+	private static int readUShort(InputStream in) throws IOException {
+		int b = readUByte(in);
+		return (readUByte(in) << 8) | b;
+	}
+    
+    /*
+     * Reads unsigned byte.
+     */
+    private static int readUByte(InputStream in) throws IOException {
+	int b = in.read();
+	if (b == -1) {
+	    throw new EOFException();
+	}
+        if (b < -1 || b > 255) {
+            // Report on this.in, not argument in; see read{Header, Trailer}.
+            throw new IOException(in.getClass().getName() + ".read() returned value out of range -1..255: " + b);
+        }
+	return b;
+    }
+
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/GZipUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/GZipUtils.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/gzip/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Attrs.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Attrs.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Attrs.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Attrs.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,295 @@
+package aQute.libg.header;
+
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.lib.collections.*;
+import aQute.libg.version.*;
+
+public class Attrs implements Map<String, String> {
+	public enum Type {
+		STRING(null), LONG(null), VERSION(null), DOUBLE(null), STRINGS(STRING), LONGS(LONG), VERSIONS(VERSION), DOUBLES(DOUBLE);
+
+		Type	sub;
+
+		Type(Type sub) {
+			this.sub = sub;
+		}
+
+	}
+
+	/**
+	 * <pre>
+	 * Provide-Capability ::= capability ::=
+	 * name-space ::= typed-attr ::= type ::= scalar ::=
+	 * capability ( ',' capability )*
+	 * name-space
+	 *     ( ’;’ directive | typed-attr )*
+	 * symbolic-name
+	 * extended ( ’:’ type ) ’=’ argument
+	 * scalar | list
+	 * ’String’ | ’Version’ | ’Long’
+	 * list ::=
+	 * ’List<’ scalar ’>’
+	 * </pre>
+	 */
+	static String					EXTENDED	= "[\\-0-9a-zA-Z\\._]+";
+	static String					SCALAR		= "String|Version|Long|Double";
+	static String					LIST		= "List\\s*<\\s*(" + SCALAR + ")\\s*>";
+	public static final Pattern		TYPED		= Pattern.compile("\\s*(" + EXTENDED + ")\\s*:\\s*("+ SCALAR + "|" + LIST + ")\\s*");
+
+	private LinkedHashMap<String, String>	map;
+	private Map<String, Type>		types;
+	static Map<String, String>		EMPTY		= Collections.emptyMap();
+
+	public Attrs(Attrs... attrs) {
+		for (Attrs a : attrs) {
+			if (a != null) {
+				putAll(a);
+			}
+		}
+	}
+
+	public void clear() {
+		map.clear();
+	}
+
+	public boolean containsKey(String name) {
+		if (map == null)
+			return false;
+
+		return map.containsKey(name);
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated public boolean containsKey(Object name) {
+		assert name instanceof String;
+		if (map == null)
+			return false;
+
+		return map.containsKey((String) name);
+	}
+
+	public boolean containsValue(String value) {
+		if (map == null)
+			return false;
+
+		return map.containsValue(value);
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated public boolean containsValue(Object value) {
+		assert value instanceof String;
+		if (map == null)
+			return false;
+
+		return map.containsValue((String) value);
+	}
+
+	public Set<java.util.Map.Entry<String, String>> entrySet() {
+		if (map == null)
+			return EMPTY.entrySet();
+
+		return map.entrySet();
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated public String get(Object key) {
+		assert key instanceof String;
+		if (map == null)
+			return null;
+
+		return map.get((String) key);
+	}
+
+	public String get(String key) {
+		if (map == null)
+			return null;
+
+		return map.get(key);
+	}
+
+	public String get(String key, String deflt) {
+		String s = get(key);
+		if (s == null)
+			return deflt;
+		return s;
+	}
+
+	public boolean isEmpty() {
+		return map == null || map.isEmpty();
+	}
+
+	public Set<String> keySet() {
+		if (map == null)
+			return EMPTY.keySet();
+
+		return map.keySet();
+	}
+
+	public String put(String key, String value) {
+		if (map == null)
+			map = new LinkedHashMap<String, String>();
+
+		Matcher m = TYPED.matcher(key);
+		if (m.matches()) {
+			key = m.group(1);
+			String type = m.group(2);
+			Type t = Type.STRING;
+
+			if ( type.startsWith("List")) {
+				type = m.group(3);
+				if ( "String".equals(type))
+					t = Type.STRINGS;
+				else if ( "Long".equals(type))
+					t = Type.LONGS;
+				else if ( "Double".equals(type))
+					t = Type.DOUBLES;
+				else if ( "Version".equals(type))
+					t = Type.VERSIONS;				
+			} else {
+				if ( "String".equals(type))
+					t = Type.STRING;
+				else if ( "Long".equals(type))
+					t = Type.LONG;
+				else if ( "Double".equals(type))
+					t = Type.DOUBLE;
+				else if ( "Version".equals(type))
+					t = Type.VERSION;
+			}
+			if (types == null)
+				types = new LinkedHashMap<String, Type>();
+			types.put(key, t);
+
+			// TODO verify value?
+		}
+
+		return map.put(key, value);
+	}
+
+	public Type getType(String key) {
+		if (types == null)
+			return Type.STRING;
+		Type t = types.get(key);
+		if (t == null)
+			return Type.STRING;
+		return t;
+	}
+
+	public void putAll(Map<? extends String, ? extends String> map) {
+		for (Map.Entry<? extends String, ? extends String> e : map.entrySet())
+			put(e.getKey(), e.getValue());
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated public String remove(Object var0) {
+		assert var0 instanceof String;
+		if (map == null)
+			return null;
+
+		return map.remove((String) var0);
+	}
+
+	public String remove(String var0) {
+		if (map == null)
+			return null;
+		return map.remove(var0);
+	}
+
+	public int size() {
+		if (map == null)
+			return 0;
+		return map.size();
+	}
+
+	public Collection<String> values() {
+		if (map == null)
+			return EMPTY.values();
+
+		return map.values();
+	}
+
+	public String getVersion() {
+		return get("version");
+	}
+
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		append(sb);
+		return sb.toString();
+	}
+
+	public void append(StringBuilder sb) {
+		String del = "";
+		for (Map.Entry<String, String> e : entrySet()) {
+			sb.append(del);
+			sb.append(e.getKey());
+			sb.append("=");
+			sb.append(e.getValue());
+			del = ";";
+		}
+	}
+
+	@Deprecated public boolean equals(Object other) {
+		return super.equals(other);
+	}
+
+	@Deprecated public int hashCode() {
+		return super.hashCode();
+	}
+
+	public boolean isEqual(Attrs o) {
+		if (this == o)
+			return true;
+
+		Attrs other = o;
+
+		if (size() != other.size())
+			return false;
+
+		if (isEmpty())
+			return true;
+
+		SortedList<String> l = new SortedList<String>(keySet());
+		SortedList<String> lo = new SortedList<String>(other.keySet());
+		if (!l.isEqual(lo))
+			return false;
+
+		for (String key : keySet()) {
+			if (!get(key).equals(other.get(key)))
+				return false;
+		}
+		return true;
+
+	}
+
+	public Object getTyped(String adname) {
+		String s = get(adname);
+		if (s == null)
+			return null;
+
+		Type t = getType(adname);
+		return convert(t, s);
+	}
+
+	private Object convert(Type t, String s) {
+		if (t.sub == null) {
+			switch (t) {
+			case STRING:
+				return s;
+			case LONG:
+				return Long.parseLong(s.trim());
+			case VERSION:
+				return Version.parseVersion(s);
+			}
+			return null;
+		}
+		List<Object> list = new ArrayList<Object>();
+		String split[] = s.split("\\s*\\(\\?!\\),\\s*");
+		for (String p : split) {
+			p = p.replaceAll("\\\\", "");
+			list.add(convert(t.sub, p));
+		}
+		return list;
+	}
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Attrs.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Attrs.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,138 @@
+package aQute.libg.header;
+
+import java.util.*;
+
+import aQute.libg.generics.*;
+import aQute.libg.qtokens.*;
+import aQute.libg.reporter.*;
+
+public class OSGiHeader {
+
+	static public Parameters parseHeader(String value) {
+		return parseHeader(value, null);
+	}
+
+	/**
+	 * Standard OSGi header parser. This parser can handle the format clauses
+	 * ::= clause ( ',' clause ) + clause ::= name ( ';' name ) (';' key '='
+	 * value )
+	 * 
+	 * This is mapped to a Map { name => Map { attr|directive => value } }
+	 * 
+	 * @param value
+	 *            A string
+	 * @return a Map<String,Map<String,String>>
+	 */
+	static public Parameters parseHeader(String value, Reporter logger) {
+		return parseHeader(value, logger, new Parameters());
+	}
+
+	static public Parameters parseHeader(String value, Reporter logger, Parameters result) {
+		if (value == null || value.trim().length() == 0)
+			return result;
+
+		QuotedTokenizer qt = new QuotedTokenizer(value, ";=,");
+		char del = 0;
+		do {
+			boolean hadAttribute = false;
+			Attrs clause = new Attrs();
+			List<String> aliases = Create.list();
+			String name = qt.nextToken(",;");
+
+			del = qt.getSeparator();
+			if (name == null || name.length() == 0) {
+				if (logger != null && logger.isPedantic()) {
+					logger.warning("Empty clause, usually caused by repeating a comma without any name field or by having spaces after the backslash of a property file: "
+							+ value);
+				}
+				if (name == null)
+					break;
+			} else {
+				name = name.trim();
+
+				aliases.add(name);
+				while (del == ';') {
+					String adname = qt.nextToken();
+					if ((del = qt.getSeparator()) != '=') {
+						if (hadAttribute)
+							if (logger != null) {
+								logger.error("Header contains name field after attribute or directive: "
+										+ adname
+										+ " from "
+										+ value
+										+ ". Name fields must be consecutive, separated by a ';' like a;b;c;x=3;y=4");
+							}
+						if (adname != null && adname.length() > 0)
+							aliases.add(adname.trim());
+					} else {
+						String advalue = qt.nextToken();
+						if (clause.containsKey(adname)) {
+							if (logger != null && logger.isPedantic())
+								logger.warning("Duplicate attribute/directive name " + adname
+										+ " in " + value
+										+ ". This attribute/directive will be ignored");
+						}
+						if (advalue == null) {
+							if (logger != null)
+								logger.error("No value after '=' sign for attribute " + adname);
+							advalue = "";
+						}
+						clause.put(adname.trim(), advalue.trim());
+						del = qt.getSeparator();
+						hadAttribute = true;
+					}
+				}
+
+				// Check for duplicate names. The aliases list contains
+				// the list of nams, for each check if it exists. If so,
+				// add a number of "~" to make it unique.
+				for (String clauseName : aliases) {
+					if (result.containsKey(clauseName)) {
+						if (logger != null && logger.isPedantic())
+							logger.warning("Duplicate name "
+									+ clauseName
+									+ " used in header: '"
+									+ clauseName
+									+ "'. Duplicate names are specially marked in Bnd with a ~ at the end (which is stripped at printing time).");
+						while (result.containsKey(clauseName))
+							clauseName += "~";
+					}
+					result.put(clauseName, clause);
+				}
+			}
+		} while (del == ',');
+		return result;
+	}
+
+	public static Attrs parseProperties(String input) {
+		return parseProperties(input, null);
+	}
+
+	public static Attrs parseProperties(String input, Reporter logger) {
+		if (input == null || input.trim().length() == 0)
+			return new Attrs();
+
+		Attrs result = new Attrs();
+		QuotedTokenizer qt = new QuotedTokenizer(input, "=,");
+		char del = ',';
+
+		while (del == ',') {
+			String key = qt.nextToken(",=");
+			String value = "";
+			del = qt.getSeparator();
+			if (del == '=') {
+				value = qt.nextToken(",=");
+				del = qt.getSeparator();
+			}
+			result.put(key, value);
+		}
+		if (del != 0) {
+			if (logger == null)
+				throw new IllegalArgumentException("Invalid syntax for properties: " + input);
+			logger.error("Invalid syntax for properties: " + input);
+		}
+
+		return result;
+	}
+
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Parameters.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Parameters.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Parameters.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Parameters.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,203 @@
+package aQute.libg.header;
+
+import java.util.*;
+
+import aQute.lib.collections.*;
+import aQute.libg.reporter.*;
+
+public class Parameters implements Map<String, Attrs> {
+	private LinkedHashMap<String, Attrs>	map;
+	static Map<String, Attrs>				EMPTY	= Collections.emptyMap();
+	String									error;
+
+	public Parameters() {
+	}
+
+	public Parameters(String header) {
+		OSGiHeader.parseHeader(header, null, this);
+	}
+
+	public Parameters(String header, Reporter reporter) {
+		OSGiHeader.parseHeader(header, reporter, this);
+	}
+
+	public void clear() {
+		map.clear();
+	}
+
+	public boolean containsKey(final String name) {
+		if (map == null)
+			return false;
+
+		return map.containsKey(name);
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated public boolean containsKey(Object name) {
+		assert name instanceof String;
+		if (map == null)
+			return false;
+
+		return map.containsKey((String) name);
+	}
+
+	public boolean containsValue(Attrs value) {
+		if (map == null)
+			return false;
+
+		return map.containsValue(value);
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated public boolean containsValue(Object value) {
+		assert value instanceof Attrs;
+		if (map == null)
+			return false;
+
+		return map.containsValue((Attrs) value);
+	}
+
+	public Set<java.util.Map.Entry<String, Attrs>> entrySet() {
+		if (map == null)
+			return EMPTY.entrySet();
+
+		return map.entrySet();
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated public Attrs get(Object key) {
+		assert key instanceof String;
+		if (map == null)
+			return null;
+
+		return map.get((String) key);
+	}
+
+	public Attrs get(String key) {
+		if (map == null)
+			return null;
+
+		return map.get(key);
+	}
+
+	public boolean isEmpty() {
+		return map == null || map.isEmpty();
+	}
+
+	public Set<String> keySet() {
+		if (map == null)
+			return EMPTY.keySet();
+
+		return map.keySet();
+	}
+
+	public Attrs put(String key, Attrs value) {
+		assert key != null;
+		assert value != null;
+
+		if (map == null)
+			map = new LinkedHashMap<String, Attrs>();
+
+		return map.put(key, value);
+	}
+
+	public void putAll(Map<? extends String, ? extends Attrs> map) {
+		if (this.map == null) {
+			if (map.isEmpty())
+				return;
+			this.map = new LinkedHashMap<String, Attrs>();
+		}
+		this.map.putAll(map);
+	}
+	public void putAllIfAbsent(Map<String, ? extends Attrs> map) {
+		for(Map.Entry<String, ? extends Attrs> entry : map.entrySet() ) {
+			if ( !containsKey(entry.getKey()))
+				put(entry.getKey(), entry.getValue());
+		}
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated public Attrs remove(Object var0) {
+		assert var0 instanceof String;
+		if (map == null)
+			return null;
+
+		return map.remove((String) var0);
+	}
+
+	public Attrs remove(String var0) {
+		if (map == null)
+			return null;
+		return map.remove(var0);
+	}
+
+	public int size() {
+		if (map == null)
+			return 0;
+		return map.size();
+	}
+
+	public Collection<Attrs> values() {
+		if (map == null)
+			return EMPTY.values();
+
+		return map.values();
+	}
+
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		append(sb);
+		return sb.toString();
+	}
+
+	public void append(StringBuilder sb) {
+		String del = "";
+		for (Map.Entry<String, Attrs> s : entrySet()) {
+			sb.append(del);
+			sb.append(s.getKey());
+			if (!s.getValue().isEmpty()) {
+				sb.append(';');
+				s.getValue().append(sb);
+			}
+
+			del = ",";
+		}
+	}
+
+	@Deprecated
+	public boolean equals(Object other) {
+		return super.equals(other);
+	}
+	
+	@Deprecated
+	public int hashCode() {
+		return super.hashCode();
+	}
+	
+
+	public boolean isEqual(Parameters other) {
+		if (this == other)
+			return true;
+
+		if (size() != other.size())
+			return false;
+
+		if (isEmpty())
+			return true;
+
+		SortedList<String> l = new SortedList<String>(keySet());
+		SortedList<String> lo = new SortedList<String>(other.keySet());
+		if (!l.isEqual(lo))
+			return false;
+
+		for (String key : keySet()) {
+			if (!get(key).isEqual(other.get(key)))
+				return false;
+		}
+		return true;
+	}
+
+	public Map<String,? extends Map<String,String>> asMapMap() {
+		return this;
+	}
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Parameters.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/Parameters.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/header/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/header/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/header/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/header/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.1.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/log/Logger.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/log/Logger.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/log/Logger.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/log/Logger.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,16 @@
+package aQute.libg.log;
+
+import java.util.*;
+
+
+public interface Logger {
+	void error(String s, Object ... args);
+	void warning(String s, Object ... args);
+	void progress(String s, Object ... args);
+	
+	List<String> getWarnings();
+	List<String> getErrors();
+	List<String> getProgress();
+	
+	boolean isPedantic();
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/log/Logger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/log/Logger.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/log/Logger.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/log/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/log/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/log/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/log/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/map/MAP.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/map/MAP.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/map/MAP.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/map/MAP.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,45 @@
+package aQute.libg.map;
+
+import java.util.*;
+
+/**
+ * Easy way to build a map:
+ * 
+ * 	Map<String,Integer> s = MAP.$("a",2).$("b",3);
+ *
+ */
+public class MAP {
+
+	static public class MAPX<K, V> extends LinkedHashMap<K, V> {
+		private static final long	serialVersionUID	= 1L;
+		public MAPX<K, V> $(K key, V value) {
+			put(key, value);
+			return this;
+		}
+
+		public MAPX<K, V> $(Map<K,V> all) {
+			putAll(all);
+			return this;
+		}
+		public Hashtable<K,V> asHashtable() {
+			return new Hashtable<K,V>(this);
+		}
+	}
+
+	public static <Kx, Vx> MAPX<Kx, Vx> $(Kx key, Vx value) {
+		MAPX<Kx, Vx> map = new MAPX<Kx, Vx>();
+		map.put(key, value);
+		return map;
+	}
+	
+	
+	public <K,V> Map<K,V> dictionary(Dictionary<K,V> dict ) {
+		Map<K,V> map = new LinkedHashMap<K, V>();
+		for ( Enumeration<K> e = dict.keys(); e.hasMoreElements(); ) {
+			K k = e.nextElement();
+			V v = dict.get(k);
+			map.put(k,v);
+		}
+		return map;
+	}
+}
\ No newline at end of file

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/map/MAP.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/map/MAP.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/map/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/map/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/map/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/map/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.2.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/QuotedTokenizer.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/QuotedTokenizer.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/QuotedTokenizer.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/QuotedTokenizer.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,116 @@
+package aQute.libg.qtokens;
+
+import java.util.*;
+
+import aQute.libg.generics.*;
+
+public class QuotedTokenizer {
+	String	string;
+	int		index				= 0;
+	String	separators;
+	boolean	returnTokens;
+	boolean	ignoreWhiteSpace	= true;
+	String	peek;
+	char	separator;
+
+	public QuotedTokenizer(String string, String separators, boolean returnTokens ) {
+		if ( string == null )
+			throw new IllegalArgumentException("string argument must be not null");
+		this.string = string;
+		this.separators = separators;
+		this.returnTokens = returnTokens;
+	}
+	public QuotedTokenizer(String string, String separators) {
+		this(string,separators,false);
+	}
+
+	public String nextToken(String separators) {
+		separator = 0;
+		if ( peek != null ) {
+			String tmp = peek;
+			peek = null;
+			return tmp;
+		}
+		
+		if ( index == string.length())
+			return null;
+		
+		StringBuilder sb = new StringBuilder();
+
+		while (index < string.length()) {
+			char c = string.charAt(index++);
+
+			if ( Character.isWhitespace(c)) {
+				if ( index == string.length())
+					break;
+				sb.append(c);
+				continue;
+			}
+			
+			if (separators.indexOf(c) >= 0) {
+				if (returnTokens)
+					peek = Character.toString(c);
+				else
+					separator = c;
+				break;
+			}
+
+			switch (c) {
+				case '"' :
+				case '\'' :
+					quotedString(sb, c);
+					break;
+
+				default :
+					sb.append(c);
+			}
+		}
+		String result = sb.toString().trim();
+		if ( result.length()==0 && index==string.length())
+			return null;
+		return result;
+	}
+
+	public String nextToken() {
+		return nextToken(separators);
+	}
+
+	private void quotedString(StringBuilder sb, char c) {
+		char quote = c;
+		while (index < string.length()) {
+			c = string.charAt(index++);
+			if (c == quote)
+				break;
+			if (c == '\\' && index < string.length()
+					&& string.charAt(index + 1) == quote)
+				c = string.charAt(index++);
+			sb.append(c);
+		}
+	}
+
+	public String[] getTokens() {
+		return getTokens(0);
+	}
+
+	private String [] getTokens(int cnt){
+		String token = nextToken();
+		if ( token == null ) 
+			return new String[cnt];
+		
+		String result[] = getTokens(cnt+1);
+		result[cnt]=token;
+		return result;
+	}
+
+	public char getSeparator() { return separator; }
+	
+	public List<String> getTokenSet() {
+		List<String> list = Create.list();
+		String token = nextToken();
+		while ( token != null ) {
+			list.add(token);
+			token = nextToken();
+		}
+		return list;
+	}
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/QuotedTokenizer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/QuotedTokenizer.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/QuotedTokenizer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,15 @@
+package aQute.libg.reporter;
+
+import java.util.*;
+
+
+public interface Reporter {
+	void error(String s, Object ... args);
+	void warning(String s, Object ... args);
+	void progress(String s, Object ... args);
+	void trace(String s, Object ... args);
+	List<String> getWarnings();
+	List<String> getErrors();
+	
+	boolean isPedantic();
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,182 @@
+package aQute.libg.reporter;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.libg.generics.*;
+
+/**
+ * Mainly used for testing where reporters are needed.
+ * 
+ */
+public class ReporterAdapter implements Reporter {
+	final List<String>	errors		= new ArrayList<String>();
+	final List<String>	warnings	= new ArrayList<String>();
+	final Formatter		out;
+	boolean				trace;
+	boolean				pedantic;
+	boolean				exceptions;
+
+	/**
+	 * @return the exceptions
+	 */
+	public boolean isExceptions() {
+		return exceptions;
+	}
+
+	/**
+	 * @param exceptions
+	 *            the exceptions to set
+	 */
+	public void setExceptions(boolean exceptions) {
+		this.exceptions = exceptions;
+	}
+
+	/**
+	 * @return the out
+	 */
+	public Formatter getOut() {
+		return out;
+	}
+
+	/**
+	 * @return the trace
+	 */
+	public boolean isTrace() {
+		return trace;
+	}
+
+	/**
+	 * @param pedantic
+	 *            the pedantic to set
+	 */
+	public void setPedantic(boolean pedantic) {
+		this.pedantic = pedantic;
+	}
+
+	public ReporterAdapter() {
+		out = null;
+	}
+
+	public ReporterAdapter(Appendable app) {
+		out = new Formatter(app);
+	}
+
+	public void error(String s, Object... args) {
+		String e = String.format(s, args);
+		errors.add(e);
+		trace("ERROR: %s", e);
+	}
+
+	public void exception(Throwable t, String s, Object... args) {
+		String e = String.format(s, args);
+		errors.add(e);
+		trace("ERROR: %s", e);
+		if (isExceptions() || isTrace())
+			if ( t instanceof InvocationTargetException )
+				t.getCause().printStackTrace(System.err);
+			else
+				t.printStackTrace(System.err);
+	}
+
+	public void warning(String s, Object... args) {
+		String e = String.format(s, args);
+		warnings.add(e);
+		trace("warning: %s", e);
+	}
+
+	public void progress(String s, Object... args) {
+		if (out != null) {
+			out.format(s, args);
+			if ( !s.endsWith("\n"))
+				out.format("\n");
+		}
+	}
+
+	public void trace(String s, Object... args) {
+		if (trace && out != null) {
+			out.format("# "+s+"\n", args);
+			out.flush();
+		}
+	}
+
+	public List<String> getWarnings() {
+		return warnings;
+	}
+
+	public List<String> getErrors() {
+		return errors;
+	}
+
+	public boolean isPedantic() {
+		return false;
+	}
+
+	public void setTrace(boolean b) {
+		this.trace = b;
+	}
+
+	public boolean isOk() {
+		return errors.isEmpty();
+	}
+
+	public boolean isPerfect() {
+		return isOk() && warnings.isEmpty();
+	}
+
+	public boolean check(String... pattern) {
+		Set<String> missed = Create.set();
+
+		if (pattern != null) {
+			for (String p : pattern) {
+				boolean match = false;
+				Pattern pat = Pattern.compile(p);
+				for (Iterator<String> i = errors.iterator(); i.hasNext();) {
+					if (pat.matcher(i.next()).find()) {
+						i.remove();
+						match = true;
+					}
+				}
+				for (Iterator<String> i = warnings.iterator(); i.hasNext();) {
+					if (pat.matcher(i.next()).find()) {
+						i.remove();
+						match = true;
+					}
+				}
+				if (!match)
+					missed.add(p);
+
+			}
+		}
+		if (missed.isEmpty() && isPerfect())
+			return true;
+
+		if (!missed.isEmpty())
+			error("Missed the following patterns in the warnings or errors: %s", missed);
+
+		return false;
+	}
+
+	/**
+	 * Report the errors and warnings
+	 */
+
+	public void report(Appendable out) {
+		Formatter f = new Formatter(out);
+		report("Error", getErrors(), f);
+		report("Warning", getWarnings(), f);
+		f.flush();
+	}
+
+	void report(String title, Collection<String> list, Formatter f) {
+		if (list.isEmpty())
+			return;
+		f.format(title + (list.size() > 1 ? "s" : "")+"\n");
+		int n=0;
+		for (String s : list) {
+			f.format("%3s. %s\n", n++, s);
+		}
+	}
+
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.2

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,8 @@
+package aQute.libg.sax;
+
+import org.xml.sax.ContentHandler;
+
+public interface ContentFilter extends ContentHandler {
+	void setParent(ContentHandler parent);
+	ContentHandler getParent();
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,71 @@
+package aQute.libg.sax;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+public class ContentFilterImpl implements ContentFilter {
+
+	private ContentHandler parent;
+
+	public void setParent(ContentHandler parent) {
+		this.parent = parent;
+		
+	}
+
+	public ContentHandler getParent() {
+		return parent;
+	}
+
+	public void setDocumentLocator(Locator locator) {
+		parent.setDocumentLocator(locator);
+	}
+
+	public void startDocument() throws SAXException {
+		parent.startDocument();
+	}
+
+	public void endDocument() throws SAXException {
+		parent.endDocument();
+	}
+
+	public void startPrefixMapping(String prefix, String uri)
+			throws SAXException {
+		parent.startPrefixMapping(prefix, uri);
+	}
+
+	public void endPrefixMapping(String prefix) throws SAXException {
+		parent.endPrefixMapping(prefix);
+	}
+
+	public void startElement(String uri, String localName, String qName,
+			Attributes atts) throws SAXException {
+		parent.startElement(uri, localName, qName, atts);
+	}
+
+	public void endElement(String uri, String localName, String qName)
+			throws SAXException {
+		parent.endElement(uri, localName, qName);
+	}
+
+	public void characters(char[] ch, int start, int length)
+			throws SAXException {
+		parent.characters(ch, start, length);
+	}
+
+	public void ignorableWhitespace(char[] ch, int start, int length)
+			throws SAXException {
+		parent.ignorableWhitespace(ch, start, length);
+	}
+
+	public void processingInstruction(String target, String data)
+			throws SAXException {
+		parent.processingInstruction(target, data);
+	}
+
+	public void skippedEntity(String name) throws SAXException {
+		parent.skippedEntity(name);
+	}
+
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,36 @@
+package aQute.libg.sax;
+
+import org.xml.sax.Attributes;
+
+public class SAXElement {
+
+	private final String uri;
+	private final String localName;
+	private final String qName;
+	private final Attributes atts;
+
+	public SAXElement(String uri, String localName, String qName,
+			Attributes atts) {
+		this.uri = uri;
+		this.localName = localName;
+		this.qName = qName;
+		this.atts = atts;
+	}
+
+	public String getUri() {
+		return uri;
+	}
+
+	public String getLocalName() {
+		return localName;
+	}
+
+	public String getqName() {
+		return qName;
+	}
+
+	public Attributes getAtts() {
+		return atts;
+	}
+
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,29 @@
+package aQute.libg.sax;
+
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.XMLReader;
+
+public class SAXUtil {
+	
+	public static XMLReader buildPipeline(Result output, ContentFilter... filters) throws Exception {
+		SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+		TransformerHandler handler = factory.newTransformerHandler();
+		handler.setResult(output);
+		
+		ContentHandler last = handler;
+		if (filters != null) for (ContentFilter filter : filters) {
+			filter.setParent(last);
+			last = filter;
+		}
+		XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
+		reader.setContentHandler(last);
+		
+		return reader;
+	}
+	
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,49 @@
+package aQute.libg.sax.filters;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import aQute.libg.sax.ContentFilterImpl;
+
+public abstract class ElementSelectionFilter extends ContentFilterImpl{
+	
+	int depth = 0;
+	int hiddenDepth = -1;
+	
+	protected abstract boolean select(int depth, String uri, String localName, String qName, Attributes attribs);
+	
+	@Override
+	public final void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+		if (hiddenDepth < 0) {
+			boolean allow = select(depth, uri, localName, qName, atts);
+			if (allow)
+				super.startElement(uri, localName, qName, atts);
+			else
+				hiddenDepth = 0;
+		} else {
+			hiddenDepth ++;
+		}
+		depth++;
+	}
+	
+	@Override
+	public final void endElement(String uri, String localName, String qName) throws SAXException {
+		if (hiddenDepth < 0) {
+			super.endElement(uri, localName, qName);
+		} else {
+			hiddenDepth --;
+		}
+		depth --;
+	}
+	
+	@Override
+	public void characters(char[] ch, int start, int length) throws SAXException {
+		if (hiddenDepth < 0) super.characters(ch, start, length);
+	}
+	
+	@Override
+	public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+		if (hiddenDepth < 0) super.ignorableWhitespace(ch, start, length);
+	}
+	
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,57 @@
+package aQute.libg.sax.filters;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import aQute.libg.sax.ContentFilterImpl;
+import aQute.libg.sax.SAXElement;
+
+public class MergeContentFilter extends ContentFilterImpl {
+
+	private int elementDepth = 0;
+	
+	private final List<SAXElement> rootElements = new LinkedList<SAXElement>();
+	
+	@Override
+	public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+		if (elementDepth++ == 0) {
+			if (rootElements.isEmpty())
+				super.startElement(uri, localName, qName, atts);
+			else if (!rootElements.get(0).getqName().equals(qName))
+				throw new SAXException(String.format("Documents have inconsistent root element names: first was %s, current is %s.", rootElements.get(0).getqName(), qName));
+			rootElements.add(new SAXElement(uri, localName, qName, atts));
+		} else {
+			super.startElement(uri, localName, qName, atts);
+		}
+	}
+
+	@Override
+	public void endElement(String uri, String localName, String qName) throws SAXException {
+		if (--elementDepth > 0) {
+			super.endElement(uri, localName, qName);
+		}
+	}
+	
+	@Override
+	public void processingInstruction(String target, String data) throws SAXException {
+		if (rootElements.isEmpty())
+			super.processingInstruction(target, data);
+	}
+	
+	public void closeRootAndDocument() throws SAXException {
+		if (!rootElements.isEmpty()) {
+			SAXElement root = rootElements.get(0);
+			super.endElement(root.getUri(), root.getLocalName(), root.getqName());
+		}
+		super.endDocument();
+	}
+	
+	public List<SAXElement> getRootElements() {
+		return Collections.unmodifiableList(rootElements);
+	}
+
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/filters/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sax/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Replacer.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Replacer.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Replacer.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Replacer.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,5 @@
+package aQute.libg.sed;
+
+public interface Replacer {
+    String process(String line);
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Replacer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Replacer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Sed.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Sed.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Sed.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Sed.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,99 @@
+package aQute.libg.sed;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+public class Sed {
+    final File                 file;
+    final Replacer             macro;
+    File                       output;
+    boolean backup = true;
+
+    final Map<Pattern, String> replacements = new LinkedHashMap<Pattern, String>();
+
+    public Sed(Replacer macro, File file) {
+        assert file.isFile();
+        this.file = file;
+        this.macro = macro;
+    }
+    
+    public Sed(File file) {
+        assert file.isFile();
+        this.file = file;
+        this.macro = null;
+    }
+
+    public void setOutput(File f) {
+        output = f;
+    }
+
+    public void replace(String pattern, String replacement) {
+        replacements.put(Pattern.compile(pattern), replacement);
+    }
+
+    public int doIt() throws IOException {
+    	int actions = 0;
+        BufferedReader brdr = new BufferedReader(new InputStreamReader( new FileInputStream(file),"UTF-8"));
+        File out;
+        if (output != null)
+            out = output;
+        else
+            out = new File(file.getAbsolutePath() + ".tmp");
+        PrintWriter pw = new PrintWriter(new OutputStreamWriter( new FileOutputStream(out),"UTF-8"));
+        try {
+            String line;
+            while ((line = brdr.readLine()) != null) {
+                for (Pattern p : replacements.keySet()) {
+                    String replace = replacements.get(p);
+                    Matcher m = p.matcher(line);
+
+                    StringBuffer sb = new StringBuffer();
+                    while (m.find()) {
+                        String tmp = setReferences(m, replace);
+                        if ( macro != null)
+                        	tmp = Matcher.quoteReplacement(macro.process(tmp));
+                        m.appendReplacement(sb, tmp);
+                        actions++;
+                    }
+                    m.appendTail(sb);
+
+                    line = sb.toString();
+                }
+                pw.println(line);
+            }
+            pw.close();
+            if (output == null) {
+            	if ( backup ) {
+                    File bak = new File(file.getAbsolutePath() + ".bak");
+            		file.renameTo(bak);
+            	}
+                out.renameTo(file);
+            }
+        } finally {
+            brdr.close();
+            pw.close();
+        }
+        return actions;
+    }
+
+    private String setReferences(Matcher m, String replace) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < replace.length(); i++) {
+            char c = replace.charAt(i);
+            if (c == '$' && i < replace.length() - 1
+                    && Character.isDigit(replace.charAt(i + 1))) {
+                int n = replace.charAt(i + 1) - '0';
+                if ( n <= m.groupCount() )
+                    sb.append(m.group(n));
+                i++;
+            } else
+                sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    public void setBackup(boolean b) {
+    	this.backup=b;
+    }
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Sed.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/Sed.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0.1

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/Tarjan.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/Tarjan.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/Tarjan.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/Tarjan.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,108 @@
+package aQute.libg.tarjan;
+
+import static java.lang.Math.*;
+
+import java.util.*;
+
+public class Tarjan<T> {
+
+	public class Node {
+		final T				name;
+		final List<Node>	adjacent	= new ArrayList<Node>();
+		int					low			= -1;
+		int					index		= -1;
+
+		public Node(T name) {
+			this.name = name;
+		}
+		
+		public String toString() {
+			return name + "{" + index + "," + low + "}";
+		}
+	}
+
+	private int				index	= 0;
+	private List<Node>		stack	= new ArrayList<Node>();
+	private Set<Set<T>>	scc		= new HashSet<Set<T>>();
+	private Node			root	= new Node(null);
+
+	
+//	   public ArrayList<ArrayList<Node>> tarjan(Node v, AdjacencyList list){
+//	       v.index = index;
+//	       v.lowlink = index;
+//	       index++;
+//	       stack.add(0, v);
+//	       for(Edge e : list.getAdjacent(v)){
+//	           Node n = e.to;
+//	           if(n.index == -1){
+//	               tarjan(n, list);
+//	               v.lowlink = Math.min(v.lowlink, n.lowlink);
+//	           }else if(stack.contains(n)){
+//	               v.lowlink = Math.min(v.lowlink, n.index);
+//	           }
+//	       }
+//	       if(v.lowlink == v.index){
+//	           Node n;
+//	           ArrayList<Node> component = new ArrayList<Node>();
+//	           do{
+//	               n = stack.remove(0);
+//	               component.add(n);
+//	           }while(n != v);
+//	           SCC.add(component);
+//	       }
+//	       return SCC;
+//	   }
+
+	void tarjan(Node v) {
+		v.index = index;
+		v.low = index;
+		index++;
+		stack.add(0, v);
+		for (Node n : v.adjacent) {
+			if (n.index == -1) {
+				// first time visit
+				tarjan(n);
+				v.low = min(v.low, n.low);
+			} else if (stack.contains(n)) {
+				v.low = min(v.low, n.index);
+			}
+		}
+
+		if (v!=root && v.low == v.index) {
+			Set<T> component = new HashSet<T>();
+			Node n;
+			do {
+				n = stack.remove(0);
+				component.add(n.name);
+			} while (n != v);
+			scc.add(component);
+		}
+	}
+
+	Set<Set<T>> getResult(Map<T, ? extends Collection<T>> graph) {
+		Map<T, Node> index = new HashMap<T, Node>();
+
+		for (Map.Entry<T, ? extends Collection<T>> entry : graph.entrySet()) {
+			Node node = getNode(index, entry.getKey());
+			root.adjacent.add(node);
+			for (T adj : entry.getValue())
+				node.adjacent.add(getNode(index, adj));
+		}
+		tarjan(root);
+		return scc;
+	}
+
+	private Node getNode(Map<T, Node> index, T key) {
+		Node node = index.get(key);
+		if (node == null) {
+			node = new Node(key);
+			index.put(key, node);
+		}
+		return node;
+	}
+
+	public static <T> Collection<? extends Collection<T>> tarjan(Map<T, ? extends Collection<T>> graph) {
+		Tarjan<T> tarjan = new Tarjan<T>();
+		return tarjan.getResult(graph);
+	}
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/Tarjan.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/Tarjan.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/tarjan/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,11 @@
+package aQute.libg.tuple;
+
+public class Pair<A,B> {
+	final public A a;
+	final public B b;
+	
+	public Pair(A a, B b) {
+		this.a = a;
+		this.b = b;
+	}
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/Pair.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/tuple/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/Version.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/version/Version.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/version/Version.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/version/Version.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,166 @@
+package aQute.libg.version;
+
+import java.util.regex.*;
+
+public class Version implements Comparable<Version> {
+    final int                   major;
+    final int                   minor;
+    final int                   micro;
+    final String                qualifier;
+    public final static String  VERSION_STRING = "(\\d+)(\\.(\\d+)(\\.(\\d+)(\\.([-_\\da-zA-Z]+))?)?)?";
+    public final static Pattern VERSION        = Pattern
+                                                       .compile(VERSION_STRING);
+    public final static Version LOWEST         = new Version();
+    public final static Version HIGHEST        = new Version(Integer.MAX_VALUE,
+                                                       Integer.MAX_VALUE,
+                                                       Integer.MAX_VALUE,
+                                                       "\uFFFF");
+
+    public static final Version	emptyVersion	= LOWEST;
+    public static final Version	ONE	= new Version(1,0,0);
+
+    public Version() {
+        this(0);
+    }
+
+    public Version(int major, int minor, int micro, String qualifier) {
+        this.major = major;
+        this.minor = minor;
+        this.micro = micro;
+        this.qualifier = qualifier;
+    }
+
+    public Version(int major, int minor, int micro) {
+        this(major, minor, micro, null);
+    }
+
+    public Version(int major, int minor) {
+        this(major, minor, 0, null);
+    }
+
+    public Version(int major) {
+        this(major, 0, 0, null);
+    }
+
+    public Version(String version) {
+    	version = version.trim();
+        Matcher m = VERSION.matcher(version);
+        if (!m.matches())
+            throw new IllegalArgumentException("Invalid syntax for version: "
+                    + version);
+
+        major = Integer.parseInt(m.group(1));
+        if (m.group(3) != null)
+            minor = Integer.parseInt(m.group(3));
+        else
+            minor = 0;
+
+        if (m.group(5) != null)
+            micro = Integer.parseInt(m.group(5));
+        else
+            micro = 0;
+
+        qualifier = m.group(7);
+    }
+
+    public int getMajor() {
+        return major;
+    }
+
+    public int getMinor() {
+        return minor;
+    }
+
+    public int getMicro() {
+        return micro;
+    }
+
+    public String getQualifier() {
+        return qualifier;
+    }
+
+    public int compareTo(Version other) {
+        if (other == this)
+            return 0;
+
+        Version o = other;
+        if (major != o.major)
+            return major - o.major;
+
+        if (minor != o.minor)
+            return minor - o.minor;
+
+        if (micro != o.micro)
+            return micro - o.micro;
+
+        int c = 0;
+        if (qualifier != null)
+            c = 1;
+        if (o.qualifier != null)
+            c += 2;
+
+        switch (c) {
+        case 0:
+            return 0;
+        case 1:
+            return 1;
+        case 2:
+            return -1;
+        }
+        return qualifier.compareTo(o.qualifier);
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(major);
+        sb.append(".");
+        sb.append(minor);
+        sb.append(".");
+        sb.append(micro);
+        if (qualifier != null) {
+            sb.append(".");
+            sb.append(qualifier);
+        }
+        return sb.toString();
+    }
+
+    public boolean equals(Object ot) {
+        if ( ! (ot instanceof Version))
+            return false;
+        
+        return compareTo((Version)ot) == 0;
+    }
+
+    public int hashCode() {
+        return major * 97 ^ minor * 13 ^ micro
+                + (qualifier == null ? 97 : qualifier.hashCode());
+    }
+
+    public int get(int i) {
+        switch(i) {
+        case 0 : return major;
+        case 1 : return minor;
+        case 2 : return micro;
+        default:
+            throw new IllegalArgumentException("Version can only get 0 (major), 1 (minor), or 2 (micro)");
+        }
+    }
+    
+    public static Version parseVersion(String version) {
+		if (version == null) {
+			return LOWEST;
+		}
+
+		version = version.trim();
+		if (version.length() == 0) {
+			return LOWEST;
+		}
+
+		return new Version(version);
+
+    }
+    
+    public Version getWithoutQualifier() {
+    	return new Version(major,minor,micro);
+    }
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/Version.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/Version.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/Version.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/VersionRange.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/version/VersionRange.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/version/VersionRange.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/version/VersionRange.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,96 @@
+package aQute.libg.version;
+
+import java.util.*;
+import java.util.regex.*;
+
+public class VersionRange {
+	Version			high;
+	Version			low;
+	char			start	= '[';
+	char			end		= ']';
+
+	static Pattern	RANGE	= Pattern.compile("(\\(|\\[)\\s*(" +
+									Version.VERSION_STRING + ")\\s*,\\s*(" +
+									Version.VERSION_STRING + ")\\s*(\\)|\\])");
+
+	public VersionRange(String string) {
+		string = string.trim();
+		Matcher m = RANGE.matcher(string);
+		if (m.matches()) {
+			start = m.group(1).charAt(0);
+			String v1 = m.group(2);
+			String v2 = m.group(10);
+			low = new Version(v1);
+			high = new Version(v2);
+			end = m.group(18).charAt(0);
+			if (low.compareTo(high) > 0)
+				throw new IllegalArgumentException(
+						"Low Range is higher than High Range: " + low + "-" +
+								high);
+
+		} else
+			high = low = new Version(string);
+	}
+
+	public boolean isRange() {
+		return high != low;
+	}
+
+	public boolean includeLow() {
+		return start == '[';
+	}
+
+	public boolean includeHigh() {
+		return end == ']';
+	}
+
+	public String toString() {
+		if (high == low)
+			return high.toString();
+
+		StringBuilder sb = new StringBuilder();
+		sb.append(start);
+		sb.append(low);
+		sb.append(',');
+		sb.append(high);
+		sb.append(end);
+		return sb.toString();
+	}
+
+	public Version getLow() {
+		return low;
+	}
+
+	public Version getHigh() {
+		return high;
+	}
+
+	public boolean includes(Version v) {
+		if ( !isRange() ) {
+			return low.compareTo(v) <=0;
+		}
+		if (includeLow()) {
+			if (v.compareTo(low) < 0)
+				return false;
+		} else if (v.compareTo(low) <= 0)
+			return false;
+
+		if (includeHigh()) {
+			if (v.compareTo(high) > 0)
+				return false;
+		} else if (v.compareTo(high) >= 0)
+			return false;
+		
+		return true;
+	}
+	
+	public Iterable<Version> filter( final Iterable<Version> versions) {
+		List<Version> list = new ArrayList<Version>();
+		for ( Version v : versions) {
+			if ( includes(v))
+				list.add(v);
+		}
+		return list;
+	}
+	
+}
\ No newline at end of file

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/VersionRange.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/VersionRange.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/VersionRange.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/version/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/version/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/version/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/version/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0.1

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java Thu Jun  7 21:57:32 2012
@@ -0,0 +1,44 @@
+package aQute.libg.xslt;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import javax.xml.transform.*;
+import javax.xml.transform.stream.*;
+
+public class Transform {
+    static TransformerFactory transformerFactory = TransformerFactory
+                                                         .newInstance();
+
+    static Map<URL, Templates> cache          = new ConcurrentHashMap<URL, 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);
+        if (templates == null) {
+            InputStream xsltIn = xslt.openStream();
+            try {
+                templates = transformerFactory
+                        .newTemplates(new StreamSource(xsltIn));
+
+                cache.put(xslt, templates);
+            } finally {
+                in.close();
+            }
+        }
+        Result xmlResult = new StreamResult(out);
+        Source xmlSource = new StreamSource(in);
+        Transformer t = templates.newTransformer();
+        t.transform(xmlSource, xmlResult);
+        out.flush();
+    }
+
+    public static void transform(URL xslt, InputStream in, OutputStream out) throws Exception {
+        transform(transformerFactory,xslt, in, out);
+    }
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/Transform.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/packageinfo?rev=1347815&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/packageinfo (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/libg/xslt/packageinfo Thu Jun  7 21:57:32 2012
@@ -0,0 +1 @@
+version 1.0

Modified: felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/AbstractDependencyFilter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/AbstractDependencyFilter.java?rev=1347815&r1=1347814&r2=1347815&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/AbstractDependencyFilter.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/AbstractDependencyFilter.java Thu Jun  7 21:57:32 2012
@@ -66,7 +66,7 @@ public abstract class AbstractDependency
 
         public DependencyFilter( String expression, String defaultValue )
         {
-            m_instruction = Instruction.getPattern( expression );
+            m_instruction = new Instruction( expression );
             m_defaultValue = defaultValue;
         }
 

Modified: felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java?rev=1347815&r1=1347814&r2=1347815&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java Thu Jun  7 21:57:32 2012
@@ -41,6 +41,7 @@ import javax.xml.transform.stream.Stream
 
 import aQute.bnd.service.AnalyzerPlugin;
 import aQute.lib.osgi.Analyzer;
+import aQute.lib.osgi.Descriptors.PackageRef;
 import aQute.lib.osgi.Jar;
 import aQute.lib.osgi.Processor;
 import aQute.lib.osgi.Resource;
@@ -74,7 +75,7 @@ public class BlueprintPlugin implements 
         Set<String> headers = Create.set();
 
         String bpHeader = analyzer.getProperty( "Bundle-Blueprint", "OSGI-INF/blueprint" );
-        Map<String, Map<String, String>> map = Processor.parseHeader( bpHeader, null );
+        Map<String, ? extends Map<String, String>> map = Processor.parseHeader( bpHeader, null );
         for ( String root : map.keySet() )
         {
             Jar jar = analyzer.getJar();
@@ -138,9 +139,10 @@ public class BlueprintPlugin implements 
                             continue;
                         }
                     }
-                    if ( !analyzer.getReferred().containsKey( pkg ) )
+                    PackageRef pkgRef = analyzer.getPackageRef( pkg );
+                    if ( !analyzer.getReferred().containsKey( pkgRef ) )
                     {
-                        analyzer.getReferred().put( pkg, a.getProperties() );
+                        analyzer.getReferred().put( pkgRef ).putAll( a.getProperties() );
                     }
                 }
             }

Modified: felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java?rev=1347815&r1=1347814&r2=1347815&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java Thu Jun  7 21:57:32 2012
@@ -757,8 +757,8 @@ public class BundlePlugin extends Abstra
             {
                 Set optionalPackages = getOptionalPackages( currentProject );
 
-                Map<String, Map<String, String>> values = new Analyzer().parseHeader( importPackages );
-                for ( Map.Entry<String, Map<String, String>> entry : values.entrySet() )
+                Map<String, ? extends Map<String, String>> values = new Analyzer().parseHeader( importPackages );
+                for ( Map.Entry<String, ? extends Map<String, String>> entry : values.entrySet() )
                 {
                     String pkg = entry.getKey();
                     Map<String, String> options = entry.getValue();