Sync bndlib code

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1381708 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Actionable.java b/bundleplugin/src/main/java/aQute/bnd/service/Actionable.java
new file mode 100644
index 0000000..4e805a5
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Actionable.java
@@ -0,0 +1,48 @@
+package aQute.bnd.service;
+
+import java.util.*;
+
+/**
+ * An interface to allow bnd to provide commands on elements. This interface can
+ * provide information about the implementer but it can also provide information
+ * about its elements. These elements are identified by a <i>target</i>. A
+ * target is one or more objects that uniquely identify a child in the
+ * container. The exact protocol for the target is left to the implementers,
+ * this interface is just a conduit between the bnd world (no Eclipse etc) and
+ * the GUI world, using only bnd and java interfaces.
+ */
+public interface Actionable {
+	/**
+	 * Return a map with command names (potentially localized) and a Runnable.
+	 * The caller can execute the caller at will.
+	 * 
+	 * @param target
+	 *            the target object, null if commands for the encompassing
+	 *            entity is sought (e.g. the repo itself).
+	 * @return A Map with the actions or null if no actions are available.
+	 * @throws Exception
+	 */
+	Map<String,Runnable> actions(Object... target) throws Exception;
+
+	/**
+	 * Return a tooltip for the given target or the encompassing entity if null
+	 * is passed.
+	 * 
+	 * @param target
+	 *            the target, any number of parameters to identify
+	 * @return the tooltip or null
+	 * @throws Exception
+	 */
+	String tooltip(Object... target) throws Exception;
+
+	/**
+	 * Provide a title for an element.
+	 * 
+	 * @param target
+	 *            the target, any number of parameters to identify
+	 * @return the text for this element
+	 * @throws Exception
+	 */
+
+	String title(Object... target) throws Exception;
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Refreshable.java b/bundleplugin/src/main/java/aQute/bnd/service/Refreshable.java
index aeac258..73afa43 100644
--- a/bundleplugin/src/main/java/aQute/bnd/service/Refreshable.java
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Refreshable.java
@@ -3,7 +3,7 @@
 import java.io.*;
 
 public interface Refreshable {
-	boolean refresh();
+	boolean refresh() throws Exception;
 
 	File getRoot();
 }
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/RemoteRepositoryPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/RemoteRepositoryPlugin.java
index 8110fab..e87f3b5 100644
--- a/bundleplugin/src/main/java/aQute/bnd/service/RemoteRepositoryPlugin.java
+++ b/bundleplugin/src/main/java/aQute/bnd/service/RemoteRepositoryPlugin.java
@@ -7,17 +7,16 @@
 	/**
 	 * Retrieve a resource handle from the repository. For all implementations
 	 * of this interface, calling {@code getFile(bsn, range, strategy, props)}
-	 * should always return the same result as
-	 * {@code getResource(bsn, range, strategy, props).request()}.
+	 * should always return the same result as {@link RepositoryPlugin#get(String, aQute.bnd.version.Version, Map)}
 	 * 
-	 * @param bsn
-	 * @param range
-	 * @param strategy
-	 * @param properties
+	 * @param bsn the bsn of the revision
+	 * @param version the version of the revision
+	 * @param strategy strategy
+	 * @param properties any properties
 	 * @return
 	 * @throws Exception
 	 */
-	ResourceHandle getHandle(String bsn, String range, Strategy strategy, Map<String,String> properties)
+	ResourceHandle getHandle(String bsn, String version, Strategy strategy, Map<String,String> properties)
 			throws Exception;
 
 	File getCacheDirectory();
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
index 73847f7..f3ee1f0 100644
--- a/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
+++ b/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
@@ -6,113 +6,63 @@
 
 import aQute.bnd.version.*;
 
+/**
+ * A Repository Plugin abstract a bnd repository. This interface allows bnd to
+ * find programs from their bsn and revisions from their bsn-version
+ * combination. It is also possible to put revisions in a repository if the
+ * repository is not read only.
+ */
 public interface RepositoryPlugin {
-	public enum Strategy {
-		LOWEST, HIGHEST, EXACT
-	}
-
 	/**
 	 * Options used to steer the put operation
 	 */
-	public class PutOptions {
+	class PutOptions {
+		public String	BUNDLE	= "application/vnd.osgi.bundle";
+		public String	LIB		= "application/vnd.aQute.lib";
+
 		/**
-		 * The <b>SHA1</b> digest of the artifact to put into the repository.<br/>
-		 * <br/>
+		 * The <b>SHA1</b> digest of the artifact to put into the repository.
 		 * When specified the digest of the <b>fetched</b> artifact will be
 		 * calculated and verified against this digest, <b>before</b> putting
-		 * the artifact into the repository.<br/>
-		 * <br/>
-		 * An exception is thrown if the specified digest and the calculated
-		 * digest do not match.
+		 * the artifact into the repository. </p> An exception is thrown if the
+		 * specified digest and the calculated digest do not match.
 		 */
-		public byte[]	digest				= null;
+		public byte[]	digest	= null;
 
 		/**
-		 * Allow the implementation to change the artifact.<br/>
-		 * <br/>
-		 * When set to true the implementation is allowed to change the artifact
-		 * when putting it into the repository.<br/>
-		 * <br/>
-		 * An exception is thrown when set to false and the implementation can't
-		 * put the artifact into the repository without changing it.
+		 * Specify the mime type of the importing stream. This can be either
+		 * {@link #BUNDLE} or {@link #LIB}. If left open, it is up to the
+		 * repository to guess the content type.
 		 */
-		public boolean	allowArtifactChange	= false;
-
-		/**
-		 * Generate a <b>SHA1</b> digest.<br/>
-		 * <br/>
-		 * When set to true the implementation generates a digest of the
-		 * artifact as it is put into the repository and returns that digest in
-		 * the result.
-		 */
-		public boolean	generateDigest		= false;
-
-		/**
-		 * Create a 'latest' artifact when it did not exist.<br/>
-		 * <br/>
-		 * When set to true the implementation is requested to create a 'latest'
-		 * artifact.
-		 */
-		public boolean	createLatest		= false;
+		public String	type;
 	}
 
+	PutOptions	DEFAULTOPTIONS	= new PutOptions();
+
 	/**
 	 * Results returned by the put operation
 	 */
-	public class PutResult {
+	class PutResult {
 		/**
-		 * The artifact as it was put in the repository.<br/>
+		 * A (potentially public) uri to the revision as it was put in the
+		 * repository.<br/>
 		 * <br/>
-		 * This can be a URI to the artifact (when it was put into the
-		 * repository), or null when the artifact was not put into the
-		 * repository (for example because it was already in the repository).
+		 * This can be a URI to the given artifact (when it was put into the
+		 * repository). This does not have to be a File URI!
 		 */
 		public URI		artifact	= null;
 
 		/**
-		 * The 'latest' artifact as it was put in the repository.<br/>
-		 * <br/>
-		 * Only set when {@link PutOptions#createLatest} was set to true and the
-		 * 'latest' artifact did not exist, or when the 'latest' artifact did
-		 * exists and was older than the artifact being put in the repository.
-		 */
-		public URI		latest		= null;
-
-		/**
 		 * The <b>SHA1</b> digest of the artifact as it was put into the
 		 * repository.<br/>
 		 * <br/>
-		 * This will be null when {@link PutOptions#generateDigest} was null, or
-		 * when {@link #artifact} is null.
+		 * This can be null and it can differ from the input digest if the
+		 * repository rewrote the stream for optimization reason. If the
 		 */
 		public byte[]	digest		= null;
 	}
 
 	/**
-	 * Return a URL to a matching version of the given bundle.
-	 * 
-	 * @param bsn
-	 *            Bundle-SymbolicName of the searched bundle
-	 * @param range
-	 *            Version range for this bundle,"latest" if you only want the
-	 *            latest, or null when you want all.
-	 * @param strategy
-	 *            Get the highest or the lowest
-	 * @return A list of URLs sorted on version, lowest version is at index 0.
-	 *         null is returned when no files with the given bsn ould be found.
-	 * @throws Exception
-	 *             when anything goes wrong
-	 */
-	File get(String bsn, String range, Strategy strategy, Map<String,String> properties) throws Exception;
-
-	/**
-	 * Answer if this repository can be used to store files.
-	 * 
-	 * @return true if writable
-	 */
-	boolean canWrite();
-
-	/**
 	 * Put an artifact (from the InputStream) into the repository.<br/>
 	 * <br/>
 	 * There is NO guarantee that the artifact on the input stream has not been
@@ -123,7 +73,9 @@
 	 * @param stream
 	 *            The input stream with the artifact
 	 * @param options
-	 *            The put options. See {@link RepositoryPlugin.PutOptions}
+	 *            The put options. See {@link RepositoryPlugin.PutOptions}, can
+	 *            be {@code null}, which will then take the default options like
+	 *            new PutOptions().
 	 * @return The result of the put, never null. See
 	 *         {@link RepositoryPlugin.PutResult}
 	 * @throws Exception
@@ -138,16 +90,99 @@
 	PutResult put(InputStream stream, PutOptions options) throws Exception;
 
 	/**
+	 * The caller can specify any number of DownloadListener objects that are
+	 * called back when a download is finished (potentially before the get
+	 * method has returned).
+	 */
+
+	interface DownloadListener {
+		/**
+		 * Called when the file is successfully downloaded from a remote
+		 * repository.
+		 * 
+		 * @param file
+		 *            The file that was downloaded
+		 * @throws Exception
+		 *             , are logged and ignored
+		 */
+		void success(File file) throws Exception;
+
+		/**
+		 * Called when the file could not be downloaded from a remote
+		 * repository.
+		 * 
+		 * @param file
+		 *            The file that was intended to be downloaded.
+		 * @throws Exception
+		 *             , are logged and ignored
+		 */
+		void failure(File file, String reason) throws Exception;
+
+		/**
+		 * Can be called back regularly before success/failure but never after.
+		 * Indicates how far the download has progressed in percents. Since
+		 * downloads can be restarted, it is possible that the percentage
+		 * decreases.
+		 * 
+		 * @param file
+		 *            The file that was intended to be downloaded
+		 * @param percentage
+		 *            Percentage of file downloaded (can go down)
+		 * @return true if the download should continue, fails if it should be
+		 *         canceled (and fail)
+		 * @throws Exception
+		 *             , are logged and ignored
+		 */
+		boolean progress(File file, int percentage) throws Exception;
+	}
+
+	/**
+	 * Return a URL to a matching version of the given bundle.
+	 * <p/>
+	 * If download listeners are specified then the returned file is not
+	 * guaranteed to exist before a download listener is notified of success or
+	 * failure. The callback can happen before the method has returned. If the
+	 * returned file is null then download listeners are not called back.
+	 * <p/>
+	 * The intention of the Download Listeners is to allow a caller to obtain
+	 * references to files that do not yet exist but are to be downloaded. If
+	 * the downloads were done synchronously in the call, then no overlap of
+	 * downloads could take place.
+	 * 
+	 * @param bsn
+	 *            Bundle-SymbolicName of the searched bundle
+	 * @param version
+	 *            Version requested
+	 * @param listeners
+	 *            Zero or more download listener that will be notified of the
+	 *            outcome.
+	 * @return A file to the revision or null if not found
+	 * @throws Exception
+	 *             when anything goes wrong, in this case no listeners will be
+	 *             called back.
+	 */
+	File get(String bsn, Version version, Map<String,String> properties, DownloadListener... listeners)
+			throws Exception;
+
+	/**
+	 * Answer if this repository can be used to store files.
+	 * 
+	 * @return true if writable
+	 */
+	boolean canWrite();
+
+	/**
 	 * Return a list of bsns that are present in the repository.
 	 * 
-	 * @param regex
-	 *            if not null, match against the bsn and if matches, return
-	 *            otherwise skip
-	 * @return A list of bsns that match the regex parameter or all if regex is
-	 *         null
+	 * @param pattern
+	 *            A <ahref="https://en.wikipedia.org/wiki/Glob_%28programming%29">glob pattern</a>
+	 *            to be matched against bsns present in the repository, or {@code null}.
+	 * @return A list of bsns that match the pattern parameter or all if pattern
+	 *         is null; repositories that do not support browsing or querying
+	 *         should return an empty list.
 	 * @throws Exception
 	 */
-	List<String> list(String regex) throws Exception;
+	List<String> list(String pattern) throws Exception;
 
 	/**
 	 * Return a list of versions.
@@ -155,7 +190,7 @@
 	 * @throws Exception
 	 */
 
-	List<Version> versions(String bsn) throws Exception;
+	SortedSet<Version> versions(String bsn) throws Exception;
 
 	/**
 	 * @return The name of the repository
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Strategy.java b/bundleplugin/src/main/java/aQute/bnd/service/Strategy.java
new file mode 100644
index 0000000..c24cd37
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Strategy.java
@@ -0,0 +1,5 @@
+package aQute.bnd.service;
+
+public enum Strategy {
+	LOWEST, EXACT, HIGHEST;
+}