improve performance of resolver in workspaces with many sigil projects - prevent cyclical resolver tasks


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@963491 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/builders/SigilIncrementalProjectBuilder.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/builders/SigilIncrementalProjectBuilder.java
index d05be8f..9205692 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/builders/SigilIncrementalProjectBuilder.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/builders/SigilIncrementalProjectBuilder.java
@@ -44,6 +44,9 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 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.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaModelMarker;
 import org.eclipse.jdt.core.JavaCore;
@@ -56,7 +59,6 @@
 
 public class SigilIncrementalProjectBuilder extends IncrementalProjectBuilder
 {
-
     @Override
     protected IProject[] build( int kind, @SuppressWarnings("unchecked") Map args, IProgressMonitor monitor )
         throws CoreException
@@ -216,25 +218,34 @@
 
     private static void loginfo( String message )
     {
-        BuildConsole console = findConsole();
-        MessageConsoleStream stream = console.getMessageStream();
-        stream.println( "INFO: " + message );
+        log("INFO: " + message);
     }
 
-
     private static void logwarn( String message )
     {
-        BuildConsole console = findConsole();
-        MessageConsoleStream stream = console.getMessageStream();
-        stream.println( "WARN: " + message );
+        log( "WARN: " + message );
     }
 
 
     private static void logerror( String message )
     {
-        BuildConsole console = findConsole();
-        MessageConsoleStream stream = console.getMessageStream();
-        stream.println( "ERROR: " + message );
+        log( "ERROR: " + message );
+    }
+
+    private static void log(final String message)
+    {
+        // do this in background to avoid deadlock with ui 
+        Job job = new Job("log") {
+            @Override
+            protected IStatus run(IProgressMonitor arg0)
+            {
+                BuildConsole console = findConsole();
+                MessageConsoleStream stream = console.getMessageStream();
+                stream.println( message );
+                return Status.OK_STATUS;
+            }
+        };
+        job.schedule();
     }
 
 
diff --git a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/resources/ProjectResourceListener.java b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/resources/ProjectResourceListener.java
index d833e48..463abf0 100644
--- a/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/resources/ProjectResourceListener.java
+++ b/sigil/eclipse/core/src/org/apache/felix/sigil/eclipse/internal/resources/ProjectResourceListener.java
@@ -21,6 +21,7 @@
 import java.util.LinkedList;
 
 import org.apache.felix.sigil.eclipse.SigilCore;
+import org.apache.felix.sigil.eclipse.job.ResolveProjectsJob;
 import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
 import org.apache.felix.sigil.model.ICapabilityModelElement;
 import org.apache.felix.sigil.model.IModelElement;
@@ -33,10 +34,10 @@
 import org.eclipse.core.resources.IResourceDeltaVisitor;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
-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.core.runtime.IProgressMonitor;
+//import org.eclipse.core.runtime.IStatus;
+//import org.eclipse.core.runtime.Status;
+//import org.eclipse.core.runtime.jobs.Job;
 
 public class ProjectResourceListener implements IResourceChangeListener
 {
@@ -53,6 +54,9 @@
         try
         {
             switch ( event.getType() ) {
+                case IResourceChangeEvent.PRE_REFRESH:
+                    handleRefresh(event);
+                    break;
                 case IResourceChangeEvent.PRE_DELETE:
                     handlePreDelete(event);
                     break;
@@ -60,6 +64,8 @@
                     handlePostChange(event);
                     break;
             }
+            
+            handleUpdate();
         }
         catch (CoreException e)
         {
@@ -67,6 +73,43 @@
         }
     }
 
+    private void handleUpdate()
+    {
+        if( capabilities.size() > 0 ) {
+            final LinkedList<ICapabilityModelElement> changes = new LinkedList<ICapabilityModelElement>(capabilities);
+            capabilities.clear();
+            
+            ResolveProjectsJob job = new ResolveProjectsJob(ResourcesPlugin.getWorkspace(), changes);
+            job.schedule();        
+        }
+    }
+    
+    private void handleRefresh(IResourceChangeEvent event) throws CoreException
+    {
+        IResourceDelta delta = event.getDelta();
+        if ( delta != null )
+        {
+            delta.accept( new IResourceDeltaVisitor()
+            {
+                public boolean visit( IResourceDelta delta ) throws CoreException
+                {
+                    IResource resource = delta.getResource();
+                    if ( resource instanceof IProject )
+                    {
+                        IProject project = ( IProject ) resource;
+                        if ( SigilCore.isSigilProject( project ) )
+                        {
+                            readCapabilities(project);
+                        }
+                        // Recurse no more
+                        return false;
+                    }
+                    return true;
+                }
+            } );            
+        }
+    }    
+
     private LinkedList<ICapabilityModelElement> capabilities = new LinkedList<ICapabilityModelElement>();
     
     private void handlePostChange(IResourceChangeEvent event) throws CoreException
@@ -97,25 +140,7 @@
                     }
                     return true;
                 }
