Latest bnd code

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1351156 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/Project.java b/bundleplugin/src/main/java/aQute/bnd/build/Project.java
index 192be5d..1ec2c33 100644
--- a/bundleplugin/src/main/java/aQute/bnd/build/Project.java
+++ b/bundleplugin/src/main/java/aQute/bnd/build/Project.java
@@ -199,7 +199,7 @@
 						sourcepath.add(getBase());
 
 					// Set default bin directory
-					output = getFile(getProperty("bin", "bin")).getAbsoluteFile();
+					output = getOutput0();
 					if (!output.exists()) {
 						output.mkdirs();
 						getWorkspace().changedFile(output);
@@ -213,11 +213,7 @@
 					}
 
 					// Where we store all our generated stuff.
-					target = getFile(getProperty("target", "generated"));
-					if (!target.exists()) {
-						target.mkdirs();
-						getWorkspace().changedFile(target);
-					}
+					target = getTarget0();
 
 					// Where the launched OSGi framework stores stuff
 					String runStorageStr = getProperty(Constants.RUNSTORAGE);
@@ -289,6 +285,25 @@
 		}
 	}
 
+	/**
+	 * @return
+	 */
+	private File getOutput0() {
+		return getFile(getProperty("bin", "bin")).getAbsoluteFile();
+	}
+
+	/**
+	 * 
+	 */
+	private File getTarget0() {
+		File target = getFile(getProperty("target", "generated"));
+		if (!target.exists()) {
+			target.mkdirs();
+			getWorkspace().changedFile(target);
+		}
+		return target;
+	}
+
 	public File getSrc() {
 		return new File(getBase(), getProperty("src", "src"));
 	}
@@ -1542,14 +1557,15 @@
 	}
 
 	public void clean() throws Exception {
-		File target = getTarget();
+		File target = getTarget0();
 		if (target.isDirectory() && target.getParentFile() != null) {
 			IO.delete(target);
 			target.mkdirs();
 		}
+		File output = getOutput0();
 		if (getOutput().isDirectory())
-			IO.delete(getOutput());
-		getOutput().mkdirs();
+			IO.delete(output);
+		output.mkdirs();
 	}
 
 	public File[] build() throws Exception {
@@ -1783,8 +1799,8 @@
 			return;
 		}
 		@SuppressWarnings("rawtypes")
-		Map x = (Map) getProperties();
-		scripters.get(0).eval((Map<String,Object>) x, new StringReader(script));
+		Map x = getProperties();
+		scripters.get(0).eval(x, new StringReader(script));
 	}
 
 	public String _repos(String args[]) throws Exception {
@@ -1809,11 +1825,11 @@
 
 		if (what == null || what.equals("lead"))
 			return syntax.getLead();
-		if (what == null || what.equals("example"))
+		if (what.equals("example"))
 			return syntax.getExample();
-		if (what == null || what.equals("pattern"))
+		if (what.equals("pattern"))
 			return syntax.getPattern();
-		if (what == null || what.equals("values"))
+		if (what.equals("values"))
 			return syntax.getValues();
 
 		return "Invalid type specified for help: lead, example, pattern, values";
@@ -2030,7 +2046,7 @@
 		}
 	}
 
