Patch to address ui/classpath consistency issues when adding and removing projects from workspace that provide dependencies (related to FELIX-1349)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@919635 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/SigilCore.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/SigilCore.java
index 95a2d40..b2b3fa8 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/SigilCore.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/SigilCore.java
@@ -278,6 +278,7 @@
         installs = new OSGiInstallManager();
 
         globalRepositoryManager = new GlobalRepositoryManager();
+        globalRepositoryManager.initialise();
         
         projectManager = new SigilProjectManager();
 
@@ -513,18 +514,19 @@
         Set<ISigilProjectModel> affected = SigilCore.getRoot().resolveDependentProjects( caps, monitor );
 
         if ( project != null ) {
-            affected.add( project );
+            affected.remove( project );
         }
 
         SubMonitor progress = SubMonitor.convert( monitor, affected.size() * 20 );
         for ( ISigilProjectModel dependent : affected )
         {
+            //dependent.flushDependencyState();
             rebuild( dependent, progress );
         }
     }
 
 
-    private static void rebuild( ISigilProjectModel dependent, SubMonitor progress )
+    public static void rebuild( ISigilProjectModel dependent, SubMonitor progress )
     {
         try
         {
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/model/project/SigilProject.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/model/project/SigilProject.java
index 737a183..2dbe8de 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/model/project/SigilProject.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/model/project/SigilProject.java
@@ -99,6 +99,8 @@
 
     private IEclipsePreferences preferences;
 
+    private List<IRequirementModelElement> lastReqs = new LinkedList<IRequirementModelElement>();
+    private List<ICapabilityModelElement> lastCaps = new LinkedList<ICapabilityModelElement>();
 
     public SigilProject()
     {
@@ -150,16 +152,23 @@
         
         if ( reqsChanged ) {
             processRequirementsChanges(progress.newChild(600));
+            SigilCore.rebuild(this, progress.newChild(50));
         }
         
-        progress.setWorkRemaining( 300 );
+        progress.setWorkRemaining( 250 );
 
         if ( capsChanged ) {
             changes.addAll(caps);
-            SigilCore.rebuildBundleDependencies( this, changes, progress.newChild( 300 ) );
+            SigilCore.rebuildBundleDependencies( this, changes, progress.newChild( 250 ) );
         }        
     }
     
+    public void flushDependencyState() {
+        synchronized(this) {
+            lastReqs.clear();
+        }
+    }
+    
     private void processRequirementsChanges(IProgressMonitor monitor) throws CoreException 
     {
         SubMonitor progress = SubMonitor.convert( monitor, 100 );
@@ -220,9 +229,6 @@
         }
     }
 
-    private List<IRequirementModelElement> lastReqs = new LinkedList<IRequirementModelElement>();
-    private List<ICapabilityModelElement> lastCaps = new LinkedList<ICapabilityModelElement>();
-            
     private void checkChanges(IProgressMonitor monitor, final List<IRequirementModelElement> reqs, final List<ICapabilityModelElement> caps)
     {
         visit(new IModelWalker()
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/SigilRepositoryManager.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/SigilRepositoryManager.java
index 0ce36d1..8a29575 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/SigilRepositoryManager.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/SigilRepositoryManager.java
@@ -103,7 +103,8 @@
         ArrayList<IBundleRepository> repos = new ArrayList<IBundleRepository>();
         HashSet<String> ids = new HashSet<String>();
 
-        for ( IRepositoryModel repo : findRepositories() )
+        IRepositoryModel[] models = findRepositories();
+        for ( IRepositoryModel repo : models )
         {
             try
             {
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/WorkspaceRepository.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/WorkspaceRepository.java
index 80df5df..2e95b44 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/WorkspaceRepository.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/WorkspaceRepository.java
@@ -39,7 +39,6 @@
 import org.eclipse.core.resources.IResourceDelta;
 import org.eclipse.core.resources.IResourceDeltaVisitor;
 import org.eclipse.core.resources.IResourceVisitor;
-import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Platform;
@@ -49,7 +48,9 @@
 public class WorkspaceRepository extends AbstractBundleRepository implements IResourceChangeListener
 {
 
-    private static final int UPDATE_MASK = IResourceDelta.CONTENT | IResourceDelta.DESCRIPTION | IResourceDelta.OPEN;
+    private static final int UPDATE_MASK = IResourceDelta.CONTENT | IResourceDelta.OPEN;
+    
+    static final int EVENT_MASKS = IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_REFRESH;
 
     public WorkspaceRepository( String id )
     {
@@ -147,6 +148,9 @@
         try
         {
             switch (event.getType()) {
+                case IResourceChangeEvent.PRE_DELETE:
+                    handleDelete(event);
+                    break;
                 case IResourceChangeEvent.PRE_REFRESH:
                     handleRefresh(event);
                     break;
@@ -161,6 +165,19 @@
         }
     }
 
+    private HashSet<IProject> deleted = new HashSet<IProject>();
+
+    private void handleDelete(IResourceChangeEvent event)
+    {
+        if ( event.getResource() instanceof IProject ) {
+            IProject project = (IProject) event.getResource();
+            if ( isSigilProject(project) )
+            {
+                deleted.add(project);
+            }
+        }
+    }
+
 
     private void handleRefresh(IResourceChangeEvent event)
     {
@@ -171,26 +188,25 @@
 
     private void handleChange(IResourceChangeEvent event) throws CoreException
     {
+        final boolean[] notify = new boolean[1];
+        
         event.getDelta().accept( new IResourceDeltaVisitor()
         {
             public boolean visit( IResourceDelta delta ) throws CoreException
             {
-                boolean result;
+                boolean checkMembers = true;
 
                 IResource resource = delta.getResource();
-                if ( resource instanceof IWorkspaceRoot )
-                {
-                    result = true;
-                }
-                else if ( resource instanceof IProject )
+                if ( resource instanceof IProject )
                 {
                     IProject project = ( IProject ) resource;
-                    if ( SigilCore.isSigilProject( project ) )
+                    if ( isSigilProject(project) )
                     {
                         switch ( delta.getKind() )
                         {
                             case IResourceDelta.CHANGED:
-                                if ( ( delta.getFlags() & UPDATE_MASK ) == 0 )
+                                int flag = delta.getFlags();
+                                if ( ( flag & UPDATE_MASK ) == 0 )
                                 {
                                     break;
                                 }
@@ -198,14 +214,14 @@
                                 // fall through on purpose
                             case IResourceDelta.ADDED: // fall through on purpose
                             case IResourceDelta.REMOVED: // fall through on purpose
-                                notifyChange();
+                                notify[0] = true;
                                 break;
                         }
-                        result = true;
+                        checkMembers = true;
                     }
                     else
                     {
-                        result = false;
+                        checkMembers = false;
                     }
                 }
                 else if ( resource.getName().equals( SigilCore.SIGIL_PROJECT_FILE ) )
@@ -215,17 +231,23 @@
                         case IResourceDelta.CHANGED:
                         case IResourceDelta.ADDED:
                         case IResourceDelta.REMOVED:
-                            notifyChange();
+                            notify[0] = true;
                     }
-                    result = false;
+                    checkMembers = false;
                 }
-                else
-                {
-                    result = false;
-                }
-                return result;
+                return checkMembers && !notify[0];
             }
         } );
+        
+        if (notify[0]) {
+            notifyChange();
+        }
+    }
+
+
+    private boolean isSigilProject(IProject project)
+    {
+        return SigilCore.isSigilProject( project ) || deleted.remove(project);
     }
 
 }
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/WorkspaceRepositoryProvider.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/WorkspaceRepositoryProvider.java
index 140fe5a..7b3be0d 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/WorkspaceRepositoryProvider.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/repository/eclipse/WorkspaceRepositoryProvider.java
@@ -24,7 +24,6 @@
 
 import org.apache.felix.sigil.repository.IBundleRepository;
 import org.apache.felix.sigil.repository.IRepositoryProvider;
-import org.eclipse.core.resources.IResourceChangeEvent;
 import org.eclipse.core.resources.ResourcesPlugin;
 
 
@@ -44,7 +43,7 @@
         if ( repository == null )
         {
             repository = new WorkspaceRepository( id );
-            ResourcesPlugin.getWorkspace().addResourceChangeListener( repository, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_REFRESH );
+            ResourcesPlugin.getWorkspace().addResourceChangeListener( repository, WorkspaceRepository.EVENT_MASKS );            
         }
         return repository;
     }
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/job/ResolveProjectsJob.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/job/ResolveProjectsJob.java
index dbd69fb..ee31d12 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/job/ResolveProjectsJob.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/job/ResolveProjectsJob.java
@@ -26,14 +26,14 @@
 import org.apache.felix.sigil.eclipse.SigilCore;
 import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
 import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.WorkspaceJob;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.MultiStatus;
-import org.eclipse.core.runtime.jobs.Job;
 
 
-public class ResolveProjectsJob extends Job
+public class ResolveProjectsJob extends WorkspaceJob
 {
     final Collection<ISigilProjectModel> sigilProjects;
     
@@ -54,14 +54,17 @@
 
 
     @Override
-    protected IStatus run( IProgressMonitor monitor )
+    public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException
     {
         MultiStatus status = new MultiStatus( SigilCore.PLUGIN_ID, 0, "Error resolving Sigil projects", null );
 
+        boolean flush = sigilProjects.size() > 0;
+        
         for ( ISigilProjectModel sigilProject : sigilProjects )
         {
             try
             {
+                if ( flush ) sigilProject.flushDependencyState();
                 sigilProject.rebuildDependencies(monitor);
             }
             catch ( CoreException e )
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/model/project/ISigilProjectModel.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/model/project/ISigilProjectModel.java
index 4b3445c..21638cb 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/model/project/ISigilProjectModel.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/model/project/ISigilProjectModel.java
@@ -83,6 +83,8 @@
     void save( IProgressMonitor monitor, boolean rebuildDependencies ) throws CoreException;
     
     void rebuildDependencies(IProgressMonitor monitor) throws CoreException;
+    
+    void flushDependencyState();
 
 
     /**
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/startup/SigilStartup.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/startup/SigilStartup.java
index a0e4d6d..7e0015a 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/startup/SigilStartup.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/startup/SigilStartup.java
@@ -34,28 +34,16 @@
 
     public void earlyStartup()
     {
-        // Create a task to run the resolver
-        final Runnable resolver = new Runnable()
+        // Register a repository change listener to re-run the resolver when repository changes
+        SigilCore.getGlobalRepositoryManager().addRepositoryChangeListener( new IRepositoryChangeListener()
         {
-            public void run()
+            public void repositoryChanged( RepositoryChangeEvent event )
             {
                 IWorkspace workspace = ResourcesPlugin.getWorkspace();
                 ResolveProjectsJob job = new ResolveProjectsJob( workspace );
                 job.setSystem( true );
                 job.schedule();
             }
-        };
-
-        // Register a repository change listener to re-run the resolver when repository changes
-        SigilCore.getGlobalRepositoryManager().addRepositoryChangeListener( new IRepositoryChangeListener()
-        {
-            public void repositoryChanged( RepositoryChangeEvent event )
-            {
-                resolver.run();
-            }
         } );
-
-        // Run the resolver now
-        resolver.run();
     }
 }
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/SigilProjectEditorPart.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/SigilProjectEditorPart.java
index 852574a..104363c 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/SigilProjectEditorPart.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/SigilProjectEditorPart.java
@@ -46,7 +46,6 @@
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.dialogs.ErrorDialog;
 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
 import org.eclipse.jface.operation.IRunnableWithProgress;
@@ -236,15 +235,30 @@
 
     public void resourceChanged( IResourceChangeEvent event )
     {
-        switch (event.getType()) {
-            case IResourceChangeEvent.PRE_REFRESH:
-                handleRefresh(event);
-                break;
-            case IResourceChangeEvent.POST_CHANGE:
-                handleChange(event);
-                break;
+        try
+        {
+            switch (event.getType()) {
+                case IResourceChangeEvent.PRE_REFRESH:
+                    handleRefresh(event);
+                    break;
+                case IResourceChangeEvent.POST_BUILD:
+                    handleBuild(event);
+                    break;
+                case IResourceChangeEvent.POST_CHANGE:
+                    handleChange(event);
+                    break;
+            }
         }
+        catch ( CoreException e )
+        {
+            ErrorDialog.openError( getSite().getShell(), "Error", null, e.getStatus() );
+        }
+    }
 
+
+    private void handleBuild(IResourceChangeEvent event) throws CoreException
+    {
+        refreshView();
     }
 
 
@@ -255,39 +269,32 @@
     }
 
 
-    private void handleChange(IResourceChangeEvent event)
+    private void handleChange(IResourceChangeEvent event) throws CoreException
     {
         IResourceDelta delta = event.getDelta();
         final IFile editorFile = ( ( IFileEditorInput ) getEditorInput() ).getFile();
-        try
+        delta.accept( new IResourceDeltaVisitor()
         {
-            delta.accept( new IResourceDeltaVisitor()
+            public boolean visit( IResourceDelta delta ) throws CoreException
             {
-                public boolean visit( IResourceDelta delta ) throws CoreException
+                int kind = delta.getKind();
+                IResource resource = delta.getResource();
+                if ( resource instanceof IProject )
                 {
-                    int kind = delta.getKind();
-                    IResource resource = delta.getResource();
-                    if ( resource instanceof IProject )
-                    {
-                        int flags = delta.getFlags();
-                        return handleProjectChange(editorFile, (IProject) resource, kind, flags);
-                    }
-
-                    if ( resource instanceof IFile )
-                    {
-                        handleFileChange(editorFile, (IFile) resource, kind);
-                        // Recurse no more
-                        return false;
-                    }
-
-                    return true;
+                    int flags = delta.getFlags();
+                    return handleProjectChange(editorFile, (IProject) resource, kind, flags);
                 }
-            } );
-        }
-        catch ( CoreException e )
-        {
-            ErrorDialog.openError( getSite().getShell(), "Error", null, e.getStatus() );
-        }
+
+                if ( resource instanceof IFile )
+                {
+                    handleFileChange(editorFile, (IFile) resource, kind);
+                    // Recurse no more
+                    return false;
+                }
+
+                return true;
+            }
+        } );
     }
 
 
@@ -324,15 +331,24 @@
         {
             return false;
         }
-        if ( kind == IResourceDelta.CHANGED && ( flags & IResourceDelta.MARKERS ) > 0 )
+        if ( kind == IResourceDelta.CHANGED )
         {
-            loadUnresolvedDependencies();
-            refreshAllPages();
+            int mask = flags & (IResourceDelta.MARKERS);
+            if ( mask > 0 ) {
+                refreshView();
+            }
         }
         return true;
     }
 
 
+    private void refreshView() throws CoreException
+    {
+        loadUnresolvedDependencies();
+        refreshAllPages();
+    }
+
+
     protected void refreshAllPages()
     {
         Runnable op = new Runnable()
@@ -370,14 +386,8 @@
         tempProject.setBundle(null);
         project.setBundle( null );
         refreshAllPages();
-        try
-        {
-            project.rebuildDependencies(Job.getJobManager().createProgressGroup());
-        }
-        catch (CoreException e)
-        {
-            SigilCore.error( "Failed to update depedencies " + this, e );
-        }
+        ResolveProjectsJob job = new ResolveProjectsJob(project);
+        job.schedule();        
     }
 
 
@@ -397,7 +407,7 @@
         }
 
         ResourcesPlugin.getWorkspace().addResourceChangeListener( this, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_REFRESH );
-
+                
         if ( input instanceof IFileEditorInput )
         {
             try