You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@continuum.apache.org by oc...@apache.org on 2010/05/06 11:23:34 UTC

svn commit: r941625 [6/24] - in /continuum/branches/continuum-flat-multi-module: ./ continuum-api/ continuum-api/src/main/java/org/apache/continuum/builder/distributed/ continuum-api/src/main/java/org/apache/continuum/builder/distributed/manager/ conti...

Modified: continuum/branches/continuum-flat-multi-module/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-flat-multi-module/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java?rev=941625&r1=941624&r2=941625&view=diff
==============================================================================
--- continuum/branches/continuum-flat-multi-module/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java (original)
+++ continuum/branches/continuum-flat-multi-module/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java Thu May  6 09:23:13 2010
@@ -19,49 +19,40 @@ package org.apache.continuum.builder.dis
  * under the License.
  */
 
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.continuum.builder.distributed.executor.DistributedBuildTaskQueueExecutor;
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
 import org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor;
+import org.apache.continuum.builder.distributed.util.DistributedBuildUtil;
 import org.apache.continuum.builder.utils.ContinuumBuildConstant;
 import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
 import org.apache.continuum.dao.BuildDefinitionDao;
 import org.apache.continuum.dao.BuildResultDao;
 import org.apache.continuum.dao.ProjectDao;
-import org.apache.continuum.dao.ProjectScmRootDao;
 import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
 import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.OverallDistributedBuildQueue;
 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
 import org.apache.continuum.utils.ContinuumUtils;
+import org.apache.continuum.utils.ProjectSorter;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.configuration.ConfigurationException;
 import org.apache.maven.continuum.configuration.ConfigurationService;
-import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.project.ProjectDependency;
-import org.apache.maven.continuum.model.project.ProjectDeveloper;
-import org.apache.maven.continuum.model.project.ProjectNotifier;
-import org.apache.maven.continuum.model.scm.ChangeFile;
-import org.apache.maven.continuum.model.scm.ChangeSet;
-import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
-import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
-import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.codehaus.plexus.PlexusConstants;
 import org.codehaus.plexus.PlexusContainer;