-	File getPackageInfoFile(String packageName) throws IOException {
+	File getPackageInfoFile(String packageName) {
 		String path = packageName.replace('.', '/') + "/packageinfo";
 		return IO.getFile(getSrc(), path);
 
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java b/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java
index 6a97311..78d12e3 100644
--- a/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java
+++ b/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java
@@ -210,7 +210,7 @@
 			java.setTimeout(timeout + 1000, TimeUnit.MILLISECONDS);
 
 		try {
-			int result = java.execute((InputStream) null, System.err, System.err);
+			int result = java.execute(System.in, System.err, System.err);
 			if (result == Integer.MIN_VALUE)
 				return TIMEDOUT;
 			reportResult(result);
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java b/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java
index daee3d3..573a61e 100644
--- a/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java
+++ b/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java
@@ -242,7 +242,7 @@
 		signal(this);
 	}
 
-	private void copy(InputStream in, OutputStream out) throws Exception {
+	void copy(InputStream in, OutputStream out) throws Exception {
 		byte data[] = new byte[10000];
 		int size = in.read(data);
 		while (size > 0) {
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java b/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java
new file mode 100644
index 0000000..9e71975
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java
@@ -0,0 +1,157 @@
+package aQute.bnd.build;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import aQute.bnd.service.RepositoryPlugin;
+import aQute.lib.osgi.Jar;
+import aQute.libg.version.Version;
+import aQute.libg.version.VersionRange;
+
+public class WorkspaceRepository implements RepositoryPlugin {
+	private final Workspace	workspace;
+
+	public WorkspaceRepository(Workspace workspace) {
+		this.workspace = workspace;
+	}
+
+	public File[] get(String bsn, String range) throws Exception {
+		Collection<Project> projects = workspace.getAllProjects();
+		SortedMap<Version,File> foundVersion = new TreeMap<Version,File>();
+		for (Project project : projects) {
+			File[] build = project.build(false);
+			if (build != null) {
+				for (File file : build) {
+					Jar jar = new Jar(file);
+					if (bsn.equals(jar.getBsn())) {
+						Version version = new Version(jar.getVersion());
+						boolean exact = range.matches("[0-9]+\\.[0-9]+\\.[0-9]+\\..*");
+						if ("latest".equals(range) || matchVersion(range, version, exact)) {
+							foundVersion.put(version, file);
+						}
+					}
+				}
+			}
+		}
+
+		File[] result = new File[foundVersion.size()];
+		result = foundVersion.values().toArray(result);
+		if (!"latest".equals(range)) {
+			return result;
+		} else {
+			if (result.length > 0) {
+				return new File[] {
+					result[0]
+				};
+			} else {
+				return new File[0];
+			}
+		}
+	}
+
+	public File get(String bsn, String range, Strategy strategy, Map<String,String> properties) throws Exception {
+		File[] files = get(bsn, range);
+
+		if (files.length == 0) {
+			return null;
+		}
+
+		if (strategy == Strategy.EXACT) {
+			return files[0];
+		} else if (strategy == Strategy.HIGHEST) {
+			return files[files.length - 1];
+		} else if (strategy == Strategy.LOWEST) {
+			return files[0];
+		}
+
+		return null;
+	}
+
+	private boolean matchVersion(String range, Version version, boolean exact) {
+		if (range == null || range.trim().length() == 0)
+			return true;
+		VersionRange vr = new VersionRange(range);
+
+		boolean result;
+		if (exact) {
+			if (vr.isRange())
+				result = false;
+			else
+				result = vr.getHigh().equals(version);
+		} else {
+			result = vr.includes(version);
+		}
+		return result;
+	}
+
+	public boolean canWrite() {
+		return false;
+	}
+
+	public File put(Jar jar) throws Exception {
+		return null;
+	}
+
+	public List<String> list(String regex) throws Exception {
+		List<String> names = new ArrayList<String>();
+		Collection<Project> projects = workspace.getAllProjects();
+		for (Project project : projects) {
+			File[] build = project.build(false);
+			if (build != null) {
+				for (File file : build) {
+					Jar jar = new Jar(file);
+					String bsn = jar.getBsn();
+					if (regex != null) {
+						Pattern pattern = Pattern.compile(regex);
+						Matcher matcher = pattern.matcher(bsn);
+						if (matcher.matches()) {
+							if (!names.contains(bsn)) {
+								names.add(bsn);
+							}
+						}
+					} else {
+						if (!names.contains(bsn)) {
+							names.add(bsn);
+						}
+					}
+				}
+			}
+		}
+
+		return names;
+	}
+
+	public List<Version> versions(String bsn) throws Exception {
+		List<Version> versions = new ArrayList<Version>();
+		Collection<Project> projects = workspace.getAllProjects();
+		for (Project project : projects) {
+			File[] build = project.build(false);
+			if (build != null) {
+				for (File file : build) {
+					Jar jar = new Jar(file);
+					if (bsn.equals(jar.getBsn())) {
+						versions.add(new Version(jar.getVersion()));
+					}
+				}
+			}
+		}
+
+		return versions;
+	}
+
+	public String getName() {
+		return "Workspace";
+	}
+
+	public String getLocation() {
+		return "Workspace";
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/make/calltree/CalltreeResource.java b/bundleplugin/src/main/java/aQute/bnd/make/calltree/CalltreeResource.java
index a41e337..ddcf0f5 100644
--- a/bundleplugin/src/main/java/aQute/bnd/make/calltree/CalltreeResource.java
+++ b/bundleplugin/src/main/java/aQute/bnd/make/calltree/CalltreeResource.java
@@ -121,7 +121,7 @@
 														}
 													};
 
-	private static void xref(Map<Clazz.MethodDef,Set<Clazz.MethodDef>> references, Clazz.MethodDef source,
+	static void xref(Map<Clazz.MethodDef,Set<Clazz.MethodDef>> references, Clazz.MethodDef source,
 			Clazz.MethodDef reference) {
 		Set<Clazz.MethodDef> set = references.get(source);
 		if (set == null)
diff --git a/bundleplugin/src/main/java/aQute/bnd/make/coverage/CoverageResource.java b/bundleplugin/src/main/java/aQute/bnd/make/coverage/CoverageResource.java
index 0a1b8ab..56abb77 100644
--- a/bundleplugin/src/main/java/aQute/bnd/make/coverage/CoverageResource.java
+++ b/bundleplugin/src/main/java/aQute/bnd/make/coverage/CoverageResource.java
@@ -61,7 +61,8 @@
 				currentClass = className;
 			}
 			Tag method = doMethod(new Tag("method"), m.getKey());
-			classTag.addContent(method);
+			if ( classTag != null)
+				classTag.addContent(method);
 			for (MethodDef r : m.getValue()) {
 				Tag ref = doMethod(new Tag("ref"), r);
 				method.addContent(ref);
diff --git a/bundleplugin/src/main/java/aQute/bnd/make/metatype/MetaTypeReader.java b/bundleplugin/src/main/java/aQute/bnd/make/metatype/MetaTypeReader.java
index beb1a36..cd0fc4b 100644
--- a/bundleplugin/src/main/java/aQute/bnd/make/metatype/MetaTypeReader.java
+++ b/bundleplugin/src/main/java/aQute/bnd/make/metatype/MetaTypeReader.java
@@ -158,7 +158,7 @@
 		adt.addAttribute("min", min);
 		adt.addAttribute("description", description);
 
-		if (optionLabels != null) {
+		if (optionLabels != null && optionValues != null) {
 			for (int i = 0; i < optionLabels.length; i++) {
 				Tag option = new Tag(adt, "Option");
 				option.addAttribute("label", optionLabels[i]);
diff --git a/bundleplugin/src/main/java/aQute/bnd/maven/support/MavenEntry.java b/bundleplugin/src/main/java/aQute/bnd/maven/support/MavenEntry.java
index fd4459a..fe185a1 100644
--- a/bundleplugin/src/main/java/aQute/bnd/maven/support/MavenEntry.java
+++ b/bundleplugin/src/main/java/aQute/bnd/maven/support/MavenEntry.java
@@ -28,7 +28,7 @@
 	Properties					properties;
 	private boolean				propertiesChanged;
 	FutureTask<File>			artifact;
-	private String				artifactPath;
+	String						artifactPath;
 
 	/**
 	 * Constructor.
@@ -139,7 +139,7 @@
 	 * @return
 	 * @throws MalformedURLException
 	 */
-	private boolean download(URI repo, String path) throws MalformedURLException {
+	boolean download(URI repo, String path) throws MalformedURLException {
 		try {
 			URL url = toURL(repo, path);
 			System.err.println("Downloading " + repo + " path " + path + " url " + url);
diff --git a/bundleplugin/src/main/java/aQute/bnd/maven/support/ProjectPom.java b/bundleplugin/src/main/java/aQute/bnd/maven/support/ProjectPom.java
index 6a8130c..07e10c6 100644
--- a/bundleplugin/src/main/java/aQute/bnd/maven/support/ProjectPom.java
+++ b/bundleplugin/src/main/java/aQute/bnd/maven/support/ProjectPom.java
@@ -140,6 +140,7 @@
 		System.err.println("Replce: " + in);
 		if (in == null) {
 			System.err.println("null??");
+			in = "<<???>>";
 		}
 		Matcher matcher = MACRO.matcher(in);
 		int last = 0;
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/SortedList.java b/bundleplugin/src/main/java/aQute/lib/collections/SortedList.java
index ad5ef4c..0747fa3 100644
--- a/bundleplugin/src/main/java/aQute/lib/collections/SortedList.java
+++ b/bundleplugin/src/main/java/aQute/lib/collections/SortedList.java
@@ -45,7 +45,7 @@
 	class It implements ListIterator<T> {
 		int	n;
 
-		private It(int n) {
+		It(int n) {
 			this.n = n;
 		}
 
diff --git a/bundleplugin/src/main/java/aQute/lib/deployer/FileRepo.java b/bundleplugin/src/main/java/aQute/lib/deployer/FileRepo.java
index 3e79730..a89d4e0 100644
--- a/bundleplugin/src/main/java/aQute/lib/deployer/FileRepo.java
+++ b/bundleplugin/src/main/java/aQute/lib/deployer/FileRepo.java
@@ -44,8 +44,6 @@
 			throw new IllegalArgumentException("Location must be set on a FileRepo plugin");
 
 		root = new File(location);
-		if (!root.isDirectory())
-			throw new IllegalArgumentException("Repository is not a valid directory " + root);
 
 		String readonly = map.get(READONLY);
 		if (readonly != null && Boolean.valueOf(readonly).booleanValue())
diff --git a/bundleplugin/src/main/java/aQute/lib/filter/Filter.java b/bundleplugin/src/main/java/aQute/lib/filter/Filter.java
index 2a7792c..853f617 100755
--- a/bundleplugin/src/main/java/aQute/lib/filter/Filter.java
+++ b/bundleplugin/src/main/java/aQute/lib/filter/Filter.java
@@ -24,7 +24,7 @@
 	final static int	GE			= 2;
 	final static int	APPROX		= 3;
 
-	private String		filter;
+	String		filter;
 
 	abstract class Query {
 		static final String	GARBAGE		= "Trailing garbage";
diff --git a/bundleplugin/src/main/java/aQute/lib/index/Index.java b/bundleplugin/src/main/java/aQute/lib/index/Index.java
index da19f68..1781798 100644
--- a/bundleplugin/src/main/java/aQute/lib/index/Index.java
+++ b/bundleplugin/src/main/java/aQute/lib/index/Index.java
@@ -21,7 +21,7 @@
 	final static int					MAGIC		= 0x494C4458;
 	final static int					KEYSIZE		= 4;
 
-	private FileChannel					file;
+	FileChannel					file;
 	final int							pageSize	= 4096;
 	final int							keySize;
 	final int							valueSize	= 8;
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java b/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
index 8af9bc7..3c0c9b2 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 Properties								bndInfo;
+	static Manifest									bndInfo;
 
 	// Bundle parameters
 	private Jar										dot;
@@ -643,11 +643,11 @@
 	 * @return version or unknown.
 	 */
 	public String getBndVersion() {
-		return getBndInfo("version", "1.42.1");
+		return getBndInfo("Bundle-Version", "<unknown>");
 	}
 
 	public long getBndLastModified() {
-		String time = getBndInfo("modified", "0");
+		String time = getBndInfo("Bnd-LastModified", "0");
 		try {
 			return Long.parseLong(time);
 		}
@@ -658,25 +658,18 @@
 	}
 
 	public String getBndInfo(String key, String defaultValue) {
-		synchronized (Analyzer.class) {
-			if (bndInfo == null) {
-				bndInfo = new Properties();
-				InputStream in = Analyzer.class.getResourceAsStream("bnd.info");
-				try {
-					if (in != null) {
-						bndInfo.load(in);
-						in.close();
-					}
-				}
-				catch (IOException ioe) {
-					warning("Could not read bnd.info in " + Analyzer.class.getPackage() + ioe);
-				}
-				finally {
-					IO.close(in);
-				}
+		if (bndInfo == null) {
+			try {
+				bndInfo = new Manifest(getClass().getResourceAsStream("META-INF/MANIFEST.MF"));
+			}
+			catch (Exception e) {
+				return defaultValue;
 			}
 		}
-		return bndInfo.getProperty(key, defaultValue);
+		String value = bndInfo.getMainAttributes().getValue(key);
+		if (value == null)
+			return defaultValue;
+		return value;
 	}
 
 	/**
@@ -965,7 +958,7 @@
 			PackageRef ep = i.next();
 			Attrs parameters = exports.get(ep);
 
-			String noimport = parameters.get(NO_IMPORT_DIRECTIVE);
+			String noimport = parameters == null ? null : parameters.get(NO_IMPORT_DIRECTIVE);
 			if (noimport != null && noimport.equalsIgnoreCase("true"))
 				continue;
 
@@ -1368,8 +1361,7 @@
 		if (map == null) {
 			classpathExports.put(packageRef, map = new Attrs());
 		}
-		for (@SuppressWarnings("unchecked")
-		Enumeration<String> t = (Enumeration<String>) p.propertyNames(); t.hasMoreElements();) {
+		for (Enumeration<String> t = (Enumeration<String>) p.propertyNames(); t.hasMoreElements();) {
 			String key = t.nextElement();
 			String value = map.get(key);
 			if (value == null) {
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
index 58d112d..b44118a 100755
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
@@ -70,7 +70,6 @@
 		doIncludeResources(dot);
 		doWab(dot);
 
-		doBndInfo(dot);
 
 		// Check if we override the calculation of the
 		// manifest. We still need to calculated it because
@@ -106,7 +105,7 @@
 
 		if (getProperty(POM) != null)
 			dot.putResource("pom.xml", new PomResource(dot.getManifest()));
-
+		
 		if (!isNoBundle())
 			doVerify(dot);
 
@@ -126,20 +125,6 @@
 		return dot;
 	}
 
-	/**
-	 * Make sure any bnd.info files are properly processed
-	 * 
-	 * @param jar
-	 */
-
-	private void doBndInfo(Jar jar) {
-		for (Entry<String,Resource> e : jar.getResources().entrySet()) {
-			if (e.getKey().endsWith("/bnd.info")) {
-				PreprocessResource pp = new PreprocessResource(this, e.getValue());
-				e.setValue(pp);
-			}
-		}
-	}
 
 	/**
 	 * Check if we need to calculate any checksums.
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Descriptors.java b/bundleplugin/src/main/java/aQute/lib/osgi/Descriptors.java
index c15e436..f9c6a31 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Descriptors.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Descriptors.java
@@ -59,7 +59,7 @@
 		final String	fqn;
 		final boolean	java;
 
-		private PackageRef(String binaryName) {
+		PackageRef(String binaryName) {
 			this.binaryName = fqnToBinary(binaryName);
 			this.fqn = binaryToFQN(binaryName);
 			this.java = this.fqn.startsWith("java."); // &&
@@ -69,7 +69,7 @@
 			// delegate anyway. So lost the understanding why I did it??
 		}
 
-		private PackageRef() {
+		PackageRef() {
 			this.binaryName = "";
 			this.fqn = ".";
 			this.java = false;
@@ -226,6 +226,11 @@
 			return fqn.compareTo(other.getFQN());
 		}
 
+		@Override
+		public int hashCode() {
+			return super.hashCode();
+		}
+
 	}
 
 	private static class ArrayRef implements TypeRef {
@@ -301,6 +306,11 @@
 			return getFQN().compareTo(other.getFQN());
 		}
 
+		@Override
+		public int hashCode() {
+			return super.hashCode();
+		}
+
 	}
 
 	public TypeRef getTypeRef(String binaryClassName) {
@@ -385,7 +395,7 @@
 		final TypeRef[]	prototype;
 		final String	descriptor;
 
-		private Descriptor(String descriptor) {
+		Descriptor(String descriptor) {
 			this.descriptor = descriptor;
 			int index = 0;
 			List<TypeRef> types = Create.list();
diff --git a/bundleplugin/src/main/java/aQute/libg/cafs/CAFS.java b/bundleplugin/src/main/java/aQute/libg/cafs/CAFS.java
index 38e67be..db2a175 100644
--- a/bundleplugin/src/main/java/aQute/libg/cafs/CAFS.java
+++ b/bundleplugin/src/main/java/aQute/libg/cafs/CAFS.java
@@ -339,7 +339,7 @@
 		channel.force(false);
 	}
 
-	private short checksum(int flags, int compressedLength, int totalLength, byte[] sha1) {
+	short checksum(int flags, int compressedLength, int totalLength, byte[] sha1) {
 		CRC32 crc = new CRC32();
 		crc.update(flags);
 		crc.update(flags >> 8);
diff --git a/bundleplugin/src/main/java/aQute/libg/forker/Forker.java b/bundleplugin/src/main/java/aQute/libg/forker/Forker.java
index 3929ca4..14bb0f8 100644
--- a/bundleplugin/src/main/java/aQute/libg/forker/Forker.java
+++ b/bundleplugin/src/main/java/aQute/libg/forker/Forker.java
@@ -64,7 +64,7 @@
 		/**
 		 * Cancel this job
 		 */
-		private void cancel() {
+		void cancel() {
 			if (!canceled.getAndSet(true)) {
 				synchronized (this) {
 					if (t != null)
@@ -166,7 +166,7 @@
 	 * 
 	 * @param done
 	 */
-	private void done(Job done) {
+	void done(Job done) {
 		synchronized (this) {
 			System.err.println("count = " + count);
 			executing.remove(done);
diff --git a/bundleplugin/src/main/java/aQute/libg/header/Attrs.java b/bundleplugin/src/main/java/aQute/libg/header/Attrs.java
index 8ff65dd..40fefcc 100644
--- a/bundleplugin/src/main/java/aQute/libg/header/Attrs.java
+++ b/bundleplugin/src/main/java/aQute/libg/header/Attrs.java
@@ -289,6 +289,15 @@
 					return Long.parseLong(s.trim());
 				case VERSION :
 					return Version.parseVersion(s);
+				case DOUBLE :
+					return Double.parseDouble(s.trim());
+					
+				case DOUBLES :
+				case LONGS :
+				case STRINGS :
+				case VERSIONS :
+					// Cannot happen since the sub is null
+					return null;
 			}
 			return null;
 		}
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java b/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
index 8d782cf..90da59b 100644
--- a/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
+++ b/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
@@ -31,7 +31,7 @@
 		}, new InvocationHandler() {
 
 			public Object invoke(Object target, Method method, Object[] args) throws Throwable {
-				if (reporter.isExceptions()) {
+				if (reporter.isExceptions() && args!=null) {
 					for (Object o : args) {
 						if (o instanceof Throwable)
 							((Throwable) o).printStackTrace();
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/packageinfo b/bundleplugin/src/main/java/aQute/libg/reporter/packageinfo
index ef7df68..0117a56 100644
--- a/bundleplugin/src/main/java/aQute/libg/reporter/packageinfo
+++ b/bundleplugin/src/main/java/aQute/libg/reporter/packageinfo
@@ -1 +1 @@
-version 1.2
+version 1.3