Further patches related to FELIX-1324 - now abstracts uri scheme behind a resolver that allows for substitution of "real" urls for meta stubs:

start:sigil:<bsn>:version

for example

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@831004 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/common/runtime/sigil.properties b/sigil/common/runtime/sigil.properties
index 23156cc..e2144c0 100644
--- a/sigil/common/runtime/sigil.properties
+++ b/sigil/common/runtime/sigil.properties
@@ -12,7 +12,7 @@
 	org.apache.felix.sigil.common.runtime, \
 
 -imports: \
-	org.apache.felix.sigil.common.runtime,\
+	org.apache.felix.sigil.common.runtime, \
 	org.osgi.framework, \
 	org.osgi.framework.launch, \
 	org.osgi.service.packageadmin, \
diff --git a/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java b/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java
index 57c1ed7..6aa0a48 100644
--- a/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java
+++ b/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java
@@ -19,6 +19,7 @@
 package org.apache.felix.sigil.common.runtime;
 
 import java.io.BufferedReader;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -38,6 +39,30 @@
 
 public class BundleForm
 {    
+    public interface Resolver {
+        URI[] resolve(URI base) throws URISyntaxException;
+    }
+    
+    public interface ResolutionContext {
+        Resolver findResolver(URI uri);
+    }
+    
+    private static final Resolver NULL_RESOLVER = new Resolver() {
+
+        public URI[] resolve(URI base)
+        {
+            return new URI[] { base };
+        }
+        
+    };
+    private static final ResolutionContext NULL_CONTEXT = new ResolutionContext()
+    {      
+        public Resolver findResolver(URI uri)
+        {
+            return NULL_RESOLVER;
+        }
+    };
+    
     public static class BundleStatus
     {
         private String location;
@@ -101,29 +126,83 @@
         }
     }
     
-    private String[] bundles;
-    private Set<String> startMap = new HashSet<String>();
+    private URI[] bundles;
+    private Set<URI> startMap = new HashSet<URI>();
 
     public BundleForm() {
     }
     