@@ -73,6 +64,8 @@ import org.codehaus.plexus.personality.p
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
 import org.codehaus.plexus.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -86,15 +79,13 @@ public class DefaultDistributedBuildMana
 {
     private static final Logger log = LoggerFactory.getLogger( DefaultDistributedBuildManager.class );
 
-    /**
-     * @plexus.requirement
-     */
-    private ConfigurationService configurationService;
+    private Map<String, OverallDistributedBuildQueue> overallDistributedBuildQueues =
+        Collections.synchronizedMap( new HashMap<String, OverallDistributedBuildQueue>() );
 
     /**
      * @plexus.requirement
      */
-    private InstallationService installationService;
+    private ConfigurationService configurationService;
 
     /**
      * @plexus.requirement
@@ -109,22 +100,15 @@ public class DefaultDistributedBuildMana
     /**
      * @plexus.requirement
      */
-    private ProjectScmRootDao projectScmRootDao;
-
-    /**
-     * @plexus.requirement
-     */
     private BuildResultDao buildResultDao;
 
     /**
      * @plexus.requirement
      */
-    private ContinuumNotificationDispatcher notifierDispatcher;
+    private DistributedBuildUtil distributedBuildUtil;
 
     private PlexusContainer container;
 
-    private Map<String, DistributedBuildTaskQueueExecutor> taskQueueExecutors;
-
     // --------------------------------
     //  Plexus Lifecycle
     // --------------------------------
@@ -137,26 +121,77 @@ public class DefaultDistributedBuildMana
     public void initialize()
         throws InitializationException
     {
-        taskQueueExecutors = new HashMap<String, DistributedBuildTaskQueueExecutor>();
-
         List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
 
         if ( agents != null )
         {
+            synchronized( overallDistributedBuildQueues )
+            {
+                for ( BuildAgentConfiguration agent : agents )
+                {
+                    if ( agent.isEnabled() )
+                    {
+                        try
+                        {
+                            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( agent.getUrl() );
+
+                            if ( client.ping() )
+                            {
+                                log.info(
+                                    "agent is enabled, create distributed build queue for build agent '" + agent.getUrl() + "'" );
+                                createDistributedBuildQueueForAgent( agent.getUrl() );
+                            }
+                            else
+                            {
+                                log.info( "unable to ping build agent '" + agent.getUrl() + "'" );
+                            }
+                        }
+                        catch ( MalformedURLException e )
+                        {
+                            // do not throw exception, just log it
+                            log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating distributed build queue" );
+                        }
+                        catch ( ContinuumException e )
+                        {
+                            throw new InitializationException(
+                                "Error while initializing distributed build queues", e );
+                        }
+                        catch ( Exception e )
+                        {
+                            agent.setEnabled( false );
+                            log.info( "unable to ping build agent '" + agent.getUrl() + "': " +
+                                ContinuumUtils.throwableToString( e ) );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public void reload()
+        throws ContinuumException
+    {
+        List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
+
+        if ( agents == null )
+        {
+            return;
+        }
+
+        synchronized( overallDistributedBuildQueues )
+        {
             for ( BuildAgentConfiguration agent : agents )
             {
-                if ( agent.isEnabled() )
+                if ( agent.isEnabled() && !overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
                 {
                     try
                     {
-                        SlaveBuildAgentTransportClient client =
-                            new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) );
-
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( agent.getUrl() );
+    
                         if ( client.ping() )
                         {
-                            log.info(
-                                "agent is enabled, add TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
-                            addTaskQueueExecutor( agent.getUrl() );
+                            log.info( "agent is enabled, create distributed build queue for build agent '" + agent.getUrl() + "'" );
+                            createDistributedBuildQueueForAgent( agent.getUrl() );
                         }
                         else
                         {
@@ -166,12 +201,7 @@ public class DefaultDistributedBuildMana
                     catch ( MalformedURLException e )
                     {
                         // do not throw exception, just log it
-                        log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating task queue executor" );
-                    }
-                    catch ( ContinuumException e )
-                    {
-                        throw new InitializationException(
-                            "Error while initializing distributed build task queue executors", e );
+                        log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating distributed build queue" );
                     }
                     catch ( Exception e )
                     {
@@ -180,376 +210,330 @@ public class DefaultDistributedBuildMana
                             ContinuumUtils.throwableToString( e ) );
                     }
                 }
+                else if ( !agent.isEnabled() && overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
+                {
+                    log.info( "agent is disabled, remove distributed build queue for build agent '" + agent.getUrl() + "'" );
+                    removeDistributedBuildQueueOfAgent( agent.getUrl() );
+                }
             }
         }
     }
 
-    public void reload()
-        throws ContinuumException
+    public void prepareBuildProjects( Map<Integer, Integer>projectsBuildDefinitionsMap, BuildTrigger buildTrigger, int projectGroupId, 
+                                      String projectGroupName, String scmRootAddress, int scmRootId, List<ProjectScmRoot> scmRoots )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
+    	PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, buildTrigger,
+                                                                      projectGroupId, projectGroupName, 
+                                                                      scmRootAddress, scmRootId );
 
-        for ( BuildAgentConfiguration agent : agents )
+        OverallDistributedBuildQueue overallDistributedBuildQueue = getOverallDistributedBuildQueueByGroup( projectGroupId, scmRoots, scmRootId );
+
+        if ( overallDistributedBuildQueue == null )
         {
-            if ( agent.isEnabled() && !taskQueueExecutors.containsKey( agent.getUrl() ) )
+            if ( hasBuildagentGroup( projectsBuildDefinitionsMap ) )
             {
-                try
-                {
-                    SlaveBuildAgentTransportClient client =
-                        new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) );
-
-                    if ( client.ping() )
-                    {
-                        log.info( "agent is enabled, add TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
-                        addTaskQueueExecutor( agent.getUrl() );
-                    }
-                    else
-                    {
-                        log.info( "unable to ping build agent '" + agent.getUrl() + "'" );
-                    }
-                }
-                catch ( MalformedURLException e )
+                if ( !hasBuildagentInGroup( projectsBuildDefinitionsMap ) )
                 {
-                    // do not throw exception, just log it
-                    log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating task queue executor" );
+                    log.warn( "No build agent configured in build agent group. Not building projects." );
+    
+                    throw new NoBuildAgentInGroupException( "No build agent configured in build agent group" );
                 }
-                catch ( Exception e )
+                else
                 {
-                    agent.setEnabled( false );
-                    log.info( "unable to ping build agent '" + agent.getUrl() + "': " +
-                        ContinuumUtils.throwableToString( e ) );
+                    // get overall distributed build queue from build agent group
+                    log.info( "getting the least busy build agent from the build agent group" );
+                    overallDistributedBuildQueue = getOverallDistributedBuildQueueByAgentGroup( projectsBuildDefinitionsMap );
                 }
             }
-            else if ( !agent.isEnabled() && taskQueueExecutors.containsKey( agent.getUrl() ) )
+            else
             {
-                log.info( "agent is disabled, remove TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
-                removeAgentFromTaskQueueExecutor( agent.getUrl() );
+                // project does not have build agent group
+                log.info( "project does not have a build agent group, getting the least busy build agent" );
+                overallDistributedBuildQueue = getOverallDistributedBuildQueue();
             }
         }
-    }
-
-    public void removeAgentFromTaskQueueExecutor( String buildAgentUrl )
-        throws ContinuumException
-    {
-        log.info( "remove TaskQueueExecutor for build agent '" + buildAgentUrl + "'" );
-        ThreadedDistributedBuildTaskQueueExecutor executor =
-            (ThreadedDistributedBuildTaskQueueExecutor) taskQueueExecutors.get( buildAgentUrl );
-
-        if ( executor == null )
-        {
-            return;
-        }
 
-        try
+        if ( overallDistributedBuildQueue != null )
         {
-            executor.stop();
-            container.release( executor );
-        }
-        catch ( StoppingException e )
-        {
-            throw new ContinuumException( "Error while stopping task queue executor", e );
+            try
+            {
+                overallDistributedBuildQueue.addToDistributedBuildQueue( task );
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Error while enqueuing prepare build task", e );
+                throw new ContinuumException( "Error occurred while enqueuing prepare build task", e );
+            }
         }
-        catch ( ComponentLifecycleException e )
+        else
         {
-            throw new ContinuumException( "Error while releasing task queue executor from container", e );
-        }
-
-        taskQueueExecutors.remove( buildAgentUrl );
-    }
-
-    public boolean isBuildAgentBusy( String buildAgentUrl )
-    {
-        DistributedBuildTaskQueueExecutor executor = taskQueueExecutors.get( buildAgentUrl );
+            log.warn( "No build agent configured. Not building projects." );
 
-        if ( executor != null && executor.getCurrentTask() != null )
-        {
-            log.info( "build agent '" + buildAgentUrl + "' is busy" );
-            return true;
+            throw new NoBuildAgentException( "No build agent configured" );
         }
 
-        log.info( "build agent '" + buildAgentUrl + "' is not busy" );
-        return false;
+        // call in case we disabled a build agent
+        reload();
     }
 
-    private void addTaskQueueExecutor( String url )
+    public void removeDistributedBuildQueueOfAgent( String buildAgentUrl )
         throws ContinuumException
     {
-        try
-        {
-            DistributedBuildTaskQueueExecutor taskQueueExecutor = (DistributedBuildTaskQueueExecutor) container.
-                lookup( DistributedBuildTaskQueueExecutor.class, "distributed-build-project" );
-            taskQueueExecutor.setBuildAgentUrl( url );
-            taskQueueExecutors.put( url, taskQueueExecutor );
-        }
-        catch ( ComponentLookupException e )
+        if ( overallDistributedBuildQueues.containsKey( buildAgentUrl ) )
         {
-            throw new ContinuumException( "Unable to lookup TaskQueueExecutor for distributed-build-project", e );
+            List<PrepareBuildProjectsTask> tasks = null;
+
+            synchronized( overallDistributedBuildQueues )
+            {
+                OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+                try
+                {
+                    if ( overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null )
+                    {
+                        log.error( "Unable to remove build agent because it is currently being used" );
+                        throw new ContinuumException( "Unable to remove build agent because it is currently being used" );
+                    }
+
+                    tasks = overallDistributedBuildQueue.getProjectsInQueue();
+
+                    overallDistributedBuildQueue.getDistributedBuildQueue().removeAll( tasks );
+
+                    ( (ThreadedDistributedBuildTaskQueueExecutor) overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor() ).stop();
+
+                    container.release( overallDistributedBuildQueue );
+
+                    overallDistributedBuildQueues.remove( buildAgentUrl );
+
+                    log.info( "remove distributed build queue for build agent '" + buildAgentUrl + "'" );
+                }
+                catch ( TaskQueueException e )
+                {
+                    log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
+                    throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+                }
+                catch ( ComponentLifecycleException e )
+                {
+                    log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
+                    throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+                }
+                catch ( StoppingException e )
+                {
+                    log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
+                    throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+                }
+            }
         }
     }
 
-    public void cancelDistributedBuild( String buildAgentUrl, int projectGroupId, String scmRootAddress )
+    public Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue()
         throws ContinuumException
     {
-        DistributedBuildTaskQueueExecutor taskQueueExecutor = taskQueueExecutors.get( buildAgentUrl );
+        Map<String, List<PrepareBuildProjectsTask>> map = new HashMap<String, List<PrepareBuildProjectsTask>>();
 
-        if ( taskQueueExecutor != null )
+        synchronized( overallDistributedBuildQueues )
         {
-            if ( taskQueueExecutor.getCurrentTask() != null )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                if ( taskQueueExecutor.getCurrentTask() instanceof PrepareBuildProjectsTask )
-                {
-                    PrepareBuildProjectsTask currentTask = (PrepareBuildProjectsTask) taskQueueExecutor.getCurrentTask()
-                        ;
+                List<PrepareBuildProjectsTask> tasks = new ArrayList<PrepareBuildProjectsTask>();
 
-                    if ( currentTask.getProjectGroupId() == projectGroupId &&
-                        currentTask.getScmRootAddress().equals( scmRootAddress ) )
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
                     {
-                        log.info( "cancelling task for project group " + projectGroupId + " with scm root address " +
-                            scmRootAddress );
-                        taskQueueExecutor.cancelTask( currentTask );
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
 
-                        try
-                        {
-                            SlaveBuildAgentTransportClient client =
-                                new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
-                            client.cancelBuild();
-                        }
-                        catch ( Exception e )
+                        List<Map<String, Object>> projects = client.getProjectsInPrepareBuildQueue();
+    
+                        for ( Map<String, Object> context : projects )
                         {
-                            log.error( "Error while cancelling build in build agent '" + buildAgentUrl + "'" );
-                            throw new ContinuumException(
-                                "Error while cancelling build in build agent '" + buildAgentUrl + "'", e );
+                            tasks.add( getPrepareBuildProjectsTask( context ) );
                         }
-                    }
-                    else
-                    {
-                        log.info( "current task not for project group " + projectGroupId + " with scm root address " +
-                            scmRootAddress );
+    
+                        map.put( buildAgentUrl, tasks );
                     }
                 }
-                else
+                catch ( MalformedURLException e )
                 {
-                    log.info( "current task not a prepare build projects task, not cancelling" );
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl ); 
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error while retrieving projects in prepare build queue", e );
                 }
             }
-            else
-            {
-                log.info( "no current task in build agent '" + buildAgentUrl + "'" );
-            }
-        }
-        else
-        {
-            log.info( "no task queue executor defined for build agent '" + buildAgentUrl + "'" );
         }
+
+        // call reload in case we disable a build agent
+        reload();
+
+        return map;
     }
 
-    public void updateBuildResult( Map<String, Object> context )
+    public Map<String, PrepareBuildProjectsTask> getProjectsCurrentlyPreparingBuild()
         throws ContinuumException
     {
-        try
-        {
-            int projectId = ContinuumBuildConstant.getProjectId( context );
-            int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
-
-            log.info( "update build result of project '" + projectId + "'" );
-
-            Project project = projectDao.getProjectWithAllDetails( projectId );
-            BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-
-            BuildResult oldBuildResult =
-                buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
-
-            int buildNumber;
-
-            if ( ContinuumBuildConstant.getBuildState( context ) == ContinuumProjectState.OK )
-            {
-                buildNumber = project.getBuildNumber() + 1;
-            }
-            else
-            {
-                buildNumber = project.getBuildNumber();
-            }
-
-            // ----------------------------------------------------------------------
-            // Make the buildResult
-            // ----------------------------------------------------------------------
-
-            BuildResult buildResult = convertMapToBuildResult( context );
+        Map<String, PrepareBuildProjectsTask> map = new HashMap<String, PrepareBuildProjectsTask>();
 
-            if ( buildResult.getState() != ContinuumProjectState.CANCELLED )
+        synchronized( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                buildResult.setBuildDefinition( buildDefinition );
-                buildResult.setBuildNumber( buildNumber );
-                buildResult.setModifiedDependencies( getModifiedDependencies( oldBuildResult, context ) );
-                buildResult.setScmResult( getScmResult( context ) );
-
-                Date date = ContinuumBuildConstant.getLatestUpdateDate( context );
-                if ( date != null )
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                        Map<String, Object> project = client.getProjectCurrentlyPreparingBuild();
+    
+                        if ( !project.isEmpty() )
+                        {
+                            map.put( buildAgentUrl, getPrepareBuildProjectsTask( project ) );
+                        }
+                    }
+                }
+                catch ( MalformedURLException e )
                 {
-                    buildResult.setLastChangedDate( date.getTime() );
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
                 }
-                else if ( oldBuildResult != null )
+                catch ( Exception e )
                 {
-                    buildResult.setLastChangedDate( oldBuildResult.getLastChangedDate() );
+                    throw new ContinuumException( "Error retrieving projects currently preparing build in " + buildAgentUrl, e );
                 }
-
-                buildResultDao.addBuildResult( project, buildResult );
-
-                project.setOldState( project.getState() );
-                project.setState( ContinuumBuildConstant.getBuildState( context ) );
-                project.setBuildNumber( buildNumber );
-                project.setLatestBuildId( buildResult.getId() );
-            }
-            else
-            {
-                project.setState( project.getOldState() );
-                project.setOldState( 0 );
             }
+        }
 
-            projectDao.updateProject( project );
-
-            File buildOutputFile = configurationService.getBuildOutputFile( buildResult.getId(), project.getId() );
-
-            FileWriter fstream = new FileWriter( buildOutputFile );
-            BufferedWriter out = new BufferedWriter( fstream );
-            out.write( ContinuumBuildConstant.getBuildOutput( context ) == null ? ""
-                : ContinuumBuildConstant.getBuildOutput( context ) );
-            out.close();
+        // call reload in case we disable a build agent
+        reload();
 
-            if ( buildResult.getState() != ContinuumProjectState.CANCELLED )
-            {
-                notifierDispatcher.buildComplete( project, buildDefinition, buildResult );
-            }
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new ContinuumException( "Error while updating build result for project", e );
-        }
-        catch ( ConfigurationException e )
-        {
-            throw new ContinuumException( "Error retrieving build output file", e );
-        }
-        catch ( IOException e )
-        {
-            throw new ContinuumException( "Error while writing build output to file", e );
-        }
+        return map;
     }
-
-    public void prepareBuildFinished( Map<String, Object> context )
+ 
+    public Map<String, BuildProjectTask> getProjectsCurrentlyBuilding()
         throws ContinuumException
     {
-        int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
-        String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
+        Map<String, BuildProjectTask> map = new HashMap<String, BuildProjectTask>();
 
-        try
+        synchronized( overallDistributedBuildQueues )
         {
-            ProjectScmRoot scmRoot =
-                projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId, scmRootAddress );
-
-            String error = ContinuumBuildConstant.getScmError( context );
-
-            if ( StringUtils.isEmpty( error ) )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                scmRoot.setState( ContinuumProjectState.UPDATED );
-            }
-            else
-            {
-                scmRoot.setState( ContinuumProjectState.ERROR );
-                scmRoot.setError( error );
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                        Map<String, Object> project = client.getProjectCurrentlyBuilding();
+    
+                        if ( !project.isEmpty() )
+                        {
+                            map.put( buildAgentUrl, getBuildProjectTask( project ) );
+                        }
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error retrieving projects currently building in " + buildAgentUrl, e );
+                }
             }
+        }
 