-            } );
-            
-            if( capabilities.size() > 0 ) {
-                final LinkedList<ICapabilityModelElement> changes = new LinkedList<ICapabilityModelElement>(capabilities);
-                capabilities.clear();
-                
-                Job job = new Job("Rebuild project dependencies")
-                {
-                    
-                    @Override
-                    protected IStatus run(IProgressMonitor monitor)
-                    {
-                        SigilCore.rebuildBundleDependencies(null, changes, monitor);
-                        return Status.OK_STATUS;
-                    }
-                };
-                job.setRule(ResourcesPlugin.getWorkspace().getRoot());
-                job.schedule();
-            }
+            } );            
         }
     }
 
@@ -147,6 +172,4 @@
             }
         });
     }
-
-
 }
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 2bfff2b..7c24d6c 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
@@ -22,9 +22,15 @@
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedList;
 
 import org.apache.felix.sigil.eclipse.SigilCore;
 import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
+import org.apache.felix.sigil.model.ICapabilityModelElement;
+import org.apache.felix.sigil.model.IModelElement;
+import org.apache.felix.sigil.model.IModelWalker;
+import org.apache.felix.sigil.model.IRequirementModelElement;
+import org.apache.felix.sigil.model.eclipse.ISigilBundle;
 import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.WorkspaceJob;
 import org.eclipse.core.runtime.CoreException;
