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

svn commit: r1381708 [1/3] - in /felix/trunk/bundleplugin/src/main/java/aQute: bnd/build/ bnd/build/model/ bnd/build/model/conversions/ bnd/component/ bnd/differ/ bnd/filerepo/ bnd/help/ bnd/make/calltree/ bnd/make/component/ bnd/make/coverage/ bnd/mav...

Author: mcculls
Date: Thu Sep  6 18:28:06 2012
New Revision: 1381708

URL: http://svn.apache.org/viewvc?rev=1381708&view=rev
Log:
Sync bndlib code

Added:
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/DownloadBlocker.java   (with props)
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/service/Actionable.java   (with props)
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/service/Strategy.java   (with props)
    felix/trunk/bundleplugin/src/main/java/aQute/lib/settings/
    felix/trunk/bundleplugin/src/main/java/aQute/lib/settings/Settings.java   (with props)
    felix/trunk/bundleplugin/src/main/java/aQute/lib/settings/packageinfo
Removed:
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/repo/eclipse/EclipseRepo.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/settings/Settings.java
    felix/trunk/bundleplugin/src/main/java/aQute/lib/deployer/FileInstallRepo.java
Modified:
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Container.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Project.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectBuilder.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectMessages.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/packageinfo
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/HeaderReader.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/filerepo/FileRepo.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/help/Syntax.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/make/calltree/CalltreeResource.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/make/component/ServiceComponent.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/make/coverage/Coverage.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/maven/MavenCommand.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/maven/MavenRepository.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/maven/support/MavenRemoteRepository.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Analyzer.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Annotation.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Builder.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/ClassDataCollector.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Clazz.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CommandResource.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Constants.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Jar.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Macro.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Processor.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/service/Refreshable.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/service/RemoteRepositoryPlugin.java
    felix/trunk/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
    felix/trunk/bundleplugin/src/main/java/aQute/lib/collections/ExtList.java
    felix/trunk/bundleplugin/src/main/java/aQute/lib/collections/SortedList.java
    felix/trunk/bundleplugin/src/main/java/aQute/lib/deployer/FileRepo.java
    felix/trunk/bundleplugin/src/main/java/aQute/lib/io/IO.java
    felix/trunk/bundleplugin/src/main/java/aQute/lib/json/ByteArrayHandler.java
    felix/trunk/bundleplugin/src/main/java/aQute/lib/json/JSONCodec.java
    felix/trunk/bundleplugin/src/main/java/aQute/lib/json/packageinfo
    felix/trunk/bundleplugin/src/main/java/aQute/libg/command/Command.java
    felix/trunk/bundleplugin/src/main/java/aQute/libg/cryptography/Digester.java
    felix/trunk/bundleplugin/src/main/java/aQute/libg/cryptography/MD5.java
    felix/trunk/bundleplugin/src/main/java/aQute/libg/cryptography/SHA1.java
    felix/trunk/bundleplugin/src/main/java/aQute/libg/cryptography/SHA256.java
    felix/trunk/bundleplugin/src/main/java/aQute/libg/qtokens/QuotedTokenizer.java
    felix/trunk/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java
    felix/trunk/bundleplugin/src/main/java/aQute/libg/sed/ReplacerAdapter.java

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Container.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Container.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Container.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Container.java Thu Sep  6 18:28:06 2012
@@ -5,46 +5,54 @@ import java.util.*;
 import java.util.jar.*;
 
 import aQute.bnd.osgi.*;