-            projectScmRootDao.updateProjectScmRoot( scmRoot );
+        // call reload in case we disable a build agent
+        reload();
 
-            notifierDispatcher.prepareBuildComplete( scmRoot );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new ContinuumException( "Error while updating project scm root '" + scmRootAddress + "'", e );
-        }
+        return map;
     }
 
-    public Map<String, PrepareBuildProjectsTask> getDistributedBuildProjects()
+    public Map<String, List<BuildProjectTask>> getProjectsInBuildQueue()
+        throws ContinuumException
     {
-        Map<String, PrepareBuildProjectsTask> map = new HashMap<String, PrepareBuildProjectsTask>();
+        Map<String, List<BuildProjectTask>> map = new HashMap<String, List<BuildProjectTask>>();
 
-        for ( String url : taskQueueExecutors.keySet() )
+        synchronized( overallDistributedBuildQueues )
         {
-            DistributedBuildTaskQueueExecutor taskQueueExecutor = taskQueueExecutors.get( url );
-
-            if ( taskQueueExecutor.getCurrentTask() != null )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                PrepareBuildProjectsTask task = (PrepareBuildProjectsTask) taskQueueExecutor.getCurrentTask();
+                List<BuildProjectTask> tasks = new ArrayList<BuildProjectTask>();
 
-                map.put( url, task );
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                        List<Map<String, Object>> projects = client.getProjectsInBuildQueue();
+    
+                        for ( Map<String, Object> context : projects )
+                        {
+                            tasks.add( getBuildProjectTask( context ) );
+                        }
+    
+                        map.put( buildAgentUrl, tasks );
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl ); 
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error while retrieving projects in build queue", e );
+                }
             }
         }
 
+        // call reload in case we disable a build agent
+        reload();
+
         return map;
     }
 
