Work on FELIX-1324, now able to boot osgi applications using trivial file format:

install:http://somewhere.org/foo.jar
start:file:/tmp/bar.jar

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@830903 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Main.java b/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Main.java
index b0edd2f..e0a1362 100644
--- a/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Main.java
+++ b/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Main.java
@@ -49,6 +49,8 @@
 
     private static Framework framework;
     private static final Options options;
+    
+    private static boolean verbose = false;
 
     static
     {
@@ -58,6 +60,7 @@
         options.addOption( "a", "address", true, "Address to bind server to [default all]" );
         options.addOption( "c", "clean", false, "Clean bundle cache directory on init" );
         options.addOption( "s", "startLevel", true, "Start level for framework" );
+        options.addOption( "v", "verbose", false, "Verbose output" );
     }
 
 
@@ -76,6 +79,8 @@
             }
             else
             {
+                verbose = cl.hasOption('v');
+                
                 Map<String, String> config = buildConfig( cl );
 
                 framework = factory.newFramework( config );
@@ -188,6 +193,7 @@
     }
     
     public static void log(String msg) {
-        System.out.println( msg );
+        if ( verbose )
+            System.out.println( msg );
     }
 }
diff --git a/sigil/eclipse/runtime/icons/logo16x16.gif b/sigil/eclipse/runtime/icons/logo16x16.gif
new file mode 100644
index 0000000..0c344d8
--- /dev/null
+++ b/sigil/eclipse/runtime/icons/logo16x16.gif
Binary files differ
diff --git a/sigil/eclipse/runtime/plugin.xml b/sigil/eclipse/runtime/plugin.xml
index 49d9878..c1b4a27 100644
--- a/sigil/eclipse/runtime/plugin.xml
+++ b/sigil/eclipse/runtime/plugin.xml
@@ -40,8 +40,8 @@
          point="org.eclipse.debug.ui.launchShortcuts">
       <shortcut
             class="org.apache.felix.sigil.eclipse.runtime.shortcut.OSGiLaunchShortCut"
-            icon="etc/images/newton.png"
-            id="org.cauldron.sigil.launching.shortcut"
+            icon="/icons/logo16x16.gif"
+            id="org.apache.felix.sigil.eclipse.runtime.shortcut"
             label="OSGi Application"
             modes="run,debug">
          <contextualLaunch>
@@ -64,14 +64,14 @@
    <extension
          point="org.eclipse.jdt.launching.classpathProviders">
       <classpathProvider
-            class="org.cauldron.sigil.runtime.launch.NewtonSourcePathProvider"
-            id="org.cauldron.sigil.classpath.Provider"/>
+            class="org.apache.felix.sigil.eclipse.runtime.source.SigilSourcePathProvider"
+            id="org.apache.felix.sigil.classpath.Provider"/>
    </extension>
    <extension
          point="org.eclipse.debug.ui.launchConfigurationTypeImages">
       <launchConfigurationTypeImage
             configTypeID="org.apache.felix.sigil.eclipse.runtime.OSGi"
-            icon="etc/images/newton.png"
+            icon="icons/logo16x16.gif"
             id="org.apache.felix.sigil.eclipse.runtime.OSGi">
       </launchConfigurationTypeImage>
    </extension>
diff --git a/sigil/eclipse/runtime/sigil.properties b/sigil/eclipse/runtime/sigil.properties
index 45f2b4d..714009d 100644
--- a/sigil/eclipse/runtime/sigil.properties
+++ b/sigil/eclipse/runtime/sigil.properties
@@ -7,6 +7,7 @@
 	org.apache.felix.sigil.eclipse.runtime, \
 
 -resources: \
+	icons=icons, \
 	plugin.xml, \
 
 -sourcedirs: \
@@ -16,17 +17,18 @@
 	org.apache.felix.sigil.common.runtime, \
 	org.apache.felix.sigil.eclipse, \
 	org.apache.felix.sigil.eclipse.install, \
-	org.apache.felix.sigil.model, \
-	org.apache.felix.sigil.model.eclipse, \
-	org.apache.felix.sigil.model.osgi, \
-	org.apache.felix.sigil.repository, \
+	org.apache.felix.sigil.eclipse.model.project;version=0.9.0, \
 	org.apache.felix.sigil.ui.eclipse.ui, \
 	org.apache.felix.sigil.ui.eclipse.ui.util, \
