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 2008/12/11 12:02:40 UTC

svn commit: r725657 - in /continuum/branches/continuum-parallel-builds: continuum-api/src/main/java/org/apache/continuum/buildmanager/ continuum-api/src/main/java/org/apache/continuum/taskqueue/ continuum-core/src/main/java/org/apache/continuum/buildma...

Author: oching
Date: Thu Dec 11 03:02:39 2008
New Revision: 725657

URL: http://svn.apache.org/viewvc?rev=725657&view=rev
Log:
- updated implementation of parallel builds manager
- added tests
- changed instantiation-strategy of task queues to per-lookup

Added:
    continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildsManager.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/buildmanager/ParallelBuildsManager.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/test/java/org/apache/continuum/buildmanager/ParallelBuildsManagerTest.java
Removed:
    continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildManager.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/buildmanager/DefaultBuildManager.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/test/java/org/apache/continuum/buildmanager/DefaultBuildManagerTest.java
Modified:
    continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallBuildQueue.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueue.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java
    continuum/branches/continuum-parallel-builds/continuum-core/src/main/resources/META-INF/plexus/components.xml
    continuum/branches/continuum-parallel-builds/continuum-model/pom.xml
    continuum/branches/continuum-parallel-builds/continuum-model/src/main/mdo/continuum.xml

Added: continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildsManager.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildsManager.java?rev=725657&view=auto
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildsManager.java (added)
+++ continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildsManager.java Thu Dec 11 03:02:39 2008
@@ -0,0 +1,82 @@
+package org.apache.continuum.buildmanager;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.continuum.taskqueue.OverallBuildQueue;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+
+/**
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ *
+ */
+public interface BuildsManager
+{       
+    // NOTE: deng parallel builds 
+    // I think we can move out the prepare build queue from the build manager?
+    //      only builds and checkouts should be executed in parallel? :D
+    
+    public void buildProjects( List<Project> projects, Map<Integer, BuildDefinition> projectsBuildDefinitionsMap, int trigger ) throws BuildManagerException;
+    
+    public void buildProject( int projectId, BuildDefinition buildDefinition, String projectName, int trigger ) throws BuildManagerException;
+    
+    //public void prepareBuildProjects( Collection<Map<Integer, Integer>> projectsBuildDefinitions, int trigger, int scheduleId );
+    
+    //public void prepareBuildProject( int projectId, BuildDefinition buildDefinition, String projectName, int trigger, int scheduleId );
+    
+    // project checkout doesn't require dependency checking
+    public void checkoutProject( int projectId, String projectName, File workingDirectory, String scmUsername, String scmPassword, BuildDefinition defaultBuildDefinition ) throws BuildManagerException;
+        
+    public boolean cancelBuild( int projectId ) throws BuildManagerException;
+    
+    public boolean cancelAllBuilds() throws BuildManagerException;
+    
+    public boolean cancelBuildInQueue( int buildQueueId ) throws BuildManagerException;
+    
+    public boolean cancelCheckout(int projectId) throws BuildManagerException;
+    
+    public boolean cancelAllCheckouts() throws BuildManagerException;
+    
+    //public boolean cancelPrepareBuild(int projectId) throws BuildManagerException;
+    
+    //public boolean cancelAllPrepareBuilds() throws BuildManagerException;
+    
+    public void removeProjectFromBuildQueue( int projectId ) throws BuildManagerException;
+    
+    public void removeProjectsFromBuildQueue( int[] projectIds );
+    
+    public void removeProjectFromCheckoutQueue( int projectId ) throws BuildManagerException;
+    
+    public void removeProjectsFromCheckoutQueue( int[] projectIds );
+    
+    //public void removeProjectFromPrepareBuildQueue( int projectId );
+    
+   // public void removeProjectsFromPrepareBuildQueue( int[] projectIds );
+    
+    public void addOverallBuildQueue( OverallBuildQueue overallBuildQueue );
+    
+    public void removeOverallBuildQueue( int overallBuildQueueId ) throws BuildManagerException;
+
+}

Modified: continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallBuildQueue.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallBuildQueue.java?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallBuildQueue.java (original)
+++ continuum/branches/continuum-parallel-builds/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallBuildQueue.java Thu Dec 11 03:02:39 2008
@@ -39,6 +39,14 @@
     
     void setId( int id );
     