-    public List<Installation> getAvailableInstallations( String buildAgentUrl )
-        throws ContinuumException
+    public boolean isBuildAgentBusy( String buildAgentUrl )
     {
-        List<Installation> installations = new ArrayList<Installation>();
-
-        try
+        synchronized ( overallDistributedBuildQueues )
         {
-            SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
-
-            List<Map<String, String>> installationsList = client.getAvailableInstallations();
+            OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
 
-            for ( Map context : installationsList )
+            if ( overallDistributedBuildQueue != null && 
+                 overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null )
             {
-                Installation installation = new Installation();
-                installation.setName( ContinuumBuildConstant.getInstallationName( context ) );
-                installation.setType( ContinuumBuildConstant.getInstallationType( context ) );
-                installation.setVarName( ContinuumBuildConstant.getInstallationVarName( context ) );
-                installation.setVarValue( ContinuumBuildConstant.getInstallationVarValue( context ) );
-                installations.add( installation );
+                log.info( "build agent '" + buildAgentUrl + "' is busy" );
+                return true;
             }
 
-            return installations;
-        }
-        catch ( Exception e )
-        {
-            throw new ContinuumException( "Unable to get available installations of build agent", e );
+            log.info( "build agent '" + buildAgentUrl + "' is not busy" );
+            return false;
         }
     }
 
-    public void startProjectBuild( int projectId )
+    public void cancelDistributedBuild( String buildAgentUrl )
         throws ContinuumException
     {
         try
         {
-            Project project = projectDao.getProject( projectId );
-            project.setState( ContinuumProjectState.BUILDING );
-            projectDao.updateProject( project );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            log.error( "Error while updating project's state", e );
-            throw new ContinuumException( "Error while updating project's state", e );
-        }
-    }
+            if ( isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+    
+                client.cancelBuild();
+            }
 
-    public void startPrepareBuild( Map<String, Object> context )
-        throws ContinuumException
-    {
-        try
+            // call reload in case we disable the build agent
+            reload();
+        }
+        catch ( MalformedURLException e )
         {
-            int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
-            String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
-
-            ProjectScmRoot scmRoot =
-                projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId, scmRootAddress );
-            scmRoot.setOldState( scmRoot.getState() );
-            scmRoot.setState( ContinuumProjectState.UPDATING );
-            projectScmRootDao.updateProjectScmRoot( scmRoot );
+            log.error( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumException( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl );
         }
-        catch ( ContinuumStoreException e )
+        catch ( Exception e )
         {
-            log.error( "Error while updating project scm root's state", e );
-            throw new ContinuumException( "Error while updating project scm root's state", e );
+            log.error( "Error occurred while cancelling build in build agent " + buildAgentUrl, e );
+            throw new ContinuumException( "Error occurred while cancelling build in build agent " + buildAgentUrl, e );
         }
     }
 
@@ -567,30 +551,33 @@ public class DefaultDistributedBuildMana
 
         try
         {
-            SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
+            if ( isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
 
-            Map result = client.getBuildResult( projectId );
+                Map<String, Object> result = client.getBuildResult( projectId );
 
-            if ( result != null )
-            {
-                int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( result );
+                if ( result != null )
+                {
+                    int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( result );
 
-                Project project = projectDao.getProjectWithAllDetails( projectId );
-                BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+                    Project project = projectDao.getProjectWithAllDetails( projectId );
+                    BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
 
-                BuildResult oldBuildResult =
-                    buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
+                    BuildResult oldBuildResult =
+                        buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
 
-                BuildResult buildResult = convertMapToBuildResult( result );
-                buildResult.setBuildDefinition( buildDefinition );
-                buildResult.setBuildNumber( project.getBuildNumber() + 1 );
-                buildResult.setModifiedDependencies( getModifiedDependencies( oldBuildResult, result ) );
-                buildResult.setScmResult( getScmResult( result ) );
+                    BuildResult buildResult = distributedBuildUtil.convertMapToBuildResult( result );
+                    buildResult.setBuildDefinition( buildDefinition );
+                    buildResult.setBuildNumber( project.getBuildNumber() + 1 );
+                    buildResult.setModifiedDependencies( distributedBuildUtil.getModifiedDependencies( oldBuildResult, result ) );
+                    buildResult.setScmResult( distributedBuildUtil.getScmResult( result ) );
 
-                String buildOutput = ContinuumBuildConstant.getBuildOutput( result );
+                    String buildOutput = ContinuumBuildConstant.getBuildOutput( result );
 
-                map.put( ContinuumBuildConstant.KEY_BUILD_RESULT, buildResult );
-                map.put( ContinuumBuildConstant.KEY_BUILD_OUTPUT, buildOutput );
+                    map.put( ContinuumBuildConstant.KEY_BUILD_RESULT, buildResult );
+                    map.put( ContinuumBuildConstant.KEY_BUILD_OUTPUT, buildOutput );
+                }
             }
         }
         catch ( MalformedURLException e )
@@ -602,92 +589,44 @@ public class DefaultDistributedBuildMana
             throw new ContinuumException( "Error while retrieving build result for project" + projectId, e );
         }
 
+        // call reload in case we disable the build agent
+        reload();
+
         return map;
     }
 
-    public Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+    public List<Installation> getAvailableInstallations( String buildAgentUrl )
         throws ContinuumException
     {
-        BuildDefinition buildDefinition;
+        List<Installation> installations = new ArrayList<Installation>();
 
         try
         {
-            buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new ContinuumException( "Failed to retrieve build definition: " + buildDefinitionId, e );
-        }
-
-        Profile profile = buildDefinition.getProfile();
-        if ( profile == null )
-        {
-            return Collections.EMPTY_MAP;
-        }
-        Map<String, String> envVars = new HashMap<String, String>();
-        String javaHome = getJavaHomeValue( buildDefinition );
-        if ( !StringUtils.isEmpty( javaHome ) )
-        {
-            envVars.put( installationService.getEnvVar( InstallationService.JDK_TYPE ), javaHome );
-        }
-        Installation builder = profile.getBuilder();
-        if ( builder != null )
-        {
-            envVars.put( installationService.getEnvVar( installationType ), builder.getVarValue() );
-        }
-        envVars.putAll( getEnvironmentVariables( buildDefinition ) );
-        return envVars;
-    }
+            if ( isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
 
-    public void updateProject( Map<String, Object> context )
-        throws ContinuumException
-    {
-        try
-        {
-            Project project = projectDao.getProject( ContinuumBuildConstant.getProjectId( context ) );
+                List<Map<String, String>> installationsList = client.getAvailableInstallations();
 
-            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getGroupId( context ) ) )
-            {
-                project.setGroupId( ContinuumBuildConstant.getGroupId( context ) );
-            }
-            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getArtifactId( context ) ) )
-            {
-                project.setArtifactId( ContinuumBuildConstant.getArtifactId( context ) );
-            }
-            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getVersion( context ) ) )
-            {
-                project.setVersion( ContinuumBuildConstant.getVersion( context ) );
-            }
-            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectName( context ) ) )
-            {
-                project.setName( ContinuumBuildConstant.getProjectName( context ) );
-            }
-            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectDescription( context ) ) )
-            {
-                project.setDescription( ContinuumBuildConstant.getProjectDescription( context ) );
-            }
-            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectUrl( context ) ) )
-            {
-                project.setUrl( ContinuumBuildConstant.getProjectUrl( context ) );
-            }
-            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getScmUrl( context ) ) )
-            {
-                project.setScmUrl( ContinuumBuildConstant.getScmUrl( context ) );
-            }
-            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getScmTag( context ) ) )
-            {
-                project.setScmTag( ContinuumBuildConstant.getScmTag( context ) );
+                for ( Map context : installationsList )
+                {
+                    Installation installation = new Installation();
+                    installation.setName( ContinuumBuildConstant.getInstallationName( context ) );
+                    installation.setType( ContinuumBuildConstant.getInstallationType( context ) );
+                    installation.setVarName( ContinuumBuildConstant.getInstallationVarName( context ) );
+                    installation.setVarValue( ContinuumBuildConstant.getInstallationVarValue( context ) );
+                    installations.add( installation );
+                }
             }