-	org.apache.felix.sigil.utils, \
+	org.eclipse.core.commands.common;resolve=compile, \
 	org.eclipse.core.resources, \
+	org.eclipse.core.runtime, \
+	org.eclipse.jdt.core, \
 	org.eclipse.jdt.debug.ui.launchConfigurations, \
-	org.eclipse.jface.fieldassist, \
+	org.eclipse.jface.dialogs, \
 	org.eclipse.jface.viewers, \
+	org.eclipse.jface.window, \
+	org.eclipse.swt.widgets, \
 	org.osgi.framework, \
 
 -requires: \
@@ -37,6 +39,9 @@
 	org.eclipse.equinox.common;version=3.4.0, \
 	org.eclipse.jdt.launching;version=3.4.1, \
 	org.eclipse.swt;version=3.4.2, \
+	org.eclipse.ui.ide;version=3.4.2, \
 	org.eclipse.ui.workbench;version=3.4.2, \
 
+option;addMissingImports: false
+
 # end
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 7b8b98c..aa38e60 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
@@ -26,10 +26,12 @@
 import java.util.Arrays;
 import java.util.Properties;
 
+import org.apache.felix.sigil.common.runtime.BundleForm;
 import org.apache.felix.sigil.common.runtime.Client;
 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.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -41,6 +43,7 @@
 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,
@@ -81,6 +84,17 @@
         runner.run( vmconfig, launch, monitor );
 
         Client client = connect( config );
+        
+        BundleForm form = OSGiLaunchConfigurationHelper.getBundleForm(config);
+        
+        try
+        {
+            client.apply(form);
+        }
+        catch (Exception e)
+        {
+            throw SigilCore.newCoreException("Failed to apply bundle form", e);
+        }
 
         SigilCore.log( "Connected " + client.isConnected() );
     }
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/FilteredModelView.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/FilteredModelView.java
index de377b1..3432380 100644
--- a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/FilteredModelView.java
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/FilteredModelView.java
@@ -39,7 +39,6 @@
     private StructuredViewer viewer;
     private String txt = "";
 
-
     public FilteredModelView( Composite parent, int style )
     {
         super( parent, style );
@@ -95,10 +94,6 @@
         });
     }
 
-    public void addChangeListener( IChangeListener listener ) {
-        
-    }
-    
     private void initLayout()
     {
         Text bundleTxt = createSelectionBox( this );
@@ -133,7 +128,6 @@
                 else
                 {
                     IStructuredSelection sel = ( IStructuredSelection ) event.getSelection();
-                    System.out.println( "Selected " + sel.toList() );
                     selected.addAll( sel.toList() );
                 }
             }
@@ -239,6 +233,10 @@
         }
         this.elementDescriptor = elementDescriptor;
     }
