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/lib/osgi/Analyzer.java b/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
index 3c0c9b2..4f26d94 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
@@ -47,7 +47,7 @@
 
 public class Analyzer extends Processor {
 	private final SortedSet<Clazz.JAVA>				ees						= new TreeSet<Clazz.JAVA>();
-	static Manifest									bndInfo;
+	static Properties								bndInfo;
 
 	// Bundle parameters
 	private Jar										dot;
@@ -139,7 +139,7 @@
 				for (String dir : current.getDirectories().keySet()) {
 					PackageRef packageRef = getPackageRef(dir);
 					Resource resource = current.getResource(dir + "/packageinfo");
-					setPackageInfo(packageRef, resource, classpathExports);
+					getExportVersionsFromPackageInfo(packageRef, resource, classpathExports);
 				}
 			}
 
@@ -149,6 +149,7 @@
 			if (s != null) {
 				activator = getTypeRefFromFQN(s);
 				referTo(activator);
+				trace("activator %s %s", s, activator);
 			}
 
 			// Execute any plugins
@@ -560,7 +561,7 @@
 		return value.trim();
 	}
 
-	public String _bsn(String args[]) {
+	public String _bsn(@SuppressWarnings("unused") String args[]) {
 		return getBsn();
 	}
 
@@ -643,11 +644,11 @@
 	 * @return version or unknown.
 	 */
 	public String getBndVersion() {
-		return getBndInfo("Bundle-Version", "<unknown>");
+		return getBndInfo("version", "<unknown>");
 	}
 
 	public long getBndLastModified() {
-		String time = getBndInfo("Bnd-LastModified", "0");
+		String time = getBndInfo("lastmodified", "0");
 		try {
 			return Long.parseLong(time);
 		}
@@ -660,13 +661,25 @@
 	public String getBndInfo(String key, String defaultValue) {
 		if (bndInfo == null) {
 			try {
-				bndInfo = new Manifest(getClass().getResourceAsStream("META-INF/MANIFEST.MF"));
+				Properties bndInfoLocal = new Properties();
+				URL url = Analyzer.class.getResource("bnd.info");
+				if (url != null) {
+					InputStream in = url.openStream();
+					try {
+						bndInfoLocal.load(in);
+					}
+					finally {
+						in.close();
+					}
+				}
+				bndInfo = bndInfoLocal;
 			}
 			catch (Exception e) {
+				e.printStackTrace();
 				return defaultValue;
 			}
 		}
-		String value = bndInfo.getMainAttributes().getValue(key);
+		String value = bndInfo.getProperty(key);
 		if (value == null)
 			return defaultValue;
 		return value;
@@ -1345,38 +1358,43 @@
 	 * @param value
 	 * @throws Exception
 	 */
-	void setPackageInfo(PackageRef packageRef, Resource r, Packages classpathExports) throws Exception {
+	void getExportVersionsFromPackageInfo(PackageRef packageRef, Resource r, Packages classpathExports) throws Exception {
 		if (r == null)
 			return;
 
 		Properties p = new Properties();
-		InputStream in = r.openInputStream();
 		try {
-			p.load(in);
-		}
-		finally {
-			in.close();
-		}
-		Attrs map = classpathExports.get(packageRef);
-		if (map == null) {
-			classpathExports.put(packageRef, map = new Attrs());
-		}
-		for (Enumeration<String> t = (Enumeration<String>) p.propertyNames(); t.hasMoreElements();) {
-			String key = t.nextElement();
-			String value = map.get(key);
-			if (value == null) {
-				value = p.getProperty(key);
-
-				// Messy, to allow directives we need to
-				// allow the value to start with a ':' since we cannot
-				// encode this in a property name
-
-				if (value.startsWith(":")) {
-					key = key + ":";
-					value = value.substring(1);
-				}
-				map.put(key, value);
+			InputStream in = r.openInputStream();
+			try {
+				p.load(in);
 			}
+			finally {
+				in.close();
+			}
+			Attrs map = classpathExports.get(packageRef);
+			if (map == null) {
+				classpathExports.put(packageRef, map = new Attrs());
+			}
+			for (Enumeration<String> t = (Enumeration<String>) p.propertyNames(); t.hasMoreElements();) {
+				String key = t.nextElement();
+				String value = map.get(key);
+				if (value == null) {
+					value = p.getProperty(key);
+
+					// Messy, to allow directives we need to
+					// allow the value to start with a ':' since we cannot
+					// encode this in a property name
+
+					if (value.startsWith(":")) {
+						key = key + ":";
+						value = value.substring(1);
+					}
+					map.put(key, value);
+				}
+			}
+		}
+		catch (Exception e) {
+			msgs.NoSuchFile_(r);
 		}
 	}
 
@@ -1628,7 +1646,7 @@
 						// to overlap
 						if (!packageRef.isMetaData()) {
 							Resource pinfo = jar.getResource(prefix + packageRef.getPath() + "/packageinfo");
-							setPackageInfo(packageRef, pinfo, classpathExports);
+							getExportVersionsFromPackageInfo(packageRef, pinfo, classpathExports);
 						}
 					}
 				}
@@ -1677,7 +1695,7 @@
 							contained.put(packageRef);
 							if (!packageRef.isMetaData()) {
 								Resource pinfo = jar.getResource(prefix + packageRef.getPath() + "/packageinfo");
-								setPackageInfo(packageRef, pinfo, classpathExports);
+								getExportVersionsFromPackageInfo(packageRef, pinfo, classpathExports);
 							}
 						}
 						if (info != null)
@@ -1903,39 +1921,12 @@
 	final static String	DEFAULT_PROVIDER_POLICY	= "${range;[==,=+)}";
 	final static String	DEFAULT_CONSUMER_POLICY	= "${range;[==,+)}";
 
-	@SuppressWarnings("deprecation")
 	public String getVersionPolicy(boolean implemented) {
 		if (implemented) {
-			String s = getProperty(PROVIDER_POLICY);
-			if (s != null)
-				return s;
-
-			s = getProperty(VERSIONPOLICY_IMPL);
-			if (s != null)
-				return s;
-
-			return getProperty(VERSIONPOLICY, DEFAULT_PROVIDER_POLICY);
+			return getProperty(PROVIDER_POLICY, DEFAULT_PROVIDER_POLICY);
 		}
-		String s = getProperty(CONSUMER_POLICY);
-		if (s != null)
-			return s;
 
-		s = getProperty(VERSIONPOLICY_USES);
-		if (s != null)
-			return s;
-
-		return getProperty(VERSIONPOLICY, DEFAULT_CONSUMER_POLICY);
-
-		// String vp = implemented ? getProperty(VERSIONPOLICY_IMPL) :
-		// getProperty(VERSIONPOLICY_USES);
-		//
-		// if (vp != null)
-		// return vp;
-		//
-		// if (implemented)
-		// return getProperty(VERSIONPOLICY_IMPL, "{$range;[==,=+}");
-		// else
-		// return getProperty(VERSIONPOLICY, "${range;[==,+)}");
+		return getProperty(CONSUMER_POLICY, DEFAULT_CONSUMER_POLICY);
 	}
 
 	/**
@@ -2303,7 +2294,7 @@
 		return ees.first();
 	}
 
-	public String _ee(String args[]) {
+	public String _ee(@SuppressWarnings("unused") String args[]) {
 		return getLowestEE().getEE();
 	}
 
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
index b44118a..f49d6e3 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
@@ -247,7 +247,7 @@
 		changedFile(f);
 	}
 
-	protected void changedFile(File f) {}
+	protected void changedFile(@SuppressWarnings("unused") File f) {}
 
 	/**
 	 * Sign the jar file. -sign : <alias> [ ';' 'password:=' <password> ] [ ';'
@@ -256,7 +256,7 @@
 	 * @return
 	 */
 
-	void sign(Jar jar) throws Exception {
+	void sign(@SuppressWarnings("unused") Jar jar) throws Exception {
 		String signing = getProperty("-sign");
 		if (signing == null)
 			return;
@@ -283,6 +283,7 @@
 		Parameters conditionals = getParameters(CONDITIONAL_PACKAGE);
 		if (conditionals.isEmpty())
 			return null;
+		trace("do Conditional Package %s", conditionals);
 		Instructions instructions = new Instructions(conditionals);
 
 		Collection<PackageRef> referred = instructions.select(getReferred().keySet(), false);
@@ -294,7 +295,10 @@
 			for (Jar cpe : getClasspath()) {
 				Map<String,Resource> map = cpe.getDirectories().get(pref.getPath());
 				if (map != null) {
-					jar.addDirectory(map, false);
+					copy(jar, cpe, pref.getPath(), false);
+// Now use copy so that bnd.info is processed, next line should be 
+// removed in the future TODO
+//					jar.addDirectory(map, false);
 					break;
 				}
 			}
@@ -429,7 +433,7 @@
 		return sourcePath;
 	}
 
-	private void doVerify(Jar dot) throws Exception {
+	private void doVerify(@SuppressWarnings("unused") Jar dot) throws Exception {
 		Verifier verifier = new Verifier(this);
 		// Give the verifier the benefit of our analysis
 		// prevents parsing the files twice
@@ -608,8 +612,18 @@
 	 * @param overwriteResource
 	 */
 	private void copy(Jar dest, Jar srce, String path, boolean overwrite) {
+		trace("copy d=" + dest + " s=" + srce +" p="+ path);
 		dest.copy(srce, path, overwrite);
-
+		
+		// bnd.info sources must be preprocessed
+		String bndInfoPath = path + "/bnd.info";
+		Resource r = dest.getResource(bndInfoPath);
+		if ( r != null && !(r instanceof PreprocessResource)) {
+			trace("preprocessing bnd.info");
+			PreprocessResource pp = new PreprocessResource(this, r);
+			dest.putResource(bndInfoPath, pp);
+		}
+		
 		if (hasSources()) {
 			String srcPath = "OSGI-OPT/src/" + path;
 			Map<String,Resource> srcContents = srce.getDirectories().get(srcPath);
@@ -926,7 +940,7 @@
 		}
 	}
 
-	private void noSuchFile(Jar jar, String clause, Map<String,String> extra, String source, String destinationPath)
+	private void noSuchFile(Jar jar, @SuppressWarnings("unused") String clause, Map<String,String> extra, String source, String destinationPath)
 			throws Exception {
 		Jar src = getJarFromName(source, "Include-Resource " + source);
 		if (src != null) {
@@ -1398,7 +1412,7 @@
 	 * @throws Exception
 	 */
 
-	public void doDiff(Jar dot) throws Exception {
+	public void doDiff(@SuppressWarnings("unused") Jar dot) throws Exception {
 		Parameters diffs = parseHeader(getProperty("-diff"));
 		if (diffs.isEmpty())
 			return;
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java b/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java
index 7c3d759..04a8406 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java
@@ -3,30 +3,30 @@
 import aQute.lib.osgi.Descriptors.TypeRef;
 
 public class ClassDataCollector {
-	public void classBegin(int access, TypeRef name) {}
+	public void classBegin(@SuppressWarnings("unused") int access, @SuppressWarnings("unused") TypeRef name) {}
 
 	public boolean classStart(int access, TypeRef className) {
 		classBegin(access, className);
 		return true;
 	}
 
-	public void extendsClass(TypeRef zuper) throws Exception {}
+	public void extendsClass(@SuppressWarnings("unused") TypeRef zuper) throws Exception {}
 
-	public void implementsInterfaces(TypeRef[] interfaces) throws Exception {}
+	public void implementsInterfaces(@SuppressWarnings("unused") TypeRef[] interfaces) throws Exception {}
 
-	public void addReference(TypeRef ref) {}
+	public void addReference(@SuppressWarnings("unused") TypeRef ref) {}
 
-	public void annotation(Annotation annotation) {}
+	public void annotation(@SuppressWarnings("unused") Annotation annotation) {}
 
-	public void parameter(int p) {}
+	public void parameter(@SuppressWarnings("unused") int p) {}
 
-	public void method(Clazz.MethodDef defined) {}
+	public void method(@SuppressWarnings("unused") Clazz.MethodDef defined) {}
 
-	public void field(Clazz.FieldDef defined) {}
+	public void field(@SuppressWarnings("unused") Clazz.FieldDef defined) {}
 
-	public void reference(Clazz.MethodDef referenced) {}
+	public void reference(@SuppressWarnings("unused") Clazz.MethodDef referenced) {}
 
-	public void reference(Clazz.FieldDef referenced) {}
+	public void reference(@SuppressWarnings("unused") Clazz.FieldDef referenced) {}
 
 	public void classEnd() throws Exception {}
 
@@ -61,21 +61,24 @@
 	 *            The access flags
 	 * @throws Exception
 	 */
-	public void innerClass(TypeRef innerClass, TypeRef outerClass, String innerName, int innerClassAccessFlags)
+	public void innerClass(TypeRef innerClass, TypeRef outerClass, String innerName, @SuppressWarnings("unused") int innerClassAccessFlags)
 			throws Exception {}
 
-	public void signature(String signature) {}
+	public void signature(@SuppressWarnings("unused") String signature) {}
 
-	public void constant(Object object) {}
+	public void constant(@SuppressWarnings("unused") Object object) {}
 
 	public void memberEnd() {}
 
-	public void version(int minor, int major) {
+	public void version(@SuppressWarnings("unused") int minor, @SuppressWarnings("unused") int major) {
 		// TODO Auto-generated method stub
 
 	}
 
-	public void referenceMethod(int access, TypeRef className, String method, String descriptor) {
+	public void referenceMethod(@SuppressWarnings("unused")
+	int access, @SuppressWarnings("unused")
+	TypeRef className, @SuppressWarnings("unused")
+	String method, @SuppressWarnings("unused") String descriptor) {
 		// TODO Auto-generated method stub
 
 	}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java b/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java
index d54b084..87ce8a5 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java
@@ -69,7 +69,7 @@
 			return major >= J2SE5.major;
 		}
 
-		public static JAVA getJava(int major, int minor) {
+		public static JAVA getJava(int major, @SuppressWarnings("unused") int minor) {
 			for (JAVA j : JAVA.values()) {
 				if (j.major == major)
 					return j;
@@ -629,7 +629,7 @@
 			pool[poolIndex] = intPool[poolIndex];
 	}
 
-	protected void pool(Object[] pool, int[] intPool) {}
+	protected void pool(@SuppressWarnings("unused") Object[] pool, @SuppressWarnings("unused") int[] intPool) {}
 
 	/**
 	 * @param in
@@ -1127,8 +1127,7 @@
 		}
 		if (collect)
 			return new Annotation(name, elements, member, policy);
-		else
-			return null;
+		return null;
 	}
 
 	private Object doElementValue(DataInputStream in, ElementType member, RetentionPolicy policy, boolean collect)
@@ -1572,8 +1571,7 @@
 	public int getAccess() {
 		if (innerAccess == -1)
 			return accessx;
-		else
-			return innerAccess;
+		return innerAccess;
 	}
 
 	public TypeRef getClassName() {
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/CommandResource.java b/bundleplugin/src/main/java/aQute/lib/osgi/CommandResource.java
index 0fa43fe..eefc1e2 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/CommandResource.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/CommandResource.java
@@ -48,7 +48,7 @@
 				cmd.var("PATH", path);
 				domain.trace("PATH: %s", path);
 			}
-			OutputStreamWriter osw = new OutputStreamWriter(out);
+			OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
 			int result = cmd.execute(command, stdout, errors);
 			osw.append(stdout);
 			osw.flush();
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java b/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
index df0bbf0..7454087 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
@@ -52,6 +52,11 @@
 	String							CREATED_BY									= "Created-By";
 	String							TOOL										= "Tool";
 	String							TESTCASES									= "Test-Cases";
+        /**
+         * @deprecated Use {@link Constants#TESTCASES}.
+         */
+        @Deprecated
+        String                                                  TESTSUITES                                                                      = "Test-Suites";
 	String							SIGNATURE_TEST								= "-signaturetest";
 
 	String							headers[]									= {
@@ -90,8 +95,6 @@
 	String							NOEXTRAHEADERS								= "-noextraheaders";
 	String							NOMANIFEST									= "-nomanifest";
 	String							NOUSES										= "-nouses";
-	@Deprecated
-	String							NOPE										= "-nope";
 	String							NOBUNDLES									= "-nobundles";
 	String							PEDANTIC									= "-pedantic";
 	String							PLUGIN										= "-plugin";
@@ -106,6 +109,7 @@
 	String							RUNPROPERTIES								= "-runproperties";
 	String							RUNSYSTEMPACKAGES							= "-runsystempackages";
 	String							RUNBUNDLES									= "-runbundles";
+	String							RUNREPOS									= "-runrepos";
 	String							RUNPATH										= "-runpath";
 	String							RUNSTORAGE									= "-runstorage";
 	String							RUNBUILDS									= "-runbuilds";
@@ -126,14 +130,8 @@
 	String							TESTCONTINUOUS								= "-testcontinuous";
 	String							UNDERTEST									= "-undertest";
 	String							VERBOSE										= "-verbose";
-	@Deprecated
-	String							VERSIONPOLICY_IMPL							= "-versionpolicy-impl";
-	@Deprecated
-	String							VERSIONPOLICY_USES							= "-versionpolicy-uses";
 	String							PROVIDER_POLICY								= "-provider-policy";
 	String							CONSUMER_POLICY								= "-consumer-policy";
-	@Deprecated
-	String							VERSIONPOLICY								= "-versionpolicy";
 	String							WAB											= "-wab";
 	String							WABLIB										= "-wablib";
 	String							REQUIRE_BND									= "-require-bnd";
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java b/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java
index c92de90..bfb80bb 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java
@@ -88,8 +88,8 @@
 							sb.append("(\\..*)?");
 							wildcards = true;
 							break loop;
-						} else
-							sb.append("\\.");
+						}
+						sb.append("\\.");
 
 						break;
 					case '*' :
@@ -130,8 +130,7 @@
 
 		if (literal)
 			return match.equals(value);
-		else
-			return getMatcher(value).matches();
+		return getMatcher(value).matches();
 	}
 
 	public boolean isNegated() {
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Instructions.java b/bundleplugin/src/main/java/aQute/lib/osgi/Instructions.java
index 679c374..6ac56dd 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Instructions.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Instructions.java
@@ -48,7 +48,7 @@
 		if (map == null)
 			return false;
 
-		return map.containsKey((Instruction) name);
+		return map.containsKey(name);
 	}
 
 	public boolean containsValue(Attrs value) {
@@ -64,7 +64,7 @@
 		if (map == null)
 			return false;
 
-		return map.containsValue((Attrs) value);
+		return map.containsValue(value);
 	}
 
 	public Set<java.util.Map.Entry<Instruction,Attrs>> entrySet() {
@@ -80,7 +80,7 @@
 		if (map == null)
 			return null;
 
-		return map.get((Instruction) key);
+		return map.get(key);
 	}
 
 	public Attrs get(Instruction key) {
@@ -109,11 +109,11 @@
 	}
 
 	public void putAll(Map< ? extends Instruction, ? extends Attrs> map) {
-		if (this.map == null)
+		if (this.map == null) {
 			if (map.isEmpty())
 				return;
-			else
-				this.map = new LinkedHashMap<Instruction,Attrs>();
+			this.map = new LinkedHashMap<Instruction,Attrs>();
+		}
 		this.map.putAll(map);
 	}
 
@@ -123,7 +123,7 @@
 		if (map == null)
 			return null;
 
-		return map.remove((Instruction) var0);
+		return map.remove(var0);
 	}
 
 	public Attrs remove(Instruction var0) {
@@ -212,8 +212,7 @@
 			if (i.matches(value)) {
 				if (i.isNegated())
 					return false; // we deny this one explicitly
-				else
-					return true; // we allow it explicitly
+				return true; // we allow it explicitly
 			}
 		}
 		return false;
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java b/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java
index 032a7d1..76a4b0d 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java
@@ -78,11 +78,9 @@
 		String name = f.getName();
 		if (name.equals("bin") || name.equals("src"))
 			return f.getParentFile().getName();
-		else {
-			if (name.endsWith(".jar"))
-				name = name.substring(0, name.length() - 4);
-			return name;
-		}
+		if (name.endsWith(".jar"))
+			name = name.substring(0, name.length() - 4);
+		return name;
 	}
 
 	public Jar(String string, InputStream resourceAsStream) throws IOException {
@@ -455,7 +453,7 @@
 
 			for (Map.Entry< ? , ? > entry : org.getAttributes(name).entrySet()) {
 				String nice = clean((String) entry.getValue());
-				attrs.put((Attributes.Name) entry.getKey(), nice);
+				attrs.put(entry.getKey(), nice);
 			}
 		}
 		return result;
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java b/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
index 36c16dd..3e109d6 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
@@ -190,8 +190,7 @@
 			Processor parent = source.start.getParent();
 			if (parent != null)
 				return parent.getProperty(varname);
-			else
-				return null;
+			return null;
 		}
 
 		Processor rover = domain;
@@ -262,11 +261,11 @@
 		return Processor.join(set, ",");
 	}
 
-	public String _pathseparator(String args[]) {
+	public String _pathseparator(@SuppressWarnings("unused") String args[]) {
 		return File.pathSeparator;
 	}
 
-	public String _separator(String args[]) {
+	public String _separator(@SuppressWarnings("unused") String args[]) {
 		return File.separator;
 	}
 
@@ -331,11 +330,10 @@
 
 		if (args.length > 3)
 			return args[3];
-		else
-			return "";
+		return "";
 	}
 
-	public String _now(String args[]) {
+	public String _now(@SuppressWarnings("unused") String args[]) {
 		return new Date().toString();
 	}
 
@@ -476,19 +474,18 @@
 		if (args.length < 2) {
 			domain.warning("Need at least one file name for ${dir;...}");
 			return null;
-		} else {
-			String del = "";
-			StringBuilder sb = new StringBuilder();
-			for (int i = 1; i < args.length; i++) {
-				File f = domain.getFile(args[i]);
-				if (f.exists() && f.getParentFile().exists()) {
-					sb.append(del);
-					sb.append(f.getParentFile().getAbsolutePath());
-					del = ",";
-				}
-			}
-			return sb.toString();
 		}
+		String del = "";
+		StringBuilder sb = new StringBuilder();
+		for (int i = 1; i < args.length; i++) {
+			File f = domain.getFile(args[i]);
+			if (f.exists() && f.getParentFile().exists()) {
+				sb.append(del);
+				sb.append(f.getParentFile().getAbsolutePath());
+				del = ",";
+			}
+		}
+		return sb.toString();
 
 	}
 
@@ -496,19 +493,18 @@
 		if (args.length < 2) {
 			domain.warning("Need at least one file name for ${basename;...}");
 			return null;
-		} else {
-			String del = "";
-			StringBuilder sb = new StringBuilder();
-			for (int i = 1; i < args.length; i++) {
-				File f = domain.getFile(args[i]);
-				if (f.exists() && f.getParentFile().exists()) {
-					sb.append(del);
-					sb.append(f.getName());
-					del = ",";
-				}
-			}
-			return sb.toString();
 		}
+		String del = "";
+		StringBuilder sb = new StringBuilder();
+		for (int i = 1; i < args.length; i++) {
+			File f = domain.getFile(args[i]);
+			if (f.exists() && f.getParentFile().exists()) {
+				sb.append(del);
+				sb.append(f.getName());
+				del = ",";
+			}
+		}
+		return sb.toString();
 
 	}
 
@@ -516,14 +512,13 @@
 		if (args.length < 2) {
 			domain.warning("Need at least one file name for ${isfile;...}");
 			return null;
-		} else {
-			boolean isfile = true;
-			for (int i = 1; i < args.length; i++) {
-				File f = new File(args[i]).getAbsoluteFile();
-				isfile &= f.isFile();
-			}
-			return isfile ? "true" : "false";
 		}
+		boolean isfile = true;
+		for (int i = 1; i < args.length; i++) {
+			File f = new File(args[i]).getAbsoluteFile();
+			isfile &= f.isFile();
+		}
+		return isfile ? "true" : "false";
 
 	}
 
@@ -531,14 +526,13 @@
 		if (args.length < 2) {
 			domain.warning("Need at least one file name for ${isdir;...}");
 			return null;
-		} else {
-			boolean isdir = true;
-			for (int i = 1; i < args.length; i++) {
-				File f = new File(args[i]).getAbsoluteFile();
-				isdir &= f.isDirectory();
-			}
-			return isdir ? "true" : "false";
 		}
+		boolean isdir = true;
+		for (int i = 1; i < args.length; i++) {
+			File f = new File(args[i]).getAbsoluteFile();
+			isdir &= f.isDirectory();
+		}
+		return isdir ? "true" : "false";
 
 	}
 
@@ -611,7 +605,7 @@
 		return Processor.join(result, ",");
 	}
 
-	public String _currenttime(String args[]) {
+	public String _currenttime(@SuppressWarnings("unused") String args[]) {
 		return Long.toString(System.currentTimeMillis());
 	}
 
@@ -849,7 +843,7 @@
 		}
 	}
 
-	public static void verifyCommand(String args[], String help, Pattern[] patterns, int low, int high) {
+	public static void verifyCommand(String args[], @SuppressWarnings("unused") String help, Pattern[] patterns, int low, int high) {
 		String message = "";
 		if (args.length > high) {
 			message = "too many arguments";
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Packages.java b/bundleplugin/src/main/java/aQute/lib/osgi/Packages.java
index fae4597..64e4a4e 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Packages.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Packages.java
@@ -35,7 +35,7 @@
 		if (map == null)
 			return false;
 
-		return map.containsKey((PackageRef) name);
+		return map.containsKey(name);
 	}
 
 	public boolean containsValue(Attrs value) {
@@ -51,7 +51,7 @@
 		if (map == null)
 			return false;
 
-		return map.containsValue((Attrs) value);
+		return map.containsValue(value);
 	}
 
 	public Set<java.util.Map.Entry<PackageRef,Attrs>> entrySet() {
@@ -67,7 +67,7 @@
 		if (map == null)
 			return null;
 
-		return map.get((PackageRef) key);
+		return map.get(key);
 	}
 
 	public Attrs get(PackageRef key) {
@@ -106,11 +106,11 @@
 	}
 
 	public void putAll(Map< ? extends PackageRef, ? extends Attrs> map) {
-		if (this.map == null)
+		if (this.map == null) {
 			if (map.isEmpty())
 				return;
-			else
-				this.map = new LinkedHashMap<PackageRef,Attrs>();
+			this.map = new LinkedHashMap<PackageRef,Attrs>();
+		}
 		this.map.putAll(map);
 	}
 
@@ -127,7 +127,7 @@
 		if (map == null)
 			return null;
 
-		return map.remove((PackageRef) var0);
+		return map.remove(var0);
 	}
 
 	public Attrs remove(PackageRef var0) {
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java b/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java
index d7179d6..608e9a0 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java
@@ -58,9 +58,9 @@
 		properties = new Properties(parent);
 	}
 
-	public Processor(Processor parent) {
-		this(parent.properties);
-		this.parent = parent;
+	public Processor(Processor child) {
+		this(child.properties);
+		this.parent = child;
 	}
 
 	public void setParent(Processor processor) {
@@ -77,8 +77,7 @@
 	public Processor getTop() {
 		if (parent == null)
 			return this;
-		else
-			return parent.getTop();
+		return parent.getTop();
 	}
 
 	public void getInfo(Reporter processor, String prefix) {
@@ -111,8 +110,7 @@
 		Processor p = current.get();
 		if (p == null)
 			return this;
-		else
-			return p;
+		return p;
 	}
 
 	public void warning(String string, Object... args) {
@@ -338,7 +336,7 @@
 				key = removeDuplicateMarker(key);
 
 				try {
-					Class< ? > c = (Class< ? >) loader.loadClass(key);
+					Class< ? > c = loader.loadClass(key);
 					Object plugin = c.newInstance();
 					customize(plugin, entry.getValue());
 					list.add(plugin);
@@ -453,7 +451,7 @@
 		toBeClosed.clear();
 	}
 
-	public String _basedir(String args[]) {
+	public String _basedir(@SuppressWarnings("unused") String args[]) {
 		if (base == null)
 			throw new IllegalArgumentException("No base dir set");
 
@@ -859,7 +857,7 @@
 		return printClauses(exports, false);
 	}
 
-	public static String printClauses(Map< ? , ? extends Map< ? , ? >> exports, boolean checkMultipleVersions)
+	public static String printClauses(Map< ? , ? extends Map< ? , ? >> exports, @SuppressWarnings("unused") boolean checkMultipleVersions)
 			throws IOException {
 		StringBuilder sb = new StringBuilder();
 		String del = "";
@@ -919,8 +917,7 @@
 	public Macro getReplacer() {
 		if (replacer == null)
 			return replacer = new Macro(this, getMacroDomains());
-		else
-			return replacer;
+		return replacer;
 	}
 
 	/**
@@ -961,7 +958,7 @@
 		return result;
 	}
 
-	public boolean updateModified(long time, String reason) {
+	public boolean updateModified(long time, @SuppressWarnings("unused") String reason) {
 		if (time > lastModified) {
 			lastModified = time;
 			return true;
@@ -1127,8 +1124,7 @@
 	public String normalize(String f) {
 		if (f.startsWith(base.getAbsolutePath() + "/"))
 			return f.substring(base.getAbsolutePath().length() + 1);
-		else
-			return f;
+		return f;
 	}
 
 	public String normalize(File f) {
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java b/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java
index 27026ae..2759049 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java
@@ -42,7 +42,7 @@
 		String	name;
 		int		target;
 
-		EE(String name, int source, int target) {
+		EE(String name, @SuppressWarnings("unused") int source, int target) {
 			this.name = name;
 			this.target = target;
 		}
@@ -488,7 +488,7 @@
 		}
 	}
 
-	private void verifyType(Attrs.Type type, String string) {
+	private void verifyType(@SuppressWarnings("unused") Attrs.Type type, @SuppressWarnings("unused") String string) {
 
 	}
 
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/eclipse/EclipseClasspath.java b/bundleplugin/src/main/java/aQute/lib/osgi/eclipse/EclipseClasspath.java
index 2244fd2..cb511e7 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/eclipse/EclipseClasspath.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/eclipse/EclipseClasspath.java
@@ -50,7 +50,7 @@
 	 * @throws IOException
 	 */
 
-	public EclipseClasspath(Reporter reporter, File workspace, File project, int options) throws Exception {
+	public EclipseClasspath(Reporter reporter, File workspace, File project, @SuppressWarnings("unused") int options) throws Exception {
 		this.project = project.getCanonicalFile();
 		this.workspace = workspace.getCanonicalFile();
 		this.reporter = reporter;
@@ -184,8 +184,8 @@
 				File b = new File(base);
 				File f = new File(b, remainder.replace('/', File.separatorChar));
 				return f;
-			} else
-				reporter.error("Can't find replacement variable for: " + path);
+			}
+			reporter.error("Can't find replacement variable for: " + path);
 		} else
 			reporter.error("Cant split variable path: " + path);
 		return null;
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/resource/CapReq.java b/bundleplugin/src/main/java/aQute/lib/osgi/resource/CapReq.java
new file mode 100644
index 0000000..3f07825
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/resource/CapReq.java
@@ -0,0 +1,97 @@
+package aQute.lib.osgi.resource;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+class CapReq implements Capability, Requirement {
+	
+	static enum MODE { Capability, Requirement }
+	
+	private final MODE mode;
+	private final String	namespace;
+	private final Resource	resource;
+	private final Map<String,String>	directives;
+	private final Map<String,Object>	attributes;
+
+	CapReq(MODE mode, String namespace, Resource resource, Map<String, String> directives, Map<String, Object> attributes) {
+		this.mode = mode;
+		this.namespace = namespace;
+		this.resource = resource;
+		this.directives = new HashMap<String,String>(directives);
+		this.attributes = new HashMap<String,Object>(attributes);
+	}
+
+	public String getNamespace() {
+		return namespace;
+	}
+
+	public Map<String,String> getDirectives() {
+		return Collections.unmodifiableMap(directives);
+	}
+
+	public Map<String,Object> getAttributes() {
+		return Collections.unmodifiableMap(attributes);
+	}
+
+	public Resource getResource() {
+		return resource;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
+		result = prime * result + ((directives == null) ? 0 : directives.hashCode());
+		result = prime * result + ((mode == null) ? 0 : mode.hashCode());
+		result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
+		result = prime * result + ((resource == null) ? 0 : resource.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;
+		CapReq other = (CapReq) obj;
+		if (attributes == null) {
+			if (other.attributes != null)
+				return false;
+		} else if (!attributes.equals(other.attributes))
+			return false;
+		if (directives == null) {
+			if (other.directives != null)
+				return false;
+		} else if (!directives.equals(other.directives))
+			return false;
+		if (mode != other.mode)
+			return false;
+		if (namespace == null) {
+			if (other.namespace != null)
+				return false;
+		} else if (!namespace.equals(other.namespace))
+			return false;
+		if (resource == null) {
+			if (other.resource != null)
+				return false;
+		} else if (!resource.equals(other.resource))
+			return false;
+		return true;
+	}
+
+	@Override
+	public String toString() {
+		return mode + " [namespace=" + namespace + ", resource=" + System.identityHashCode(resource) + ", directives="
+				+ directives + ", attributes=" + attributes + "]";
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/resource/CapReqBuilder.java b/bundleplugin/src/main/java/aQute/lib/osgi/resource/CapReqBuilder.java
new file mode 100644
index 0000000..654c7de
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/resource/CapReqBuilder.java
@@ -0,0 +1,74 @@
+package aQute.lib.osgi.resource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+import aQute.lib.osgi.resource.CapReq.MODE;
+import aQute.libg.filters.AndFilter;
+import aQute.libg.filters.Filter;
+import aQute.libg.filters.SimpleFilter;
+import aQute.libg.version.VersionRange;
+
+public class CapReqBuilder {
+
+	private final String				namespace;
+	private Resource					resource;
+	private final Map<String,Object>	attributes	= new HashMap<String,Object>();
+	private final Map<String,String>	directives	= new HashMap<String,String>();
+
+	public CapReqBuilder(String namespace) {
+		this.namespace = namespace;
+	}
+	
+	public String getNamespace() {
+		return namespace;
+	}
+	
+	public CapReqBuilder setResource(Resource resource) {
+		this.resource = resource;
+		return this;
+	}
+
+	public CapReqBuilder addAttribute(String name, Object value) {
+		attributes.put(name, value);
+		return this;
+	}
+
+	public CapReqBuilder addDirective(String name, String value) {
+		directives.put(name, value);
+		return this;
+	}
+	
+	public Capability buildCapability() {
+		// TODO check the thrown exception
+		if (resource == null) throw new IllegalStateException("Cannot build Capability with null Resource.");
+		return new CapReq(MODE.Capability, namespace, resource, directives, attributes);
+	}
+	
+	public Requirement buildRequirement() {
+		// TODO check the thrown exception
+		if (resource == null) throw new IllegalStateException("Cannot build Requirement with null Resource.");
+		return new CapReq(MODE.Requirement, namespace, resource, directives, attributes);
+	}
+
+	public Requirement buildSyntheticRequirement() {
+		return new CapReq(MODE.Requirement, namespace, null, directives, attributes);
+	}
+	
+	public static final CapReqBuilder createPackageRequirement(String pkgName, VersionRange range) {
+		Filter filter;
+		SimpleFilter pkgNameFilter = new SimpleFilter(PackageNamespace.PACKAGE_NAMESPACE, pkgName);
+		if (range != null)
+			filter = new AndFilter().addChild(pkgNameFilter).addChild(Filters.fromVersionRange(range));
+		else
+			filter = pkgNameFilter;
+		
+		return new CapReqBuilder(PackageNamespace.PACKAGE_NAMESPACE).addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/resource/Filters.java b/bundleplugin/src/main/java/aQute/lib/osgi/resource/Filters.java
new file mode 100644
index 0000000..20af48d
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/resource/Filters.java
@@ -0,0 +1,42 @@
+package aQute.lib.osgi.resource;
+
+import aQute.libg.filters.AndFilter;
+import aQute.libg.filters.Filter;
+import aQute.libg.filters.NotFilter;
+import aQute.libg.filters.Operator;
+import aQute.libg.filters.SimpleFilter;
+import aQute.libg.version.VersionRange;
+
+public class Filters {
+	
+	public static Filter fromVersionRange(VersionRange range) {
+		return fromVersionRange(range, "version");
+	}
+	
+	public static Filter fromVersionRange(VersionRange range, @SuppressWarnings("unused") String versionAttr) {
+		if (range == null)
+			return null;
+		
+		Filter left;
+		if (range.includeLow())
+			left = new SimpleFilter("version", Operator.GreaterThanOrEqual, range.getLow().toString());
+		else
+			left = new NotFilter(new SimpleFilter("version", Operator.LessThanOrEqual, range.getLow().toString()));
+		
+		Filter right;
+		if (!range.isRange())
+			right = null;
+		else if (range.includeHigh())
+			right = new SimpleFilter("version", Operator.LessThanOrEqual, range.getHigh().toString());
+		else
+			right = new NotFilter(new SimpleFilter("version", Operator.GreaterThanOrEqual, range.getHigh().toString()));
+		
+		Filter result;
+		if (right != null)
+			result = new AndFilter().addChild(left).addChild(right);
+		else
+			result = left;
+		
+		return result;
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/resource/ResourceBuilder.java b/bundleplugin/src/main/java/aQute/lib/osgi/resource/ResourceBuilder.java
new file mode 100644
index 0000000..cd9b982
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/resource/ResourceBuilder.java
@@ -0,0 +1,48 @@
+package aQute.lib.osgi.resource;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class ResourceBuilder {
+
+	private final ResourceImpl		resource		= new ResourceImpl();
+	private final List<Capability>	capabilities	= new LinkedList<Capability>();
+	private final List<Requirement>	requirements	= new LinkedList<Requirement>();
+
+	private boolean					built			= false;
+
+	public ResourceBuilder addCapability(CapReqBuilder builder) {
+		if (built)
+			throw new IllegalStateException("Resource already built");
+
+		Capability cap = builder.setResource(resource).buildCapability();
+		capabilities.add(cap);
+
+		return this;
+	}
+
+	public ResourceBuilder addRequirement(CapReqBuilder builder) {
+		if (built)
+			throw new IllegalStateException("Resource already built");
+
+		Requirement req = builder.setResource(resource).buildRequirement();
+		requirements.add(req);
+
+		return this;
+	}
+
+	public Resource build() {
+		if (built)
+			throw new IllegalStateException("Resource already built");
+		built = true;
+
+		resource.setCapabilities(capabilities);
+		resource.setRequirements(requirements);
+		return resource;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/resource/ResourceImpl.java b/bundleplugin/src/main/java/aQute/lib/osgi/resource/ResourceImpl.java
new file mode 100644
index 0000000..3fa6218
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/resource/ResourceImpl.java
@@ -0,0 +1,67 @@
+package aQute.lib.osgi.resource;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+class ResourceImpl implements Resource {
+
+	private List<Capability>				allCapabilities;
+	private Map<String,List<Capability>>	capabilityMap;
+
+	private List<Requirement>				allRequirements;
+	private Map<String,List<Requirement>>	requirementMap;
+
+	void setCapabilities(List<Capability> capabilities) {
+		allCapabilities = capabilities;
+
+		capabilityMap = new HashMap<String,List<Capability>>();
+		for (Capability capability : capabilities) {
+			List<Capability> list = capabilityMap.get(capability.getNamespace());
+			if (list == null) {
+				list = new LinkedList<Capability>();
+				capabilityMap.put(capability.getNamespace(), list);
+			}
+			list.add(capability);
+		}
+	}
+
+	public List<Capability> getCapabilities(String namespace) {
+		return namespace == null ? allCapabilities : capabilityMap.get(namespace);
+	}
+
+	void setRequirements(List<Requirement> requirements) {
+		allRequirements = requirements;
+
+		requirementMap = new HashMap<String,List<Requirement>>();
+		for (Requirement requirement : requirements) {
+			List<Requirement> list = requirementMap.get(requirement.getNamespace());
+			if (list == null) {
+				list = new LinkedList<Requirement>();
+				requirementMap.put(requirement.getNamespace(), list);
+			}
+			list.add(requirement);
+		}
+	}
+
+	public List<Requirement> getRequirements(String namespace) {
+		return namespace == null ? allRequirements : requirementMap.get(namespace);
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("ResourceImpl [caps=");
+		builder.append(allCapabilities);
+		builder.append(", reqs=");
+		builder.append(allRequirements);
+		builder.append("]");
+		return builder.toString();
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/resource/packageinfo b/bundleplugin/src/main/java/aQute/lib/osgi/resource/packageinfo
new file mode 100644
index 0000000..a4f1546
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/resource/packageinfo
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file