-            project.setParent( getProjectParent( context ) );
-            project.setDependencies( getProjectDependencies( context ) );
-            project.setDevelopers( getProjectDevelopers( context ) );
-            project.setNotifiers( getProjectNotifiers( context ) );
 
-            projectDao.updateProject( project );
+            // call reload in case we disable the build agent
+            reload();
+
+            return installations;
         }
-        catch ( ContinuumStoreException e )
+        catch ( Exception e )
         {
-            throw new ContinuumException( "Unable to update project from working copy", e );
+            throw new ContinuumException( "Unable to get available installations of build agent", e );
         }
     }
 
@@ -712,8 +651,11 @@ public class DefaultDistributedBuildMana
                     directory = "";
                 }
 
-                SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
-                return client.generateWorkingCopyContent( projectId, directory, baseUrl, imageBaseUrl );
+                if ( isAgentAvailable( buildAgentUrl ) )
+                {
+                    SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                    return client.generateWorkingCopyContent( projectId, directory, baseUrl, imageBaseUrl );
+                }
             }
             catch ( MalformedURLException e )
             {
@@ -724,9 +666,13 @@ public class DefaultDistributedBuildMana
                 log.error( "Error while generating working copy content from build agent " + buildAgentUrl, e );
             }
         }
+
+        // call reload in case we disable the build agent
+        reload();
+
         return "";
     }
-
+    
     public String getFileContent( int projectId, String directory, String filename )
         throws ContinuumException
     {
@@ -743,8 +689,11 @@ public class DefaultDistributedBuildMana
 
             try
             {
-                SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
-                return client.getProjectFileContent( projectId, directory, filename );
+                if ( isAgentAvailable( buildAgentUrl ) )
+                {
+                    SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                    return client.getProjectFileContent( projectId, directory, filename );
+                }
             }
             catch ( MalformedURLException e )
             {
@@ -755,561 +704,797 @@ public class DefaultDistributedBuildMana
                 log.error( "Error while retrieving content of " + filename, e );
             }
         }
+
+        // call reload in case we disable the build agent
+        reload();
+
         return "";
     }
 
-    public boolean shouldBuild( Map<String, Object> context )
+    public void removeFromPrepareBuildQueue( String buildAgentUrl, int projectGroupId, int scmRootId )
+        throws ContinuumException
     {
         try
         {
-            int projectId = ContinuumBuildConstant.getProjectId( context );
-
-            int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
-
-            int trigger = ContinuumBuildConstant.getTrigger( context );
-
-            Project project = projectDao.getProjectWithAllDetails( projectId );
-
-            BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-
-            BuildResult oldBuildResult =
-                buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
-
-            List<ProjectDependency> modifiedDependencies = getModifiedDependencies( oldBuildResult, context );
-
-            List<ChangeSet> changes = getScmChanges( context );
-
-            if ( buildDefinition.isBuildFresh() )
+            if ( isAgentAvailable( buildAgentUrl ) )
             {
-                log.info( "FreshBuild configured, building" );
-                return true;
-            }
-            if ( buildDefinition.isAlwaysBuild() )
-            {
-                log.info( "AlwaysBuild configured, building" );
-                return true;
-            }
-            if ( oldBuildResult == null )
-            {
-                log.info( "The project was never be built with the current build definition, building" );
-                return true;
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                client.removeFromPrepareBuildQueue( projectGroupId, scmRootId );
             }
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId + 
+                       " from prepare build queue: Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumException( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId + 
+                                          " from prepare build queue: Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId + 
+                       " from prepare build queue of agent " + buildAgentUrl, e );
+            throw new ContinuumException( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" +
+                                          scmRootId + " from prepare build queue of agent " + buildAgentUrl, e );
+        }
 
-            //CONTINUUM-1428
-            if ( project.getOldState() == ContinuumProjectState.ERROR ||
-                oldBuildResult.getState() == ContinuumProjectState.ERROR )
-            {
-                log.info( "Latest state was 'ERROR', building" );
-                return true;
-            }
+        // call reload in case we disable the build agent
+        reload();
+    }
 
-            if ( trigger == ContinuumProjectState.TRIGGER_FORCED )
+    public void removeFromBuildQueue( String buildAgentUrl, int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        try
+        {
+            if ( isAgentAvailable( buildAgentUrl ) )
             {
-                log.info( "The project build is forced, building" );
-                return true;
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                client.removeFromBuildQueue( projectId, buildDefinitionId );
             }
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Unable to remove project " + projectId + 
+                       " from build queue: Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumException( "Unable to remove project " + projectId + 
+                                          " from build queue: Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error occurred while removing project " + projectId +
+                       " from build queue of agent " + buildAgentUrl, e );
+            throw new ContinuumException( "Error occurred while removing project " + projectId + 
+                                          " from build queue of agent " + buildAgentUrl, e );
+        }
 
-            Date date = ContinuumBuildConstant.getLatestUpdateDate( context );
-            if ( date != null && oldBuildResult.getLastChangedDate() >= date.getTime() )
+        // call reload in case we disable the build agent
+        reload();
+    }
+
+    public void removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws ContinuumException
+    {
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                log.info( "No changes found,not building" );
-                return false;
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                        client.removeFromPrepareBuildQueue( hashCodes );
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    log.error( "Error trying to remove projects from prepare build queue. Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Error trying to remove projects from prepare build queue of agent " + buildAgentUrl, e );
+                }
             }
-            else if ( date != null && changes.isEmpty() )
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+    }
+
+    public void removeFromBuildQueue( List<String> hashCodes )
+        throws ContinuumException
+    {
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                // fresh checkout from build agent that's why changes is empty
-                log.info( "Changes found in the current project, building" );
-                return true;
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                        client.removeFromBuildQueue( hashCodes );
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    log.error( "Error trying to remove projects from build queue. Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Error trying to remove projects from build queue of agent " + buildAgentUrl, e );
+                }
             }
+        }
 
-            boolean shouldBuild = false;
+        // call reload in case we disable a build agent
+        reload();
+    }
 
-            boolean allChangesUnknown = true;
+    public boolean isProjectInAnyPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        boolean found = false;
 
-            if ( project.getOldState() != ContinuumProjectState.NEW &&
-                project.getOldState() != ContinuumProjectState.CHECKEDOUT &&
-                project.getState() != ContinuumProjectState.NEW &&
-                project.getState() != ContinuumProjectState.CHECKEDOUT )
+        synchronized( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                // Check SCM changes
-                allChangesUnknown = checkAllChangesUnknown( changes );
-
-                if ( allChangesUnknown )
+                try
                 {
-                    if ( !changes.isEmpty() )
+                    if ( isAgentAvailable( buildAgentUrl ) )
                     {
-                        log.info(
-                            "The project was not built because all changes are unknown (maybe local modifications or ignored files not defined in your SCM tool." );
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+
+                        List<Map<String, Object>> projects = client.getProjectsAndBuildDefinitionsInPrepareBuildQueue();
+    
+                        for ( Map<String, Object> context : projects )
+                        {
+                            int pid = ContinuumBuildConstant.getProjectId( context );
+                            int buildId = ContinuumBuildConstant.getBuildDefinitionId( context );
+
+                            if ( pid == projectId && buildId == buildDefinitionId )
+                            {
+                                found = true;
+                                break;
+                            }
+
+                        }
                     }
-                    else
+
+                    if ( found )
                     {
-                        log.info(
-                            "The project was not built because no changes were detected in sources since the last build." );
+                        break;
                     }
                 }
-
-                // Check dependencies changes
-                if ( modifiedDependencies != null && !modifiedDependencies.isEmpty() )
+                catch ( MalformedURLException e )
                 {
-                    log.info( "Found dependencies changes, building" );
-                    shouldBuild = true;
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl ); 
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error while retrieving projects in prepare build queue", e );
                 }
             }