+    
+    public IElementDescriptor<T> getElementDescriptor() {
+        return elementDescriptor;
+    }
 
 
     public void setFilter( IFilter<T> filter )
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/FormSelectionDialog.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/FormSelectionDialog.java
new file mode 100644
index 0000000..d1ac51f
--- /dev/null
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/FormSelectionDialog.java
@@ -0,0 +1,84 @@
+package org.apache.felix.sigil.eclipse.runtime.config;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.model.BaseWorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+public class FormSelectionDialog extends Dialog
+{
+    private IFile formFile;
+    
+    public FormSelectionDialog(Shell parent)
+    {
+        super(parent);
+    }
+
+    @Override
+    protected Control createDialogArea(Composite parent)
+    {
+        Composite composite = (Composite) super.createDialogArea(parent);
+        new Label(composite, SWT.NONE).setText("Select bundle form file from workspace:");
+        Tree tree = new Tree(composite, SWT.SINGLE);
+
+        TreeViewer viewer = new TreeViewer(tree);
+        viewer.setContentProvider(new BaseWorkbenchContentProvider());
+        viewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
+        viewer.addSelectionChangedListener(new ISelectionChangedListener()
+        {        
+            public void selectionChanged(SelectionChangedEvent evt)
+            {
+                if (evt.getSelection().isEmpty()) {
+                    updateFile(null);
+                }
+                else {
+                    StructuredSelection sel = (StructuredSelection) evt.getSelection();
+                    IResource r = (IResource) sel.getFirstElement();
+                    if ( r instanceof IFile ) {
+                        IFile f = (IFile) r;
+                        updateFile(f);
+                    }
+                    else {
+                        updateFile(null);
+                    }
+                }
+            }
+        });
+        viewer.setLabelProvider(new WorkbenchLabelProvider());
+        
+        tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+        
+        return composite;
+    }
+    
+    public IFile getFormFile() {
+        return formFile;
+    }
+
+    protected void updateFile(IFile file)
+    {
+        formFile = file;
+        
+        if ( file == null ) {
+            getButton(Window.OK).setEnabled(false);            
+        }
+        else {
+            getButton(Window.OK).setEnabled(true);            
+        }
+    }
+
+}
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/IChangeListener.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/IChangeListener.java
deleted file mode 100644
index 7d23203..0000000
--- a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/IChangeListener.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.apache.felix.sigil.eclipse.runtime.config;
-
-public interface IChangeListener
-{
-
-}
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiConfigurationView.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiConfigurationView.java
deleted file mode 100644
index 19edfbc..0000000
--- a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiConfigurationView.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.felix.sigil.eclipse.runtime.config;
-
-
-import org.apache.felix.sigil.eclipse.SigilCore;
-import org.apache.felix.sigil.model.IModelElement;
-import org.apache.felix.sigil.model.IModelWalker;
-import org.apache.felix.sigil.model.eclipse.ISigilBundle;
-import org.apache.felix.sigil.ui.eclipse.ui.util.IElementDescriptor;
-import org.apache.felix.sigil.ui.eclipse.ui.util.IFilter;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-
-
-/**
- * @author dave
- *
- */
-public class OSGiConfigurationView extends Composite
-{
-    private Job job;
-    private FilteredModelView<ISigilBundle> available;
-    private FilteredModelView<ISigilBundle> selected;
-
-    /**
-     * @param parent
-     * @param osGiLaunchConfigurationTab
-     */
-    public OSGiConfigurationView( Composite parent, OSGiLaunchConfigurationTab osGiLaunchConfigurationTab )
-    {
-        super( parent, SWT.NONE );
-        initLayout();
-    }
-
-
-    @Override
-    public void dispose()
-    {
-        if ( job != null ) {
-            job.cancel();
-        }
-        
-        super.dispose();
-    }
-
-
-    /**
-     * 
-     */
-    private void initLayout()
-    {
-        // components
-        Composite left = new Composite( this, SWT.NONE );
-        Composite middle = new Composite(this, SWT.NONE);
-        Composite right = new Composite(this, SWT.NONE);
-
-        available = new FilteredModelView<ISigilBundle>(left, SWT.NONE);
-        selected = new FilteredModelView<ISigilBundle>(right, SWT.NONE);
-        
-        Button addBtn = new Button( middle, SWT.PUSH );
-        addBtn.setText( "->" );
-        Button removeBtn = new Button( middle, SWT.PUSH );
-        removeBtn.setText( "<-" );
-        
-        // customisations
-        addBtn.addSelectionListener( new SelectionAdapter()
-        {
-            @Override
-            public void widgetSelected( SelectionEvent e )
-            {
-                handleAdd();
-            }
-        } );
-        
-        removeBtn.addSelectionListener( new SelectionAdapter()
-        {
-            @Override
-            public void widgetSelected( SelectionEvent e )
-            {
-                handleRemove();
-            }
-        } );
-        
-        IElementDescriptor<ISigilBundle> descriptor = new IElementDescriptor<ISigilBundle>()
-        {
-            public String getLabel( ISigilBundle element )
-            {
-                return element.getSymbolicName() + " version " + element.getVersion();
-            }
-
-
-            public String getName( ISigilBundle element )
-            {
-                return element.getSymbolicName();
-            }
-        };
-        
-        available.setElementDescriptor( descriptor );
-        selected.setElementDescriptor( descriptor );
-        
-        available.setFilter( new IFilter<ISigilBundle>() {
-            public boolean select( ISigilBundle element )
-            {
-                return !selected.getElements().contains( element );
-            }
-        } );
-        
-        // layout
-        available.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
-        selected.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
-        
-        left.setLayout( new GridLayout( 1, false ) );
-        middle.setLayout( new GridLayout( 1, false ) );
-        right.setLayout( new GridLayout( 1, false ) );
-
-        left.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
-        middle.setLayoutData( new GridData( SWT.FILL, SWT.FILL, false, true ) );
-        right.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
-        
-        setLayout( new GridLayout( 3, false ) );
-        
-        startSearch(available);
-    }
-
-    private void startSearch(final FilteredModelView<ISigilBundle> view) {
-        job = new Job( "Finding bundles" )
-        {
-            @Override
-            protected IStatus run( final IProgressMonitor monitor )
-            {
-                SigilCore.getGlobalRepositoryManager().visit( new IModelWalker()
-                {
-                    public boolean visit( IModelElement element )
-                    {
-                        if ( element instanceof ISigilBundle )
-                        {
-                            ISigilBundle sb = ( ISigilBundle ) element;
-                            
-                            view.addElement( sb );
-                            
-                            return false;
-                        }
-                        else
-                        {
-                            return !monitor.isCanceled();
-                        }
-                    }
-                } );
-
-                return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
-            }
-        };
-        job.schedule();
-    }
-
-
-    private void handleAdd()
-    {
-        selected.addElements( available.getSelectedElements() );
-        available.refresh();
-    }
-
-    private void handleRemove()
-    {
-        selected.removeElements( selected.getSelectedElements() );
-        available.refresh();
-    }
-
-
-}
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationConstants.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationConstants.java
new file mode 100644
index 0000000..b39a713
--- /dev/null
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationConstants.java
@@ -0,0 +1,9 @@
+package org.apache.felix.sigil.eclipse.runtime.config;
+
+public interface OSGiLaunchConfigurationConstants
+{
+
+    String FORM_FILE_LOCATION = "org.apache.felix.sigil.form.location";
+    String AUTOMATIC_ADD = "org.apache.felix.sigil.automatic.add";
+
+}
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
new file mode 100644
index 0000000..8eb658e
--- /dev/null
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/config/OSGiLaunchConfigurationHelper.java
@@ -0,0 +1,54 @@
+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 abff591..f44497a 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
@@ -19,10 +19,27 @@
 
 package org.apache.felix.sigil.eclipse.runtime.config;
 
