Use local copy of latest bndlib code for pre-release testing purposes
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1347815 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/AnalyzerPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/AnalyzerPlugin.java
new file mode 100644
index 0000000..3efe8ee
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/AnalyzerPlugin.java
@@ -0,0 +1,20 @@
+package aQute.bnd.service;
+
+import aQute.lib.osgi.*;
+
+public interface AnalyzerPlugin {
+
+ /**
+ * This plugin is called after analysis. The plugin is free to modify the
+ * jar and/or change the classpath information (see referred, contained).
+ * This plugin is called after analysis of the JAR but before manifest
+ * generation.
+ *
+ * @param analyzer
+ * @return true if the classpace has been modified so that the bundle
+ * classpath must be reanalyzed
+ * @throws Exception
+ */
+
+ boolean analyzeJar(Analyzer analyzer) throws Exception;
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/BndListener.java b/bundleplugin/src/main/java/aQute/bnd/service/BndListener.java
new file mode 100644
index 0000000..e937110
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/BndListener.java
@@ -0,0 +1,23 @@
+package aQute.bnd.service;
+
+import java.io.*;
+import java.util.concurrent.atomic.*;
+
+import aQute.libg.reporter.*;
+
+public class BndListener {
+ final AtomicInteger inside = new AtomicInteger();
+
+ public void changed(File file) {
+ }
+ public void begin() { inside.incrementAndGet();}
+ public void end() { inside.decrementAndGet(); }
+
+ public boolean isInside() {
+ return inside.get()!=0;
+ }
+
+ public void signal(Reporter reporter) {
+
+ }
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/CommandPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/CommandPlugin.java
new file mode 100644
index 0000000..34c72c2
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/CommandPlugin.java
@@ -0,0 +1,30 @@
+package aQute.bnd.service;
+
+import aQute.bnd.build.*;
+
+/**
+ * A plugin that makes it possible to
+ * @author aqute
+ *
+ */
+public interface CommandPlugin {
+ /**
+ * Is run before a command is executed. These plugins are called
+ * in the order of declaration.
+ *
+ * @param project The project for which the command runs
+ *
+ * @param command the command name
+ */
+ void before(Project project, String command);
+
+ /**
+ * Is run after a command is executed. These plugins are
+ * called in the reverse order of declaration.
+ *
+ * @param project The project for which the command runs
+ *
+ * @param command the command name
+ */
+ void after(Project project, String command, Throwable outcome);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Compiler.java b/bundleplugin/src/main/java/aQute/bnd/service/Compiler.java
new file mode 100644
index 0000000..626b68c
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Compiler.java
@@ -0,0 +1,11 @@
+package aQute.bnd.service;
+
+import java.io.*;
+import java.util.*;
+
+import aQute.bnd.build.*;
+
+public interface Compiler {
+ boolean compile(Project project, Collection<File> sources, Collection<Container> buildpath,
+ File bin) throws Exception;
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/DependencyContributor.java b/bundleplugin/src/main/java/aQute/bnd/service/DependencyContributor.java
new file mode 100644
index 0000000..e6a88ff
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/DependencyContributor.java
@@ -0,0 +1,9 @@
+package aQute.bnd.service;
+
+import java.util.*;
+
+import aQute.bnd.build.*;
+
+public interface DependencyContributor {
+ void addDependencies(Project project, Set<String> dependencies);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Deploy.java b/bundleplugin/src/main/java/aQute/bnd/service/Deploy.java
new file mode 100644
index 0000000..e1d92e1
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Deploy.java
@@ -0,0 +1,12 @@
+package aQute.bnd.service;
+
+import aQute.bnd.build.*;
+import aQute.lib.osgi.*;
+
+/**
+ * Deploy this artifact to maven.
+ *
+ */
+public interface Deploy {
+ boolean deploy(Project project, Jar jar) throws Exception;
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/EclipseJUnitTester.java b/bundleplugin/src/main/java/aQute/bnd/service/EclipseJUnitTester.java
new file mode 100644
index 0000000..a2af9b0
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/EclipseJUnitTester.java
@@ -0,0 +1,6 @@
+package aQute.bnd.service;
+
+public interface EclipseJUnitTester {
+ void setPort(int port);
+ void setHost( String host);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/IndexProvider.java b/bundleplugin/src/main/java/aQute/bnd/service/IndexProvider.java
new file mode 100644
index 0000000..5454c2d
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/IndexProvider.java
@@ -0,0 +1,13 @@
+package aQute.bnd.service;
+
+import java.net.URL;
+import java.util.List;
+import java.util.Set;
+
+public interface IndexProvider {
+
+ List<URL> getIndexLocations() throws Exception;
+
+ Set<ResolutionPhase> getSupportedPhases();
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/LauncherPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/LauncherPlugin.java
new file mode 100644
index 0000000..f858500
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/LauncherPlugin.java
@@ -0,0 +1,9 @@
+package aQute.bnd.service;
+
+import aQute.bnd.build.*;
+
+public interface LauncherPlugin {
+ ProjectLauncher getLauncher(Project project) throws Exception;
+
+ ProjectTester getTester(Project project);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/MakePlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/MakePlugin.java
new file mode 100644
index 0000000..20a1849
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/MakePlugin.java
@@ -0,0 +1,21 @@
+package aQute.bnd.service;
+
+import java.util.*;
+
+import aQute.lib.osgi.*;
+
+public interface MakePlugin {
+
+ /**
+ * This plugin is called when Include-Resource detects a reference to a resource
+ * that it can not find in the file system.
+ *
+ * @param builder The current builder
+ * @param source The source string (i.e. the place where bnd looked)
+ * @param arguments Any arguments on the clause in Include-Resource
+ * @return A resource or null if no resource could be made
+ * @throws Exception
+ */
+ Resource make(Builder builder, String source, Map<String,String> arguments) throws Exception;
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/OBRIndexProvider.java b/bundleplugin/src/main/java/aQute/bnd/service/OBRIndexProvider.java
new file mode 100644
index 0000000..9ba5b04
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/OBRIndexProvider.java
@@ -0,0 +1,11 @@
+package aQute.bnd.service;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+@Deprecated
+public interface OBRIndexProvider {
+ Collection<URL> getOBRIndexes() throws IOException;
+ Set<OBRResolutionMode> getSupportedModes();
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/OBRResolutionMode.java b/bundleplugin/src/main/java/aQute/bnd/service/OBRResolutionMode.java
new file mode 100644
index 0000000..78f9801
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/OBRResolutionMode.java
@@ -0,0 +1,6 @@
+package aQute.bnd.service;
+
+@Deprecated
+public enum OBRResolutionMode {
+ build, runtime
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Plugin.java b/bundleplugin/src/main/java/aQute/bnd/service/Plugin.java
new file mode 100644
index 0000000..065fac8
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Plugin.java
@@ -0,0 +1,31 @@
+package aQute.bnd.service;
+
+import java.util.*;
+
+import aQute.libg.reporter.*;
+
+/**
+ * An optional interface for plugins. If a plugin implements this interface then
+ * it can receive the reminaing attributes and directives given in its clause as
+ * well as the reporter to use.
+ *
+ */
+public interface Plugin {
+ /**
+ * Give the plugin the remaining properties.
+ *
+ * When a plugin is declared, the clause can contain extra properties.
+ * All the properties and directives are given to the plugin to use.
+ *
+ * @param map attributes and directives for this plugin's clause
+ */
+ void setProperties(Map<String,String> map);
+
+ /**
+ * Set the current reporter. This is called at init time. This plugin
+ * should report all errors and warnings to this reporter.
+ *
+ * @param processor
+ */
+ void setReporter(Reporter processor);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Refreshable.java b/bundleplugin/src/main/java/aQute/bnd/service/Refreshable.java
new file mode 100644
index 0000000..e5e62e9
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Refreshable.java
@@ -0,0 +1,8 @@
+package aQute.bnd.service;
+
+import java.io.*;
+
+public interface Refreshable {
+ boolean refresh();
+ File getRoot();
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Registry.java b/bundleplugin/src/main/java/aQute/bnd/service/Registry.java
new file mode 100755
index 0000000..90fca36
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Registry.java
@@ -0,0 +1,11 @@
+package aQute.bnd.service;
+
+import java.util.*;
+
+/**
+ * A registry for objects.
+ */
+public interface Registry {
+ <T> List<T> getPlugins(Class<T> c);
+ <T> T getPlugin(Class<T> c);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/RegistryPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/RegistryPlugin.java
new file mode 100644
index 0000000..7a46849
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/RegistryPlugin.java
@@ -0,0 +1,9 @@
+package aQute.bnd.service;
+
+
+/**
+ * A plugin that wants a registry
+ */
+public interface RegistryPlugin {
+ void setRegistry(Registry registry);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/RemoteRepositoryPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/RemoteRepositoryPlugin.java
new file mode 100644
index 0000000..e441a4c
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/RemoteRepositoryPlugin.java
@@ -0,0 +1,20 @@
+package aQute.bnd.service;
+
+import java.io.*;
+import java.util.*;
+
+public interface RemoteRepositoryPlugin extends RepositoryPlugin {
+ /**
+ * 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()}.
+ * @param bsn
+ * @param range
+ * @param strategy
+ * @param properties
+ * @return
+ * @throws Exception
+ */
+ ResourceHandle getHandle(String bsn, String range, Strategy strategy, Map<String,String> properties) throws Exception;
+
+ File getCacheDirectory();
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/RepositoryListenerPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/RepositoryListenerPlugin.java
new file mode 100644
index 0000000..13899f7
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/RepositoryListenerPlugin.java
@@ -0,0 +1,16 @@
+package aQute.bnd.service;
+
+import java.io.*;
+
+import aQute.lib.osgi.*;
+
+public interface RepositoryListenerPlugin {
+
+ /**
+ * Called when a bundle is added to a repository.
+ * @param repository
+ * @param jar
+ * @param file
+ */
+ void bundleAdded(RepositoryPlugin repository, Jar jar, File file);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
new file mode 100644
index 0000000..91b0a7e
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
@@ -0,0 +1,91 @@
+package aQute.bnd.service;
+
+import java.io.*;
+import java.util.*;
+
+import aQute.lib.osgi.*;
+import aQute.libg.version.*;
+
+public interface RepositoryPlugin {
+ public enum Strategy {
+ LOWEST, HIGHEST, EXACT
+ }
+
+ /**
+ * 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.
+ * @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
+ */
+ @Deprecated File[] get(String bsn, String range) throws Exception;
+
+ /**
+ * 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 a JAR file in the repository.
+ *
+ * @param jar
+ * @throws Exception
+ */
+ File put(Jar jar) throws Exception;
+
+ /**
+ * 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
+ * @throws Exception
+ */
+ List<String> list(String regex) throws Exception;
+
+ /**
+ * Return a list of versions.
+ *
+ * @throws Exception
+ */
+
+ List<Version> versions(String bsn) throws Exception;
+
+ /**
+ * @return The name of the repository
+ */
+ String getName();
+
+ /**
+ * Return a location identifier of this repository
+ */
+
+ String getLocation();
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/ResolutionPhase.java b/bundleplugin/src/main/java/aQute/bnd/service/ResolutionPhase.java
new file mode 100644
index 0000000..0fd7ec9
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/ResolutionPhase.java
@@ -0,0 +1,5 @@
+package aQute.bnd.service;
+
+public enum ResolutionPhase {
+ build, runtime
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/ResourceHandle.java b/bundleplugin/src/main/java/aQute/bnd/service/ResourceHandle.java
new file mode 100644
index 0000000..be7f79b
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/ResourceHandle.java
@@ -0,0 +1,12 @@
+package aQute.bnd.service;
+
+import java.io.*;
+
+public interface ResourceHandle {
+
+ public enum Location { local, remote_cached, remote }
+
+ String getName();
+ Location getLocation();
+ File request() throws IOException;
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/Scripter.java b/bundleplugin/src/main/java/aQute/bnd/service/Scripter.java
new file mode 100644
index 0000000..2e4e1d3
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/Scripter.java
@@ -0,0 +1,10 @@
+package aQute.bnd.service;
+
+import java.io.*;
+import java.util.*;
+
+public interface Scripter {
+
+ void eval(Map<String, Object> x, StringReader stringReader);
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/SignerPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/SignerPlugin.java
new file mode 100644
index 0000000..aaef646
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/SignerPlugin.java
@@ -0,0 +1,15 @@
+package aQute.bnd.service;
+
+import aQute.lib.osgi.*;
+
+public interface SignerPlugin {
+ /**
+ * Sign the current jar. The alias is the given certificate
+ * keystore.
+ *
+ * @param builder The current builder that contains the jar to sign
+ * @param alias The keystore certificate alias
+ * @throws Exception When anything goes wrong
+ */
+ void sign(Builder builder, String alias) throws Exception;
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/action/Action.java b/bundleplugin/src/main/java/aQute/bnd/service/action/Action.java
new file mode 100644
index 0000000..5167827
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/action/Action.java
@@ -0,0 +1,7 @@
+package aQute.bnd.service.action;
+
+import aQute.bnd.build.*;
+
+public interface Action {
+ void execute( Project project, String action) throws Exception;
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/action/NamedAction.java b/bundleplugin/src/main/java/aQute/bnd/service/action/NamedAction.java
new file mode 100644
index 0000000..5a1c697
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/action/NamedAction.java
@@ -0,0 +1,6 @@
+package aQute.bnd.service.action;
+
+
+public interface NamedAction extends Action {
+ String getName();
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/action/packageinfo b/bundleplugin/src/main/java/aQute/bnd/service/action/packageinfo
new file mode 100644
index 0000000..ec0efd4
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/action/packageinfo
@@ -0,0 +1 @@
+version 1.43.1
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/diff/Delta.java b/bundleplugin/src/main/java/aQute/bnd/service/diff/Delta.java
new file mode 100644
index 0000000..eec4781
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/diff/Delta.java
@@ -0,0 +1,19 @@
+package aQute.bnd.service.diff;
+
+/**
+ * The Delta provides information about the {@link Diff} object. It tells the
+ * relation between the newer and older compared elements.
+ *
+ */
+public enum Delta {
+
+ // ORDER IS IMPORTANT FOR TRANSITIONS TABLE!
+
+ /**
+ *
+ */
+ IGNORED, // for all
+ UNCHANGED, CHANGED, MICRO, MINOR, MAJOR, // content
+ REMOVED, ADDED; // structural
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/diff/Diff.java b/bundleplugin/src/main/java/aQute/bnd/service/diff/Diff.java
new file mode 100644
index 0000000..43bf4e5
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/diff/Diff.java
@@ -0,0 +1,23 @@
+package aQute.bnd.service.diff;
+
+import java.util.*;
+
+public interface Diff {
+ interface Ignore {
+ boolean contains(Diff diff);
+ }
+
+ Delta getDelta();
+ Delta getDelta(Ignore ignore);
+
+ Type getType();
+ String getName();
+ Tree getOlder();
+ Tree getNewer();
+
+ Collection<? extends Diff> getChildren();
+
+ Diff get(String name);
+
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/diff/Differ.java b/bundleplugin/src/main/java/aQute/bnd/service/diff/Differ.java
new file mode 100644
index 0000000..869a237
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/diff/Differ.java
@@ -0,0 +1,13 @@
+package aQute.bnd.service.diff;
+
+import aQute.lib.osgi.*;
+
+/**
+ * Compare two Jars and report the differences.
+ */
+public interface Differ {
+ Tree tree(Analyzer source ) throws Exception;
+ Tree tree(Jar source) throws Exception;
+
+ Tree deserialize(Tree.Data data) throws Exception;
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/diff/Tree.java b/bundleplugin/src/main/java/aQute/bnd/service/diff/Tree.java
new file mode 100644
index 0000000..7072ac1
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/diff/Tree.java
@@ -0,0 +1,29 @@
+package aQute.bnd.service.diff;
+
+public interface Tree {
+
+ public class Data {
+ public String name;
+ public Type type = Type.METHOD;
+ public Delta add = Delta.MINOR;
+ public Delta rem = Delta.MAJOR;
+ public Data[] children = null;
+ public String comment = null;
+ }
+
+ Data serialize();
+
+ Tree[] getChildren();
+
+ String getName();
+
+ Type getType();
+
+ Delta ifAdded();
+
+ Delta ifRemoved();
+
+ Diff diff(Tree older);
+
+ Tree get(String name);
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/diff/Type.java b/bundleplugin/src/main/java/aQute/bnd/service/diff/Type.java
new file mode 100644
index 0000000..d71b9f4
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/diff/Type.java
@@ -0,0 +1,10 @@
+package aQute.bnd.service.diff;
+
+public enum Type {
+ ACCESS, BUNDLE, API, MANIFEST, PACKAGE, CLASS, INTERFACE, ANNOTATION, ENUM, EXTENDS, IMPLEMENTS, FIELD, METHOD, ANNOTATED, PROPERTY, RESOURCE, CUSTOM, CLAUSE, HEADER, PARAMETER, CLASS_VERSION, RESOURCES, CONSTANT, RETURN, VERSION, DEPRECATED;
+
+ public boolean isInherited() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/packageinfo b/bundleplugin/src/main/java/aQute/bnd/service/packageinfo
new file mode 100644
index 0000000..0ff7674
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/packageinfo
@@ -0,0 +1 @@
+version 1.45.0
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/url/TaggedData.java b/bundleplugin/src/main/java/aQute/bnd/service/url/TaggedData.java
new file mode 100644
index 0000000..53332f4
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/url/TaggedData.java
@@ -0,0 +1,37 @@
+package aQute.bnd.service.url;
+
+import java.io.InputStream;
+
+/**
+ * Represents a data stream that has a tag associated with it; the primary
+ * use-case is an HTTP response stream with an ETag header.
+ *
+ * @author Neil Bartlett
+ *
+ */
+public class TaggedData {
+
+ private final String tag;
+ private final InputStream inputStream;
+
+ public TaggedData(String tag, InputStream inputStream) {
+ this.tag = tag;
+ this.inputStream = inputStream;
+ }
+
+ /**
+ * Returns the ETag for the retrieved resource, or {@code null} if the ETag
+ * was not provided by the server.
+ */
+ public String getTag() {
+ return tag;
+ }
+
+ /**
+ * Returns the input stream containing the resource data.
+ */
+ public InputStream getInputStream() {
+ return inputStream;
+ }
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/url/URLConnector.java b/bundleplugin/src/main/java/aQute/bnd/service/url/URLConnector.java
new file mode 100644
index 0000000..e853509
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/url/URLConnector.java
@@ -0,0 +1,49 @@
+package aQute.bnd.service.url;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+public interface URLConnector {
+
+ /**
+ * Connect to the specified URL.
+ *
+ * @param url
+ * @return
+ * @throws IOException
+ */
+ InputStream connect(URL url) throws IOException;
+
+ /**
+ * Connect to the specified URL, also returning the ETag if available.
+ *
+ * @param url
+ * The remote URL.
+ * @return An instance of {@link TaggedData}; note that the
+ * {@link TaggedData#getTag()} method <strong>may</strong> return
+ * {@code null} if the resource has no tag.
+ * @throws IOException
+ *
+ * @since 1.1
+ */
+ TaggedData connectTagged(URL url) throws IOException;
+
+ /**
+ * Connect to the specified URL while providing the last known tag for the
+ * remote resource; the response will be {@code null} if the remote resource
+ * is unchanged.
+ *
+ * @param url
+ * The remote URL.
+ * @param tag
+ * The last known tag value for the resource.
+ * @return An instance of {@link TaggedData}, or {@code null} if the
+ * resource has not modified (i.e., if it has the same tag value).
+ * @throws IOException
+ *
+ * @since 1.1
+ */
+ TaggedData connectTagged(URL url, String tag) throws IOException;
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/url/packageinfo b/bundleplugin/src/main/java/aQute/bnd/service/url/packageinfo
new file mode 100644
index 0000000..7ae9673
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/service/url/packageinfo
@@ -0,0 +1 @@
+version 1.1
\ No newline at end of file