+        }
 
-            // Check changes
-            if ( !shouldBuild && ( ( !allChangesUnknown && !changes.isEmpty() ) ||
-                project.getExecutorId().equals( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR ) ) )
-            {
-                shouldBuild = shouldBuild( changes, buildDefinition, project, getMavenProjectVersion( context ),
-                                           getMavenProjectModules( context ) );
-            }
-
-            if ( shouldBuild )
-            {
-                log.info( "Changes found in the current project, building" );
-            }
-            else
-            {
-                log.info( "No changes in the current project, not building" );
-            }
+        // call reload in case we disable a build agent
+        reload();
 
-            return shouldBuild;
+        if ( found )
+        {
+            return true;
         }
-        catch ( ContinuumStoreException e )
+        else
         {
-            log.error( "Failed to determine if project should build", e );
+            return false;
         }
-        catch ( ContinuumException e )
+    }
+
+    public boolean isProjectInAnyBuildQueue( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        Map<String, List<BuildProjectTask>> map = getProjectsInBuildQueue();
+
+        for ( String url : map.keySet() )
         {
-            log.error( "Failed to determine if project should build", e );
+            for ( BuildProjectTask task : map.get( url ) )
+            {
+                if ( task.getProjectId() == projectId && task.getBuildDefinitionId() == buildDefinitionId )
+                {
+                    return true;
+                }
+            }
         }
 
         return false;
     }
 
-    private boolean shouldBuild( List<ChangeSet> changes, BuildDefinition buildDefinition, Project project,
-                                 String mavenProjectVersion, List<String> mavenProjectModules )
+    public boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws ContinuumException
     {
-        //Check if it's a recursive build
-        boolean isRecursive = false;
-        if ( StringUtils.isNotEmpty( buildDefinition.getArguments() ) )
-        {
-            isRecursive = buildDefinition.getArguments().indexOf( "-N" ) < 0 &&
-                buildDefinition.getArguments().indexOf( "--non-recursive" ) < 0;
-        }
+        boolean found = false;
 
-        if ( isRecursive && changes != null && !changes.isEmpty() )
+        synchronized( overallDistributedBuildQueues )
         {
-            if ( log.isInfoEnabled() )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                log.info( "recursive build and changes found --> building" );
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                        List<Map<String, Object>> projects = client.getProjectsAndBuildDefinitionsCurrentlyPreparingBuild();
+    
+                        for ( Map<String, Object> context : projects )
+                        {
+                            int pid = ContinuumBuildConstant.getProjectId( context );
+                            int buildId = ContinuumBuildConstant.getBuildDefinitionId( context );
+    
+                            if ( pid == projectId && buildId == buildDefinitionId )
+                            {
+                                found = true;
+                                break;
+                            }
+                        }
+                    }
+
+                    if ( found )
+                    {
+                        break;
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error retrieving projects currently preparing build in " + buildAgentUrl, e );
+                }
             }
-            return true;
         }
 
-        if ( !project.getVersion().equals( mavenProjectVersion ) )
+        // call reload in case we disable a build agent
+        reload();
+
+        if ( found )
         {
-            log.info( "Found changes in project's version ( maybe project was recently released ), building" );
             return true;
         }
-
-        if ( changes == null || changes.isEmpty() )
+        else
         {
-            if ( log.isInfoEnabled() )
-            {
-                log.info( "Found no changes, not building" );
-            }
             return false;
         }
+    }
 
-        //check if changes are only in sub-modules or not
-        List<ChangeFile> files = new ArrayList<ChangeFile>();
-        for ( ChangeSet changeSet : changes )
-        {
-            files.addAll( changeSet.getFiles() );
-        }
+    public boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        Map<String, BuildProjectTask> map = getProjectsCurrentlyBuilding();
 
-        int i = 0;
-        while ( i <= files.size() - 1 )
+        for ( String url : map.keySet() )
         {
-            ChangeFile file = files.get( i );
-            if ( log.isDebugEnabled() )
+            BuildProjectTask task = map.get( url );
+
+            if ( task.getProjectId() == projectId && task.getBuildDefinitionId() == buildDefinitionId )
             {
-                log.debug( "changeFile.name " + file.getName() );
-                log.debug( "check in modules " + mavenProjectModules );
+                return true;
             }
-            boolean found = false;
-            if ( mavenProjectModules != null )
+        }
+
+        return false;
+    }
+
+    private String getBuildAgent( int projectId )
+        throws ContinuumException
+    {
+        String agentUrl = null;
+
+        synchronized( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                for ( String module : mavenProjectModules )
+                OverallDistributedBuildQueue overallDistributedBuildQueue = 
+                    overallDistributedBuildQueues.get( buildAgentUrl );
+    
+                if ( overallDistributedBuildQueue != null )
                 {
-                    if ( file.getName().indexOf( module ) >= 0 )
+                    try
                     {
-                        if ( log.isDebugEnabled() )
+                        if ( isAgentAvailable( buildAgentUrl ) )
                         {
-                            log.debug( "changeFile.name " + file.getName() + " removed because in a module" );
+                            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                            
+                            if ( client.isProjectCurrentlyBuilding( projectId ) )
+                            {
+                                agentUrl = buildAgentUrl;
+                                break;
+                            }
                         }
-                        files.remove( file );
-                        found = true;
-                        break;
                     }
-                    if ( log.isDebugEnabled() )
+                    catch ( MalformedURLException e )
+                    {
+                        log.warn( "Unable to check if project " + projectId + " is currently building in agent: Invalid build agent url" + buildAgentUrl );
+                    }
+                    catch ( Exception e )
                     {
-                        log.debug( "not removing file " + file.getName() + " not in module " + module );
+                        log.warn( "Unable to check if project " + projectId + " is currently building in agent", e );
                     }
                 }
             }
-            if ( !found )
-            {
-                i++;
-            }
         }
 
-        boolean shouldBuild = !files.isEmpty();
+        // call reload in case we disable a build agent
+        reload();
 
-        if ( !shouldBuild )
-        {
-            log.info( "Changes are only in sub-modules." );
-        }
+        return agentUrl;
+    }
 
-        if ( log.isDebugEnabled() )
+    private void createDistributedBuildQueueForAgent( String buildAgentUrl )
+        throws ComponentLookupException
+    {
+        if ( !overallDistributedBuildQueues.containsKey( buildAgentUrl ) )
         {
-            log.debug( "shoulbuild = " + shouldBuild );
-        }
+            OverallDistributedBuildQueue overallDistributedBuildQueue =
+                (OverallDistributedBuildQueue) container.lookup( OverallDistributedBuildQueue.class );
+            overallDistributedBuildQueue.setBuildAgentUrl( buildAgentUrl );
+            overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().setBuildAgentUrl( buildAgentUrl );
 
-        return shouldBuild;
+            overallDistributedBuildQueues.put( buildAgentUrl, overallDistributedBuildQueue );
+        }
     }
 