+import java.net.URL;
+
+
+import org.apache.felix.sigil.common.runtime.BundleForm;
+import org.apache.felix.sigil.eclipse.SigilCore;
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
 import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
 
 /**
  * @author dave
@@ -31,7 +48,8 @@
 public class OSGiLaunchConfigurationTab extends AbstractLaunchConfigurationTab
 {
 
-    private OSGiConfigurationView configurationView;
+    private Text formText;
+    private String formLocation;
 
     /* (non-Javadoc)
      * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
@@ -46,17 +64,84 @@
      */
     public void createControl( Composite parent )
     {
-        configurationView = new OSGiConfigurationView(parent, this);
+        Composite configurationView = new Composite(parent, SWT.NONE);
+        new Label(configurationView, SWT.NONE).setText("Form");
+
+        // components
+        formText = new Text(configurationView, SWT.BORDER);
+
+        // layout
+        formText.setLayoutData( new GridData( SWT.FILL, SWT.CENTER, true, false ) );
+        
+        formText.addKeyListener(new KeyAdapter()
+        {
+            @Override
+            public void keyReleased(KeyEvent e)
+            {
+                updateLocation();
+            }
+        });
+        
+        Button browse = new Button(configurationView, SWT.PUSH);
+        browse.setText("Browse");
+        
+        browse.addSelectionListener( new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                FormSelectionDialog dialog =
+                    new FormSelectionDialog(getShell());
+                if ( dialog.open() == Window.OK ) {
+                    formLocation = dialog.getFormFile().getFullPath().toOSString();
+                    formText.setText(formLocation);
+                    updateLocation();
+                }
+            }
+        });
+        
+        
+        configurationView.setLayout( new GridLayout( 3, false ) );
+
         setControl(configurationView);
     }
 