-    public static BundleForm resolve(URL formURL) throws IOException, URISyntaxException {
+    public BundleStatus[] resolve(ResolutionContext ctx) throws IOException, URISyntaxException {
+        if ( ctx == null ) {
+            ctx = NULL_CONTEXT;
+        }
+        
+        ArrayList<BundleStatus> ret = new ArrayList<BundleStatus>(bundles.length);
+        
+        for ( int i = 0; i < bundles.length; i++ ) {
+            Resolver resolver = ctx.findResolver(bundles[i]);
+            if ( resolver == null ) {
+                resolver = NULL_RESOLVER;
+            }
+            URI[] resolved = resolver.resolve(bundles[i]);
+            for ( URI uri : resolved ) {
+                ret.add( toBundle(uri, isStarted(bundles[i])) );
+            }
+        }
+        
+        return ret.toArray(new BundleStatus[ret.size()] );
+
+    }
+    
+    private BundleStatus toBundle(URI uri, boolean started) throws IOException
+    {
+        URL url = uri.toURL();
+        InputStream in = url.openStream();
+        try {
+            JarInputStream jin = new JarInputStream(in);
+            Manifest mf = jin.getManifest();
+            Attributes attr = mf.getMainAttributes();
+            String bsn = attr.getValue(Constants.BUNDLE_SYMBOLICNAME);
+            String ver = attr.getValue(Constants.BUNDLE_VERSION);
+            BundleStatus st = new BundleStatus();
+            st.setBundleSymbolicName(bsn);
+            st.setVersion(ver);
+            st.setLocation(url.toExternalForm());
+            st.setStatus(started ? Bundle.ACTIVE : Bundle.INSTALLED);
+            return st;
+        }
+        finally {
+            try
+            {
+                in.close();
+            }
+            catch (IOException e)
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static BundleForm create(URL formURL) throws IOException, URISyntaxException {
         InputStream in = formURL.openStream();
         try {
             BundleForm f = new BundleForm();
             BufferedReader r = new BufferedReader(new InputStreamReader(in));
-            LinkedList<String> locs = new LinkedList<String>();
+            LinkedList<URI> locs = new LinkedList<URI>();
             for(;;) {
                 String l = r.readLine();
                 if ( l == null ) break;
-                URI uri = URI.create(l);
-                String status = uri.getScheme();
-                uri = URI.create(uri.getSchemeSpecificPart());
-                String loc = uri.toString();
-                locs.add( loc );
-                f.setStarted(loc, "start".equalsIgnoreCase(status) );
+                l = l.trim();
+                if ( !l.startsWith( "#" ) ) {
+                    URI uri = URI.create(l);
+                    String status = uri.getScheme();
+                    uri = URI.create(uri.getSchemeSpecificPart());
+                    locs.add( uri );
+                    f.setStarted(uri, "start".equalsIgnoreCase(status) );
+                }
             }
-            f.setBundles(locs.toArray(new String[locs.size()]));
+            f.setBundles(locs.toArray(new URI[locs.size()]));
             return f;
         }
         finally {
@@ -139,59 +218,26 @@
         }
     }
 
-    public void setBundles(String[] bundles) {
+    public void setBundles(URI[] bundles) {
         this.bundles = bundles;
     }
     
-    public String[] getBundles()
+    public URI[] getBundles()
     {
         return bundles;
     }
 
-    public boolean isStarted(String url)
+    public boolean isStarted(URI uri)
     {
-        return startMap.contains(url);
+        return startMap.contains(uri);
     }
     
-    public void setStarted(String url, boolean started) {
+    public void setStarted(URI uri, boolean started) {
         if ( started ) {
-            startMap.add(url);
+            startMap.add(uri);
         }
         else {
-            startMap.remove(url);
+            startMap.remove(uri);
         }
-    }
-    
-    public BundleStatus[] toStatus() throws IOException  {
-        ArrayList<BundleStatus> ret = new ArrayList<BundleStatus>(bundles.length);
-        for ( String loc : bundles ) {
-            URL url = new URL(loc);
-            InputStream in = url.openStream();
-            try {
-                JarInputStream jin = new JarInputStream(in);
-                Manifest mf = jin.getManifest();
-                Attributes attr = mf.getMainAttributes();
-                String bsn = attr.getValue(Constants.BUNDLE_SYMBOLICNAME);
-                String ver = attr.getValue(Constants.BUNDLE_VERSION);
-                BundleStatus st = new BundleStatus();
-                st.setBundleSymbolicName(bsn);
-                st.setVersion(ver);
-                st.setLocation(loc);
-                st.setStatus(isStarted(loc) ? Bundle.ACTIVE : Bundle.INSTALLED);
-                ret.add(st);
-            }
-            finally {
-                try
-                {
-                    in.close();
-                }
-                catch (IOException e)
-                {
-                    // TODO Auto-generated catch block
-                    e.printStackTrace();
-                }
-            }
-        }
-        return ret.toArray(new BundleStatus[ret.size()] );
-    }
+    }    
 }
diff --git a/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java b/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java
index 807b783..8f9daa3 100644
--- a/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java
+++ b/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java
@@ -92,9 +92,7 @@
         out = null;
     }
 
-    public void apply(BundleForm form) throws IOException, BundleException {
-        BundleStatus[] newStatus = form.toStatus();
-
+    public void apply(BundleForm.BundleStatus[] newStatus) throws IOException, BundleException {
         BundleStatus[] currentStatus = status();
         
         stopOldBundles(currentStatus, newStatus);
diff --git a/sigil/eclipse/runtime/sigil.properties b/sigil/eclipse/runtime/sigil.properties
index 714009d..9d2d8c2 100644
--- a/sigil/eclipse/runtime/sigil.properties
+++ b/sigil/eclipse/runtime/sigil.properties
@@ -7,17 +7,22 @@
 	org.apache.felix.sigil.eclipse.runtime, \
 
 -resources: \
-	icons=icons, \
+	icons, \
 	plugin.xml, \
 
 -sourcedirs: \
 	src, \
 
 -imports: \
+	org.apache.felix.sigil.common.osgi;version=0.9.0, \
 	org.apache.felix.sigil.common.runtime, \
 	org.apache.felix.sigil.eclipse, \
 	org.apache.felix.sigil.eclipse.install, \
 	org.apache.felix.sigil.eclipse.model.project;version=0.9.0, \
+	org.apache.felix.sigil.model;version=0.9.0, \
+	org.apache.felix.sigil.model.eclipse;version=0.9.0, \
+	org.apache.felix.sigil.model.osgi;version=0.9.0, \
+	org.apache.felix.sigil.repository;version=0.9.0, \
 	org.apache.felix.sigil.ui.eclipse.ui, \
 	org.apache.felix.sigil.ui.eclipse.ui.util, \
 	org.eclipse.core.commands.common;resolve=compile, \
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/LaunchHelper.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/LaunchHelper.java
index a02902c..7250bba 100644
--- a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/LaunchHelper.java
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/LaunchHelper.java
@@ -19,10 +19,19 @@
 
 package org.apache.felix.sigil.eclipse.runtime;
 
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.Properties;
 
+import org.apache.felix.sigil.common.runtime.BundleForm;
 import org.apache.felix.sigil.common.runtime.Runtime;
+import org.apache.felix.sigil.eclipse.SigilCore;
 import org.apache.felix.sigil.eclipse.install.IOSGiInstall;
+import org.apache.felix.sigil.eclipse.runtime.config.OSGiLaunchConfigurationConstants;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.debug.core.ILaunchConfiguration;
 
 public class LaunchHelper {
@@ -53,4 +62,45 @@
     {
         return 1000;
     }
+    
+    public static URL toURL(String loc) throws MalformedURLException
+    {
+        URL url = null;
+        try
+        {
+            url = new URL(loc);
+        }
+        catch (MalformedURLException e)
+        {
+            IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(loc));
+            if ( f.exists() ) {
+                url = f.getLocation().toFile().toURL();
+            }
+            else {
+                throw new MalformedURLException("Unknown file " + loc );
+            }
+        }
+        return url;
+    }
+
+    public static BundleForm getBundleForm(ILaunchConfiguration config) throws CoreException
+    {
+        String loc = config.getAttribute(OSGiLaunchConfigurationConstants.FORM_FILE_LOCATION, (String) null);
+        try
+        {
+            URL url = toURL(loc);
+            SigilCore.log("Resolving " + url);
+            return BundleForm.create(url);
+        }
+        catch (Exception e)
+        {
+            throw SigilCore.newCoreException("Failed to parse bundle form file", e);
+        }
+    }
+
+    public static String getRepositoryManagerName(ILaunchConfiguration config)
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/OSGiLauncher.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/OSGiLauncher.java
index aa38e60..cab1f2f 100644
--- a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/OSGiLauncher.java
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/OSGiLauncher.java
@@ -21,6 +21,7 @@
 
 
 import java.io.IOException;
+
 import java.net.ConnectException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -31,7 +32,7 @@
 import org.apache.felix.sigil.common.runtime.Main;
 import org.apache.felix.sigil.eclipse.SigilCore;
 import org.apache.felix.sigil.eclipse.install.IOSGiInstall;
-import org.apache.felix.sigil.eclipse.runtime.config.OSGiLaunchConfigurationHelper;
+import org.apache.felix.sigil.repository.IRepositoryManager;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -43,7 +44,6 @@
 import org.eclipse.jdt.launching.IVMInstall;
 import org.eclipse.jdt.launching.IVMRunner;
 import org.eclipse.jdt.launching.VMRunnerConfiguration;
-import org.osgi.framework.BundleException;
 
 
 public class OSGiLauncher extends AbstractJavaLaunchConfigurationDelegate implements ILaunchConfigurationDelegate,
@@ -85,11 +85,13 @@
 
         Client client = connect( config );
         
-        BundleForm form = OSGiLaunchConfigurationHelper.getBundleForm(config);
+        BundleForm form = LaunchHelper.getBundleForm(config);
         
         try
         {
-            client.apply(form);
+            String name = LaunchHelper.getRepositoryManagerName(config);
+            IRepositoryManager manager = SigilCore.getRepositoryManager(name);
+            client.apply(form.resolve(new RuntimeBundleResolver(manager)));
         }
         catch (Exception e)
         {
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/RuntimeBundleResolver.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/RuntimeBundleResolver.java
new file mode 100644
index 0000000..8c4416d
--- /dev/null
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/RuntimeBundleResolver.java
@@ -0,0 +1,98 @@
+package org.apache.felix.sigil.eclipse.runtime;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+
+import org.apache.felix.sigil.common.osgi.VersionRange;
+import org.apache.felix.sigil.common.runtime.BundleForm.ResolutionContext;
+import org.apache.felix.sigil.common.runtime.BundleForm.Resolver;
+import org.apache.felix.sigil.eclipse.SigilCore;
+import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
+import org.apache.felix.sigil.model.ModelElementFactory;
+import org.apache.felix.sigil.model.eclipse.ISigilBundle;
+import org.apache.felix.sigil.model.osgi.IRequiredBundle;
+import org.apache.felix.sigil.repository.IBundleResolver;
+import org.apache.felix.sigil.repository.IRepositoryManager;
+import org.apache.felix.sigil.repository.IResolution;
+import org.apache.felix.sigil.repository.ResolutionConfig;
+import org.apache.felix.sigil.repository.ResolutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.osgi.framework.Version;
+
+public class RuntimeBundleResolver implements ResolutionContext
+{
+
+    public class SigilBundleResolver implements Resolver
+    {
+        public URI[] resolve(URI base) throws URISyntaxException
+        {
+            ArrayList<URI> uris = new ArrayList<URI>(1);
+            
+            IBundleResolver resolver = manager.getBundleResolver();
+            IRequiredBundle element = ModelElementFactory.getInstance().newModelElement(IRequiredBundle.class);
+            String[] parts = base.getSchemeSpecificPart().split(":");
+            switch( parts.length ) {
+                case 2:
+                    Version v = Version.parseVersion(parts[1]);
+                    element.setVersions(new VersionRange(false, v, v, false));
+                    // fall through on purpose
+                case 1:
+                    element.setSymbolicName(parts[0]);
+                    break;
+                default:
+                    throw new URISyntaxException(base.toString(), "Unexpected number of parts: " + parts.length);
+            }
+            try
+            {
+                ResolutionConfig config = new ResolutionConfig(ResolutionConfig.IGNORE_ERRORS);
+                IResolution resolution = resolver.resolve(element, config, null);
+                if ( resolution.getBundles().isEmpty() ) {
+                    SigilCore.error( "Failed to resolve bundle for " + base );
+                }
+                for ( ISigilBundle b : resolution.getBundles() ) {
+                    ISigilProjectModel p = b.getAncestor(ISigilProjectModel.class);
+                    if ( p != null ) {
+                        uris.add(p.findBundleLocation().toFile().toURI());
+                    }
+                    else {
+                        b.synchronize(null);
+                        uris.add( b.getLocation().toFile().toURI() );
+                    }
+                }
+            }
+            catch (ResolutionException e)
+            {
+                SigilCore.error("Failed to resolve " + base, e);
+            }
+            catch (IOException e)
+            {
+                SigilCore.error("Failed to synchronize " + base, e);
+            }
+            catch (CoreException e)
+            {
+                SigilCore.error("Failed to access " + base, e);
+            }
+            SigilCore.log( "Resolved " + uris );
+            return uris.toArray(new URI[uris.size()]);
+        }
+    }
+    
+    private final IRepositoryManager manager;
+    
+    public RuntimeBundleResolver(IRepositoryManager manager) {
+        this.manager = manager;
+    }
+
+    public Resolver findResolver(URI uri)
+    {
+        SigilCore.log( "Finding resolver for " + uri.getScheme() );
+        if ( "sigil".equals( uri.getScheme() ) ) {
+            SigilCore.log( "Found resolver for " + uri.getScheme() );
+            return new SigilBundleResolver();
+        }
+        return null;
+    }
+    
+}
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationHelper.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationHelper.java
deleted file mode 100644
index 8eb658e..0000000
--- a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationHelper.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.apache.felix.sigil.eclipse.runtime.config;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-import org.apache.felix.sigil.common.runtime.BundleForm;
-import org.apache.felix.sigil.eclipse.SigilCore;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.debug.core.ILaunchConfiguration;
-
-public class OSGiLaunchConfigurationHelper
-{
-
-    public static URL toURL(String loc) throws MalformedURLException
-    {
-        URL url = null;
-        try
-        {
-            url = new URL(loc);
-        }
-        catch (MalformedURLException e)
-        {
-            IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(loc));
-            if ( f.exists() ) {
-                url = f.getLocation().toFile().toURL();
-            }
-            else {
-                throw new MalformedURLException("Unknown file " + loc );
-            }
-        }
-        return url;
-    }
-
-    public static BundleForm getBundleForm(ILaunchConfiguration config) throws CoreException
-    {
-        String loc = config.getAttribute(OSGiLaunchConfigurationConstants.FORM_FILE_LOCATION, (String) null);
-        try
-        {
-            URL url = OSGiLaunchConfigurationHelper.toURL(loc);
-            SigilCore.log("Resolving " + url);
-            return BundleForm.resolve(url);
-        }
-        catch (Exception e)
-        {
-            throw SigilCore.newCoreException("Failed to parse bundle form file", e);
-        }
-    }
-
-}
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationTab.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationTab.java
index f44497a..bfc27e8 100644
--- a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationTab.java
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationTab.java
@@ -24,6 +24,7 @@
 
 import org.apache.felix.sigil.common.runtime.BundleForm;
 import org.apache.felix.sigil.eclipse.SigilCore;
+import org.apache.felix.sigil.eclipse.runtime.LaunchHelper;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
@@ -110,9 +111,9 @@
         if ( loc.trim().length() > 0 ) {
             try
             {
-                URL url = OSGiLaunchConfigurationHelper.toURL(loc);
+                URL url = LaunchHelper.toURL(loc);
                 SigilCore.log("Resolving " + url);
-                BundleForm.resolve(url);
+                BundleForm.create(url);
                 setErrorMessage(null);
                 setDirty(true);
             }