-    private boolean checkAllChangesUnknown( List<ChangeSet> changes )
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroupAndScmRoot( int projectGroupId, int scmRootId )
+        throws ContinuumException
     {
-        for ( ChangeSet changeSet : changes )
+        synchronized( overallDistributedBuildQueues )
         {
-            List<ChangeFile> changeFiles = changeSet.getFiles();
-
-            for ( ChangeFile changeFile : changeFiles )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                if ( !"unknown".equalsIgnoreCase( changeFile.getStatus() ) )
+                OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+                try
                 {
-                    return false;
+                    for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
+                    {
+                        if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
+                        {
+                            return distributedBuildQueue;
+                        }
+                    }
+                }
+                catch ( TaskQueueException e )
+                {
+                    log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId, e );
+                    throw new ContinuumException( "Error occurred while retrieving distributed build queue of group", e );
                 }
             }
         }
 
-        return true;
+        return null;
     }
 
-    private List<ProjectDependency> getModifiedDependencies( BuildResult oldBuildResult, Map<String, Object> context )
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueueByScmRoot( ProjectScmRoot scmRoot, int projectGroupId )
         throws ContinuumException
     {
-        if ( oldBuildResult == null )
-        {
-            return null;
-        }
+        int scmRootId = scmRoot.getId();
 
-        try
+        synchronized( overallDistributedBuildQueues )
         {
-            Project project = projectDao.getProjectWithAllDetails( ContinuumBuildConstant.getProjectId( context ) );
-            List<ProjectDependency> dependencies = project.getDependencies();
-
-            if ( dependencies == null )
-            {
-                dependencies = new ArrayList<ProjectDependency>();
-            }
-
-            if ( project.getParent() != null )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                dependencies.add( project.getParent() );
-            }
+                OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
 
-            if ( dependencies.isEmpty() )
-            {
-                return null;
-            }
-
-            List<ProjectDependency> modifiedDependencies = new ArrayList<ProjectDependency>();
-
-            for ( ProjectDependency dep : dependencies )
-            {
-                Project dependencyProject =
-                    projectDao.getProject( dep.getGroupId(), dep.getArtifactId(), dep.getVersion() );
-
-                if ( dependencyProject != null )
+                try
                 {
-                    List<BuildResult> buildResults =
-                        buildResultDao.getBuildResultsInSuccessForProject( dependencyProject.getId(),
-                                                                           oldBuildResult.getEndTime() );
-                    if ( buildResults != null && !buildResults.isEmpty() )
+                    for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
                     {
-                        log.debug( "Dependency changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
-                            dep.getVersion() );
-                        modifiedDependencies.add( dep );
+                        if ( task.getProjectScmRootId() == scmRootId )
+                        {
+                            return distributedBuildQueue;
+                        }
                     }
-                    else
+
+                    Task task = distributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask();
+                    if ( task != null && ( (PrepareBuildProjectsTask) task ).getProjectScmRootId() == scmRootId )
                     {
-                        log.debug( "Dependency not changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
-                            dep.getVersion() );
+                        return distributedBuildQueue;
+                    }
+
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        List<Project> projects = projectDao.getProjectsInGroup( projectGroupId );
+                        List<Integer> pIds = new ArrayList<Integer>();
+
+                        for ( Project project : projects )
+                        {
+                            if ( project.getScmUrl().startsWith( scmRoot.getScmRootAddress() ) )
+                            {
+                                pIds.add( project.getId() );
+                            }
+                        }
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+
+                        if ( client.isProjectScmRootInQueue( scmRootId, pIds ) )
+                        {
+                            return distributedBuildQueue;
+                        }
                     }
                 }
-                else
+                catch ( TaskQueueException e )
+                {
+                    log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId, e );
+                    throw new ContinuumException( "Error occurred while retrieving distributed build queue of scmRoot", e );
+                }
+                catch ( MalformedURLException e )
+                {
+                    log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId + 
+                               ": Invalid build agent url " + buildAgentUrl );
+                    throw new ContinuumException( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId + 
+                               ": Invalid build agent url " + buildAgentUrl );
+                }
+                catch ( Exception e )
                 {
-                    log.debug( "Skip non Continuum project: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
-                        dep.getVersion() );
+                    log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId, e );
+                    throw new ContinuumException( "Error occurred while retrieving distributed build queue of scmRoot", e );
                 }
             }
-
-            return modifiedDependencies;
-        }
-        catch ( ContinuumStoreException e )
-        {
-            log.warn( "Can't get the project dependencies", e );
         }
 
         return null;
     }
 
-    private String getBuildAgent( int projectId )
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroup( int projectGroupId, List<ProjectScmRoot> scmRoots, int scmRootId )
         throws ContinuumException
     {
-        Map<String, PrepareBuildProjectsTask> map = getDistributedBuildProjects();
-
-        for ( String url : map.keySet() )
+        if ( scmRoots != null )
         {
-            PrepareBuildProjectsTask task = map.get( url );
-
-            for ( Integer id : task.getProjectsBuildDefinitionsMap().keySet() )
+            for ( ProjectScmRoot scmRoot : scmRoots )
             {
-                if ( projectId == id )
+                if ( scmRoot.getId() == scmRootId )
                 {
-                    return url;
+                    break;
+                }
+                else if ( scmRoot.getProjectGroup().getId() == projectGroupId )
+                {
+                    return getOverallDistributedBuildQueueByScmRoot( scmRoot, projectGroupId );
                 }
             }
         }
-
         return null;
     }
 
-    private BuildResult convertMapToBuildResult( Map<String, Object> context )
-    {
-        BuildResult buildResult = new BuildResult();
-
-        buildResult.setStartTime( ContinuumBuildConstant.getStartTime( context ) );
-        buildResult.setEndTime( ContinuumBuildConstant.getEndTime( context ) );
-        buildResult.setError( ContinuumBuildConstant.getBuildError( context ) );
-        buildResult.setExitCode( ContinuumBuildConstant.getBuildExitCode( context ) );
-        buildResult.setState( ContinuumBuildConstant.getBuildState( context ) );
-        buildResult.setTrigger( ContinuumBuildConstant.getTrigger( context ) );
-        buildResult.setBuildUrl( ContinuumBuildConstant.getBuildAgentUrl( context ) );
-
-        return buildResult;
-    }
-
-    private String getJavaHomeValue( BuildDefinition buildDefinition )
+    // need to change this
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueueByHashCode( int hashCode )
+        throws ContinuumException
     {
-        Profile profile = buildDefinition.getProfile();
-        if ( profile == null )
-        {
-            return null;
-        }
-        Installation jdk = profile.getJdk();
-        if ( jdk == null )
+        synchronized( overallDistributedBuildQueues )
         {
-            return null;
-        }
-        return jdk.getVarValue();
-    }
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
 
-    private Map<String, String> getEnvironmentVariables( BuildDefinition buildDefinition )
-    {
-        Profile profile = buildDefinition.getProfile();
-        Map<String, String> envVars = new HashMap<String, String>();
-        if ( profile == null )
-        {
-            return envVars;
-        }
-        List<Installation> environmentVariables = profile.getEnvironmentVariables();
-        if ( environmentVariables.isEmpty() )
-        {
-            return envVars;
-        }
-        for ( Installation installation : environmentVariables )
-        {
-            envVars.put( installation.getVarName(), installation.getVarValue() );
+                try
+                {
+                    for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
+                    {
+                        if ( task.getHashCode() == hashCode )
+                        {
+                            return distributedBuildQueue;
+                        }
+                    }
+                }
+                catch ( TaskQueueException e )
+                {
+                    log.error( "Error occurred while retrieving distributed build queue", e );
+                    throw new ContinuumException( "Error occurred while retrieving distributed build queue", e );
+                }
+            }
         }