+    /**
+     * Returns the name of the "overall" build queue
+     * @return
+     */
+    String getName();
+    
+    void setName( String name );
+    
     /* Checkout Queue */
     
     /**

Added: continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/buildmanager/ParallelBuildsManager.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/buildmanager/ParallelBuildsManager.java?rev=725657&view=auto
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/buildmanager/ParallelBuildsManager.java (added)
+++ continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/buildmanager/ParallelBuildsManager.java Thu Dec 11 03:02:39 2008
@@ -0,0 +1,674 @@
+package org.apache.continuum.buildmanager;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.taskqueue.OverallBuildQueue;
+import org.apache.maven.continuum.buildqueue.BuildProjectTask;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.scm.queue.CheckOutTask;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Parallel builds manager.
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @plexus.component role="org.apache.continuum.buildmanager.BuildsManager" role-hint="parallel"
+ */
+public class ParallelBuildsManager
+    implements BuildsManager
+{
+    private Logger log = LoggerFactory.getLogger( ParallelBuildsManager.class );
+        
+    // map must be synchronized
+    private Map<Integer, OverallBuildQueue> overallBuildQueues =
+        Collections.synchronizedMap( new HashMap<Integer, OverallBuildQueue>() );
+    
+    private static final int BUILD_QUEUE = 1;
+    
+    private static final int CHECKOUT_QUEUE = 2;
+    
+    private static final int PREPARE_BUILD_QUEUE = 3;
+    
+    /**
+     * @plexus.requirement
+     */
+    private BuildDefinitionDao buildDefinitionDao;
+        
+    // REQUIREMENTS:
+    // UI:
+    // - add a new page for adding a build queue. It should have a build queue name that 
+    //   will be used to associate it with a schedule. The number of build queues that can 
+    //   be added should respect the "Number of Allowed Builds in Parallel" set in the 
+    //   General Configuration.
+    // - in the add/edit schedule page, add a list box that contains the build queues which 
+    //   would allow the user to select which build queue(s) to associate with the schedule.
+    //
+    // Back-end:
+    // 1. when a build is triggered:
+    //    * check for available build queue(s) associated with the schedule. Get the first available 
+    //          build queue.
+    //    * add the project to the associated build queue's checkout queue or build queue depending 
+    //          whether the project is configured to always "build fresh"
+    //    * once the build finishes, remove the project build instance from the associated build queue
+    //    * build the next project in the queue
+    //2. for releases:
+    //    * projects to be released will be built in sequence in a queue of their own. As long as 
+    //          they don't modify the build state or working copy it is ok to build the original 
+    //          project simultaneously. If the working copy changes are made in place for bumping 
+    //          versions, suggest blocking it and being built elsewhere.
+        
+    public void buildProject( int projectId, BuildDefinition buildDefinition, String projectName, int trigger ) throws BuildManagerException
+    {   
+        try
+        {
+            if( isInQueue( projectId, BUILD_QUEUE ) )
+            {
+                log.warn( "Project already queued." );
+                return;
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while checking if the project is already in queue: " + e.getMessage() );
+        }
+        
+        OverallBuildQueue overallBuildQueue =
+            getOverallBuildQueue( projectId, BUILD_QUEUE, buildDefinition.getSchedule().getBuildQueues() );
+                
+        String buildDefinitionLabel = buildDefinition.getDescription();
+        if ( StringUtils.isEmpty( buildDefinitionLabel ) )
+        {
+            buildDefinitionLabel = buildDefinition.getGoals();
+        }
+        
+        Task buildTask = new BuildProjectTask( projectId, buildDefinition.getId(), trigger, projectName,
+                                                 buildDefinitionLabel);
+        try
+        {   
+            overallBuildQueue.addToBuildQueue( buildTask );
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while adding project to build queue: "  + e.getMessage() );
+        }        
+    }
+    
+    public void buildProjects( List<Project> projects,
+                   Map<Integer, BuildDefinition> projectsBuildDefinitionsMap, int trigger ) throws BuildManagerException
+    {   
+        int firstProjectId = 0;        
+        // get id of the first project in the list that is not yet in the build queue
+        for( Project project : projects )
+        {
+            try
+            {
+                if( !isInQueue( project.getId(), BUILD_QUEUE ) )
+                {
+                    firstProjectId = project.getId();
+                    break;
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.warn( "Error occurred while verifying if project is already queued." );
+                continue;
+            }
+        }
+         
+        if( firstProjectId != 0 )
+        {
+            BuildDefinition buildDef = projectsBuildDefinitionsMap.get( firstProjectId );
+            OverallBuildQueue overallBuildQueue =
+                getOverallBuildQueue( firstProjectId, BUILD_QUEUE, buildDef.getSchedule().getBuildQueues() );;
+            
+            if( overallBuildQueue != null )
+            {
+                for( Project project :  projects )
+                {   
+                    try
+                    {
+                        if( isInQueue( project.getId(), BUILD_QUEUE ) )
+                        {
+                            continue;
+                        }
+                    }
+                    catch ( TaskQueueException e )
+                    {
+                        log.warn( "Error occurred while verifying if project is already queued." );
+                        continue;
+                    }
+                    
+                    BuildDefinition buildDefinition = projectsBuildDefinitionsMap.get( project.getId() );
+                    String buildDefinitionLabel = buildDefinition.getDescription();
+                    if ( StringUtils.isEmpty( buildDefinitionLabel ) )
+                    {
+                        buildDefinitionLabel = buildDefinition.getGoals();
+                    }
+                    
+                    Task buildTask = new BuildProjectTask( project.getId(), buildDefinition.getId(), trigger, project.getName(),
+                                                             buildDefinitionLabel);
+                    try
+                    {   
+                        overallBuildQueue.addToBuildQueue( buildTask );
+                    }
+                    catch ( TaskQueueException e )
+                    {
+                        throw new BuildManagerException( "Error occurred while adding project to build queue: "  + e.getMessage() );
+                    }
+                }
+            }
+        }
+        else
+        {
+            log.error( "Projects are already in build queue." );
+            throw new BuildManagerException( "Projects are already in build queue." );
+        }
+    }    
+    
+    public boolean cancelBuildInQueue( int buildQueueId ) throws BuildManagerException
+    {            
+        synchronized( overallBuildQueues )
+        {       
+            OverallBuildQueue overallBuildQueue = null;
+            try
+            {                
+                overallBuildQueue = overallBuildQueues.get( buildQueueId );
+                if( overallBuildQueue != null )
+                {
+                    overallBuildQueue.cancelCurrentBuild();
+                }
+                else
+                {
+                    log.warn( "Project not found in any of the build queues." );
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Cannot cancel build on build queue '" + overallBuildQueue.getName() + "'." );
+                throw new BuildManagerException( "Cannot cancel build on build queue '" + overallBuildQueue.getName() +
+                                 "': " + e.getMessage() );
+            }            
+            return true;
+        }                
+    }
+
+    public boolean cancelAllBuilds() throws BuildManagerException
+    {   
+        synchronized( overallBuildQueues )
+        {
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            OverallBuildQueue overallBuildQueue = null;
+            
+            try
+            {                
+                for( Integer key : keySet )
+                {
+                    overallBuildQueue = overallBuildQueues.get( key );                
+                    overallBuildQueue.cancelCurrentBuild();                
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Cannot cancel build on build queue '" + overallBuildQueue.getName() + "'." );
+                throw new BuildManagerException( "Cannot cancel build on build queue '" + overallBuildQueue.getName() +
+                                 "': " + e.getMessage() );
+            }            
+            return true;
+        }
+    }
+
+    public boolean cancelAllCheckouts() throws BuildManagerException
+    {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    /*public boolean cancelAllPrepareBuilds() throws BuildManagerException
+    {
+        // TODO Auto-generated method stub
+        return false;
+    }*/
+
+    public boolean cancelBuild(int projectId) throws BuildManagerException
+    {   
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueue( projectId, BUILD_QUEUE );
+            if( overallBuildQueue != null )
+            {
+                overallBuildQueue.cancelBuildTask(  projectId );
+            }
+            else
+            {
+                throw new BuildManagerException( "Project not found in any of the build queues." );
+            }
+        }
+        catch( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while cancelling build: " +
+                 e.getMessage() );        
+        }
+        
+        return true;
+    }
+
+    // TODO: should this be permitted? (might need to execute svn cleanup?)
+    public boolean cancelCheckout(int projectId) throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueue( projectId, CHECKOUT_QUEUE );
+            if( overallBuildQueue != null )
+            {
+                //overallBuildQueue.getCheckoutQueue()
+            }
+            else
+            {
+                throw new BuildManagerException( "Project not found in any of the checkout queues." );
+            }
+        }
+        catch( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while cancelling build: " +
+                 e.getMessage() );        
+        }
+        
+        return true;
+    }
+
+    /*public boolean cancelPrepareBuild(int projectId) throws BuildManagerException
+    {
+        // TODO Auto-generated method stub
+        return false;
+    }*/
+
+    public void checkoutProject( int projectId, String projectName, File workingDirectory, String scmUsername, String scmPassword, BuildDefinition defaultBuildDefinition ) throws BuildManagerException
+    {   
+        try
+        {
+            if( isInQueue( projectId, CHECKOUT_QUEUE ) )
+            {
+                log.warn( "Project already in checkout queue." );
+                return;
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while checking if the project is already in queue: " + e.getMessage() );
+        }
+        
+        OverallBuildQueue overallBuildQueue =
+            getOverallBuildQueue( projectId, CHECKOUT_QUEUE, defaultBuildDefinition.getSchedule().getBuildQueues() );
+        
+        CheckOutTask checkoutTask =
+            new CheckOutTask( projectId, workingDirectory, projectName, scmUsername, scmPassword );
+        try
+        {
+            overallBuildQueue.addToCheckoutQueue( checkoutTask );
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while adding project to checkout queue: " + e.getMessage() );
+        }        
+    }
+
+    /*public void prepareBuildProject( int projectId, BuildDefinition buildDefinition, String projectName, int trigger, int scheduleId )
+    {
+        // TODO Auto-generated method stub
+
+    }*/
+
+    /*public void prepareBuildProjects( Collection<Map<Integer, Integer>> projectsBuildDefinitions, int trigger, int scheduleId )
+    {
+        // TODO Auto-generated method stub
+
+    }*/
+
+    public void removeProjectFromBuildQueue( int projectId ) throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueue( projectId, BUILD_QUEUE );
+            if( overallBuildQueue != null )
+            {
+                overallBuildQueue.removeProjectFromBuildQueue( projectId );
+            }
+            else
+            {
+                throw new BuildManagerException( "Project not found in any of the build queues." );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while removing project from build queue: " +
+                e.getMessage() );
+        }
+    }
+
+    public void removeProjectFromCheckoutQueue( int projectId ) throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueue( projectId, CHECKOUT_QUEUE );
+            if( overallBuildQueue != null )
+            {
+                overallBuildQueue.removeProjectFromCheckoutQueue( projectId );
+            }
+            else
+            {
+                throw new BuildManagerException( "Project not found in any of the checkout queues." );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while removing project from checkout queue: " +
+                e.getMessage() );
+        }
+    }
+
+    /*public void removeProjectFromPrepareBuildQueue( int projectId )
+    {
+        // TODO Auto-generated method stub
+
+    }*/
+
+    public void removeProjectsFromBuildQueue( int[] projectIds )
+    {
+        for( int i = 0; i < projectIds.length; i++ )
+        {
+            try
+            {
+                OverallBuildQueue overallBuildQueue = getOverallBuildQueue( projectIds[i], BUILD_QUEUE );
+                if( overallBuildQueue != null )
+                {
+                    overallBuildQueue.removeProjectFromBuildQueue( projectIds[i] );
+                }
+                else
+                {
+                    log.error( "Project '" + projectIds[i] + "' not found in any of the build queues." );
+                    continue;
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Error occurred while removing project '" + projectIds[i] + "' from build queue." );
+                continue;
+            }
+        }
+    }
+
+    public void removeProjectsFromCheckoutQueue( int[] projectIds )
+    {
+        for( int i = 0; i < projectIds.length; i++ )
+        {
+            try
+            {
+                OverallBuildQueue overallBuildQueue = getOverallBuildQueue( projectIds[i], CHECKOUT_QUEUE );
+                if( overallBuildQueue != null )
+                {
+                    overallBuildQueue.removeProjectFromCheckoutQueue( projectIds[i] );
+                }
+                else
+                {
+                    log.error( "Project '" + projectIds[i] + "' not found in any of the checkout queues." );
+                    continue;
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Error occurred while removing project '" + projectIds[i] + "' from checkout queue." );
+                continue;
+            }
+        }
+    }
+
+    public void removeProjectsFromPrepareBuildQueue( int[] projectIds )
+    {
+        // TODO Auto-generated method stub
+    }
+    
+    public void addOverallBuildQueue( OverallBuildQueue overallBuildQueue )
+    {
+        synchronized( overallBuildQueues )
+        {
+            this.overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue );
+        }
+    }
+    
+    public void removeOverallBuildQueue( int overallBuildQueueId ) throws BuildManagerException
+    {
+        List<BuildProjectTask> tasks = null;
+        List<CheckOutTask> checkoutTasks = null;
+        
+        synchronized( overallBuildQueues )        
+        {   
+            OverallBuildQueue overallBuildQueue = overallBuildQueues.get( overallBuildQueueId );
+            try
+            {
+                tasks = overallBuildQueue.getProjectsInBuildQueue();                
+                checkoutTasks = overallBuildQueue.getCheckOutTasksInQueue();
+                
+                overallBuildQueue.getBuildQueue().removeAll( tasks );
+                overallBuildQueue.getCheckoutQueue().removeAll( checkoutTasks );
+                 
+                overallBuildQueue = null;
+            }
+            catch ( TaskQueueException e )
+            {
+                throw new BuildManagerException(
+                         "Cannot remove build queue. An error occurred while retrieving queued tasks." );
+            }
+                        
+            this.overallBuildQueues.remove( overallBuildQueueId );
+        }
+        
+        try
+        {
+            for( BuildProjectTask task : tasks )
+            {
+                BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( task.getBuildDefinitionId() );
+                buildProject( task.getProjectId(), buildDefinition, task.getProjectName(), task.getTrigger() );                    
+            }
+         
+            for( CheckOutTask task : checkoutTasks )
+            {
+                BuildDefinition buildDefinition = buildDefinitionDao.getDefaultBuildDefinition( task.getProjectId() );
+                checkoutProject( task.getProjectId(), task.getProjectName(), task.getWorkingDirectory(),
+                                      task.getScmUserName(), task.getScmPassword(), buildDefinition );                    
+            }
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildManagerException(
+                "Cannot remove build queue: " + e.getMessage() );
+        }
+    }
+    
+    public Map<Integer, OverallBuildQueue> getOverallBuildQueues()
+    {
+        return overallBuildQueues;
+    }
+    
+    private boolean isInQueue( int projectId, int typeOfQueue )
+        throws TaskQueueException
+    {   
+        synchronized( overallBuildQueues )
+        {
+            Set<Integer> keySet = overallBuildQueues.keySet();        
+            for( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                if( typeOfQueue == BUILD_QUEUE )
+                {
+                    if( overallBuildQueue.isInBuildQueue( projectId ) )
+                    {
+                        return true;
+                    }
+                }
+                else if( typeOfQueue == CHECKOUT_QUEUE )
+                {
+                    if( overallBuildQueue.isInCheckoutQueue( projectId ) )
+                    {
+                        return true;
+                    }
+                }
+                /*else if( typeOfQueue == PREPARE_BUILD_QUEUE )
+                {
+                    if( overallBuildQueue.isInPrepareBuildQueue( projectId ) )
+                    {
+                        return true;
+                    }
+                }*/
+            }
+            
+            return false;
+        }
+    }
+    
+    private OverallBuildQueue getOverallBuildQueue( int projectId, int typeOfQueue )    
+        throws TaskQueueException
+    {
+        synchronized( overallBuildQueues )
+        {
+            OverallBuildQueue whereQueued = null;
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            
+            for( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                if( typeOfQueue == BUILD_QUEUE )
+                {
+                    if( overallBuildQueue.isInBuildQueue( projectId ) )
+                    {
+                        whereQueued = overallBuildQueue;
+                        break;
+                    }
+                }
+                else if( typeOfQueue == CHECKOUT_QUEUE )
+                {
+                    if( overallBuildQueue.isInCheckoutQueue( projectId ) )
+                    {
+                        whereQueued = overallBuildQueue;
+                        break;
+                    }
+                }
+                /*else if( typeOfQueue == PREPARE_BUILD_QUEUE )
+                {
+                    if( overallBuildQueue.isInPrepareBuildQueue( projectId ) )
+                    {
+                        whereQueued = overallBuildQueue;
+                        break;
+                    }
+                }*/
+            }
+            
+            return whereQueued;
+        }
+    }
+    
+    private OverallBuildQueue getOverallBuildQueue( int projectId, int typeOfQueue, List<BuildQueue> buildQueues )
+        throws BuildManagerException
+    {
+        OverallBuildQueue whereToBeQueued = null; 
+        synchronized( overallBuildQueues )
+        {
+            if( overallBuildQueues == null || overallBuildQueues.isEmpty() )
+            {
+                throw new BuildManagerException( "No build queues configured." );
+            }
+            
+            int size = 0;
+            int idx = 0;
+            try
+            {
+                for( BuildQueue buildQueue : buildQueues )
+                {
+                    OverallBuildQueue overallBuildQueue = overallBuildQueues.get( buildQueue.getId() ); 
+                    if( overallBuildQueue != null )
+                    {
+                        TaskQueue taskQueue = null;
+                        if( typeOfQueue == BUILD_QUEUE )
+                        {
+                            taskQueue = overallBuildQueue.getBuildQueue();
+                        }
+                        else if( typeOfQueue == CHECKOUT_QUEUE )
+                        {   
+                            taskQueue = overallBuildQueue.getCheckoutQueue();
+                        }
+                        /*else if( typeOfQueue == PREPARE_BUILD_QUEUE )
+                        {
+                            taskQueue = overallBuildQueue.getPrepareBuildQueue();
+                        }*/
+                                                
+                        if( idx == 0 )
+                        {
+                            size = taskQueue.getQueueSnapshot().size();
+                            whereToBeQueued = overallBuildQueue;
+                        }
+                        
+                        if( taskQueue.getQueueSnapshot().size() < size )
+                        {
+                            whereToBeQueued = overallBuildQueue;
+                            size = taskQueue.getQueueSnapshot().size();
+                        }
+                        
+                        idx++;
+                    }
+                    else
+                    {
+                        log.error( "Build queue not found." );
+                    }
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                throw new BuildManagerException( "Error occurred while retrieving task quueue: " + e.getMessage() );
+            }
+        }
+        
+        if( whereToBeQueued == null )
+        {
+            throw new BuildManagerException( "No build queue found." );
+        }
+        
+        return whereToBeQueued;
+    }
+
+    public void setBuildDefinitionDao( BuildDefinitionDao buildDefinitionDao )
+    {
+        this.buildDefinitionDao = buildDefinitionDao;
+    }
+}

Modified: continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueue.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueue.java?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueue.java (original)
+++ continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueue.java Thu Dec 11 03:02:39 2008
@@ -56,6 +56,10 @@
     extends AbstractLogEnabled
     implements OverallBuildQueue, Contextualizable
 {
+    // TODO: deng parallel builds
+    // - might need to set a task queue executor for each task queue! 
+    //      change getXXXXTaskQueueExecutor() methods
+    
     // TODO:
     // - need to specify each task queue to be instantiated each time it is looked up!!!
 
@@ -83,6 +87,8 @@
     
     private int id;
     
+    private String name;
+    
     public int getId()
     {
         return id;
@@ -92,6 +98,16 @@
     {
         this.id = id;
     }
+    
+    public String getName()
+    {
+        return name;
+    }
+    
+    public void setName( String name )
+    {
+        this.name = name;
+    }
 
     /* Checkout Queue */
 
@@ -291,7 +307,7 @@
     public TaskQueueExecutor getBuildTaskQueueExecutor()
         throws ComponentLookupException
     {        
-        return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "build-project" );        
+        return ( TaskQueueExecutor ) container.lookup( TaskQueueExecutor.class, "build-project" );        
     }
 
     public void addToBuildQueue( Task buildTask )

Modified: continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java (original)
+++ continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java Thu Dec 11 03:02:39 2008
@@ -664,6 +664,8 @@
 
         context.put( AbstractContinuumAction.KEY_PROJECT_ID, new Integer( projectId ) );
 
+        // TODO: deng parallel builds 
+        // - add default build definition of project (schedule is attached to the build def) to context!
         executeAction( "add-project-to-checkout-queue", context );
     }
 

Modified: continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java (original)
+++ continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java Thu Dec 11 03:02:39 2008
@@ -56,6 +56,9 @@
         throws Exception
     {
 
+        //TODO: deng parallel builds
+        // - get the default build definition from context and pass to parallel builds manager!
+        
         Project project = (Project) getObject( context, KEY_PROJECT, null );
         if ( project == null )
         {

Modified: continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java (original)
+++ continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java Thu Dec 11 03:02:39 2008
@@ -65,6 +65,11 @@
     public synchronized void execute( Map context )
         throws Exception
     {
+    // TODO: deng parallel builds
+    // - context now contains a "list" of projects and a "map" of projectId, build definition ket-value pair
+    // - update the list of projects
+    // - pass this updated list + map of build definitions to builds manager
+        
         Project project = AbstractContinuumAction.getProject( context );
         int buildDefinitionId = AbstractContinuumAction.getBuildDefinitionId( context );
         int trigger = AbstractContinuumAction.getTrigger( context );

Modified: continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java (original)
+++ continuum/branches/continuum-parallel-builds/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java Thu Dec 11 03:02:39 2008
@@ -464,6 +464,11 @@
                 shouldBuild = true;
             }
 
+            // TODO: deng parallel builds.. 
+            // - add those projects which should be built into a list
+            //       and also add the build definition into a map of <projectId,build definition> 
+            // - set these in the context map 
+            // 
             if ( shouldBuild )
             {
                 try

Modified: continuum/branches/continuum-parallel-builds/continuum-core/src/main/resources/META-INF/plexus/components.xml
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-core/src/main/resources/META-INF/plexus/components.xml?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-core/src/main/resources/META-INF/plexus/components.xml (original)
+++ continuum/branches/continuum-parallel-builds/continuum-core/src/main/resources/META-INF/plexus/components.xml Thu Dec 11 03:02:39 2008
@@ -57,6 +57,7 @@
     <component>
       <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
       <role-hint>build-project</role-hint>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
       <implementation>org.apache.maven.continuum.buildcontroller.BuildProjectTaskExecutor</implementation>
       <requirements>
         <requirement>
@@ -71,8 +72,8 @@
     <component>
       <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
       <role-hint>build-project</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
-      <instantiation-strategy>singleton</instantiation-strategy>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+      <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>      
       <requirements>
         <requirement>
           <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
@@ -99,6 +100,7 @@
       <role-hint>check-out-project</role-hint>
       <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
       <lifecycle-handler>plexus-configurable</lifecycle-handler>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
     </component>
 
 
@@ -106,7 +108,7 @@
       <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
       <role-hint>check-out-project</role-hint>
       <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
-      <instantiation-strategy>singleton</instantiation-strategy>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
       <requirements>
         <requirement>
           <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
@@ -134,13 +136,14 @@
       <role-hint>prepare-build-project</role-hint>
       <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
       <lifecycle-handler>plexus-configurable</lifecycle-handler>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
     </component>
     
     <component>
       <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
       <role-hint>prepare-build-project</role-hint>
       <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
-      <instantiation-strategy>singleton</instantiation-strategy>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
       <requirements>
         <requirement>
           <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>

Added: continuum/branches/continuum-parallel-builds/continuum-core/src/test/java/org/apache/continuum/buildmanager/ParallelBuildsManagerTest.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-core/src/test/java/org/apache/continuum/buildmanager/ParallelBuildsManagerTest.java?rev=725657&view=auto
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-core/src/test/java/org/apache/continuum/buildmanager/ParallelBuildsManagerTest.java (added)
+++ continuum/branches/continuum-parallel-builds/continuum-core/src/test/java/org/apache/continuum/buildmanager/ParallelBuildsManagerTest.java Thu Dec 11 03:02:39 2008
@@ -0,0 +1,687 @@
+package org.apache.continuum.buildmanager;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.taskqueue.OverallBuildQueue;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.Schedule;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+
+/**
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class ParallelBuildsManagerTest
+    extends PlexusInSpringTestCase
+{
+    private ParallelBuildsManager buildsManager;
+    
+    Mockery context;
+    
+    private BuildDefinitionDao buildDefinitionDao;
+
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        buildsManager = ( ParallelBuildsManager ) lookup( BuildsManager.class, "parallel" );
+        
+        context = new JUnit3Mockery();
+        
+        buildDefinitionDao = context.mock( BuildDefinitionDao.class );
+        
+        buildsManager.setBuildDefinitionDao( buildDefinitionDao );
+    }
+
+    public void tearDown()
+        throws Exception
+    {
+        super.tearDown();
+        
+        buildsManager = null;
+    }
+    
+    private List<BuildQueue> getBuildQueues( int start, int end )
+    {
+        List<BuildQueue> buildQueues = new ArrayList<BuildQueue>();        
+        for( int i = start; i <= end; i++ )
+        {
+            BuildQueue buildQueue = new BuildQueue();
+            buildQueue.setId( i );
+            buildQueue.setName( "BUILD_QUEUE_" + String.valueOf( i ) );
+            buildQueues.add( buildQueue );
+        }
+
+        return buildQueues;
+    }
+
+    private Schedule getSchedule( int id, int start, int end )
+    {
+        Schedule schedule = new Schedule();
+        schedule.setId( id );
+        schedule.setName( "DEFAULT_SCHEDULE" );
+        schedule.setCronExpression( "0 0 * * * ?" );
+        schedule.setDelay( 100 );
+        schedule.setMaxJobExecutionTime( 10000 );
+        schedule.setBuildQueues( getBuildQueues( start, end ) );
+
+        return schedule;
+    }
+    
+    private void setupOverallBuildQueues()
+    {
+        for( int i = 1; i <= 5; i++ )
+        {
+            OverallBuildQueue overallBuildQueue = ( OverallBuildQueue ) lookup( OverallBuildQueue.class );            
+            overallBuildQueue.setId( i );
+            overallBuildQueue.setName( "BUILD_QUEUE_" + String.valueOf( i ) );
+                 
+            buildsManager.addOverallBuildQueue( overallBuildQueue );
+        }
+        
+        assertEquals( 5, buildsManager.getOverallBuildQueues().size() );
+    }
+    
+// start of tests...
+    
+    public void testBuildProjectNoProjectQueuedInAnyOverallBuildQueues()
+        throws Exception
+    {    
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1 );
+
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        OverallBuildQueue whereBuildIsQueued = overallBuildQueues.get( 1 );
+        
+        assertNotNull( whereBuildIsQueued );
+        assertEquals( 1, whereBuildIsQueued.getId() );
+        assertEquals( "BUILD_QUEUE_1", whereBuildIsQueued.getName() );
+        
+        // verify that other build queues are not used
+        assertFalse( overallBuildQueues.get( 2 ).isInBuildQueue( 1 ) );
+        assertFalse( overallBuildQueues.get( 3 ).isInBuildQueue( 1 ) );
+        assertFalse( overallBuildQueues.get( 4 ).isInBuildQueue( 1 ) );
+        assertFalse( overallBuildQueues.get( 5 ).isInBuildQueue( 1 ) );
+    }    
+
+    public void testBuildProjectProjectsAreAlreadyQueuedInOverallBuildQueues()
+        throws Exception
+    {   
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1 );        
+        buildsManager.buildProject( 2, buildDef, "continuum-project-test-2", 1 );        
+        buildsManager.buildProject( 3, buildDef, "continuum-project-test-3", 1 );
+
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        
+        assertNotNull( overallBuildQueues.get( 1 ) );
+        assertNotNull( overallBuildQueues.get( 2 ) );      
+        
+        assertTrue( overallBuildQueues.get( new Integer( 1 ) ).isInBuildQueue( 1, buildDef.getId() ) );
+        assertTrue( overallBuildQueues.get( new Integer( 1 ) ).isInBuildQueue( 3, buildDef.getId() ) );
+        assertTrue( overallBuildQueues.get( new Integer( 2 ) ).isInBuildQueue( 2, buildDef.getId() ) );        
+    }
+
+    /*public void testBuildProjectProjectAlreadyInQueue()
+        throws Exception
+    {   
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 2 ) );
+       
+        buildManager.buildProject( 1, buildDef, "continuum-project-test-1", 1 );        
+        buildManager.buildProject( 2, buildDef, "continuum-project-test-2", 1 );        
+        buildManager.buildProject( 1, buildDef, "continuum-project-test-1", 1 );
+
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildManager.getOverallBuildQueues();
+        
+        assertNotNull( overallBuildQueues.get( new Integer( 1  ) ) );
+        assertNotNull( overallBuildQueues.get( new Integer( 2 ) ) );      
+        
+        assertTrue( overallBuildQueues.get( new Integer( 1 ) ).isInBuildQueue( 1, buildDef.getId() ) );        
+        assertTrue( overallBuildQueues.get( new Integer( 2 ) ).isInBuildQueue( 2, buildDef.getId() ) );
+    }*/
+
+    public void testBuildProjects()
+        throws Exception
+    {           
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+        
+        List<Project> projects = new ArrayList<Project>();
+        Project project = new Project();
+        project.setId( 4 );
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "continuum-test-1" );        
+        project.addBuildDefinition( buildDef );
+        projects.add( project );
+        
+        project = new Project();
+        project.setId( 5 );
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "continuum-test-2" );        
+        project.addBuildDefinition( buildDef );        
+        projects.add( project );
+        
+        project = new Project();
+        project.setId( 6 );
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "continuum-test-3" );        
+        project.addBuildDefinition( buildDef );        
+        projects.add( project );
+        
+        Map<Integer, BuildDefinition> projectsBuildDefinitionsMap = new HashMap<Integer, BuildDefinition>();
+        projectsBuildDefinitionsMap.put( 4, buildDef );
+        projectsBuildDefinitionsMap.put( 5, buildDef );
+        projectsBuildDefinitionsMap.put( 6, buildDef );
+        
+        // populate build queue
+        buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1 );      
+        buildsManager.buildProject( 2, buildDef, "continuum-project-test-2", 1 );      
+        buildsManager.buildProject( 3, buildDef, "continuum-project-test-3", 1 );
+        
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        
+        assertTrue( overallBuildQueues.get( 1 ).isInBuildQueue( 1, buildDef.getId() ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInBuildQueue( 3, buildDef.getId() ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 2, buildDef.getId() ) );
+        
+        // build a set of projects
+        buildsManager.buildProjects( projects, projectsBuildDefinitionsMap, 1 );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        
+        assertFalse( overallBuildQueues.get( 1 ).isInBuildQueue( 4 ) );
+        assertFalse( overallBuildQueues.get( 1 ).isInBuildQueue( 5 ) );
+        assertFalse( overallBuildQueues.get( 1 ).isInBuildQueue( 6 ) );
+        
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 4 ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 5 ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 6 ) );
+    }
+    
+    /*public void testCancelCurrentBuild()
+        throws Exception
+    {   
+        
+    }
+    
+    public void testCancelAllBuilds()
+        throws Exception
+    {
+    }*/
+    
+    public void testRemoveProjectFromBuildQueue()
+        throws Exception
+    {   
+        // - if project is built from a group, should the whole group be cancelled?
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+        
+     // populate build queue
+        buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1 );      
+        buildsManager.buildProject( 2, buildDef, "continuum-project-test-2", 1 );      
+        buildsManager.buildProject( 3, buildDef, "continuum-project-test-3", 1 );
+        
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        
+        assertTrue( overallBuildQueues.get( 1 ).isInBuildQueue( 1, buildDef.getId() ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInBuildQueue( 3, buildDef.getId() ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 2, buildDef.getId() ) );
+        
+        // remove project 1
+        buildsManager.removeProjectFromBuildQueue( 1 );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertFalse( overallBuildQueues.get( 1 ).isInBuildQueue( 1, buildDef.getId() ) );
+        
+        // remove project 2
+        buildsManager.removeProjectFromBuildQueue( 2 );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertFalse( overallBuildQueues.get( 2 ).isInBuildQueue( 2, buildDef.getId() ) );
+        
+        // remove project 3
+        buildsManager.removeProjectFromBuildQueue( 3 );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertFalse( overallBuildQueues.get( 1 ).isInBuildQueue( 3, buildDef.getId() ) );
+    }
+
+    public void testRemoveProjectFromBuildQueueProjectNotInAnyBuildQueue()
+        throws Exception
+    {
+        setupOverallBuildQueues();
+        
+        try
+        {
+            buildsManager.removeProjectFromBuildQueue( 1 );
+            fail( "An exception should have been thrown." );
+        }
+        catch( BuildManagerException e )
+        {
+            assertEquals( "Project not found in any of the build queues.", e.getMessage() );
+        }
+    }
+    
+    public void testRemoveProjectsFromBuildQueue()
+        throws Exception
+    {
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+        
+        int[] projectIds = new int[]{ 1, 2, 3 };
+        
+     // populate build queue
+        buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1 );      
+        buildsManager.buildProject( 2, buildDef, "continuum-project-test-2", 1 );      
+        buildsManager.buildProject( 3, buildDef, "continuum-project-test-3", 1 );
+        
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        
+        assertTrue( overallBuildQueues.get( 1 ).isInBuildQueue( 1, buildDef.getId() ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInBuildQueue( 3, buildDef.getId() ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 2, buildDef.getId() ) );
+        
+        // remove all projects
+        buildsManager.removeProjectsFromBuildQueue( projectIds );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertFalse( overallBuildQueues.get( 1 ).isInBuildQueue( 1, buildDef.getId() ) );        
+        assertFalse( overallBuildQueues.get( 2 ).isInBuildQueue( 2, buildDef.getId() ) );
+        assertFalse( overallBuildQueues.get( 1 ).isInBuildQueue( 3, buildDef.getId() ) );
+    }
+    
+    public void testCheckoutProjectSingle()
+        throws Exception
+    {   
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+               
+        buildsManager.checkoutProject( 1, "continuum-test-1", new File( getBasedir(), "/target/test-working-dir/1" ),
+                                       "dummy", "dummypass", buildDef );
+        
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 1 ) );
+        
+     // verify that other build queues are not used
+        assertFalse( overallBuildQueues.get( 2 ).isInCheckoutQueue( 1 ) );
+        assertFalse( overallBuildQueues.get( 3 ).isInCheckoutQueue( 1 ) );
+        assertFalse( overallBuildQueues.get( 4 ).isInCheckoutQueue( 1 ) );
+        assertFalse( overallBuildQueues.get( 5 ).isInCheckoutQueue( 1 ) );
+    }
+
+    public void testCheckoutProjectMultiple()
+        throws Exception
+    {        
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+        
+        buildsManager.checkoutProject( 1, "continuum-test-1", new File( getBasedir(), "/target/test-working-dir/1" ),
+                                       "dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 2, "continuum-test-2", new File( getBasedir(), "/target/test-working-dir/1" ), 
+                                       "dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 3, "continuum-test-3", new File( getBasedir(), "/target/test-working-dir/1" ), 
+                                       "dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 4, "continuum-test-4", new File( getBasedir(), "/target/test-working-dir/1" ), 
+                                       "dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 5, "continuum-test-5", new File( getBasedir(), "/target/test-working-dir/1" ), 
+                                       "dummy", "dummypass", buildDef );
+        
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+       
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 1 ) );   
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 2 ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 3 ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 4 ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 5 ) );
+    }
+
+    /*public void testPrepareBuildProject()
+        throws Exception
+    {
+
+    }
+
+    public void testPrepareBuildProjectProjectAlreadyInQueue()
+        throws Exception
+    {
+
+    }*/
+
+    /*public void testPrepareBuildProjects()
+        throws Exception
+    {
+        //buildManager.prepareBuildProjects( projectsBuildDefinitions, trigger, scheduleId )
+    }*/
+
+
+    /*public void testCancelCheckoutOfProject()
+        throws Exception
+    {
+        
+    }
+
+    public void testCancelAllCheckouts()
+        throws Exception
+    {
+    
+    }
+    
+    public void testCancelCheckoutInBuildQueue()
+        throws Exception
+    {
+    
+    }*/
+    
+    /*public void testCancelCurrentPrepareBuild()
+        throws Exception
+    {
+
+    }
+*/    
+
+    public void testRemoveProjectFromCheckoutQueue()
+        throws Exception
+    {
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+               
+        buildsManager.checkoutProject( 1, "continuum-test-1", new File( getBasedir(), "/target/test-working-dir/1" ),
+                                       "dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 2, "continuum-test-2", new File( getBasedir(), "/target/test-working-dir/1" ), 
+                                       "dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 3, "continuum-test-3", new File( getBasedir(), "/target/test-working-dir/1" ), 
+                                       "dummy", "dummypass", buildDef );
+        
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 1 ) );   
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 2 ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 3 ) );
+        
+        buildsManager.removeProjectFromCheckoutQueue( 1 );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertFalse( overallBuildQueues.get( 1 ).isInCheckoutQueue( 1 ) );
+        
+        buildsManager.removeProjectFromCheckoutQueue( 2 );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertFalse( overallBuildQueues.get( 2 ).isInCheckoutQueue( 2 ) );
+        
+        buildsManager.removeProjectFromCheckoutQueue( 3 );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertFalse( overallBuildQueues.get( 1 ).isInCheckoutQueue( 3 ) );        
+    }
+    
+    public void testRemoveProjectFromCheckoutQueueProjectNotInAnyCheckoutQueue()
+        throws Exception
+    {
+        setupOverallBuildQueues();
+        
+        try
+        {
+            buildsManager.removeProjectFromCheckoutQueue( 1 );
+            fail( "An exception should have been thrown." );
+        }
+        catch ( BuildManagerException e )
+        {
+            assertEquals( "Project not found in any of the checkout queues.", e.getMessage() );
+        }         
+    }
+    
+    public void testRemoveProjectsFromCheckoutQueue()
+        throws Exception
+    {
+        setupOverallBuildQueues();
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+               
+        buildsManager.checkoutProject( 1, "continuum-test-1", new File( getBasedir(), "/target/test-working-dir/1" ),
+                                       "dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 2, "continuum-test-2", new File( getBasedir(), "/target/test-working-dir/1" ), 
+                                       "dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 3, "continuum-test-3", new File( getBasedir(), "/target/test-working-dir/1" ), 
+                                       "dummy", "dummypass", buildDef );
+        
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 1 ) );   
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 2 ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 3 ) );
+        
+        int[] projectIds = new int[]{ 1, 2 , 3 };
+        buildsManager.removeProjectsFromCheckoutQueue( projectIds );
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertFalse( overallBuildQueues.get( 1 ).isInCheckoutQueue( 1 ) );
+        assertFalse( overallBuildQueues.get( 2 ).isInCheckoutQueue( 2 ) );
+        assertFalse( overallBuildQueues.get( 1 ).isInCheckoutQueue( 3 ) );        
+    }
+
+    /*public void testRemoveProjectFromPrepareBuildQueue()
+        throws Exception
+    {
+
+    }*/
+    
+    public void testRemoveOverallBuildQueue()
+        throws Exception
+    {
+        // queued tasks (both checkout & build tasks) must be transferred to the other queues!
+        setupOverallBuildQueues();
+        assertEquals( 5, buildsManager.getOverallBuildQueues().size() );
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 3 ) );
+        
+        // populate build queue
+        buildsManager.buildProject( 1, buildDef, "continuum-build-test-1", 1 );
+        buildsManager.buildProject( 2, buildDef, "continuum-build-test-2", 1 );
+        buildsManager.buildProject( 3, buildDef, "continuum-build-test-3", 1 );
+        buildsManager.buildProject( 4, buildDef, "continuum-build-test-4", 1 );
+        buildsManager.buildProject( 5, buildDef, "continuum-build-test-5", 1 );
+        
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertTrue( overallBuildQueues.get( 1 ).isInBuildQueue( 1 ) );   
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 2 ) );
+        assertTrue( overallBuildQueues.get( 3 ).isInBuildQueue( 3 ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInBuildQueue( 4 ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 5 ) );
+        
+        // populate checkout queue
+        buildsManager.checkoutProject( 6, "continuum-checkout-test-6", 
+                   new File( getBasedir(), "/target/test-working-dir/1" ),"dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 7, "continuum-checkout-test-7", 
+                   new File( getBasedir(), "/target/test-working-dir/1" ),"dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 8, "continuum-checkout-test-8", 
+                   new File( getBasedir(), "/target/test-working-dir/1" ),"dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 9, "continuum-checkout-test-9", 
+                   new File( getBasedir(), "/target/test-working-dir/1" ),"dummy", "dummypass", buildDef );
+        buildsManager.checkoutProject( 10, "continuum-checkout-test-10", 
+                   new File( getBasedir(), "/target/test-working-dir/1" ),"dummy", "dummypass", buildDef );
+        
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 6 ) );   
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 7 ) );
+        assertTrue( overallBuildQueues.get( 3 ).isInCheckoutQueue( 8 ) );
+        assertTrue( overallBuildQueues.get( 1 ).isInCheckoutQueue( 9 ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 10 ) );
+        
+        final BuildDefinition buildDefinition = new BuildDefinition();
+        buildDefinition.setId( 1 );
+        buildDefinition.setSchedule( getSchedule( 1, 2, 3 ) );
+        
+        // set expectations
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( buildDefinition ) );
+            }
+        } );
+        
+        context.checking( new Expectations()
+        {
+            {
+                one( buildDefinitionDao ).getDefaultBuildDefinition( 6 );
+                will( returnValue( buildDefinition ) );
+                
+                one( buildDefinitionDao ).getDefaultBuildDefinition( 9 );
+                will( returnValue( buildDefinition ) );
+            }
+        } );
+        
+        buildsManager.removeOverallBuildQueue( 1 );
+        
+        // verify
+        context.assertIsSatisfied();
+        
+        overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertEquals( 4, overallBuildQueues.size() );
+        
+        // checkout queues
+        assertNull( overallBuildQueues.get( 1 ) );           
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 7 ) );
+        assertTrue( overallBuildQueues.get( 3 ).isInCheckoutQueue( 8 ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 10 ) );
+        assertTrue( overallBuildQueues.get( 3 ).isInCheckoutQueue( 6 ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInCheckoutQueue( 9 ) );
+        
+        // build queues           
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 2 ) );
+        assertTrue( overallBuildQueues.get( 3 ).isInBuildQueue( 3 ) );        
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 5 ) );
+        assertTrue( overallBuildQueues.get( 3 ).isInBuildQueue( 1 ) );
+        assertTrue( overallBuildQueues.get( 2 ).isInBuildQueue( 4 ) );
+    }
+    
+    public void testNoBuildQueuesConfigured()
+        throws Exception
+    {    
+        OverallBuildQueue overallBuildQueue = ( OverallBuildQueue ) lookup( OverallBuildQueue.class );            
+        overallBuildQueue.setId( 1 );
+        overallBuildQueue.setName( "BUILD_QUEUE_1" );
+        
+        buildsManager.addOverallBuildQueue( overallBuildQueue );
+        
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 2, 3 ) );
+
+        // test if buildProject(...) is invoked
+        try
+        {
+            buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1 );
+            fail( "An exception should have been thrown." );
+        }
+        catch ( BuildManagerException e )
+        {
+            assertEquals( "No build queue found.", e.getMessage() );
+        }
+        
+        // test if buildProjects(...) is invoked
+        List<Project> projects = new ArrayList<Project>();
+        Project project = new Project();
+        project.setId( 4 );
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "continuum-test-4" );        
+        project.addBuildDefinition( buildDef );
+        projects.add( project );
+        
+        project = new Project();
+        project.setId( 5 );
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "continuum-test-5" );        
+        project.addBuildDefinition( buildDef );        
+        projects.add( project );
+                
+        Map<Integer, BuildDefinition> projectsBuildDefinitionsMap = new HashMap<Integer, BuildDefinition>();
+        projectsBuildDefinitionsMap.put( 4, buildDef );
+        projectsBuildDefinitionsMap.put( 5, buildDef );
+        
+        try
+        {
+            buildsManager.buildProjects( projects, projectsBuildDefinitionsMap, 1 );
+            fail( "An exception should have been thrown." );
+        }
+        catch ( BuildManagerException e )
+        {
+            assertEquals( "No build queue found.", e.getMessage() );
+        }
+        
+        // test if checkoutProject(..) is invoked        
+        try
+        {
+            buildsManager.checkoutProject( 6, "continuum-checkout-test-1", new File( getBasedir(), "/target/test-working-dir/1" ),
+                                       "dummy", "dummypass", buildDef );
+            fail( "An exception should have been thrown." );
+        }
+        catch ( BuildManagerException e )
+        {
+            assertEquals( "No build queue found.", e.getMessage() );
+        }
+    }
+}