@@ -36,23 +42,32 @@
 public class ResolveProjectsJob extends WorkspaceJob
 {
     private final Collection<ISigilProjectModel> sigilProjects;
+    private final LinkedList<ICapabilityModelElement> capabilities;
     
     public ResolveProjectsJob( IWorkspace workspace )
     {
         super( "Resolving Sigil projects" );
         setRule( workspace.getRoot() );
         sigilProjects = SigilCore.getRoot().getProjects();
+        capabilities = null;
     }
 
+    public ResolveProjectsJob(IWorkspace workspace, LinkedList<ICapabilityModelElement> capabilities)
+    {
+        super( "Resolving Sigil projects" );
+        this.capabilities = capabilities;
+        setRule( workspace.getRoot() );
+        sigilProjects = SigilCore.getRoot().getProjects();
+    }
 
     public ResolveProjectsJob(ISigilProjectModel project)
     {
         super( "Resolving Sigil project" );
         setRule( project.getProject().getWorkspace().getRoot() );
         sigilProjects = Collections.singleton(project);
+        capabilities = null;
     }
 
-
     @Override
     public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException
     {
@@ -64,8 +79,10 @@
         {
             try
             {
-                if ( flush ) sigilProject.flushDependencyState();
-                sigilProject.rebuildDependencies(monitor);
+                if ( isDependent(sigilProject) ) { 
+                    if ( flush) sigilProject.flushDependencyState();
+                    sigilProject.rebuildDependencies(monitor);
+                }
             }
             catch ( CoreException e )
             {
@@ -75,4 +92,42 @@
 
         return status;
     }
+
+    private boolean isDependent(ISigilProjectModel sigilProject)
+    {
+        if ( capabilities == null ) {
+            return true;
+        }
+        else {
+            ISigilBundle b = sigilProject.getBundle();
+            if ( b == null ) {
+                // sigil project deleted can't be a dependent
+                return false;
+            }
+            else {
+                final boolean[] dep = new boolean[1];
+                
+                b.visit(new IModelWalker()
+                {
+                    public boolean visit(IModelElement element)
+                    {
+                        if (element instanceof IRequirementModelElement) {
+                            IRequirementModelElement r = (IRequirementModelElement) element;
+        
+                            for (ICapabilityModelElement c : capabilities) {
+                                if( r.accepts(c)) {
+                                    dep[0] = true;
+                                    break;
+                                }
+                            }
+                        }
+                        // found a dependency stop walking
+                        return !dep[0];
+                    }
+                });
+                
+                return dep[0];
+            }
+        }
+    }
 }
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 b33e8fc..219f383 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
@@ -26,6 +26,7 @@
 import org.apache.felix.sigil.eclipse.job.ResolveProjectsJob;
 import org.apache.felix.sigil.repository.IRepositoryChangeListener;
 import org.apache.felix.sigil.repository.RepositoryChangeEvent;
+import org.apache.felix.sigil.ui.eclipse.ui.SigilUI;
 import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -47,24 +48,29 @@
         {
             public void repositoryChanged( RepositoryChangeEvent event )
             {
-                final int update = updateCounter.incrementAndGet();
-                
-                Job job = new Job("Pending repository update") {
-                    @Override
-                    protected IStatus run(IProgressMonitor monitor)
-                    {
-                        if ( update == updateCounter.get() ) {
-                            IWorkspace workspace = ResourcesPlugin.getWorkspace();
-                            ResolveProjectsJob job = new ResolveProjectsJob( workspace );
-                            job.setSystem( true );
-                            job.schedule();
-                        }
-                        return Status.OK_STATUS;
-                    }
+                if ( !SigilUI.WORKSPACE_REPOSITORY_ID.equals( event.getRepository().getId() ) ) {
+                    final int update = updateCounter.incrementAndGet();
                     
-                };
-                job.setSystem(true);
-                job.schedule(100);
+                    Job job = new Job("Pending repository update") {
+                        @Override
+                        protected IStatus run(IProgressMonitor monitor)
+                        {
+                            if ( update == updateCounter.get() ) {
+                                IWorkspace workspace = ResourcesPlugin.getWorkspace();
+                                ResolveProjectsJob job = new ResolveProjectsJob( workspace );
+                                job.setSystem( true );
+                                job.schedule();
+                            }
+                            return Status.OK_STATUS;
+                        }
+                        
+                    };
+                    job.setSystem(true);
+                    job.schedule(100);
+                } 
+                //else {
+                //   Repository changes are handled by ProjectResourceListener 
+                //}
             }
         } );
     }
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/SigilUI.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/SigilUI.java
index 3ccfee2..a2a3a08 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/SigilUI.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/SigilUI.java
@@ -54,6 +54,8 @@
 
     public static final String ID_REPOSITORY_VIEW = "org.apache.felix.sigil.ui.repositoryBrowser";
     public static final String ID_DEPENDENCY_VIEW = "org.apache.felix.sigil.ui.bundleDependencyView";
+    
+    public static final String WORKSPACE_REPOSITORY_ID = "org.apache.felix.sigil.core.workspaceprovider";
 
     // The shared instance
     private static SigilUI plugin;
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 104363c..f10490c 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
@@ -238,9 +238,6 @@
         try
         {
             switch (event.getType()) {
-                case IResourceChangeEvent.PRE_REFRESH:
-                    handleRefresh(event);
-                    break;
                 case IResourceChangeEvent.POST_BUILD:
                     handleBuild(event);
                     break;
@@ -262,13 +259,6 @@
     }
 
 
-    private void handleRefresh(IResourceChangeEvent event)
-    {
-        ResolveProjectsJob job = new ResolveProjectsJob(project);
-        job.schedule();        
-    }
-
-
     private void handleChange(IResourceChangeEvent event) throws CoreException
     {
         IResourceDelta delta = event.getDelta();
@@ -386,8 +376,6 @@
         tempProject.setBundle(null);
         project.setBundle( null );
         refreshAllPages();
-        ResolveProjectsJob job = new ResolveProjectsJob(project);
-        job.schedule();        
     }