+    private void updateLocation()
+    {
+        String loc = formText.getText();
+        if ( loc.trim().length() > 0 ) {
+            try
+            {
+                URL url = OSGiLaunchConfigurationHelper.toURL(loc);
+                SigilCore.log("Resolving " + url);
+                BundleForm.resolve(url);
+                setErrorMessage(null);
+                setDirty(true);
+            }
+            catch (Exception e)
+            {
+                SigilCore.warn("Failed to resolve bundle form", e);
+                setErrorMessage("Invalid form file " + e.getMessage() );
+            }
+        }
+        else {
+            setErrorMessage("Missing form file");
+        }
+        updateLaunchConfigurationDialog();
+    }
+
     /* (non-Javadoc)
      * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
      */
     public void initializeFrom( ILaunchConfiguration config )
     {
-        // TODO Auto-generated method stub
-        
+        try
+        {
+            formLocation = config.getAttribute(OSGiLaunchConfigurationConstants.FORM_FILE_LOCATION, "");
+            formText.setText(formLocation);
+        }
+        catch (CoreException e)
+        {
+            SigilCore.error("Failed to initialise launch configuration view", e);
+        }
     }
 
     /* (non-Javadoc)
@@ -64,8 +149,7 @@
      */
     public void performApply( ILaunchConfigurationWorkingCopy config )
     {
-        // TODO Auto-generated method stub
-        
+        config.setAttribute(OSGiLaunchConfigurationConstants.FORM_FILE_LOCATION, formLocation);
     }
 
     /* (non-Javadoc)
@@ -73,8 +157,6 @@
      */
     public void setDefaults( ILaunchConfigurationWorkingCopy config )
     {
-        // TODO Auto-generated method stub
-        
+        config.setAttribute(OSGiLaunchConfigurationConstants.FORM_FILE_LOCATION, (String) null);
     }
-
 }