Modified: continuum/branches/continuum-parallel-builds/continuum-model/pom.xml
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-model/pom.xml?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-model/pom.xml (original)
+++ continuum/branches/continuum-parallel-builds/continuum-model/pom.xml Thu Dec 11 03:02:39 2008
@@ -63,7 +63,7 @@
           </execution>
         </executions>
         <configuration>
-          <version>1.1.3</version>
+          <version>1.1.4</version>
           <packageWithVersion>false</packageWithVersion>
           <model>src/main/mdo/continuum.xml</model>
         </configuration>

Modified: continuum/branches/continuum-parallel-builds/continuum-model/src/main/mdo/continuum.xml
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-parallel-builds/continuum-model/src/main/mdo/continuum.xml?rev=725657&r1=725656&r2=725657&view=diff
==============================================================================
--- continuum/branches/continuum-parallel-builds/continuum-model/src/main/mdo/continuum.xml (original)
+++ continuum/branches/continuum-parallel-builds/continuum-model/src/main/mdo/continuum.xml Thu Dec 11 03:02:39 2008
@@ -1030,6 +1030,27 @@
       </fields>
     </class>
     <class>
+      <name>BuildQueue</name>
+      <version>1.1.4+</version>    
+      <description><![CDATA[
+       Build queue.
+      ]]></description>
+      <fields>
+        <field>
+          <name>id</name>
+          <version>1.1.4+</version>
+          <identifier>true</identifier>
+          <type>int</type>
+        </field>
+        <field>
+          <name>name</name>
+          <version>1.1.4+</version>
+          <type>String</type>
+          <required>true</required>
+        </field>        
+      </fields>
+    </class>    
+    <class>
       <name>Schedule</name>
       <version>1.0.9+</version>
       <description><![CDATA[
@@ -1088,6 +1109,14 @@
           <version>1.0.9+</version>
           <type>String</type>
         </field>
+        <field jpox.fetch-groups="schedule-build-queues">
+          <name>buildQueues</name>
+          <version>1.1.4+</version>
+          <association xml.reference="true" stash.part="true" jpox.dependent="false">
+            <type>BuildQueue</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
       </fields>
     </class>
 
@@ -1593,7 +1622,6 @@
           <required>true</required>
         </field>
       </fields>
-    </class>
-    
+    </class>    
   </classes>
 </model>