-import aQute.bnd.service.RepositoryPlugin.Strategy;
+import aQute.bnd.service.*;
 
 public class Container {
 	public enum TYPE {
 		REPO, PROJECT, EXTERNAL, LIBRARY, ERROR
 	}
 
-	final File					file;
+	private final File			file;
+	private final String		path;
 	final TYPE					type;
 	final String				bsn;
 	final String				version;
 	final String				error;
 	final Project				project;
+	final DownloadBlocker		db;
 	volatile Map<String,String>	attributes;
 	private long				manifestTime;
 	private Manifest			manifest;
 
 	Container(Project project, String bsn, String version, TYPE type, File source, String error,
-			Map<String,String> attributes) {
+			Map<String,String> attributes, DownloadBlocker db) {
 		this.bsn = bsn;
 		this.version = version;
 		this.type = type;
 		this.file = source != null ? source : new File("/" + bsn + ":" + version + ":" + type);
+		this.path = file.getAbsolutePath();
+		
 		this.project = project;
 		this.error = error;
 		if (attributes == null || attributes.isEmpty())
 			this.attributes = Collections.emptyMap();
 		else
 			this.attributes = attributes;
+		this.db = db;
 	}
 
 	public Container(Project project, File file) {
-		this(project, file.getName(), "project", TYPE.PROJECT, file, null, null);
+		this(project, file.getName(), "project", TYPE.PROJECT, file, null, null, null);
 	}
 
-	public Container(File file) {
-		this(null, file.getName(), "project", TYPE.EXTERNAL, file, null, null);
+	public Container(File file, DownloadBlocker db) {
+		this(null, file.getName(), "project", TYPE.EXTERNAL, file, null, null, db);
 	}
 
 	public File getFile() {
+		if (db != null && db.getReason() != null) {
+			return new File(db.getReason() + ": " + file);
+		}
 		return file;
 	}
 
@@ -59,7 +67,7 @@ public class Container {
 		switch (type) {
 			case EXTERNAL :
 			case REPO :
-				files.add(file);
+				files.add(getFile());
 				return true;
 
 			case PROJECT :
@@ -106,13 +114,13 @@ public class Container {
 	@Override
 	public boolean equals(Object other) {
 		if (other instanceof Container)
-			return file.equals(((Container) other).file);
+			return path.equals(((Container) other).path);
 		return false;
 	}
 
 	@Override
 	public int hashCode() {
-		return file.hashCode();
+		return path.hashCode();
 	}
 
 	public Project getProject() {
@@ -162,7 +170,7 @@ public class Container {
 			BufferedReader rd = null;
 			String line;
 			try {
-				in = new FileInputStream(file);
+				in = new FileInputStream(getFile());
 				rd = new BufferedReader(new InputStreamReader(in, Constants.DEFAULT_CHARSET));
 				while ((line = rd.readLine()) != null) {
 					line = line.trim();

Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/DownloadBlocker.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/DownloadBlocker.java?rev=1381708&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/DownloadBlocker.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/DownloadBlocker.java Thu Sep  6 18:28:06 2012
@@ -0,0 +1,111 @@
+package aQute.bnd.build;
+
+import java.io.*;
+
+import aQute.bnd.service.*;
+import aQute.service.reporter.*;
+
+/**
+ * This class is intended to be used by the users of a {@link RepositoryPlugin}.
+ * The
+ * {@link RepositoryPlugin#get(String, aQute.bnd.version.Version, java.util.Map, aQute.bnd.service.RepositoryPlugin.DownloadListener...)}
+ * method takes one or more Download Listeners. These are called back with the
+ * success or failure of a download. This class is a simple implementation of
+ * this model, just call {@link #getReason()} and it blocks until success or
+ * failure is called.
+ */
+public class DownloadBlocker implements RepositoryPlugin.DownloadListener {
+	public enum Stage {
+		INIT, SUCCESS, FAILURE
+	};
+
+	private volatile Stage	stage	= Stage.INIT;
+	private String			failure;
+	private File			file;
+	private final Reporter	reporter;
+
+	public DownloadBlocker(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see
+	 * aQute.bnd.service.RepositoryPlugin.DownloadListener#success(java.io.File)
+	 */
+	public void success(File file) throws Exception {
+		synchronized (this) {
+			assert stage == Stage.INIT;
+			stage = Stage.SUCCESS;
+			this.file = file;
+			notifyAll();
+		}
+		if (reporter != null)
+			reporter.trace("successfully downloaded %s", file);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see
+	 * aQute.bnd.service.RepositoryPlugin.DownloadListener#failure(java.io.File,
+	 * java.lang.String)
+	 */
+	public void failure(File file, String reason) throws Exception {
+		synchronized (this) {
+			assert stage == Stage.INIT;
+			stage = Stage.FAILURE;
+			this.failure = reason;
+			this.file = file;
+			notifyAll();
+		}
+		if (reporter != null)
+			reporter.error("Download %s %s", reason, file);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see
+	 * aQute.bnd.service.RepositoryPlugin.DownloadListener#progress(java.io.
+	 * File, int)
+	 */
+	public boolean progress(File file, int percentage) throws Exception {
+		assert stage == Stage.INIT;
+		return true;
+	}
+
+	/**
+	 * Return a failure reason or null. This method will block until either
+	 * {@link #success(File)} or {@link #failure(File, String)} has been called.
+	 * It can be called many times.
+	 * 
+	 * @return null or a reason for a failure
+	 */
+	public synchronized String getReason() {
+		try {
+			while (stage == Stage.INIT)
+				wait();
+		}
+		catch (InterruptedException e) {
+			return "Interrupted";
+		}
+
+		return failure;
+	}
+
+	/**
+	 * Return the stage we're in
+	 * 
+	 * @return the current stage
+	 */
+	public Stage getStage() {
+		return stage;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		return "DownloadBlocker(" + stage + "," + file + ", " + failure + ")";
+	}
+}

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/DownloadBlocker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/DownloadBlocker.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Project.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Project.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Project.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Project.java Thu Sep  6 18:28:06 2012
@@ -7,6 +7,7 @@ import java.util.*;
 import java.util.Map.Entry;
 import java.util.concurrent.locks.*;
 import java.util.jar.*;
+import java.util.regex.*;
 
 import aQute.bnd.header.*;
 import aQute.bnd.help.*;
@@ -15,7 +16,6 @@ import aQute.bnd.osgi.*;
 import aQute.bnd.osgi.eclipse.*;
 import aQute.bnd.service.*;
 import aQute.bnd.service.RepositoryPlugin.PutResult;
-import aQute.bnd.service.RepositoryPlugin.Strategy;
 import aQute.bnd.service.action.*;
 import aQute.bnd.version.*;
 import aQute.lib.io.*;
@@ -29,6 +29,7 @@ import aQute.libg.sed.*;
 
 public class Project extends Processor {
 
+	final static Pattern		VERSION_ANNOTATION		= Pattern.compile("@\\s*(:?aQute\\.bnd\\.annotation\\.)?Version\\s*\\(\\s*(:?value\\s*=\\s*)?\"(\\d+(:?\\.\\d+(:?\\.\\d+(:?\\.[\\d\\w-_]+)?)?)?)\"\\s*\\)");
 	final static String			DEFAULT_ACTIONS			= "build; label='Build', test; label='Test', run; label='Run', clean; label='Clean', release; label='Release', refreshAll; label=Refresh, deploy;label=Deploy";
 	public final static String	BNDFILE					= "bnd.bnd";
 	public final static String	BNDCNF					= "cnf";
@@ -56,7 +57,7 @@ public class Project extends Processor {
 	boolean						delayRunDependencies	= false;
 	final ProjectMessages		msgs					= ReporterMessages.base(this, ProjectMessages.class);
 
-	public Project(Workspace workspace, @SuppressWarnings("unused") File projectDir, File buildFile) throws Exception {
+	public Project(Workspace workspace, File projectDir, File buildFile) throws Exception {
 		super(workspace);
 		this.workspace = workspace;
 		setFileMustExist(false);
@@ -227,26 +228,27 @@ public class Project extends Processor {
 					// We might have some other projects we want build
 					// before we do anything, but these projects are not in
 					// our path. The -dependson allows you to build them before.
+					// The values are possibly negated globbing patterns.
 
-					List<Project> dependencies = new ArrayList<Project>();
 					// dependencies.add( getWorkspace().getProject("cnf"));
 
 					String dp = getProperty(Constants.DEPENDSON);
-					Set<String> requiredProjectNames = new Parameters(dp).keySet();
+					Set<String> requiredProjectNames = new LinkedHashSet<String>(new Parameters(dp).keySet());
+					
+					//Allow DependencyConstributors to modify requiredProjectNames
 					List<DependencyContributor> dcs = getPlugins(DependencyContributor.class);
 					for (DependencyContributor dc : dcs)
 						dc.addDependencies(this, requiredProjectNames);
-
-					for (String p : requiredProjectNames) {
-						Project required = getWorkspace().getProject(p);
-						if (required == null)
-							msgs.MissingDependson_(p);
-						else {
-							dependencies.add(required);
-						}
-
-					}
-
+					
+					Instructions is = new Instructions(requiredProjectNames);
+					
+					Set<Instruction> unused = new HashSet<Instruction>();
+					Collection<Project> projects = getWorkspace().getAllProjects();
+					Collection<Project> dependencies = is.select(projects, unused, false);
+					
+					for (Instruction u: unused) 
+						msgs.MissingDependson_(u.getInput());							
+						
 					// We have two paths that consists of repo files, projects,
 					// or some other stuff. The doPath routine adds them to the
 					// path and extracts the projects so we can build them
@@ -367,7 +369,6 @@ public class Project extends Processor {
 
 	private List<Container> parseBuildpath() throws Exception {
 		List<Container> bundles = getBundles(Strategy.LOWEST, getProperty(Constants.BUILDPATH), Constants.BUILDPATH);
-		appendPackages(Strategy.LOWEST, getProperty(Constants.BUILDPACKAGES), bundles, ResolverMode.build);
 		return bundles;
 	}
 
@@ -422,7 +423,7 @@ public class Project extends Processor {
 						Project project = getWorkspace().getProject(bsn);
 						if (project != null && project.exists()) {
 							File f = project.getOutput();
-							found = new Container(project, bsn, versionRange, Container.TYPE.PROJECT, f, null, attrs);
+							found = new Container(project, bsn, versionRange, Container.TYPE.PROJECT, f, null, attrs, null);
 						} else {
 							msgs.NoSuchProject(bsn, spec);
 							continue;
@@ -433,9 +434,9 @@ public class Project extends Processor {
 						if (!f.exists())
 							error = "File does not exist: " + f.getAbsolutePath();
 						if (f.getName().endsWith(".lib")) {
-							found = new Container(this, bsn, "file", Container.TYPE.LIBRARY, f, error, attrs);
+							found = new Container(this, bsn, "file", Container.TYPE.LIBRARY, f, error, attrs, null);
 						} else {
-							found = new Container(this, bsn, "file", Container.TYPE.EXTERNAL, f, error, attrs);
+							found = new Container(this, bsn, "file", Container.TYPE.EXTERNAL, f, error, attrs, null);
 						}
 					} else {
 						found = getBundle(bsn, versionRange, strategyx, attrs);
@@ -453,7 +454,7 @@ public class Project extends Processor {
 				} else {
 					// Oops, not a bundle in sight :-(
 					Container x = new Container(this, bsn, versionRange, Container.TYPE.ERROR, null, bsn + ";version="
-							+ versionRange + " not found", attrs);
+							+ versionRange + " not found", attrs, null);
 					result.add(x);
 					warning("Can not find URL for bsn " + bsn);
 				}
@@ -480,72 +481,6 @@ public class Project extends Processor {
 		return getBundles(strategy, spec, null);
 	}
 
-	/**
-	 * Calculates the containers required to fulfil the {@code -buildpackages}
-	 * instruction, and appends them to the existing list of containers.
-	 * 
-	 * @param strategyx
-	 *            The package-version disambiguation strategy.
-	 * @param spec
-	 *            The value of the @{code -buildpackages} instruction.
-	 * @throws Exception
-	 */
-	public void appendPackages(Strategy strategyx, String spec, List<Container> resolvedBundles, ResolverMode mode)
-			throws Exception {
-		Map<File,Container> pkgResolvedBundles = new HashMap<File,Container>();
-
-		List<Entry<String,Attrs>> queue = new LinkedList<Map.Entry<String,Attrs>>();
-		queue.addAll(new Parameters(spec).entrySet());
-
-		while (!queue.isEmpty()) {
-			Entry<String,Attrs> entry = queue.remove(0);
-
-			String pkgName = entry.getKey();
-			Map<String,String> attrs = entry.getValue();
-
-			Container found = null;
-
-			String versionRange = attrs.get(Constants.VERSION_ATTRIBUTE);
-			if ("latest".equals(versionRange) || "snapshot".equals(versionRange))
-				found = getPackage(pkgName, versionRange, strategyx, attrs, mode);
-
-			if (found == null)
-				found = getPackage(pkgName, versionRange, strategyx, attrs, mode);
-
-			if (found != null) {
-				if (resolvedBundles.contains(found)) {
-					// Don't add his bundle because it was already included
-					// using -buildpath
-				} else {
-					List<Container> libs = found.getMembers();
-					for (Container cc : libs) {
-						Container existing = pkgResolvedBundles.get(cc.file);
-						if (existing != null)
-							addToPackageList(existing, attrs.get("packages"));
-						else {
-							addToPackageList(cc, attrs.get("packages"));
-							pkgResolvedBundles.put(cc.file, cc);
-						}
-
-						String importUses = cc.getAttributes().get("import-uses");
-						if (importUses != null)
-							queue.addAll(0, new Parameters(importUses).entrySet());
-					}
-				}
-			} else {
-				// Unable to resolve
-				Container x = new Container(this, "X", versionRange, Container.TYPE.ERROR, null, "package " + pkgName
-						+ ";version=" + versionRange + " not found", attrs);
-				resolvedBundles.add(x);
-				warning("Can not find URL for package " + pkgName);
-			}
-		}
-
-		for (Container container : pkgResolvedBundles.values()) {
-			resolvedBundles.add(container);
-		}
-	}
-
 	static void mergeNames(String names, Set<String> set) {
 		StringTokenizer tokenizer = new StringTokenizer(names, ",");
 		while (tokenizer.hasMoreTokens())
@@ -577,68 +512,6 @@ public class Project extends Processor {
 	}
 
 	/**
-	 * Find a container to fulfil a package requirement
-	 * 
-	 * @param packageName
-	 *            The package required
-	 * @param range
-	 *            The package version range required
-	 * @param strategyx
-	 *            The package-version disambiguation strategy
-	 * @param attrs
-	 *            Other attributes specified by the search.
-	 * @return
-	 * @throws Exception
-	 */
-	public Container getPackage(String packageName, String range, Strategy strategyx, Map<String,String> attrs,
-			ResolverMode mode) throws Exception {
-		if ("snapshot".equals(range))
-			return new Container(this, "", range, Container.TYPE.ERROR, null,
-					"snapshot not supported for package lookups", null);
-
-		if (attrs == null)
-			attrs = new HashMap<String,String>(2);
-		attrs.put("package", packageName);
-		attrs.put("mode", mode.name());
-
-		Strategy useStrategy = findStrategy(attrs, strategyx, range);
-
-		List<RepositoryPlugin> plugins = getPlugins(RepositoryPlugin.class);
-		for (RepositoryPlugin plugin : plugins) {
-			try {
-				File result = plugin.get(null, range, useStrategy, attrs);
-				if (result != null) {
-					if (result.getName().endsWith("lib"))
-						return new Container(this, result.getName(), range, Container.TYPE.LIBRARY, result, null, attrs);
-					return new Container(this, result.getName(), range, Container.TYPE.REPO, result, null, attrs);
-				}
-			}
-			catch (Exception e) {
-				// Ignore... lots of repos will fail here
-			}
-		}
-
-		return new Container(this, "X", range, Container.TYPE.ERROR, null, "package " + packageName + ";version="
-				+ range + " Not found in " + plugins, null);
-	}
-
-	private Strategy findStrategy(Map<String,String> attrs, Strategy defaultStrategy, String versionRange) {
-		Strategy useStrategy = defaultStrategy;
-		String overrideStrategy = attrs.get("strategy");
-		if (overrideStrategy != null) {
-			if ("highest".equalsIgnoreCase(overrideStrategy))
-				useStrategy = Strategy.HIGHEST;
-			else if ("lowest".equalsIgnoreCase(overrideStrategy))
-				useStrategy = Strategy.LOWEST;
-			else if ("exact".equalsIgnoreCase(overrideStrategy))
-				useStrategy = Strategy.EXACT;
-		}
-		if ("latest".equals(versionRange))
-			useStrategy = Strategy.HIGHEST;
-		return useStrategy;
-	}
-
-	/**
 	 * The user selected pom in a path. This will place the pom as well as its
 	 * dependencies on the list
 	 * 
@@ -663,7 +536,7 @@ public class Project extends Processor {
 			Set<Pom> dependencies = pom.getDependencies(act);
 			for (Pom sub : dependencies) {
 				File artifact = sub.getArtifact();
-				Container container = new Container(artifact);
+				Container container = new Container(artifact, null);
 				result.add(container);
 			}
 		}
@@ -753,10 +626,10 @@ public class Project extends Processor {
 			dependson.add(required);
 		}
 		for (File f : eclipse.getClasspath()) {
-			buildpath.add(new Container(f));
+			buildpath.add(new Container(f, null));
 		}
 		for (File f : eclipse.getBootclasspath()) {
-			bootclasspath.add(new Container(f));
+			bootclasspath.add(new Container(f, null));
 		}
 		sourcepath.addAll(eclipse.getSourcepath());
 		allsourcepath.addAll(eclipse.getAllSources());
@@ -939,14 +812,18 @@ public class Project extends Processor {
 		List<RepositoryPlugin> plugins = workspace.getRepositories();
 
 		if (useStrategy == Strategy.EXACT) {
+			if (!Verifier.isVersion(range))
+				return new Container(this, bsn, range, Container.TYPE.ERROR, null, bsn + ";version=" + range
+						+ " Invalid version", null, null);
 
 			// For an exact range we just iterate over the repos
 			// and return the first we find.
-
+			Version version = new Version(range);
 			for (RepositoryPlugin plugin : plugins) {
-				File result = plugin.get(bsn, range, Strategy.EXACT, attrs);
+				DownloadBlocker blocker = new DownloadBlocker(this);
+				File result = plugin.get(bsn, version, attrs, blocker);
 				if (result != null)
-					return toContainer(bsn, range, attrs, result);
+					return toContainer(bsn, range, attrs, result, blocker);
 			}
 		} else {
 			VersionRange versionRange = "latest".equals(range) ? new VersionRange("0") : new VersionRange(range);
@@ -959,7 +836,7 @@ public class Project extends Processor {
 			SortedMap<Version,RepositoryPlugin> versions = new TreeMap<Version,RepositoryPlugin>();
 			for (RepositoryPlugin plugin : plugins) {
 				try {
-					List<Version> vs = plugin.versions(bsn);
+					SortedSet<Version> vs = plugin.versions(bsn);
 					if (vs != null) {
 						for (Version v : vs) {
 							if (!versions.containsKey(v) && versionRange.includes(v))
@@ -974,11 +851,13 @@ public class Project extends Processor {
 					// Repository
 					// To query, we must have a real version
 					if (!versions.isEmpty() && Verifier.isVersion(range)) {
-						File file = plugin.get(bsn, range, useStrategy, attrs);
+						Version version = new Version(range);
+						DownloadBlocker blocker = new DownloadBlocker(this);
+						File file = plugin.get(bsn, version, attrs, blocker);
 						// and the entry must exist
 						// if it does, return this as a result
 						if (file != null)
-							return toContainer(bsn, range, attrs, file);
+							return toContainer(bsn, range, attrs, file, blocker);
 					}
 				}
 			}
@@ -1004,9 +883,10 @@ public class Project extends Processor {
 				if (provider != null) {
 					RepositoryPlugin repo = versions.get(provider);
 					String version = provider.toString();
-					File result = repo.get(bsn, version, Strategy.EXACT, attrs);
+					DownloadBlocker blocker = new DownloadBlocker(this);
+					File result = repo.get(bsn, provider, attrs, blocker);
 					if (result != null)
-						return toContainer(bsn, version, attrs, result);
+						return toContainer(bsn, version, attrs, result, blocker);
 				} else
 					msgs.FoundVersions_ForStrategy_ButNoProvider(versions, useStrategy);
 			}
@@ -1016,7 +896,7 @@ public class Project extends Processor {
 		// If we get this far we ran into an error somewhere
 
 		return new Container(this, bsn, range, Container.TYPE.ERROR, null, bsn + ";version=" + range + " Not found in "
-				+ plugins, null);
+				+ plugins, null, null);
 
 	}
 
@@ -1048,15 +928,19 @@ public class Project extends Processor {
 	 * @param result
 	 * @return
 	 */
-	protected Container toContainer(String bsn, String range, Map<String,String> attrs, File result) {
+	protected Container toContainer(String bsn, String range, Map<String,String> attrs, File result, DownloadBlocker db) {
 		File f = result;
 		if (f == null) {
 			msgs.ConfusedNoContainerFile();
 			f = new File("was null");
 		}
+		Container container;
 		if (f.getName().endsWith("lib"))
-			return new Container(this, bsn, range, Container.TYPE.LIBRARY, f, null, attrs);
-		return new Container(this, bsn, range, Container.TYPE.REPO, f, null, attrs);
+			container = new Container(this, bsn, range, Container.TYPE.LIBRARY, f, null, attrs, db);
+		else
+			container = new Container(this, bsn, range, Container.TYPE.REPO, f, null, attrs, db);
+		
+		return container;
 	}
 
 	/**
@@ -1149,16 +1033,16 @@ public class Project extends Processor {
 		}
 		File[] outputs = getBuildFiles();
 		for (File output : outputs) {
-				for (Deploy d : getPlugins(Deploy.class)) {
-					trace("Deploying %s to: %s", output.getName(), d);
-					try {
-						if (d.deploy(this, output.getName(), new BufferedInputStream(new FileInputStream(output))))
-							trace("deployed %s successfully to %s", output, d);
-					}
-					catch (Exception e) {
-						msgs.Deploying(e);
-					}
+			for (Deploy d : getPlugins(Deploy.class)) {
+				trace("Deploying %s to: %s", output.getName(), d);
+				try {
+					if (d.deploy(this, output.getName(), new BufferedInputStream(new FileInputStream(output))))
+						trace("deployed %s successfully to %s", output, d);
 				}
+				catch (Exception e) {
+					msgs.Deploying(e);
+				}
+			}
 		}
 	}
 
@@ -1265,11 +1149,11 @@ public class Project extends Processor {
 	 * Check if this project needs building. This is defined as:
 	 */
 	public boolean isStale() throws Exception {
-		if ( workspace.isOffline()) {
+		if (workspace.isOffline()) {
 			trace("working %s offline, so always stale", this);
 			return true;
 		}
-		
+
 		Set<Project> visited = new HashSet<Project>();
 		return isStale(visited);
 	}
@@ -1316,7 +1200,7 @@ public class Project extends Processor {
 					return true;
 			}
 		}
-		
+
 		return false;
 	}
 
@@ -1661,7 +1545,8 @@ public class Project extends Processor {
 		return jar;
 	}
 
-	public String _project(@SuppressWarnings("unused") String args[]) {
+	public String _project(@SuppressWarnings("unused")
+	String args[]) {
 		return getBase().getAbsolutePath();
 	}
 
@@ -1722,7 +1607,7 @@ public class Project extends Processor {
 
 	boolean replace(File f, String pattern, String replacement) throws IOException {
 		final Macro macro = getReplacer();
-		Sed sed = new Sed( new Replacer() {
+		Sed sed = new Sed(new Replacer() {
 			public String process(String line) {
 				return macro.process(line);
 			}
@@ -1755,7 +1640,8 @@ public class Project extends Processor {
 	/**
 	 * Run all before command plugins
 	 */
-	void before(@SuppressWarnings("unused") Project p, String a) {
+	void before(@SuppressWarnings("unused")
+	Project p, String a) {
 		List<CommandPlugin> testPlugins = getPlugins(CommandPlugin.class);
 		for (CommandPlugin testPlugin : testPlugins) {
 			testPlugin.before(this, a);
@@ -1765,7 +1651,8 @@ public class Project extends Processor {
 	/**
 	 * Run all after command plugins
 	 */
-	void after(@SuppressWarnings("unused") Project p, String a, Throwable t) {
+	void after(@SuppressWarnings("unused")
+	Project p, String a, Throwable t) {
 		List<CommandPlugin> testPlugins = getPlugins(CommandPlugin.class);
 		for (int i = testPlugins.size() - 1; i >= 0; i--) {
 			testPlugins.get(i).after(this, a, t);
@@ -1802,7 +1689,8 @@ public class Project extends Processor {
 	}
 
 	@SuppressWarnings("unchecked")
-	public void script(@SuppressWarnings("unused") String type, String script) throws Exception {
+	public void script(@SuppressWarnings("unused")
+	String type, String script) throws Exception {
 		// TODO check tyiping
 		List<Scripter> scripters = getPlugins(Scripter.class);
 		if (scripters.isEmpty()) {
@@ -1814,7 +1702,8 @@ public class Project extends Processor {
 		scripters.get(0).eval(x, new StringReader(script));
 	}
 
-	public String _repos(@SuppressWarnings("unused") String args[]) throws Exception {
+	public String _repos(@SuppressWarnings("unused")
+	String args[]) throws Exception {
 		List<RepositoryPlugin> repos = getPlugins(RepositoryPlugin.class);
 		List<String> names = new ArrayList<String>();
 		for (RepositoryPlugin rp : repos)
@@ -1860,7 +1749,7 @@ public class Project extends Processor {
 
 		for (Builder builder : builders) {
 			Container c = new Container(this, builder.getBsn(), builder.getVersion(), Container.TYPE.PROJECT,
-					getOutputFile(builder.getBsn()), null, null);
+					getOutputFile(builder.getBsn()), null, null, null);
 			result.add(c);
 		}
 		return result;
@@ -1908,7 +1797,8 @@ public class Project extends Processor {
 	 * @return null or the builder for a sub file.
 	 * @throws Exception
 	 */
-	public Container getDeliverable(String bsn, @SuppressWarnings("unused") Map<String,String> attrs) throws Exception {
+	public Container getDeliverable(String bsn, @SuppressWarnings("unused")
+	Map<String,String> attrs) throws Exception {
 		Collection< ? extends Builder> builders = getSubBuilders();
 		for (Builder sub : builders) {
 			if (sub.getBsn().equals(bsn))
@@ -2021,13 +1911,55 @@ public class Project extends Processor {
 	 */
 	public void setPackageInfo(String packageName, Version version) {
 		try {
-			updatePackageInfoFile(packageName, version);
+			Version current = getPackageInfoJavaVersion(packageName);
+			boolean packageInfoJava = false;
+			if (current != null) {
+				updatePackageInfoJavaFile(packageName, version);
+				packageInfoJava = true;
+			}
+			if (!packageInfoJava || getPackageInfoFile(packageName).exists()) {
+				updatePackageInfoFile(packageName, version);
+			}
 		}
 		catch (Exception e) {
 			msgs.SettingPackageInfoException_(e);
 		}
 	}
 
+	void updatePackageInfoJavaFile(String packageName, final Version newVersion) throws Exception {
+		File file = getPackageInfoJavaFile(packageName);
+
+		if (!file.exists()) {
+			return;
+		}
+
+		// If package/classes are copied into the bundle through Private-Package
+		// etc, there will be no source
+		if (!file.getParentFile().exists()) {
+			return;
+		}
+
+		Version oldVersion = getPackageInfo(packageName);
+
+		if (newVersion.compareTo(oldVersion) == 0) {
+			return;
+		}
+
+		Sed sed = new Sed(new Replacer() {
+			public String process(String line) {
+				Matcher m = VERSION_ANNOTATION.matcher(line);
+				if (m.find()) {
+					return line.substring(0, m.start(3)) + newVersion.toString() + line.substring(m.end(3));
+				}
+				return line;
+			}
+		}, file);
+
+		sed.replace(VERSION_ANNOTATION.pattern(), "$0");
+		sed.setBackup(false);
+		sed.doIt();
+	}
+
 	void updatePackageInfoFile(String packageName, Version newVersion) throws Exception {
 
 		File file = getPackageInfoFile(packageName);
@@ -2038,7 +1970,10 @@ public class Project extends Processor {
 			return;
 		}
 
-		Version oldVersion = getPackageInfo(packageName);
+		Version oldVersion = getPackageInfoVersion(packageName);
+		if (oldVersion == null) {
+			oldVersion = Version.emptyVersion;
+		}
 
 		if (newVersion.compareTo(oldVersion) == 0) {
 			return;
@@ -2055,8 +1990,6 @@ public class Project extends Processor {
 			throw new IOException("Could not create directory " + bp);
 		}
 		IO.copy(file, binary);
-
-		refresh();
 	}
 
 	File getPackageInfoFile(String packageName) {
@@ -2065,10 +1998,31 @@ public class Project extends Processor {
 
 	}
 
+	File getPackageInfoJavaFile(String packageName) {
+		String path = packageName.replace('.', '/') + "/package-info.java";
+		return IO.getFile(getSrc(), path);
+
+	}
+
 	public Version getPackageInfo(String packageName) throws IOException {
+
+		Version version = getPackageInfoJavaVersion(packageName);
+		if (version != null) {
+			return version;
+		}
+		
+		version = getPackageInfoVersion(packageName);
+		if (version != null) {
+			return version;
+		}
+
+		return Version.emptyVersion;
+	}
+
+	Version getPackageInfoVersion(String packageName) throws IOException {
 		File packageInfoFile = getPackageInfoFile(packageName);
 		if (!packageInfoFile.exists()) {
-			return Version.emptyVersion;
+			return null;
 		}
 		BufferedReader reader = null;
 		try {
@@ -2086,7 +2040,31 @@ public class Project extends Processor {
 				IO.close(reader);
 			}
 		}
-		return Version.emptyVersion;
+		return null;
+	}
+
+	Version getPackageInfoJavaVersion(String packageName) throws IOException {
+		File packageInfoJavaFile = getPackageInfoJavaFile(packageName);
+		if (!packageInfoJavaFile.exists()) {
+			return null;
+		}
+		BufferedReader reader = null;
+		try {
+			reader = IO.reader(packageInfoJavaFile);
+			String line;
+			while ((line = reader.readLine()) != null) {
+				Matcher matcher = VERSION_ANNOTATION.matcher(line);
+				if (matcher.find()) {
+					return Version.parseVersion(matcher.group(3));
+				}
+			}
+		}
+		finally {
+			if (reader != null) {
+				IO.close(reader);
+			}
+		}
+		return null;
 	}
 
 	/**
@@ -2098,7 +2076,7 @@ public class Project extends Processor {
 		if (!f.isFile() && !f.isDirectory()) {
 			msgs.AddingNonExistentFileToClassPath_(f);
 		}
-		Container container = new Container(f);
+		Container container = new Container(f, null);
 		classpath.add(container);
 	}
 

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectBuilder.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectBuilder.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectBuilder.java Thu Sep  6 18:28:06 2012
@@ -3,11 +3,16 @@ package aQute.bnd.build;
 import java.io.*;
 import java.util.*;
 
+import aQute.bnd.differ.*;
+import aQute.bnd.differ.Baseline.Info;
 import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
 
 public class ProjectBuilder extends Builder {
-	Project	project;
-	boolean	initialized;
+	private final DiffPluginImpl	differ	= new DiffPluginImpl();
+	Project							project;
+	boolean							initialized;
 
 	public ProjectBuilder(Project project) {
 		super(project);
@@ -81,4 +86,92 @@ public class ProjectBuilder extends Buil
 	protected void changedFile(File f) {
 		project.getWorkspace().changedFile(f);
 	}
+
+	/**
+	 * Compare this builder's JAR with a baseline
+	 * 
+	 * @throws Exception
+	 */
+	@Override
+	protected void doBaseline(Jar dot) throws Exception {
+
+		Jar jar = getBaselineJar(false);
+		if (jar == null) {
+			return;
+		}
+		try {
+			Baseline baseline = new Baseline(this, differ);
+
+			Set<Info> infos = baseline.baseline(dot, jar, null);
+			for (Info info : infos) {
+				if (info.mismatch) {
+					error("%s %-50s %-10s %-10s %-10s %-10s %-10s\n", info.mismatch ? '*' : ' ', info.packageName,
+							info.packageDiff.getDelta(), info.newerVersion, info.olderVersion, info.suggestedVersion,
+							info.suggestedIfProviders == null ? "-" : info.suggestedIfProviders);
+				}
+			}
+		}
+		finally {
+			jar.close();
+		}
+	}
+
+	protected Jar getBaselineJar(boolean fallback) throws Exception {
+
+		String baseline = getProperty(Constants.BASELINE);
+		if ((baseline == null || baseline.trim().length() == 0) && !fallback)
+			return null;
+
+		trace("baseline %s", baseline);
+
+		File baselineFile = null;
+		if ((baseline == null || baseline.trim().length() == 0) && fallback) {
+
+			String repoName = getProperty(Constants.BASELINEREPO);
+			if (repoName == null) {
+				repoName = getProperty(Constants.RELEASEREPO);
+				if (repoName == null) {
+					return null;
+				}
+			}
+
+			List<RepositoryPlugin> repos = getPlugins(RepositoryPlugin.class);
+			for (RepositoryPlugin repo : repos) {
+				if (repoName.equals(repo.getName())) {
+					SortedSet<Version> versions = repo.versions(getBsn());
+					if (!versions.isEmpty()) {
+						baselineFile = repo.get(getBsn(), versions.last(), null);
+					}
+					break;
+				}
+			}
+		} else {
+
+			Collection<Container> bundles = project.getBundles(Strategy.LOWEST, baseline);
+			for (Container c : bundles) {
+
+				if (c.getError() != null || c.getFile() == null) {
+					error("Erroneous baseline bundle %s", c);
+					continue;
+				}
+
+				baselineFile = c.getFile();
+				break;
+			}
+		}
+		if (fallback && baselineFile == null) {
+			return new Jar(".");
+		}
+		return new Jar(baselineFile);
+	}
+
+	/** 
+	 * Gets the baseline Jar. 
+	 * 
+	 * @return the baseline jar
+	 * @throws Exception
+	 */
+	public Jar getBaselineJar() throws Exception {
+		return getBaselineJar(true);
+	}
 }

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectLauncher.java Thu Sep  6 18:28:06 2012
@@ -8,7 +8,7 @@ import java.util.jar.*;
 
 import aQute.bnd.header.*;
 import aQute.bnd.osgi.*;
-import aQute.bnd.service.RepositoryPlugin.Strategy;
+import aQute.bnd.service.*;
 import aQute.libg.command.*;
 import aQute.libg.generics.*;
 
@@ -97,8 +97,7 @@ public abstract class ProjectLauncher {
 		timeout = Processor.getDuration(project.getProperty(Constants.RUNTIMEOUT), 0);
 		trace = Processor.isTrue(project.getProperty(Constants.RUNTRACE));
 
-		// For backward compatibility with bndtools launcher
-		List<Container> fws = project.getBundles(Strategy.HIGHEST, project.getProperty("-runfw"), "-runfw");
+		List<Container> fws = project.getBundles(Strategy.HIGHEST, project.getProperty(Constants.RUNFW), Constants.RUNFW);
 		runpath.addAll(fws);
 
 		for (Container c : runpath) {

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectMessages.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectMessages.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectMessages.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/ProjectMessages.java Thu Sep  6 18:28:06 2012
@@ -4,7 +4,6 @@ import java.io.*;
 import java.util.*;
 
 import aQute.bnd.service.*;
-import aQute.bnd.service.RepositoryPlugin.Strategy;
 import aQute.bnd.version.*;
 import aQute.service.reporter.*;
 

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/Workspace.java Thu Sep  6 18:28:06 2012
@@ -2,6 +2,7 @@ package aQute.bnd.build;
 
 import java.io.*;
 import java.lang.ref.*;
+import java.net.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
@@ -14,7 +15,9 @@ import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
 import aQute.bnd.service.action.*;
 import aQute.lib.deployer.*;
+import aQute.lib.hex.*;
 import aQute.lib.io.*;
+import aQute.lib.settings.*;
 import aQute.service.reporter.*;
 
 public class Workspace extends Processor {
@@ -29,6 +32,7 @@ public class Workspace extends Processor
 	final File									buildDir;
 	final Maven									maven		= new Maven(Processor.getExecutor());
 	private boolean								offline		= true;
+	Settings									settings	= new Settings();
 
 	/**
 	 * This static method finds the workspace and creates a project (or returns
@@ -157,7 +161,8 @@ public class Workspace extends Processor
 		}
 	}
 
-	public String _workspace(@SuppressWarnings("unused") String args[]) {
+	public String _workspace(@SuppressWarnings("unused")
+	String args[]) {
 		return getBase().getAbsolutePath();
 	}
 
@@ -270,11 +275,11 @@ public class Workspace extends Processor
 		}
 
 		@Override
-		protected void init() throws Exception {
+		protected boolean init() throws Exception {
 			if (lock.tryLock(50, TimeUnit.SECONDS) == false)
 				throw new TimeLimitExceededException("Cached File Repo is locked and can't acquire it");
 			try {
-				if (!inited) {
+				if (super.init()) {
 					inited = true;
 					if (!root.exists() && !root.mkdirs()) {
 						throw new IOException("Could not create cache directory " + root);
@@ -288,7 +293,9 @@ public class Workspace extends Processor
 					else {
 						error("Couldn't find embedded-repo.jar in bundle ");
 					}
-				}
+					return true;
+				} else
+					return false;
 			}
 			finally {
 				lock.unlock();
@@ -386,4 +393,31 @@ public class Workspace extends Processor
 		this.offline = on;
 		return this;
 	}
+
+	/**
+	 * Provide access to the global settings of this machine.
+	 * 
+	 * @throws Exception
+	 * @throws UnknownHostException
+	 */
+
+	public String _global(String[] args) throws Exception {
+		Macro.verifyCommand(args, "${global;<name>[;<default>]}, get a global setting from ~/.bnd/settings.json", null,
+				2, 3);
+
+		String key = args[1];
+		if (key.equals("key.public"))
+			return Hex.toHexString(settings.getPublicKey());
+		if (key.equals("key.private"))
+			return Hex.toHexString(settings.getPrivateKey());
+
+		String s = settings.get(key);
+		if (s != null)
+			return s;
+
+		if (args.length == 3)
+			return args[2];
+		
+		return null;
+	}
 }

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java Thu Sep  6 18:28:06 2012
@@ -7,8 +7,10 @@ import java.util.regex.*;
 import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
 import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.libg.glob.*;
 
-public class WorkspaceRepository implements RepositoryPlugin {
+public class WorkspaceRepository implements RepositoryPlugin, Actionable {
 	private final Workspace	workspace;
 
 	public WorkspaceRepository(Workspace workspace) {
@@ -87,10 +89,10 @@ public class WorkspaceRepository impleme
 	}
 
 	public PutResult put(InputStream stream, PutOptions options) throws Exception {
-		return null;
+		throw new UnsupportedOperationException("Read only repository");
 	}
 
-	public List<String> list(String regex) throws Exception {
+	public List<String> list(String pattern) throws Exception {
 		List<String> names = new ArrayList<String>();
 		Collection<Project> projects = workspace.getAllProjects();
 		for (Project project : projects) {
@@ -99,9 +101,9 @@ public class WorkspaceRepository impleme
 				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 (pattern != null) {
+						Glob glob = new Glob(pattern);
+						Matcher matcher = glob.matcher(bsn);
 						if (matcher.matches()) {
 							if (!names.contains(bsn)) {
 								names.add(bsn);
@@ -119,7 +121,7 @@ public class WorkspaceRepository impleme
 		return names;
 	}
 
-	public List<Version> versions(String bsn) throws Exception {
+	public SortedSet<Version> versions(String bsn) throws Exception {
 		List<Version> versions = new ArrayList<Version>();
 		Collection<Project> projects = workspace.getAllProjects();
 		for (Project project : projects) {
@@ -127,22 +129,66 @@ public class WorkspaceRepository impleme
 			if (build != null) {
 				for (File file : build) {
 					Jar jar = new Jar(file);
-					if (bsn.equals(jar.getBsn())) {
-						versions.add(new Version(jar.getVersion()));
+					try {
+						if (bsn.equals(jar.getBsn())) {
+							String v  = jar.getVersion();
+							if ( v == null)
+								v = "0";
+							else if (!Verifier.isVersion(v))
+								continue; // skip
+							
+							versions.add(new Version(v));
+						}
+					}
+					finally {
+						jar.close();
 					}
 				}
 			}
 		}
-
-		return versions;
+		if ( versions.isEmpty())
+			return SortedList.empty();
+		
+		return new SortedList<Version>(versions);
 	}
 
 	public String getName() {
-		return "Workspace";
+		return "Workspace " + workspace.getBase().getName();
 	}
 
 	public String getLocation() {
-		return "Workspace";
+		return workspace.getBase().getAbsolutePath();
+	}
+
+	public File get(String bsn, Version version, Map<String,String> properties, DownloadListener ... listeners) throws Exception {
+		File file = get(bsn, version.toString(), Strategy.EXACT, properties);
+		if ( file == null)
+			return null;
+		for (DownloadListener l : listeners) {
+			try {
+				l.success(file);
+			}
+			catch (Exception e) {
+				workspace.exception(e, "Workspace repo listener callback for %s" ,file);
+			}
+		}
+		return file;
+	}
+
+	
+	public Map<String,Runnable> actions(Object... target) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public String tooltip(Object... target) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public String title(Object... target) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
 	}
 
 }

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java Thu Sep  6 18:28:06 2012
@@ -24,19 +24,22 @@ import aQute.libg.tuple.*;
  */
 public class BndEditModel {
 
-	public static final String										LINE_SEPARATOR				= " \\\n\t";
+	public static final String										NEWLINE_LINE_SEPARATOR		= "\\n\\\n\t";
 	public static final String										LIST_SEPARATOR				= ",\\\n\t";
 
 	private static final String									ISO_8859_1					= "ISO-8859-1";												//$NON-NLS-1$
 
 	private static String[]										KNOWN_PROPERTIES			= new String[] {
+			Constants.BUNDLE_LICENSE, Constants.BUNDLE_CATEGORY,
+			Constants.BUNDLE_NAME, Constants.BUNDLE_DESCRIPTION, Constants.BUNDLE_COPYRIGHT, Constants.BUNDLE_UPDATELOCATION,
+			Constants.BUNDLE_VENDOR, Constants.BUNDLE_CONTACTADDRESS, Constants.BUNDLE_DOCURL,
 			Constants.BUNDLE_SYMBOLICNAME, Constants.BUNDLE_VERSION, Constants.BUNDLE_ACTIVATOR,
 			Constants.EXPORT_PACKAGE, Constants.IMPORT_PACKAGE, aQute.bnd.osgi.Constants.PRIVATE_PACKAGE,
 			aQute.bnd.osgi.Constants.SOURCES,
 			aQute.bnd.osgi.Constants.SERVICE_COMPONENT, aQute.bnd.osgi.Constants.CLASSPATH,
 			aQute.bnd.osgi.Constants.BUILDPATH, aQute.bnd.osgi.Constants.BUILDPACKAGES,
 			aQute.bnd.osgi.Constants.RUNBUNDLES, aQute.bnd.osgi.Constants.RUNPROPERTIES, aQute.bnd.osgi.Constants.SUB,
-			aQute.bnd.osgi.Constants.RUNFRAMEWORK,
+			aQute.bnd.osgi.Constants.RUNFRAMEWORK, aQute.bnd.osgi.Constants.RUNFW,
 			aQute.bnd.osgi.Constants.RUNVM,
 			// BndConstants.RUNVMARGS,
 			// BndConstants.TESTSUITES,
@@ -134,7 +137,6 @@ public class BndEditModel {
 	// EnumConverter.create(ResolveMode.class, ResolveMode.manual);
 
 	// FORMATTERS
-	private Converter<String,Object>								defaultFormatter			= new DefaultFormatter();
 	private Converter<String,String>								newlineEscapeFormatter		= new NewlineEscapedStringFormatter();
 	private Converter<String,Boolean>								defaultFalseBoolFormatter	= new DefaultBooleanFormatter(
 																										false);
@@ -166,6 +168,15 @@ public class BndEditModel {
 	@SuppressWarnings("deprecation")
 	public BndEditModel() {
 		// register converters
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_LICENSE, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_CATEGORY, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_NAME, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_DESCRIPTION, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_COPYRIGHT, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_UPDATELOCATION, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_VENDOR, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_CONTACTADDRESS, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_DOCURL, stringConverter);
 		converters.put(aQute.bnd.osgi.Constants.BUILDPATH, buildPathConverter);
 		converters.put(aQute.bnd.osgi.Constants.BUILDPACKAGES, buildPackagesConverter);
 		converters.put(aQute.bnd.osgi.Constants.RUNBUNDLES, clauseListConverter);
@@ -180,6 +191,7 @@ public class BndEditModel {
 		converters.put(aQute.bnd.osgi.Constants.SERVICE_COMPONENT, serviceComponentConverter);
 		converters.put(Constants.IMPORT_PACKAGE, importPatternConverter);
 		converters.put(aQute.bnd.osgi.Constants.RUNFRAMEWORK, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNFW, stringConverter);
 		converters.put(aQute.bnd.osgi.Constants.SUB, listConverter);
 		converters.put(aQute.bnd.osgi.Constants.RUNPROPERTIES, propertiesConverter);
 		converters.put(aQute.bnd.osgi.Constants.RUNVM, stringConverter);
@@ -192,6 +204,16 @@ public class BndEditModel {
 		converters.put(aQute.bnd.osgi.Constants.RUNREPOS, listConverter);
 		// converters.put(BndConstants.RESOLVE_MODE, resolveModeConverter);
 
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_LICENSE, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_CATEGORY, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_NAME, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_DESCRIPTION, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_COPYRIGHT, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_UPDATELOCATION, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_VENDOR, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_CONTACTADDRESS, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_DOCURL, newlineEscapeFormatter);
+
 		formatters.put(aQute.bnd.osgi.Constants.BUILDPATH, headerClauseListFormatter);
 		formatters.put(aQute.bnd.osgi.Constants.BUILDPACKAGES, headerClauseListFormatter);
 		formatters.put(aQute.bnd.osgi.Constants.RUNBUNDLES, headerClauseListFormatter);
@@ -206,6 +228,7 @@ public class BndEditModel {
 		formatters.put(aQute.bnd.osgi.Constants.SERVICE_COMPONENT, headerClauseListFormatter);
 		formatters.put(Constants.IMPORT_PACKAGE, headerClauseListFormatter);
 		formatters.put(aQute.bnd.osgi.Constants.RUNFRAMEWORK, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNFW, newlineEscapeFormatter);
 		formatters.put(aQute.bnd.osgi.Constants.SUB, stringListFormatter);
 		formatters.put(aQute.bnd.osgi.Constants.RUNPROPERTIES, propertiesFormatter);
 		formatters.put(aQute.bnd.osgi.Constants.RUNVM, newlineEscapeFormatter);
@@ -340,6 +363,78 @@ public class BndEditModel {
 		doSetObject(propertyName, oldValue, value, formatter);
 	}
 
+	public String getBundleLicense() {
+		return doGetObject(Constants.BUNDLE_LICENSE, stringConverter);
+	}
+
+	public void setBundleLicense(String bundleLicense) {
+		doSetObject(Constants.BUNDLE_LICENSE, getBundleLicense(), bundleLicense, newlineEscapeFormatter);
+	}
+
+	public String getBundleCategory() {
+		return doGetObject(Constants.BUNDLE_CATEGORY, stringConverter);
+	}
+
+	public void setBundleCategory(String bundleCategory) {
+		doSetObject(Constants.BUNDLE_CATEGORY, getBundleCategory(), bundleCategory, newlineEscapeFormatter);
+	}
+
+	public String getBundleName() {
+		return doGetObject(Constants.BUNDLE_NAME, stringConverter);
+	}
+
+	public void setBundleName(String bundleName) {
+		doSetObject(Constants.BUNDLE_NAME, getBundleName(), bundleName, newlineEscapeFormatter);
+	}
+
+	public String getBundleDescription() {
+		return doGetObject(Constants.BUNDLE_DESCRIPTION, stringConverter);
+	}
+
+	public void setBundleDescription(String bundleDescription) {
+		doSetObject(Constants.BUNDLE_DESCRIPTION, getBundleDescription(), bundleDescription, newlineEscapeFormatter);
+	}
+
+	public String getBundleCopyright() {
+		return doGetObject(Constants.BUNDLE_COPYRIGHT, stringConverter);
+	}
+
+	public void setBundleCopyright(String bundleCopyright) {
+		doSetObject(Constants.BUNDLE_COPYRIGHT, getBundleCopyright(), bundleCopyright, newlineEscapeFormatter);
+	}
+
+	public String getBundleUpdateLocation() {
+		return doGetObject(Constants.BUNDLE_UPDATELOCATION, stringConverter);
+	}
+
+	public void setBundleUpdateLocation(String bundleUpdateLocation) {
+		doSetObject(Constants.BUNDLE_UPDATELOCATION, getBundleUpdateLocation(), bundleUpdateLocation, newlineEscapeFormatter);
+	}
+
+	public String getBundleVendor() {
+		return doGetObject(Constants.BUNDLE_VENDOR, stringConverter);
+	}
+
+	public void setBundleVendor(String bundleVendor) {
+		doSetObject(Constants.BUNDLE_VENDOR, getBundleVendor(), bundleVendor, newlineEscapeFormatter);
+	}
+
+	public String getBundleContactAddress() {
+		return doGetObject(Constants.BUNDLE_CONTACTADDRESS, stringConverter);
+	}
+
+	public void setBundleContactAddress(String bundleContactAddress) {
+		doSetObject(Constants.BUNDLE_CONTACTADDRESS, getBundleContactAddress(), bundleContactAddress, newlineEscapeFormatter);
+	}
+
+	public String getBundleDocUrl() {
+		return doGetObject(Constants.BUNDLE_DOCURL, stringConverter);
+	}
+
+	public void setBundleDocUrl(String bundleDocUrl) {
+		doSetObject(Constants.BUNDLE_DOCURL, getBundleDocUrl(), bundleDocUrl, newlineEscapeFormatter);
+	}
+
 	public String getBundleSymbolicName() {
 		return doGetObject(Constants.BUNDLE_SYMBOLICNAME, stringConverter);
 	}
@@ -610,6 +705,10 @@ public class BndEditModel {
         return doGetObject(aQute.bnd.osgi.Constants.RUNFRAMEWORK, stringConverter);
     }
 
+    public String getRunFw() {
+        return doGetObject(aQute.bnd.osgi.Constants.RUNFW, stringConverter);
+    }
+
     public EE getEE() {
         return doGetObject(aQute.bnd.osgi.Constants.RUNEE, eeConverter);
     }
@@ -621,10 +720,17 @@ public class BndEditModel {
 
     
     public void setRunFramework(String clause) {
+        assert (Constants.RUNFRAMEWORK_SERVICES.equals(clause.toLowerCase().trim()) ||
+                Constants.RUNFRAMEWORK_NONE.equals(clause.toLowerCase().trim()));
         String oldValue = getRunFramework();
         doSetObject(aQute.bnd.osgi.Constants.RUNFRAMEWORK, oldValue, clause, newlineEscapeFormatter);
     }
     
+    public void setRunFw(String clause) {
+        String oldValue = getRunFw();
+        doSetObject(aQute.bnd.osgi.Constants.RUNFW, oldValue, clause, newlineEscapeFormatter);
+    }
+
     public List<Requirement> getRunRequires() {
     	return doGetObject(aQute.bnd.osgi.Constants.RUNREQUIRES, requirementListConverter);
     }

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java Thu Sep  6 18:28:06 2012
@@ -23,7 +23,7 @@ public class NewlineEscapedStringFormatt
 				break;
 			}
 			result.append(input.substring(position, newlineIndex));
-			result.append(BndEditModel.LINE_SEPARATOR);
+			result.append(BndEditModel.NEWLINE_LINE_SEPARATOR);
 			position = newlineIndex + 1;
 		}
 

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/packageinfo?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/packageinfo (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/build/model/packageinfo Thu Sep  6 18:28:06 2012
@@ -1 +1 @@
-version 2
\ No newline at end of file
+version 2.1
\ No newline at end of file

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/ComponentDef.java Thu Sep  6 18:28:06 2012
@@ -112,7 +112,7 @@ class ComponentDef {
 	}
 	
 	void sortReferences() {
-		Map<String, ReferenceDef> temp = new TreeMap(references);
+		Map<String, ReferenceDef> temp = new TreeMap<String,ReferenceDef>(references);
 		references.clear();
 		references.putAll(temp);
 	}

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/HeaderReader.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/HeaderReader.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/HeaderReader.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/component/HeaderReader.java Thu Sep  6 18:28:06 2012
@@ -34,8 +34,8 @@ public class HeaderReader extends Proces
 	private final static String BundleContextTR = "org.osgi.framework.BundleContext";
 	private final static String MapTR = Map.class.getName();
 	private final static String IntTR = int.class.getName();
-	private final static Set<String> allowed = new HashSet<String>(Arrays.asList(ComponentContextTR, BundleContextTR, MapTR));
-	private final static Set<String> allowedDeactivate = new HashSet<String>(Arrays.asList(ComponentContextTR, BundleContextTR, MapTR, IntTR));
+	final static Set<String> allowed = new HashSet<String>(Arrays.asList(ComponentContextTR, BundleContextTR, MapTR));
+	final static Set<String> allowedDeactivate = new HashSet<String>(Arrays.asList(ComponentContextTR, BundleContextTR, MapTR, IntTR));
 	
 	private final static String ServiceReferenceTR = "org.osgi.framework.ServiceReference";
 
@@ -291,7 +291,7 @@ public class HeaderReader extends Proces
 	 * @param allowedParams TODO
 	 * @return rating; 6 if invalid, lower is better
 	 */
-	private int rateLifecycle(MethodDef test, Set<String> allowedParams) {
+	int rateLifecycle(MethodDef test, Set<String> allowedParams) {
 		TypeRef[] prototype = test.getDescriptor().getPrototype();
 		if (prototype.length == 1 && ComponentContextTR.equals(prototype[0].getFQN()))
 			    return 1;
@@ -317,7 +317,7 @@ public class HeaderReader extends Proces
 	 * @param test
 	 * @return
 	 */
-	private int rateBind(MethodDef test) {
+	int rateBind(MethodDef test) {
 		TypeRef[] prototype = test.getDescriptor().getPrototype();
 		if (prototype.length == 1 && ServiceReferenceTR.equals(prototype[0].getFQN()))
 			return 1;

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java Thu Sep  6 18:28:06 2012
@@ -10,6 +10,7 @@ import aQute.bnd.header.*;
 import aQute.bnd.osgi.*;
 import aQute.bnd.service.diff.*;
 import aQute.bnd.service.diff.Tree.Data;
+import aQute.lib.collections.*;
 import aQute.lib.hex.*;
 import aQute.lib.io.*;
 import aQute.libg.cryptography.*;
@@ -153,7 +154,13 @@ public class DiffPluginImpl implements D
 				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(),
+						String paramValue = parameter.getValue();
+						if (Constants.EXPORT_PACKAGE.equals(header) && Constants.USES_DIRECTIVE.equals(parameter.getKey())) {
+							ExtList<String> uses = ExtList.from(parameter.getValue());
+							Collections.sort(uses);
+							paramValue = uses.join();
+						}
+						parameterDef.add(new Element(Type.PARAMETER, parameter.getKey() + ":" + paramValue,
 								null, CHANGED, CHANGED, null));
 					}
 					clausesDef.add(new Element(Type.CLAUSE, clause.getKey(), parameterDef, CHANGED, CHANGED, null));

Modified: felix/trunk/bundleplugin/src/main/java/aQute/bnd/filerepo/FileRepo.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/filerepo/FileRepo.java?rev=1381708&r1=1381707&r2=1381708&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/filerepo/FileRepo.java (original)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/filerepo/FileRepo.java Thu Sep  6 18:28:06 2012
@@ -8,7 +8,7 @@ import aQute.bnd.version.*;
 
 public class FileRepo {
 	File	root;
-	Pattern	REPO_FILE	= Pattern.compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+|latest)\\.(jar|lib)");
+	Pattern	REPO_FILE	= Pattern.compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+)\\.(jar|lib)");
 
 	public FileRepo(File root) {
 		this.root = root;