-        return envVars;
+
+        return null;
     }
 
-    private List<ChangeSet> getScmChanges( Map<String, Object> context )
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueueByAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitionsMap )
+        throws ContinuumException
     {
-        List<ChangeSet> changes = new ArrayList<ChangeSet>();
-        List<Map> scmChanges = ContinuumBuildConstant.getScmChanges( context );
+        OverallDistributedBuildQueue whereToBeQueued = null;
+
+        BuildAgentGroupConfiguration buildAgentGroup = getBuildAgentGroup( projectsAndBuildDefinitionsMap );
 
-        if ( scmChanges != null )
+        if ( buildAgentGroup != null )
         {
-            for ( Map map : scmChanges )
+            List<BuildAgentConfiguration> buildAgents = buildAgentGroup.getBuildAgents();
+
+            if ( buildAgents != null && buildAgents.size() > 0 )
             {
-                ChangeSet changeSet = new ChangeSet();
-                changeSet.setAuthor( ContinuumBuildConstant.getChangeSetAuthor( map ) );
-                changeSet.setComment( ContinuumBuildConstant.getChangeSetComment( map ) );
-                changeSet.setDate( ContinuumBuildConstant.getChangeSetDate( map ) );
-                setChangeFiles( changeSet, map );
-                changes.add( changeSet );
+                List<String> buildAgentUrls = new ArrayList<String>();
+                
+                for ( BuildAgentConfiguration buildAgent : buildAgents )
+                {
+                    buildAgentUrls.add( buildAgent.getUrl() );
+                }
+
+                synchronized( overallDistributedBuildQueues )
+                {
+                    int idx = 0;
+                    int size = 0;
+                    
+                    for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+                    {
+                        if ( !buildAgentUrls.isEmpty() && buildAgentUrls.contains( buildAgentUrl ) )
+                        {
+                            OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+                            if ( distributedBuildQueue != null )
+                            {
+                                try
+                                {
+                                    if ( isAgentAvailable( buildAgentUrl ) )
+                                    {
+                                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                                        int agentBuildSize = client.getBuildSizeOfAgent();
+    
+                                        if ( idx == 0 )
+                                        {
+                                            whereToBeQueued = distributedBuildQueue;
+                                            size = agentBuildSize;
+                                            idx++;
+                                        }
+    
+                                        if ( agentBuildSize < size )
+                                        {
+                                            whereToBeQueued = distributedBuildQueue;
+                                            size = agentBuildSize;
+                                        }
+                                    }
+                                }
+                                catch ( MalformedURLException e )
+                                {
+                                    log.error( "Error occurred while retrieving distributed build queue: Invalid build agent url " + buildAgentUrl );
+                                }
+                                catch ( Exception e )
+                                {
+                                    log.error( "Error occurred while retrieving distributed build queue ", e );
+                                }
+                            }
+                        }
+                    }
+                }
             }
         }
 
-        return changes;
+        return whereToBeQueued;
     }
 
-    private void setChangeFiles( ChangeSet changeSet, Map<String, Object> context )
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueue()
+        throws ContinuumException
     {
-        List<Map> changeFiles = ContinuumBuildConstant.getChangeSetFiles( context );
+        OverallDistributedBuildQueue whereToBeQueued = null;
 
-        if ( changeFiles != null )
+        synchronized ( overallDistributedBuildQueues )
         {
-            for ( Map map : changeFiles )
+            if ( overallDistributedBuildQueues.isEmpty() )
             {
-                ChangeFile changeFile = new ChangeFile();
-                changeFile.setName( ContinuumBuildConstant.getChangeFileName( map ) );
-                changeFile.setRevision( ContinuumBuildConstant.getChangeFileRevision( map ) );
-                changeFile.setStatus( ContinuumBuildConstant.getChangeFileStatus( map ) );
+                log.info( "No distributed build queues are configured for build agents" );
+                return null;
+            }
+
+            int idx = 0;
+            int size = 0;
 
-                changeSet.addFile( changeFile );
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+                if ( distributedBuildQueue != null )
+                {
+                    try
+                    {
+                        if ( isAgentAvailable( buildAgentUrl ) )
+                        {
+                            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                            int agentBuildSize = client.getBuildSizeOfAgent();
+    
+                            if ( idx == 0 )
+                            {
+                                whereToBeQueued = distributedBuildQueue;
+                                size = agentBuildSize;
+                                idx++;
+                            }
+    
+                            if ( agentBuildSize < size )
+                            {
+                                whereToBeQueued = distributedBuildQueue;
+                                size = agentBuildSize;
+                            }
+                        }
+                    }
+                    catch ( MalformedURLException e )
+                    {
+                        log.error( "Error occurred while retrieving distributed build queue: invalid build agent url " + buildAgentUrl );
+                    }
+                    catch ( Exception e )
+                    {
+                        log.error( "Error occurred while retrieving distributed build queue", e );
+                        throw new ContinuumException( "Error occurred while retrieving distributed build queue", e );
+                    }
+                }
             }
         }
+
+        return whereToBeQueued;
     }
 
-    private ProjectDependency getProjectParent( Map<String, Object> context )
+    private BuildAgentGroupConfiguration getBuildAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitions )
+        throws ContinuumException
     {
-        Map map = ContinuumBuildConstant.getProjectParent( context );
-
-        if ( map != null && map.size() > 0 )
+        if ( projectsAndBuildDefinitions == null )
         {
-            ProjectDependency parent = new ProjectDependency();
-            parent.setGroupId( ContinuumBuildConstant.getGroupId( map ) );
-            parent.setArtifactId( ContinuumBuildConstant.getArtifactId( map ) );
-            parent.setVersion( ContinuumBuildConstant.getVersion( map ) );
-
-            return parent;
+            return null;
         }
+        
+        try
+        {
+            List<Project> projects = new ArrayList<Project>();
 
-        return null;
-    }
+            for ( Integer projectId : projectsAndBuildDefinitions.keySet() )
+            {
+                projects.add( projectDao.getProjectWithDependencies( projectId ) );
+            }
 
-    private List<ProjectDependency> getProjectDependencies( Map<String, Object> context )
-    {
-        List<ProjectDependency> projectDependencies = new ArrayList<ProjectDependency>();
+            projects = ProjectSorter.getSortedProjects( projects, log );
 
-        List<Map> dependencies = ContinuumBuildConstant.getProjectDependencies( context );
+            int buildDefinitionId = projectsAndBuildDefinitions.get( projects.get( 0 ).getId() );
+            BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
 
-        if ( dependencies != null )
-        {
-            for ( Map map : dependencies )
+            Profile profile = buildDefinition.getProfile();
+
+            if ( profile != null && !StringUtils.isEmpty( profile.getBuildAgentGroup() ) )
             {
-                ProjectDependency dependency = new ProjectDependency();
-                dependency.setGroupId( ContinuumBuildConstant.getGroupId( map ) );
-                dependency.setArtifactId( ContinuumBuildConstant.getArtifactId( map ) );
-                dependency.setVersion( ContinuumBuildConstant.getVersion( map ) );
+                String groupName = profile.getBuildAgentGroup();
+
+                BuildAgentGroupConfiguration buildAgentGroup = configurationService.getBuildAgentGroup( groupName );
 
-                projectDependencies.add( dependency );

[... 208 lines stripped ...]