Latest bnd code

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1350613 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/bnd/differ/Baseline.java b/bundleplugin/src/main/java/aQute/bnd/differ/Baseline.java
index eee3e27..3228b7b 100644
--- a/bundleplugin/src/main/java/aQute/bnd/differ/Baseline.java
+++ b/bundleplugin/src/main/java/aQute/bnd/differ/Baseline.java
@@ -14,7 +14,6 @@
 
 /**
  * This class maintains
- * 
  */
 public class Baseline {
 
@@ -22,18 +21,19 @@
 		public String				packageName;
 		public Diff					packageDiff;
 		public Collection<String>	providers;
-		public Map<String, String>	attributes;
+		public Map<String,String>	attributes;
 		public Version				newerVersion;
 		public Version				olderVersion;
 		public Version				suggestedVersion;
 		public Version				suggestedIfProviders;
 		public boolean				mismatch;
-		public String				warning="";
+		public String				warning	= "";
 
 	}
 
 	final Differ	differ;
 	final Reporter	bnd;
+	Diff			diff;
 
 	public Baseline(Reporter bnd, Differ differ) throws IOException {
 		this.differ = differ;
@@ -51,25 +51,24 @@
 	 *         packages (also the ones that were ok).
 	 * @throws Exception
 	 */
-	public Set<Info> baseline(Jar newer, Jar older, Instructions packageFilters)
-			throws Exception {
+	public Set<Info> baseline(Jar newer, Jar older, Instructions packageFilters) throws Exception {
 		Tree n = differ.tree(newer);
 		Parameters nExports = getExports(newer);
 		Tree o = differ.tree(older);
 		Parameters oExports = getExports(older);
-		if ( packageFilters == null)
+		if (packageFilters == null)
 			packageFilters = new Instructions();
-		
+
 		return baseline(n, nExports, o, oExports, packageFilters);
 	}
 
-	public Set<Info> baseline(Tree n, Parameters nExports, Tree o,
-			Parameters oExports, Instructions packageFilters)
+	public Set<Info> baseline(Tree n, Parameters nExports, Tree o, Parameters oExports, Instructions packageFilters)
 			throws Exception {
-		Diff diff = n.diff(o).get("<api>");
+		diff = n.diff(o);
+		Diff apiDiff = diff.get("<api>");
 		Set<Info> infos = Create.set();
 
-		for (Diff pdiff : diff.getChildren()) {
+		for (Diff pdiff : apiDiff.getChildren()) {
 			if (pdiff.getType() != Type.PACKAGE) // Just packages
 				continue;
 
@@ -85,13 +84,13 @@
 			info.packageDiff = pdiff;
 			info.packageName = pdiff.getName();
 			info.attributes = nExports.get(info.packageName);
-			bnd.trace("attrs for %s %s", info.packageName,info.attributes);
+			bnd.trace("attrs for %s %s", info.packageName, info.attributes);
 
 			info.newerVersion = getVersion(info.attributes);
 			info.olderVersion = getVersion(oExports.get(info.packageName));
 			if (pdiff.getDelta() == Delta.UNCHANGED) {
 				info.suggestedVersion = info.olderVersion;
-				if( !info.newerVersion.equals(info.olderVersion)) {
+				if (!info.newerVersion.equals(info.olderVersion)) {
 					info.warning += "No difference but versions are equal";
 				}
 			} else if (pdiff.getDelta() == Delta.REMOVED) {
@@ -122,8 +121,7 @@
 						// by making them providers
 						Delta tryDelta = pdiff.getDelta(new Ignore() {
 							public boolean contains(Diff diff) {
-								if (diff.getType() == Type.INTERFACE
-										&& diff.getDelta() == Delta.MAJOR) {
+								if (diff.getType() == Type.INTERFACE && diff.getDelta() == Delta.MAJOR) {
 									info.providers.add(Descriptors.getShortName(diff.getName()));
 									return true;
 								}
@@ -141,22 +139,31 @@
 		return infos;
 	}
 
+	/**
+	 * Gets the generated diff
+	 * 
+	 * @return the diff
+	 */
+	public Diff getDiff() {
+		return diff;
+	}
+
 	private Version bump(Delta delta, Version last, int offset, int base) {
 		switch (delta) {
-		case UNCHANGED:
-			return last;
-		case MINOR:
-			return new Version(last.getMajor(), last.getMinor() + offset, base);
-		case MAJOR:
-			return new Version(last.getMajor() + 1, base, base);
-		case ADDED:
-			return last;
-		default:
-			return new Version(last.getMajor(), last.getMinor(), last.getMicro() + offset);
+			case UNCHANGED :
+				return last;
+			case MINOR :
+				return new Version(last.getMajor(), last.getMinor() + offset, base);
+			case MAJOR :
+				return new Version(last.getMajor() + 1, base, base);
+			case ADDED :
+				return last;
+			default :
+				return new Version(last.getMajor(), last.getMinor(), last.getMicro() + offset);
 		}
 	}
 
-	private Version getVersion(Map<String, String> map) {
+	private Version getVersion(Map<String,String> map) {
 		if (map == null)
 			return Version.LOWEST;
 
diff --git a/bundleplugin/src/main/java/aQute/bnd/differ/DiffImpl.java b/bundleplugin/src/main/java/aQute/bnd/differ/DiffImpl.java
index 7b675c2..ea6cd50 100644
--- a/bundleplugin/src/main/java/aQute/bnd/differ/DiffImpl.java
+++ b/bundleplugin/src/main/java/aQute/bnd/differ/DiffImpl.java
@@ -17,8 +17,8 @@
 
 public class DiffImpl implements Diff, Comparable<DiffImpl> {
 
-	final Element				older;
-	final Element				newer;
+	final Tree				older;
+	final Tree				newer;
 	final Collection<DiffImpl>	children;
 	final Delta					delta;
 
@@ -28,14 +28,30 @@
 	 * child delta for each child. This escalates deltas from below up.
 	 */
 	final static Delta[][]		TRANSITIONS	= {
-			{ IGNORED, UNCHANGED, CHANGED, MICRO, MINOR, MAJOR }, // IGNORED
-			{ IGNORED, UNCHANGED, CHANGED, MICRO, MINOR, MAJOR }, // UNCHANGED
-			{ IGNORED, CHANGED, CHANGED, MICRO, MINOR, MAJOR }, // CHANGED
-			{ IGNORED, MICRO, MICRO, MICRO, MINOR, MAJOR }, // MICRO
-			{ IGNORED, MINOR, MINOR, MINOR, MINOR, MAJOR }, // MINOR
-			{ IGNORED, MAJOR, MAJOR, MAJOR, MAJOR, MAJOR }, // MAJOR
-			{ IGNORED, MAJOR, MAJOR, MAJOR, MAJOR, MAJOR }, // REMOVED
-			{ IGNORED, MINOR, MINOR, MINOR, MINOR, MAJOR }, // ADDED
+			{
+			IGNORED, UNCHANGED, CHANGED, MICRO, MINOR, MAJOR
+			}, // IGNORED
+			{
+			IGNORED, UNCHANGED, CHANGED, MICRO, MINOR, MAJOR
+			}, // UNCHANGED
+			{
+			IGNORED, CHANGED, CHANGED, MICRO, MINOR, MAJOR
+			}, // CHANGED
+			{
+			IGNORED, MICRO, MICRO, MICRO, MINOR, MAJOR
+			}, // MICRO
+			{
+			IGNORED, MINOR, MINOR, MINOR, MINOR, MAJOR
+			}, // MINOR
+			{
+			IGNORED, MAJOR, MAJOR, MAJOR, MAJOR, MAJOR
+			}, // MAJOR
+			{
+			IGNORED, MAJOR, MAJOR, MAJOR, MAJOR, MAJOR
+			}, // REMOVED
+			{
+			IGNORED, MINOR, MINOR, MINOR, MINOR, MAJOR
+			}, // ADDED
 											};
 
 	/**
@@ -48,22 +64,22 @@
 	 *            The older Element
 	 * @param types
 	 */
-	DiffImpl(Element newer, Element older) {
+	public DiffImpl(Tree newer, Tree older) {
 		assert newer != null || older != null;
 		this.older = older;
 		this.newer = newer;
 
 		// Either newer or older can be null, indicating remove or add
 		// so we have to be very careful.
-		Element[] newerChildren = newer == null ? Element.EMPTY : newer.children;
-		Element[] olderChildren = older == null ? Element.EMPTY : older.children;
+		Tree[] newerChildren = newer == null ? Element.EMPTY : newer.getChildren();
+		Tree[] olderChildren = older == null ? Element.EMPTY : older.getChildren();
 
 		int o = 0;
 		int n = 0;
 		List<DiffImpl> children = new ArrayList<DiffImpl>();
 		while (true) {
-			Element nw = n < newerChildren.length ? newerChildren[n] : null;
-			Element ol = o < olderChildren.length ? olderChildren[o] : null;
+			Tree nw = n < newerChildren.length ? newerChildren[n] : null;
+			Tree ol = o < olderChildren.length ? olderChildren[o] : null;
 			DiffImpl diff;
 
 			if (nw == null && ol == null)
@@ -136,9 +152,9 @@
 			for (DiffImpl child : children) {
 				Delta sub = child.getDelta(ignore);
 				if (sub == REMOVED)
-					sub = child.older.remove;
+					sub = child.older.ifRemoved();
 				else if (sub == ADDED)
-					sub = child.newer.add;
+					sub = child.newer.ifAdded();
 
 				// The escalate method is used to calculate the default
 				// transition in the
@@ -160,7 +176,7 @@
 		return (newer == null ? older : newer).getName();
 	}
 
-	public Collection<? extends Diff> getChildren() {
+	public Collection< ? extends Diff> getChildren() {
 		return children;
 	}
 
@@ -171,8 +187,7 @@
 	public boolean equals(Object other) {
 		if (other instanceof DiffImpl) {
 			DiffImpl o = (DiffImpl) other;
-			return getDelta() == o.getDelta() && getType() == o.getType()
-					&& getName().equals(o.getName());
+			return getDelta() == o.getDelta() && getType() == o.getType() && getName().equals(o.getName());
 		}
 		return false;
 	}
@@ -207,4 +222,19 @@
 		return newer;
 	}
 
+	public Data serialize() {
+		Data data = new Data();
+		data.type = getType();
+		data.delta = delta;
+		data.name = getName();
+		data.children = new Data[children.size()];
+		
+		int i=0;		
+		for ( Diff d : children)
+			data.children[i++] = d.serialize();
+				
+		return data;
+	}
+
+
 }
diff --git a/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java b/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java
index e3a1308..2fb366b 100644
--- a/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java
+++ b/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java
@@ -14,26 +14,23 @@
 import aQute.libg.cryptography.*;
 import aQute.libg.header.*;
 
-
 /**
  * This Diff Plugin Implementation will compare JARs for their API (based on the
  * Bundle Class Path and exported packages), the Manifest, and the resources.
  * The Differences are represented in a {@link Diff} tree.
  */
 public class DiffPluginImpl implements Differ {
-	
+
 	/**
 	 * Headers that are considered major enough to parse according to spec and
 	 * compare their constituents
 	 */
-	final static Set<String>				MAJOR_HEADERS	= new TreeSet<String>(
-																	String.CASE_INSENSITIVE_ORDER);
+	final static Set<String>	MAJOR_HEADERS	= new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
 
 	/**
 	 * Headers that are considered not major enough to be considered
 	 */
-	final static Set<String>				IGNORE_HEADERS	= new TreeSet<String>(
-																	String.CASE_INSENSITIVE_ORDER);
+	final static Set<String>	IGNORE_HEADERS	= new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
 
 	static {
 		MAJOR_HEADERS.add(Constants.EXPORT_PACKAGE);
@@ -52,7 +49,6 @@
 	}
 
 	/**
-	 * 
 	 * @see aQute.bnd.service.diff.Differ#diff(aQute.lib.resource.Jar,
 	 *      aQute.lib.resource.Jar)
 	 */
@@ -60,22 +56,23 @@
 		Jar jnewer = new Jar(newer);
 		try {
 			return tree(jnewer);
-		} finally {
+		}
+		finally {
 			jnewer.close();
 		}
 	}
 
 	/**
-	 * 
 	 * @see aQute.bnd.service.diff.Differ#diff(aQute.lib.resource.Jar,
 	 *      aQute.lib.resource.Jar)
 	 */
 	public Tree tree(Jar newer) throws Exception {
 		Analyzer anewer = new Analyzer();
 		try {
-				anewer.setJar(newer);
-				return tree(anewer);
-		} finally {
+			anewer.setJar(newer);
+			return tree(anewer);
+		}
+		finally {
 			anewer.setJar((Jar) null);
 			anewer.close();
 		}
@@ -88,7 +85,7 @@
 	/**
 	 * Create an element representing a bundle from the Jar.
 	 * 
-	 * @param infos 
+	 * @param infos
 	 * @param jar
 	 *            The Jar to be analyzed
 	 * @return the elements that should be compared
@@ -104,8 +101,7 @@
 			result.add(manifestElement(manifest));
 		}
 		result.add(resourcesElement(analyzer.getJar()));
-		return new Element(Type.BUNDLE, analyzer.getJar().getName(), result, CHANGED, CHANGED,
-				null);
+		return new Element(Type.BUNDLE, analyzer.getJar().getName(), result, CHANGED, CHANGED, null);
 	}
 
 	/**
@@ -117,25 +113,22 @@
 	 */
 	private Element resourcesElement(Jar jar) throws Exception {
 		List<Element> resources = new ArrayList<Element>();
-		for (Map.Entry<String, Resource> entry : jar.getResources().entrySet()) {
+		for (Map.Entry<String,Resource> entry : jar.getResources().entrySet()) {
 
 			InputStream in = entry.getValue().openInputStream();
 			try {
 				Digester<SHA1> digester = SHA1.getDigester();
 				IO.copy(in, digester);
 				String value = Hex.toHexString(digester.digest().digest());
-				resources
-						.add(new Element(Type.RESOURCE, entry.getKey()+"="+value, null, CHANGED, CHANGED, null));
-			} finally {
+				resources.add(new Element(Type.RESOURCE, entry.getKey() + "=" + value, null, CHANGED, CHANGED, null));
+			}
+			finally {
 				in.close();
 			}
 		}
 		return new Element(Type.RESOURCES, "<resources>", resources, CHANGED, CHANGED, null);
 	}
 
-
-
-
 	/**
 	 * Create an element for each manifest header. There are
 	 * {@link #IGNORE_HEADERS} and {@link #MAJOR_HEADERS} that will be treated
@@ -157,18 +150,17 @@
 			if (MAJOR_HEADERS.contains(header)) {
 				Parameters clauses = OSGiHeader.parseHeader(value);
 				Collection<Element> clausesDef = new ArrayList<Element>();
-				for (Map.Entry<String, Attrs> clause : clauses.entrySet()) {
+				for (Map.Entry<String,Attrs> clause : clauses.entrySet()) {
 					Collection<Element> parameterDef = new ArrayList<Element>();
-					for (Map.Entry<String, String> parameter : clause.getValue().entrySet()) {
-						parameterDef.add(new Element(Type.PARAMETER, parameter.getKey() + ":" + parameter
-								.getValue(), null, CHANGED, CHANGED, null));
+					for (Map.Entry<String,String> parameter : clause.getValue().entrySet()) {
+						parameterDef.add(new Element(Type.PARAMETER, parameter.getKey() + ":" + parameter.getValue(),
+								null, CHANGED, CHANGED, null));
 					}
-					clausesDef.add(new Element(Type.CLAUSE, clause.getKey(), parameterDef,
-							CHANGED, CHANGED, null));
+					clausesDef.add(new Element(Type.CLAUSE, clause.getKey(), parameterDef, CHANGED, CHANGED, null));
 				}
 				result.add(new Element(Type.HEADER, header, clausesDef, CHANGED, CHANGED, null));
 			} else {
-				result.add(new Element(Type.HEADER, header +":"+ value, null,CHANGED, CHANGED, null));
+				result.add(new Element(Type.HEADER, header + ":" + value, null, CHANGED, CHANGED, null));
 			}
 		}
 		return new Element(Type.MANIFEST, "<manifest>", result, CHANGED, CHANGED, null);
diff --git a/bundleplugin/src/main/java/aQute/bnd/differ/Element.java b/bundleplugin/src/main/java/aQute/bnd/differ/Element.java
index 602f95c..683c7a8 100644
--- a/bundleplugin/src/main/java/aQute/bnd/differ/Element.java
+++ b/bundleplugin/src/main/java/aQute/bnd/differ/Element.java
@@ -20,7 +20,7 @@
  * unnecessary.
  */
 
-class Element implements Comparable<Element>, Tree {
+class Element implements Tree {
 	final static Element[]	EMPTY	= new Element[0];
 	final Type				type;
 	final String			name;
@@ -37,8 +37,7 @@
 		this(type, name, Arrays.asList(children), Delta.MINOR, Delta.MAJOR, null);
 	}
 
-	Element(Type type, String name, Collection<? extends Element> children, Delta add,
-			Delta remove, String comment) {
+	Element(Type type, String name, Collection< ? extends Element> children, Delta add, Delta remove, String comment) {
 		this.type = type;
 		this.name = name;
 		this.add = add;
@@ -66,6 +65,7 @@
 			Arrays.sort(this.children);
 		}
 	}
+
 	public Data serialize() {
 		Data data = new Data();
 		data.type = this.type;
@@ -94,11 +94,11 @@
 		return comment;
 	}
 
-	public int compareTo(Element other) {
-		if (type == other.type)
-			return name.compareTo(other.name);
+	public int compareTo(Tree other) {
+		if (type == other.getType())
+			return name.compareTo(other.getName());
 		else
-			return type.compareTo(other.type);
+			return type.compareTo(other.getType());
 	}
 
 	public boolean equals(Object other) {
@@ -135,10 +135,9 @@
 		}
 		return null;
 	}
-	
+
 	public String toString() {
 		return type + " " + name + " (" + add + "/" + remove + ")";
 	}
 
-
 }
diff --git a/bundleplugin/src/main/java/aQute/bnd/differ/JavaElement.java b/bundleplugin/src/main/java/aQute/bnd/differ/JavaElement.java
index e9a77a5..c5bdb4b 100644
--- a/bundleplugin/src/main/java/aQute/bnd/differ/JavaElement.java
+++ b/bundleplugin/src/main/java/aQute/bnd/differ/JavaElement.java
@@ -47,32 +47,26 @@
  * <li>MAJOR - +final
  * <li>MAJOR - +protected
  * </ul>
- * 
  */
 
 class JavaElement {
-	final static EnumSet<Type>			INHERITED		= EnumSet.of(FIELD, METHOD, EXTENDS,
-																IMPLEMENTS);
-	private static final Element		PROTECTED		= new Element(ACCESS, "protected", null,
-																MAJOR, MINOR, null);
-	private static final Element		STATIC			= new Element(ACCESS, "static", null,
-																MAJOR, MAJOR, null);
-	private static final Element		ABSTRACT		= new Element(ACCESS, "abstract", null,
-																MAJOR, MINOR, null);
-	private static final Element		FINAL			= new Element(ACCESS, "final", null, MAJOR,
-																MINOR, null);
+	final static EnumSet<Type>			INHERITED		= EnumSet.of(FIELD, METHOD, EXTENDS, IMPLEMENTS);
+	private static final Element		PROTECTED		= new Element(ACCESS, "protected", null, MAJOR, MINOR, null);
+	private static final Element		STATIC			= new Element(ACCESS, "static", null, MAJOR, MAJOR, null);
+	private static final Element		ABSTRACT		= new Element(ACCESS, "abstract", null, MAJOR, MINOR, null);
+	private static final Element		FINAL			= new Element(ACCESS, "final", null, MAJOR, MINOR, null);
 	// private static final Element DEPRECATED = new Element(ACCESS,
 	// "deprecated", null,
 	// CHANGED, CHANGED, null);
 
 	final Analyzer						analyzer;
-	final Map<PackageRef, Instructions>	providerMatcher	= Create.map();
+	final Map<PackageRef,Instructions>	providerMatcher	= Create.map();
 	final Set<TypeRef>					notAccessible	= Create.set();
-	final Map<Object, Element>			cache			= Create.map();
+	final Map<Object,Element>			cache			= Create.map();
 	MultiMap<PackageRef, //
 	Element>							packages;
 	final MultiMap<TypeRef, //
-	Element>							covariant		= new MultiMap<TypeRef, Element>();
+	Element>							covariant		= new MultiMap<TypeRef,Element>();
 	final Set<JAVA>						javas			= Create.set();
 	final Packages						exports;
 
@@ -87,10 +81,9 @@
 		this.analyzer = analyzer;
 
 		Manifest manifest = analyzer.getJar().getManifest();
-		if (manifest != null
-				&& manifest.getMainAttributes().getValue(Constants.BUNDLE_MANIFESTVERSION) != null) {
+		if (manifest != null && manifest.getMainAttributes().getValue(Constants.BUNDLE_MANIFESTVERSION) != null) {
 			exports = new Packages();
-			for (Map.Entry<String, Attrs> entry : OSGiHeader.parseHeader(
+			for (Map.Entry<String,Attrs> entry : OSGiHeader.parseHeader(
 					manifest.getMainAttributes().getValue(Constants.EXPORT_PACKAGE)).entrySet())
 				exports.put(analyzer.getPackageRef(entry.getKey()), entry.getValue());
 		} else
@@ -101,7 +94,7 @@
 		// out who the providers and consumers are
 		//
 
-		for (Entry<PackageRef, Attrs> entry : exports.entrySet()) {
+		for (Entry<PackageRef,Attrs> entry : exports.entrySet()) {
 			String value = entry.getValue().get(Constants.PROVIDER_TYPE_DIRECTIVE);
 			if (value != null) {
 				providerMatcher.put(entry.getKey(), new Instructions(value));
@@ -112,7 +105,7 @@
 		// creating the packages yet because we do not yet know
 		// which classes are accessible
 
-		packages = new MultiMap<PackageRef, Element>();
+		packages = new MultiMap<PackageRef,Element>();
 
 		for (Clazz c : analyzer.getClassspace().values()) {
 			if (c.isPublic() || c.isProtected()) {
@@ -136,27 +129,25 @@
 	private Element getLocalAPI() throws Exception {
 		List<Element> result = new ArrayList<Element>();
 
-		for (Map.Entry<PackageRef, List<Element>> entry : packages.entrySet()) {
+		for (Map.Entry<PackageRef,List<Element>> entry : packages.entrySet()) {
 			List<Element> set = entry.getValue();
 			for (Iterator<Element> i = set.iterator(); i.hasNext();) {
-				
-				if (notAccessible.contains( analyzer.getTypeRefFromFQN(i.next().getName())))
+
+				if (notAccessible.contains(analyzer.getTypeRefFromFQN(i.next().getName())))
 					i.remove();
-				
+
 			}
 			String version = exports.get(entry.getKey()).get(Constants.VERSION_ATTRIBUTE);
 			if (version != null) {
 				Version v = new Version(version);
-				set.add(new Element(Type.VERSION, v.getWithoutQualifier().toString(), null,
-						IGNORED, IGNORED, null));
+				set.add(new Element(Type.VERSION, v.getWithoutQualifier().toString(), null, IGNORED, IGNORED, null));
 			}
 			Element pd = new Element(Type.PACKAGE, entry.getKey().getFQN(), set, MINOR, MAJOR, null);
 			result.add(pd);
 		}
 
 		for (JAVA java : javas) {
-			result.add(new Element(CLASS_VERSION, java.toString(), null, Delta.CHANGED,
-					Delta.CHANGED, null));
+			result.add(new Element(CLASS_VERSION, java.toString(), null, Delta.CHANGED, Delta.CHANGED, null));
 		}
 
 		return new Element(Type.API, "<api>", result, CHANGED, CHANGED, null);
@@ -183,7 +174,7 @@
 		final Set<Element> members = new HashSet<Element>();
 		final Set<MethodDef> methods = Create.set();
 		final Set<Clazz.FieldDef> fields = Create.set();
-		final MultiMap<Clazz.Def, Element> annotations = new MultiMap<Clazz.Def, Element>();
+		final MultiMap<Clazz.Def,Element> annotations = new MultiMap<Clazz.Def,Element>();
 
 		final TypeRef name = clazz.getClassName();
 
@@ -209,11 +200,13 @@
 			boolean			memberEnd;
 			Clazz.FieldDef	last;
 
-			@Override public void version(int minor, int major) {
+			@Override
+			public void version(int minor, int major) {
 				javas.add(Clazz.JAVA.getJava(major, minor));
 			}
 
-			@Override public void method(MethodDef defined) {
+			@Override
+			public void method(MethodDef defined) {
 				if ((defined.isProtected() || defined.isPublic())) {
 					last = defined;
 					methods.add(defined);
@@ -222,14 +215,16 @@
 				}
 			}
 
-			@Override public void deprecated() {
+			@Override
+			public void deprecated() {
 				if (memberEnd)
 					clazz.setDeprecated(true);
 				else
 					last.setDeprecated(true);
 			}
 
-			@Override public void field(Clazz.FieldDef defined) {
+			@Override
+			public void field(Clazz.FieldDef defined) {
 				if (defined.isProtected() || defined.isPublic()) {
 					last = defined;
 					fields.add(defined);
@@ -237,25 +232,27 @@
 					last = null;
 			}
 
-			@Override public void constant(Object o) {
+			@Override
+			public void constant(Object o) {
 				if (last != null) {
 					// Must be accessible now
 					last.setConstant(o);
 				}
 			}
 
-			@Override public void extendsClass(TypeRef name) throws Exception {
+			@Override
+			public void extendsClass(TypeRef name) throws Exception {
 				String comment = null;
 				if (!clazz.isInterface())
 					comment = inherit(members, name);
 
 				Clazz c = analyzer.findClass(name);
 				if ((c == null || c.isPublic()) && !name.isObject())
-					members.add(new Element(Type.EXTENDS, name.getFQN(), null, MICRO, MAJOR,
-							comment));
+					members.add(new Element(Type.EXTENDS, name.getFQN(), null, MICRO, MAJOR, comment));
 			}
 
-			@Override public void implementsInterfaces(TypeRef names[]) throws Exception {
+			@Override
+			public void implementsInterfaces(TypeRef names[]) throws Exception {
 				// TODO is interface reordering important for binary
 				// compatibility??
 
@@ -264,8 +261,7 @@
 					String comment = null;
 					if (clazz.isInterface() || clazz.isAbstract())
 						comment = inherit(members, name);
-					members.add(new Element(Type.IMPLEMENTS, name.getFQN(), null, MINOR, MAJOR,
-							comment));
+					members.add(new Element(Type.IMPLEMENTS, name.getFQN(), null, MINOR, MAJOR, comment));
 				}
 			}
 
@@ -286,8 +282,7 @@
 							if (INHERITED.contains(child.type)) {
 								String n = child.getName();
 								if (child.type == METHOD) {
-									if (n.startsWith("<init>")
-											|| "getClass()".equals(child.getName())
+									if (n.startsWith("<init>") || "getClass()".equals(child.getName())
 											|| n.startsWith("wait(") || n.startsWith("notify(")
 											|| n.startsWith("notifyAll("))
 										continue;
@@ -314,7 +309,8 @@
 				return null;
 			}
 
-			@Override public void annotation(Annotation annotation) {
+			@Override
+			public void annotation(Annotation annotation) {
 				Collection<Element> properties = Create.set();
 				if (Deprecated.class.getName().equals(annotation.getName().getFQN())) {
 					if (memberEnd)
@@ -330,21 +326,20 @@
 					sb.append('=');
 					toString(sb, annotation.get(key));
 
-					properties.add(new Element(Type.PROPERTY, sb.toString(), null, CHANGED,
-							CHANGED, null));
+					properties.add(new Element(Type.PROPERTY, sb.toString(), null, CHANGED, CHANGED, null));
 				}
 
 				if (memberEnd) {
-					members.add(new Element(Type.ANNOTATED, annotation.getName().getFQN(),
-							properties, CHANGED, CHANGED, null));
+					members.add(new Element(Type.ANNOTATED, annotation.getName().getFQN(), properties, CHANGED,
+							CHANGED, null));
 					if (ProviderType.class.getName().equals(annotation.getName().getFQN())) {
 						provider.set(true);
 					} else if (ConsumerType.class.getName().equals(annotation.getName().getFQN())) {
 						provider.set(false);
 					}
 				} else if (last != null)
-					annotations.add(last, new Element(Type.ANNOTATED,
-							annotation.getName().getFQN(), properties, CHANGED, CHANGED, null));
+					annotations.add(last, new Element(Type.ANNOTATED, annotation.getName().getFQN(), properties,
+							CHANGED, CHANGED, null));
 			}
 
 			private void toString(StringBuilder sb, Object object) {
@@ -359,19 +354,20 @@
 					sb.append(object);
 			}
 
-			@Override public void innerClass(TypeRef innerClass, TypeRef outerClass,
-					String innerName, int innerClassAccessFlags) throws Exception {
+			@Override
+			public void innerClass(TypeRef innerClass, TypeRef outerClass, String innerName, int innerClassAccessFlags)
+					throws Exception {
 				Clazz clazz = analyzer.findClass(innerClass);
 				if (clazz != null)
 					clazz.setInnerAccess(innerClassAccessFlags);
 
-				if (Modifier.isProtected(innerClassAccessFlags)
-						|| Modifier.isPublic(innerClassAccessFlags))
+				if (Modifier.isProtected(innerClassAccessFlags) || Modifier.isPublic(innerClassAccessFlags))
 					return;
 				notAccessible.add(innerClass);
 			}
 
-			@Override public void memberEnd() {
+			@Override
+			public void memberEnd() {
 				memberEnd = true;
 			}
 		});
@@ -463,15 +459,14 @@
 
 			for (Iterator<MethodDef> i = synthetic.iterator(); i.hasNext();) {
 				MethodDef s = i.next();
-				if (s.getName().equals(m.getName())
-						&& Arrays.equals(s.getPrototype(), m.getPrototype())) {
+				if (s.getName().equals(m.getName()) && Arrays.equals(s.getPrototype(), m.getPrototype())) {
 					i.remove();
 					getCovariantReturns(children, s.getType());
 				}
 			}
 
-			Element member = new Element(Type.METHOD, m.getName() + toString(m.getPrototype()),
-					children, add, remove, null);
+			Element member = new Element(Type.METHOD, m.getName() + toString(m.getPrototype()), children, add, remove,
+					null);
 
 			if (!members.add(member)) {
 				members.remove(member);
@@ -505,8 +500,8 @@
 
 			getCovariantReturns(children, m.getType());
 
-			Element member = new Element(Type.METHOD, m.getName() + toString(m.getPrototype()),
-					children, add, remove, "synthetic");
+			Element member = new Element(Type.METHOD, m.getName() + toString(m.getPrototype()), children, add, remove,
+					"synthetic");
 
 			if (!members.add(member)) {
 				members.remove(member);
@@ -521,13 +516,12 @@
 
 			// Fields can have a constant value, this is a new element
 			if (f.getConstant() != null) {
-				children.add(new Element(Type.CONSTANT, f.getConstant().toString(), null, CHANGED,
-						CHANGED, null));
+				children.add(new Element(Type.CONSTANT, f.getConstant().toString(), null, CHANGED, CHANGED, null));
 			}
 
 			access(children, f.getAccess(), f.isDeprecated());
-			Element member = new Element(Type.FIELD, f.getType().getFQN() + " " + f.getName(),
-					children, MINOR, MAJOR, null);
+			Element member = new Element(Type.FIELD, f.getType().getFQN() + " " + f.getName(), children, MINOR, MAJOR,
+					null);
 
 			if (!members.add(member)) {
 				members.remove(member);
@@ -538,8 +532,7 @@
 		access(members, clazz.getAccess(), clazz.isDeprecated());
 
 		// And make the result
-		Element s = new Element(type, fqn, members, MINOR, MAJOR, comment.length() == 0 ? null
-				: comment.toString());
+		Element s = new Element(type, fqn, members, MINOR, MAJOR, comment.length() == 0 ? null : comment.toString());
 		cache.put(clazz, s);
 		return s;
 	}
@@ -577,33 +570,33 @@
 			String name = type.getBinary();
 			Element e;
 			switch (name.charAt(0)) {
-			case 'Z':
-				e = BOOLEAN_R;
-				break;
-			case 'S':
-				e = SHORT_R;
-				break;
-			case 'I':
-				e = INT_R;
-				break;
-			case 'B':
-				e = BYTE_R;
-				break;
-			case 'C':
-				e = CHAR_R;
-				break;
-			case 'J':
-				e = LONG_R;
-				break;
-			case 'F':
-				e = FLOAT_R;
-				break;
-			case 'D':
-				e = DOUBLE_R;
-				break;
+				case 'Z' :
+					e = BOOLEAN_R;
+					break;
+				case 'S' :
+					e = SHORT_R;
+					break;
+				case 'I' :
+					e = INT_R;
+					break;
+				case 'B' :
+					e = BYTE_R;
+					break;
+				case 'C' :
+					e = CHAR_R;
+					break;
+				case 'J' :
+					e = LONG_R;
+					break;
+				case 'F' :
+					e = FLOAT_R;
+					break;
+				case 'D' :
+					e = DOUBLE_R;
+					break;
 
-			default:
-				throw new IllegalArgumentException("Unknown primitive " + type);
+				default :
+					throw new IllegalArgumentException("Unknown primitive " + type);
 			}
 			elements.add(e);
 			return;
diff --git a/bundleplugin/src/main/java/aQute/bnd/differ/RepositoryElement.java b/bundleplugin/src/main/java/aQute/bnd/differ/RepositoryElement.java
new file mode 100644
index 0000000..23a5f20
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/differ/RepositoryElement.java
@@ -0,0 +1,23 @@
+package aQute.bnd.differ;
+
+import java.util.*;
+
+import aQute.bnd.service.*;
+import aQute.bnd.service.diff.*;
+import aQute.libg.version.*;
+
+public class RepositoryElement {
+
+	public static Element getTree(RepositoryPlugin repo) throws Exception {
+		List<Element> programs = new ArrayList<Element>();
+		for (String bsn : repo.list(null)) {
+			List<Element> versions = new ArrayList<Element>();
+			for (Version version : repo.versions(bsn)) {
+				versions.add(new Element(Type.VERSION, version.toString()));
+			}
+			programs.add(new Element(Type.PROGRAM, bsn, versions, Delta.MINOR, Delta.MAJOR, null));
+		}
+		return new Element(Type.REPO, repo.getName(), programs, Delta.MINOR, Delta.MAJOR, repo.getLocation());
+	}
+
+}