diff --git a/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/source/SigilSourcePathProvider.java b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/source/SigilSourcePathProvider.java
new file mode 100644
index 0000000..63ddf0a
--- /dev/null
+++ b/sigil/eclipse/runtime/src/org/apache/felix/sigil/eclipse/runtime/source/SigilSourcePathProvider.java
@@ -0,0 +1,150 @@
+package org.apache.felix.sigil.eclipse.runtime.source;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.felix.sigil.eclipse.SigilCore;
+import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
+import org.apache.felix.sigil.eclipse.runtime.config.OSGiLaunchConfigurationConstants;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jdt.launching.StandardSourcePathProvider;
+
+public class SigilSourcePathProvider extends StandardSourcePathProvider
+{
+    private static HashMap<ILaunchConfiguration, Set<IRuntimeClasspathEntry>> dynamicRuntime = new HashMap<ILaunchConfiguration, Set<IRuntimeClasspathEntry>>();
+
+    public IRuntimeClasspathEntry[] resolveClasspath(IRuntimeClasspathEntry[] entries,
+        ILaunchConfiguration configuration) throws CoreException
+    {
+        ArrayList<IRuntimeClasspathEntry> all = new ArrayList<IRuntimeClasspathEntry>(entries.length);
+        
+        all.addAll( workbenchSourcePath(entries, configuration) );
+        all.addAll( launchOverridePath( configuration ) );
+//        all.addAll( newtonSourcePath( configuration ) );
+        Set<IRuntimeClasspathEntry> dynamic = dynamicRuntime.get( configuration );
+        if ( dynamic != null ) {
+            all.addAll( dynamic );
+        }
+        
+        return (IRuntimeClasspathEntry[]) all
+                .toArray(new IRuntimeClasspathEntry[all.size()]);
+    }
+
+    private List<IRuntimeClasspathEntry> workbenchSourcePath(IRuntimeClasspathEntry[] entries, ILaunchConfiguration configuration) throws CoreException {
+        return Arrays.asList( super.resolveClasspath(entries, configuration) );
+    }
+    
+    private Collection<IRuntimeClasspathEntry> launchOverridePath(ILaunchConfiguration configuration) throws CoreException {
+        ArrayList<IRuntimeClasspathEntry> overrides = new ArrayList<IRuntimeClasspathEntry>();
+        
+        if ( configuration.getAttribute( OSGiLaunchConfigurationConstants.AUTOMATIC_ADD, true) ) {
+            for ( ISigilProjectModel n : SigilCore.getRoot().getProjects() ) {
+                overrides.add( JavaRuntime.newProjectRuntimeClasspathEntry(n.getJavaModel()));
+            }           
+        }
+        
+        return overrides;
+    }
+
+    public static void addProjectSource(ILaunchConfiguration config, ISigilProjectModel project) {
+        Set<IRuntimeClasspathEntry> dynamic = dynamicRuntime.get( config );
+        
+        if ( dynamic == null ) {
+            dynamic = new HashSet<IRuntimeClasspathEntry>();
+            dynamicRuntime.put( config, dynamic );
+        }
+        
+        IJavaProject javaProject = project.getJavaModel();
+        IRuntimeClasspathEntry cp = JavaRuntime.newProjectRuntimeClasspathEntry(javaProject);
+        
+        dynamic.add( cp );
+    }    
+    
+//    private List<IRuntimeClasspathEntry> newtonSourcePath( ILaunchConfiguration configuration ) throws CoreException {
+//        List<IRuntimeClasspathEntry> all = new ArrayList<IRuntimeClasspathEntry>();
+//        
+////        Collection<IPath> jars = findNewtonJars( configuration );
+//        
+////        IPath source = findSourcePath( configuration );
+//        
+////        for ( IPath jar : jars ) {
+////            IRuntimeClasspathEntry cp = JavaRuntime.newArchiveRuntimeClasspathEntry(jar);
+////            
+////            if ( source != null ) {
+////                cp.setSourceAttachmentPath( source );
+////                cp.setSourceAttachmentRootPath( findSrcDir( source ) );
+////            }
+////            cp.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);
+////            
+////            all.add( cp );
+////        }
+//                
+//        return all;
+//    }
+    
+//    @SuppressWarnings("unchecked")
+//    private IPath findSrcDir( IPath sourceZip ) throws CoreException {
+//        ZipFile zip = null;
+//        
+//        IPath path = null;
+//        
+//        try {
+//            File file = sourceZip.toFile();
+//            if (file.exists() && file.isFile() ) {
+//                zip = new ZipFile(file);
+//                
+//                for ( Enumeration e = zip.entries(); e.hasMoreElements(); ) {
+//                    ZipEntry entry = (ZipEntry) e.nextElement();
+//                    if ( entry.getName().endsWith( "src/" ) ); {
+//                        path = new Path( entry.getName() );
+//                        break;
+//                    }
+//                }
+//            } // else return null;
+//        }
+//        catch (ZipException e) {
+//            throw SigilCore.newCoreException("Failed to open source zip:" + sourceZip.toFile(), e);
+//        }
+//        catch (IOException e) {
+//            throw SigilCore.newCoreException("Failed to open source zip" + sourceZip.toFile(), e);
+//        }
+//        finally {
+//            if ( zip != null ) {
+//                try {
+//                    zip.close();
+//                }
+//                catch (IOException e) {
+//                    SigilCore.error( "Failed to close src zip", e);
+//                }
+//            }
+//        }
+//        
+//        return path;
+//    }
+    
+//    private Collection<IPath> findNewtonJars( ILaunchConfiguration configuration ) throws CoreException {
+//        ArrayList<IPath> paths = new ArrayList<IPath>();
+//        
+//        INewtonInstall install = NewtonLaunchConfigurationHelper.getNewtonInstall(configuration);
+//        
+//        for ( IPath path : install.getType().getDefaultBundleLocations() ) {
+//            paths.add(path);
+//        }
+//        
+//        return paths;
+//    }       
+    
+//    private IPath findSourcePath( ILaunchConfiguration configuration ) throws CoreException {
+//        INewtonInstall install = NewtonLaunchConfigurationHelper.getNewtonInstall(configuration);
+//        return install.getType().getSourceLocation();
+//    }    
+}