View Javadoc

1   package org.apache.continuum.buildmanager;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.continuum.buildqueue.BuildQueueService;
23  import org.apache.continuum.buildqueue.BuildQueueServiceException;
24  import org.apache.continuum.dao.BuildDefinitionDao;
25  import org.apache.continuum.dao.ProjectDao;
26  import org.apache.continuum.taskqueue.BuildProjectTask;
27  import org.apache.continuum.taskqueue.CheckOutTask;
28  import org.apache.continuum.taskqueue.OverallBuildQueue;
29  import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
30  import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor;
31  import org.apache.continuum.utils.build.BuildTrigger;
32  import org.apache.maven.continuum.configuration.ConfigurationService;
33  import org.apache.maven.continuum.model.project.BuildDefinition;
34  import org.apache.maven.continuum.model.project.BuildQueue;
35  import org.apache.maven.continuum.model.project.Project;
36  import org.apache.maven.continuum.model.scm.ScmResult;
37  import org.apache.maven.continuum.store.ContinuumStoreException;
38  import org.codehaus.plexus.PlexusConstants;
39  import org.codehaus.plexus.PlexusContainer;
40  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
41  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
42  import org.codehaus.plexus.context.Context;
43  import org.codehaus.plexus.context.ContextException;
44  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
45  import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
46  import org.codehaus.plexus.taskqueue.TaskQueue;
47  import org.codehaus.plexus.taskqueue.TaskQueueException;
48  import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
49  import org.codehaus.plexus.util.StringUtils;
50  import org.slf4j.Logger;
51  import org.slf4j.LoggerFactory;
52  
53  import java.io.File;
54  import java.util.Collection;
55  import java.util.Collections;
56  import java.util.HashMap;
57  import java.util.List;
58  import java.util.Map;
59  import java.util.Set;
60  import javax.annotation.Resource;
61  
62  /**
63   * Parallel builds manager.
64   *
65   * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
66   * @version $Id$
67   */
68  public class ParallelBuildsManager
69      implements BuildsManager, Contextualizable
70  {
71      private static final Logger log = LoggerFactory.getLogger( ParallelBuildsManager.class );
72  
73      // map must be synchronized!
74      private Map<Integer, OverallBuildQueue> overallBuildQueues = Collections.synchronizedMap(
75          new HashMap<Integer, OverallBuildQueue>() );
76  
77      private static final int BUILD_QUEUE = 1;
78  
79      private static final int CHECKOUT_QUEUE = 2;
80  
81      private static final int PREPARE_BUILD_QUEUE = 3;
82  
83      @Resource
84      private BuildDefinitionDao buildDefinitionDao;
85  
86      @Resource
87      private ProjectDao projectDao;
88  
89      @Resource
90      private ConfigurationService configurationService;
91  
92      @Resource
93      private BuildQueueService buildQueueService;
94  
95      private PlexusContainer container;
96  
97      /**
98       * @see BuildsManager#buildProject(int, BuildDefinition, String, BuildTrigger, ScmResult, int)
99       */
100     public void buildProject( int projectId, BuildDefinition buildDefinition, String projectName,
101                               BuildTrigger buildTrigger, ScmResult scmResult, int projectGroupId )
102         throws BuildManagerException
103     {
104         try
105         {
106             if ( isInQueue( projectId, BUILD_QUEUE, -1 ) )
107             {
108                 log.warn( "Project already queued." );
109                 return;
110             }
111             else if ( isProjectInAnyCurrentBuild( projectId ) )
112             {
113                 log.warn( "Project is already building." );
114                 return;
115             }
116         }
117         catch ( TaskQueueException e )
118         {
119             throw new BuildManagerException(
120                 "Error occurred while checking if the project is already in queue: " + e.getMessage() );
121         }
122 
123         OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectsInGroupAreQueued( projectGroupId );
124 
125         if ( overallBuildQueue == null )
126         {
127             overallBuildQueue = getOverallBuildQueue( BUILD_QUEUE, buildDefinition.getSchedule().getBuildQueues() );
128         }
129 
130         if ( overallBuildQueue != null )
131         {
132             String buildDefinitionLabel = buildDefinition.getDescription();
133 
134             if ( StringUtils.isEmpty( buildDefinitionLabel ) )
135             {
136                 buildDefinitionLabel = buildDefinition.getGoals();
137             }
138 
139             BuildProjectTask buildTask = new BuildProjectTask( projectId, buildDefinition.getId(), buildTrigger,
140                                                                projectName, buildDefinitionLabel, scmResult,
141                                                                projectGroupId );
142             try
143             {
144                 log.info( "Project '" + projectName + "' added to overall build queue '" + overallBuildQueue.getName() +
145                               "'." );
146                 overallBuildQueue.addToBuildQueue( buildTask );
147             }
148             catch ( TaskQueueException e )
149             {
150                 throw new BuildManagerException(
151                     "Error occurred while adding project to build queue: " + e.getMessage() );
152             }
153         }
154         else
155         {
156             log.warn( "No build queue configured. Not building." );
157         }
158     }
159 
160     /**
161      * @see BuildsManager#buildProjects(List, Map, BuildTrigger, Map, int)
162      */
163     public void buildProjects( List<Project> projects, Map<Integer, BuildDefinition> projectsBuildDefinitionsMap,
164                                BuildTrigger buildTrigger, Map<Integer, ScmResult> scmResultMap, int projectGroupId )
165         throws BuildManagerException
166     {
167         int firstProjectId = 0;
168         // get id of the first project in the list that is not yet in the build queue
169         for ( Project project : projects )
170         {
171             try
172             {
173                 if ( !isInQueue( project.getId(), BUILD_QUEUE, -1 ) && !isProjectInAnyCurrentBuild( project.getId() ) )
174                 {
175                     firstProjectId = project.getId();
176                     break;
177                 }
178             }
179             catch ( TaskQueueException e )
180             {
181                 log.warn( "Error occurred while verifying if project is already queued." );
182             }
183         }
184 
185         if ( firstProjectId != 0 )
186         {
187             BuildDefinition buildDef = projectsBuildDefinitionsMap.get( firstProjectId );
188 
189             if ( buildDef.getArguments() == null || buildDef.getBuildFile() == null || buildDef.getGoals() == null ||
190                 buildDef.getSchedule() == null )
191             {
192                 log.error( "Null values set on build definition (id=" + buildDef.getId() + ")" );
193                 throw new BuildManagerException( "Unable to build project due to null values set on " +
194                                                      "( GOALS , ARGUMENTS , BUILD_FILE, SCHEDULE_ID_OID ) of BUILDDEFINITION ID : " +
195                                                      buildDef.getId() + " Please notify your system adminitrator" );
196             }
197             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectsInGroupAreQueued( projectGroupId );
198 
199             if ( overallBuildQueue == null )
200             {
201                 overallBuildQueue = getOverallBuildQueue( BUILD_QUEUE, buildDef.getSchedule().getBuildQueues() );
202             }
203 
204             if ( overallBuildQueue != null )
205             {
206                 for ( Project project : projects )
207                 {
208                     try
209                     {
210                         if ( isInQueue( project.getId(), BUILD_QUEUE, projectsBuildDefinitionsMap.get(
211                             project.getId() ).getId() ) )
212                         {
213                             log.warn( "Project '" + project.getId() + "' - '" + project.getName() +
214                                           "' is already in build queue." );
215                             continue;
216                         }
217                         else if ( isProjectInAnyCurrentBuild( project.getId() ) )
218                         {
219                             log.warn( "Project '" + project.getId() + "' - '" + project.getName() +
220                                           "' is already building." );
221                             continue;
222                         }
223                     }
224                     catch ( TaskQueueException e )
225                     {
226                         log.warn( "Error occurred while verifying if project is already queued." );
227                         continue;
228                     }
229 
230                     BuildDefinition buildDefinition = projectsBuildDefinitionsMap.get( project.getId() );
231                     String buildDefinitionLabel = buildDefinition.getDescription();
232                     if ( StringUtils.isEmpty( buildDefinitionLabel ) )
233                     {
234                         buildDefinitionLabel = buildDefinition.getGoals();
235                     }
236 
237                     ScmResult scmResult = scmResultMap.get( project.getId() );
238                     BuildProjectTask buildTask = new BuildProjectTask( project.getId(), buildDefinition.getId(),
239                                                                        buildTrigger, project.getName(),
240                                                                        buildDefinitionLabel, scmResult,
241                                                                        projectGroupId );
242                     buildTask.setMaxExecutionTime( buildDefinition.getSchedule().getMaxJobExecutionTime() * 1000 );
243 
244                     try
245                     {
246                         log.info( "Project '" + project.getId() + "' - '" + project.getName() +
247                                       "' added to overall build queue '" + overallBuildQueue.getName() + "'." );
248 
249                         overallBuildQueue.addToBuildQueue( buildTask );
250                     }
251                     catch ( TaskQueueException e )
252                     {
253                         throw new BuildManagerException(
254                             "Error occurred while adding project to build queue: " + e.getMessage() );
255                     }
256                 }
257             }
258             else
259             {
260                 log.warn( "No build queue configured. Not building" );
261             }
262         }
263         else
264         {
265             log.error( "Projects are already in build queue." );
266         }
267     }
268 
269     /**
270      * @see BuildsManager#cancelBuildInQueue(int)
271      */
272     public boolean cancelBuildInQueue( int buildQueueId )
273         throws BuildManagerException
274     {
275         synchronized ( overallBuildQueues )
276         {
277             OverallBuildQueue overallBuildQueue;
278             overallBuildQueue = overallBuildQueues.get( buildQueueId );
279             if ( overallBuildQueue != null )
280             {
281                 overallBuildQueue.cancelCurrentBuild();
282             }
283             else
284             {
285                 log.warn( "Project not found in any of the build queues." );
286             }
287 
288             return true;
289         }
290     }
291 
292     /**
293      * @see BuildsManager#cancelAllBuilds()
294      */
295     public boolean cancelAllBuilds()
296         throws BuildManagerException
297     {
298         synchronized ( overallBuildQueues )
299         {
300             Set<Integer> keySet = overallBuildQueues.keySet();
301             OverallBuildQueue overallBuildQueue = null;
302             for ( Integer key : keySet )
303             {
304                 overallBuildQueue = overallBuildQueues.get( key );
305                 overallBuildQueue.cancelCurrentBuild();
306             }
307 
308             return true;
309         }
310     }
311 
312     /**
313      * @see BuildsManager#cancelAllCheckouts()
314      */
315     public boolean cancelAllCheckouts()
316         throws BuildManagerException
317     {
318         synchronized ( overallBuildQueues )
319         {
320             Set<Integer> keySet = overallBuildQueues.keySet();
321             OverallBuildQueue overallBuildQueue;
322             for ( Integer key : keySet )
323             {
324                 overallBuildQueue = overallBuildQueues.get( key );
325                 overallBuildQueue.cancelCurrentCheckout();
326             }
327 
328             return true;
329         }
330     }
331 
332     /**
333      * @see BuildsManager#cancelBuild(int)
334      */
335     public boolean cancelBuild( int projectId )
336         throws BuildManagerException
337     {
338         try
339         {
340             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
341             if ( overallBuildQueue != null )
342             {
343                 overallBuildQueue.cancelBuildTask( projectId );
344             }
345             else
346             {
347                 synchronized ( overallBuildQueues )
348                 {
349                     Set<Integer> keySet = overallBuildQueues.keySet();
350                     for ( Integer key : keySet )
351                     {
352                         overallBuildQueue = overallBuildQueues.get( key );
353                         BuildProjectTask buildTask =
354                             (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
355                         if ( buildTask != null && buildTask.getProjectId() == projectId )
356                         {
357                             overallBuildQueue.cancelBuildTask( projectId );
358                             return true;
359                         }
360                     }
361                     log.error( "Project '" + projectId + "' not found in any of the builds queues." );
362                 }
363             }
364         }
365         catch ( TaskQueueException e )
366         {
367             throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
368         }
369 
370         return true;
371     }
372 
373     /**
374      * @see BuildsManager#cancelCheckout(int)
375      */
376     public boolean cancelCheckout( int projectId )
377         throws BuildManagerException
378     {
379         try
380         {
381             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE );
382             if ( overallBuildQueue != null )
383             {
384                 overallBuildQueue.cancelCheckoutTask( projectId );
385             }
386             else
387             {
388                 synchronized ( overallBuildQueues )
389                 {
390                     Set<Integer> keySet = overallBuildQueues.keySet();
391                     for ( Integer key : keySet )
392                     {
393                         overallBuildQueue = overallBuildQueues.get( key );
394                         CheckOutTask checkoutTask =
395                             (CheckOutTask) overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask();
396                         if ( checkoutTask != null && checkoutTask.getProjectId() == projectId )
397                         {
398                             overallBuildQueue.cancelCheckoutTask( projectId );
399                             return true;
400                         }
401                     }
402                     log.info( "Project '" + projectId + "' not found in any of the checkout queues." );
403                 }
404             }
405         }
406         catch ( TaskQueueException e )
407         {
408             throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
409         }
410 
411         return true;
412     }
413 
414     public boolean cancelPrepareBuild( int projectGroupId, int scmRootId )
415         throws BuildManagerException
416     {
417         try
418         {
419             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectGroupIsQueued( projectGroupId,
420                                                                                                  scmRootId );
421 
422             if ( overallBuildQueue != null )
423             {
424                 overallBuildQueue.cancelPrepareBuildTask( projectGroupId, scmRootId );
425             }
426             else
427             {
428                 synchronized ( overallBuildQueues )
429                 {
430                     Set<Integer> keySet = overallBuildQueues.keySet();
431                     for ( Integer key : keySet )
432                     {
433                         overallBuildQueue = overallBuildQueues.get( key );
434                         PrepareBuildProjectsTask task =
435                             (PrepareBuildProjectsTask) overallBuildQueue.getPrepareBuildTaskQueueExecutor().getCurrentTask();
436                         if ( task != null && task.getProjectGroupId() == projectGroupId &&
437                             task.getProjectScmRootId() == scmRootId )
438                         {
439                             overallBuildQueue.cancelPrepareBuildTask( projectGroupId, scmRootId );
440                             return true;
441                         }
442                     }
443                     log.error( "Project group '{}' with scm root '{}' not found in any of the builds queues.",
444                                projectGroupId, scmRootId );
445                 }
446             }
447         }
448         catch ( TaskQueueException e )
449         {
450             throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
451         }
452 
453         return true;
454     }
455 
456     public boolean cancelPrepareBuild( int projectId )
457         throws BuildManagerException
458     {
459         try
460         {
461             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId,
462                                                                                             PREPARE_BUILD_QUEUE );
463 
464             if ( overallBuildQueue != null )
465             {
466                 overallBuildQueue.cancelPrepareBuildTask( projectId );
467             }
468             else
469             {
470                 synchronized ( overallBuildQueues )
471                 {
472                     Set<Integer> keySet = overallBuildQueues.keySet();
473                     for ( Integer key : keySet )
474                     {
475                         overallBuildQueue = overallBuildQueues.get( key );
476                         PrepareBuildProjectsTask task =
477                             (PrepareBuildProjectsTask) overallBuildQueue.getPrepareBuildTaskQueueExecutor().getCurrentTask();
478                         if ( task != null )
479                         {
480                             Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();
481 
482                             if ( map.size() > 0 )
483                             {
484                                 Set<Integer> projectIds = map.keySet();
485 
486                                 if ( projectIds.contains( new Integer( projectId ) ) )
487                                 {
488                                     overallBuildQueue.cancelPrepareBuildTask( projectId );
489                                     return true;
490                                 }
491                             }
492                         }
493                     }
494                     log.error( "Project '{}' not found in any of the builds queues.", projectId );
495                 }
496             }
497         }
498         catch ( TaskQueueException e )
499         {
500             throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
501         }
502 
503         return true;
504     }
505 
506     /**
507      * @see BuildsManager#checkoutProject(int, String, File, String, String, String, BuildDefinition, List)
508      */
509     public void checkoutProject( int projectId, String projectName, File workingDirectory, String scmRootUrl,
510                                  String scmUsername, String scmPassword, BuildDefinition defaultBuildDefinition,
511                                  List<Project> subProjects )
512         throws BuildManagerException
513     {
514         try
515         {
516             if ( isInQueue( projectId, CHECKOUT_QUEUE, -1 ) )
517             {
518                 log.warn( "Project already in checkout queue." );
519                 return;
520             }
521         }
522         catch ( TaskQueueException e )
523         {
524             throw new BuildManagerException(
525                 "Error occurred while checking if the project is already in queue: " + e.getMessage() );
526         }
527 
528         OverallBuildQueue overallBuildQueue = getOverallBuildQueue( CHECKOUT_QUEUE,
529                                                                     defaultBuildDefinition.getSchedule().getBuildQueues() );
530         CheckOutTask checkoutTask = new CheckOutTask( projectId, workingDirectory, projectName, scmUsername,
531                                                       scmPassword, scmRootUrl, subProjects );
532         try
533         {
534             if ( overallBuildQueue != null )
535             {
536                 log.info( "Project '" + projectName + "' added to overall build queue '" + overallBuildQueue.getName() +
537                               "'." );
538                 overallBuildQueue.addToCheckoutQueue( checkoutTask );
539             }
540             else
541             {
542                 throw new BuildManagerException(
543                     "Unable to add project to checkout queue. No overall build queue configured." );
544             }
545         }
546         catch ( TaskQueueException e )
547         {
548             throw new BuildManagerException(
549                 "Error occurred while adding project to checkout queue: " + e.getMessage() );
550         }
551     }
552 
553     /**
554      * @see BuildsManager#isInAnyBuildQueue(int)
555      */
556     public boolean isInAnyBuildQueue( int projectId )
557         throws BuildManagerException
558     {
559         try
560         {
561             return isInQueue( projectId, BUILD_QUEUE, -1 );
562         }
563         catch ( TaskQueueException e )
564         {
565             throw new BuildManagerException( e.getMessage() );
566         }
567     }
568 
569     /**
570      * @see BuildsManager#isInAnyBuildQueue(int, int)
571      */
572     public boolean isInAnyBuildQueue( int projectId, int buildDefinitionId )
573         throws BuildManagerException
574     {
575         try
576         {
577             return isInQueue( projectId, BUILD_QUEUE, buildDefinitionId );
578         }
579         catch ( TaskQueueException e )
580         {
581             throw new BuildManagerException( e.getMessage() );
582         }
583     }
584 
585     /**
586      * @see BuildsManager#isInAnyCheckoutQueue(int)
587      */
588     public boolean isInAnyCheckoutQueue( int projectId )
589         throws BuildManagerException
590     {
591         try
592         {
593             return isInQueue( projectId, CHECKOUT_QUEUE, -1 );
594         }
595         catch ( TaskQueueException e )
596         {
597             throw new BuildManagerException( e.getMessage() );
598         }
599     }
600 
601     /**
602      * @see BuildsManager#isAnyProjectCurrentlyBeingCheckedOut(int[])
603      */
604     public boolean isAnyProjectCurrentlyBeingCheckedOut( int[] projectIds )
605         throws BuildManagerException
606     {
607         for ( int projectId : projectIds )
608         {
609             Map<String, CheckOutTask> checkouts = getCurrentCheckouts();
610             Set<String> keySet = checkouts.keySet();
611             for ( String key : keySet )
612             {
613                 CheckOutTask task = checkouts.get( key );
614                 if ( task.getProjectId() == projectId )
615                 {
616                     log.info( "Project " + projectId + " is currently being checked out" );
617                     return true;
618                 }
619             }
620         }
621         return false;
622     }
623 
624     /**
625      * @see BuildsManager#isInPrepareBuildQueue(int)
626      */
627     public boolean isInPrepareBuildQueue( int projectId )
628         throws BuildManagerException
629     {
630         try
631         {
632             synchronized ( overallBuildQueues )
633             {
634                 Set<Integer> keySet = overallBuildQueues.keySet();
635                 for ( Integer key : keySet )
636                 {
637                     OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
638 
639                     if ( overallBuildQueue.isInPrepareBuildQueue( projectId ) )
640                     {
641                         return true;
642                     }
643                 }
644 
645                 return false;
646             }
647         }
648         catch ( TaskQueueException e )
649         {
650             throw new BuildManagerException( "Unable to check if projectId " + projectId + " is in prepare build queue",
651                                              e );
652         }
653     }
654 
655     /**
656      * @param projectGroupId
657      * @param scmRootId
658      * @return
659      * @see BuildsManager#isInPrepareBuildQueue(int, int)
660      */
661     public boolean isInPrepareBuildQueue( int projectGroupId, int scmRootId )
662         throws BuildManagerException
663     {
664         try
665         {
666             synchronized ( overallBuildQueues )
667             {
668                 Set<Integer> keySet = overallBuildQueues.keySet();
669                 for ( Integer key : keySet )
670                 {
671                     OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
672 
673                     if ( overallBuildQueue.isInPrepareBuildQueue( projectGroupId, scmRootId ) )
674                     {
675                         return true;
676                     }
677                 }
678 
679                 return false;
680             }
681         }
682         catch ( TaskQueueException e )
683         {
684             throw new BuildManagerException(
685                 "Unable to check if projectGroupId " + projectGroupId + " with scmRootId " + scmRootId +
686                     " is in prepare build queue", e );
687         }
688     }
689 
690     /**
691      * @see BuildsManager#isProjectInAnyCurrentBuild(int)
692      */
693     public boolean isProjectInAnyCurrentBuild( int projectId )
694         throws BuildManagerException
695     {
696         synchronized ( overallBuildQueues )
697         {
698             Set<Integer> keys = overallBuildQueues.keySet();
699             for ( Integer key : keys )
700             {
701                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
702                 BuildProjectTask task =
703                     (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
704                 if ( task != null && task.getProjectId() == projectId )
705                 {
706                     log.info( "Project " + projectId + " is currently building in " + overallBuildQueue.getName() );
707                     return true;
708                 }
709             }
710             return false;
711         }
712     }
713 
714     /**
715      * @see BuildsManager#prepareBuildProjects(Map, BuildTrigger, int, String, String, int)
716      */
717     public void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, BuildTrigger buildTrigger,
718                                       int projectGroupId, String projectGroupName, String scmRootAddress,
719                                       int scmRootId )
720         throws BuildManagerException
721     {
722         if ( isInPrepareBuildQueue( projectGroupId, scmRootId ) )
723         {
724             log.warn(
725                 "Project group {} with scm root id {} is already in prepare build queue. Will not queue anymore." );
726             return;
727         }
728 
729         Collection<Integer> buildDefs = projectsBuildDefinitionsMap.values();
730         BuildDefinition buildDef = null;
731 
732         // get the first build definition
733         try
734         {
735             for ( Integer buildDefId : buildDefs )
736             {
737                 buildDef = buildDefinitionDao.getBuildDefinition( buildDefId );
738             }
739         }
740         catch ( ContinuumStoreException e )
741         {
742             throw new BuildManagerException(
743                 "Error occurred while retrieving build definition of project group " + projectGroupId, e );
744         }
745 
746         OverallBuildQueue overallBuildQueue = getOverallBuildQueue( PREPARE_BUILD_QUEUE,
747                                                                     buildDef.getSchedule().getBuildQueues() );
748 
749         PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, buildTrigger,
750                                                                       projectGroupId, projectGroupName, scmRootAddress,
751                                                                       scmRootId );
752 
753         try
754         {
755             if ( overallBuildQueue != null )
756             {
757                 log.info( "Project group '{}' added to overall build queue '{}'", projectGroupId,
758                           overallBuildQueue.getName() );
759                 overallBuildQueue.addToPrepareBuildQueue( task );
760             }
761             else
762             {
763                 throw new BuildManagerException(
764                     "Unable to add project to prepare build queue. No overall build queue configured." );
765             }
766         }
767         catch ( TaskQueueException e )
768         {
769             throw new BuildManagerException(
770                 "Error occurred while adding project to prepare build queue: " + e.getMessage() );
771         }
772     }
773 
774     /**
775      * @see BuildsManager#removeProjectFromBuildQueue(int)
776      */
777     public void removeProjectFromBuildQueue( int projectId )
778         throws BuildManagerException
779     {
780         try
781         {
782             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
783             if ( overallBuildQueue != null )
784             {
785                 overallBuildQueue.removeProjectFromBuildQueue( projectId );
786             }
787             else
788             {
789                 log.info( "Project '" + projectId + "' not found in any of the build queues." );
790             }
791         }
792         catch ( TaskQueueException e )
793         {
794             throw new BuildManagerException(
795                 "Error occurred while removing project from build queue: " + e.getMessage() );
796         }
797     }
798 
799     /**
800      * @see BuildsManager#removeProjectFromBuildQueue(int, int, BuildTrigger, String, int)
801      */
802     public void removeProjectFromBuildQueue( int projectId, int buildDefinitionId, BuildTrigger buildTrigger,
803                                              String projectName, int projectGroupId )
804         throws BuildManagerException
805     {
806         try
807         {
808             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
809             if ( overallBuildQueue != null )
810             {
811                 overallBuildQueue.removeProjectFromBuildQueue( projectId, buildDefinitionId, buildTrigger, projectName,
812                                                                projectGroupId );
813             }
814             else
815             {
816                 log.info( "Project '" + projectId + "' not found in any of the build queues." );
817             }
818         }
819         catch ( TaskQueueException e )
820         {
821             throw new BuildManagerException(
822                 "Error occurred while removing project from build queue: " + e.getMessage() );
823         }
824     }
825 
826     /**
827      * @see BuildsManager#removeProjectFromCheckoutQueue(int)
828      */
829     public void removeProjectFromCheckoutQueue( int projectId )
830         throws BuildManagerException
831     {
832         try
833         {
834             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE );
835             if ( overallBuildQueue != null )
836             {
837                 overallBuildQueue.removeProjectFromCheckoutQueue( projectId );
838             }
839             else
840             {
841                 log.info( "Project '" + projectId + "' not found in any of the checkout queues." );
842             }
843         }
844         catch ( TaskQueueException e )
845         {
846             throw new BuildManagerException(
847                 "Error occurred while removing project from checkout queue: " + e.getMessage() );
848         }
849     }
850 
851     /**
852      * @see BuildsManager#removeProjectsFromBuildQueue(int[])
853      */
854     public void removeProjectsFromBuildQueue( int[] projectIds )
855     {
856         for ( int projectId : projectIds )
857         {
858             try
859             {
860                 OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId,
861                                                                                                 BUILD_QUEUE );
862                 if ( overallBuildQueue != null )
863                 {
864                     overallBuildQueue.removeProjectFromBuildQueue( projectId );
865                 }
866                 else
867                 {
868                     log.error( "Project '" + projectId + "' not found in any of the build queues." );
869                 }
870             }
871             catch ( TaskQueueException e )
872             {
873                 log.error( "Error occurred while removing project '" + projectId + "' from build queue." );
874             }
875         }
876     }
877 
878     /**
879      * @see BuildsManager#removeProjectsFromCheckoutQueue(int[])
880      */
881     public void removeProjectsFromCheckoutQueue( int[] projectIds )
882     {
883         for ( int projectId : projectIds )
884         {
885             try
886             {
887                 OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId,
888                                                                                                 CHECKOUT_QUEUE );
889                 if ( overallBuildQueue != null )
890                 {
891                     overallBuildQueue.removeProjectFromCheckoutQueue( projectId );
892                 }
893                 else
894                 {
895                     log.error( "Project '" + projectId + "' not found in any of the checkout queues." );
896                 }
897             }
898             catch ( TaskQueueException e )
899             {
900                 log.error( "Error occurred while removing project '" + projectId + "' from checkout queue." );
901             }
902         }
903     }
904 
905     /**
906      * @see BuildsManager#removeProjectsFromCheckoutQueueWithHashcodes(int[])
907      */
908     public void removeProjectsFromCheckoutQueueWithHashcodes( int[] hashcodes )
909         throws BuildManagerException
910     {
911         try
912         {
913             synchronized ( overallBuildQueues )
914             {
915                 Set<Integer> keySet = overallBuildQueues.keySet();
916                 for ( Integer key : keySet )
917                 {
918                     OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
919                     overallBuildQueue.removeTasksFromCheckoutQueueWithHashCodes( hashcodes );
920                 }
921             }
922         }
923         catch ( TaskQueueException e )
924         {
925             throw new BuildManagerException( "Error encountered while removing project(s) from checkout queue.", e );
926         }
927     }
928 
929     /**
930      * @see BuildsManager#removeProjectsFromBuildQueueWithHashcodes(int[])
931      */
932     public void removeProjectsFromBuildQueueWithHashcodes( int[] hashcodes )
933         throws BuildManagerException
934     {
935         try
936         {
937             synchronized ( overallBuildQueues )
938             {
939                 Set<Integer> keySet = overallBuildQueues.keySet();
940                 for ( Integer key : keySet )
941                 {
942                     OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
943                     overallBuildQueue.removeProjectsFromBuildQueueWithHashCodes( hashcodes );
944                 }
945             }
946         }
947         catch ( TaskQueueException e )
948         {
949             throw new BuildManagerException( "Error encountered while removing project(s) from build queue.", e );
950         }
951     }
952 
953     public boolean removeProjectGroupFromPrepareBuildQueue( int projectGroupId, String scmRootAddress )
954         throws BuildManagerException
955     {
956         try
957         {
958             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectGroupIsQueued( projectGroupId,
959                                                                                                  scmRootAddress );
960             if ( overallBuildQueue != null )
961             {
962                 overallBuildQueue.removeProjectFromPrepareBuildQueue( projectGroupId, scmRootAddress );
963             }
964             else
965             {
966                 log.info( "Project group '{}' with scm '{}' not found in any of the build queues.", projectGroupId,
967                           scmRootAddress );
968             }
969         }
970         catch ( TaskQueueException e )
971         {
972             throw new BuildManagerException(
973                 "Error occurred while removing project group from prepare build queue: " + e.getMessage() );
974         }
975 
976         return true;
977     }
978 
979     /**
980      * @see BuildsManager#addOverallBuildQueue(BuildQueue)
981      */
982     public void addOverallBuildQueue( BuildQueue buildQueue )
983         throws BuildManagerException
984     {
985         synchronized ( overallBuildQueues )
986         {
987             try
988             {
989                 OverallBuildQueue overallBuildQueue = (OverallBuildQueue) container.lookup( OverallBuildQueue.class );
990                 overallBuildQueue.setId( buildQueue.getId() );
991                 overallBuildQueue.setName( buildQueue.getName() );
992 
993                 if ( overallBuildQueues.get( buildQueue.getId() ) == null )
994                 {
995                     log.info( "Adding overall build queue to map : " + overallBuildQueue.getName() );
996                     overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue );
997                 }
998                 else
999                 {
1000                     log.warn( "Overall build queue already in the map." );
1001                 }
1002             }
1003             catch ( ComponentLookupException e )
1004             {
1005                 throw new BuildManagerException( "Error creating overall build queue.", e );
1006             }
1007         }
1008     }
1009 
1010     /**
1011      * @see BuildsManager#removeOverallBuildQueue(int)
1012      */
1013     public void removeOverallBuildQueue( int overallBuildQueueId )
1014         throws BuildManagerException
1015     {
1016         List<BuildProjectTask> tasks;
1017         List<CheckOutTask> checkoutTasks;
1018         List<PrepareBuildProjectsTask> prepareBuildTasks;
1019 
1020         synchronized ( overallBuildQueues )
1021         {
1022             OverallBuildQueue overallBuildQueue = overallBuildQueues.get( overallBuildQueueId );
1023             if ( overallBuildQueue.getName().equals( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) )
1024             {
1025                 throw new BuildManagerException( "Cannot remove default build queue." );
1026             }
1027 
1028             try
1029             {
1030                 if ( overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask() != null ||
1031                     overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask() != null ||
1032                     overallBuildQueue.getPrepareBuildTaskQueueExecutor().getCurrentTask() != null )
1033                 {
1034                     throw new BuildManagerException( "Cannot remove build queue. A task is currently executing." );
1035                 }
1036 
1037                 tasks = overallBuildQueue.getProjectsInBuildQueue();
1038                 checkoutTasks = overallBuildQueue.getProjectsInCheckoutQueue();
1039                 prepareBuildTasks = overallBuildQueue.getProjectsInPrepareBuildQueue();
1040 
1041                 overallBuildQueue.getBuildQueue().removeAll( tasks );
1042                 overallBuildQueue.getCheckoutQueue().removeAll( checkoutTasks );
1043                 overallBuildQueue.getPrepareBuildQueue().removeAll( prepareBuildTasks );
1044 
1045                 ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getBuildTaskQueueExecutor() ).stop();
1046                 ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getCheckoutTaskQueueExecutor() ).stop();
1047                 ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getPrepareBuildTaskQueueExecutor() ).stop();
1048                 container.release( overallBuildQueue );
1049             }
1050             catch ( TaskQueueException e )
1051             {
1052                 throw new BuildManagerException(
1053                     "Cannot remove build queue. An error occurred while retrieving queued tasks." );
1054             }
1055             catch ( ComponentLifecycleException e )
1056             {
1057                 throw new BuildManagerException(
1058                     "Cannot remove build queue. An error occurred while destroying the build queue: " +
1059                         e.getMessage() );
1060             }
1061             catch ( StoppingException e )
1062             {
1063                 throw new BuildManagerException(
1064                     "Cannot remove build queue. An error occurred while stopping the build queue: " + e.getMessage() );
1065             }
1066 
1067             this.overallBuildQueues.remove( overallBuildQueueId );
1068             log.info( "Removed overall build queue '" + overallBuildQueueId + "' from build queues map." );
1069         }
1070 
1071         for ( BuildProjectTask buildTask : tasks )
1072         {
1073             try
1074             {
1075                 BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition(
1076                     buildTask.getBuildDefinitionId() );
1077 
1078                 buildProject( buildTask.getProjectId(), buildDefinition, buildTask.getProjectName(),
1079                               buildTask.getBuildTrigger(), buildTask.getScmResult(), buildTask.getProjectGroupId() );
1080             }
1081             catch ( ContinuumStoreException e )
1082             {
1083                 log.error( "Unable to queue build task for project '" + buildTask.getProjectName() + "'" );
1084             }
1085         }
1086 
1087         for ( CheckOutTask task : checkoutTasks )
1088         {
1089             try
1090             {
1091                 BuildDefinition buildDefinition = buildDefinitionDao.getDefaultBuildDefinition( task.getProjectId() );
1092                 checkoutProject( task.getProjectId(), task.getProjectName(), task.getWorkingDirectory(),
1093                                  task.getScmRootUrl(), task.getScmUserName(), task.getScmPassword(), buildDefinition,
1094                                  task.getProjectsWithCommonScmRoot() );
1095             }
1096             catch ( ContinuumStoreException e )
1097             {
1098                 log.error( "Unable to queue checkout task for project '" + task.getProjectName() + "'" );
1099             }
1100         }
1101 
1102         for ( PrepareBuildProjectsTask prepareTask : prepareBuildTasks )
1103         {
1104             prepareBuildProjects( prepareTask.getProjectsBuildDefinitionsMap(), prepareTask.getBuildTrigger(),
1105                                   prepareTask.getProjectGroupId(), prepareTask.getProjectGroupName(),
1106                                   prepareTask.getScmRootAddress(), prepareTask.getProjectScmRootId() );
1107         }
1108     }
1109 
1110     public Map<Integer, OverallBuildQueue> getOverallBuildQueues()
1111     {
1112         return overallBuildQueues;
1113     }
1114 
1115     /**
1116      * @see BuildsManager#getCurrentBuilds()
1117      */
1118     public Map<String, BuildProjectTask> getCurrentBuilds()
1119         throws BuildManagerException
1120     {
1121         synchronized ( overallBuildQueues )
1122         {
1123             Map<String, BuildProjectTask> currentBuilds = new HashMap<String, BuildProjectTask>();
1124             Set<Integer> keys = overallBuildQueues.keySet();
1125             for ( Integer key : keys )
1126             {
1127                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1128                 BuildProjectTask task =
1129                     (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
1130                 if ( task != null )
1131                 {
1132                     currentBuilds.put( overallBuildQueue.getName(), task );
1133                 }
1134             }
1135             return currentBuilds;
1136         }
1137     }
1138 
1139     /**
1140      * @see BuildsManager#getCurrentCheckouts()
1141      */
1142     public Map<String, CheckOutTask> getCurrentCheckouts()
1143         throws BuildManagerException
1144     {
1145         synchronized ( overallBuildQueues )
1146         {
1147             Map<String, CheckOutTask> currentCheckouts = new HashMap<String, CheckOutTask>();
1148             Set<Integer> keys = overallBuildQueues.keySet();
1149             for ( Integer key : keys )
1150             {
1151                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1152                 CheckOutTask task = (CheckOutTask) overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask();
1153                 if ( task != null )
1154                 {
1155                     currentCheckouts.put( overallBuildQueue.getName(), task );
1156                 }
1157             }
1158             return currentCheckouts;
1159         }
1160     }
1161 
1162     /**
1163      * @see BuildsManager#getProjectsInBuildQueues()
1164      */
1165     public Map<String, List<BuildProjectTask>> getProjectsInBuildQueues()
1166         throws BuildManagerException
1167     {
1168         synchronized ( overallBuildQueues )
1169         {
1170             Map<String, List<BuildProjectTask>> queuedBuilds = new HashMap<String, List<BuildProjectTask>>();
1171             Set<Integer> keySet = overallBuildQueues.keySet();
1172             for ( Integer key : keySet )
1173             {
1174                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1175                 try
1176                 {
1177                     queuedBuilds.put( overallBuildQueue.getName(), overallBuildQueue.getProjectsInBuildQueue() );
1178                 }
1179                 catch ( TaskQueueException e )
1180                 {
1181                     throw new BuildManagerException(
1182                         "Error occurred while getting projects in build queue '" + overallBuildQueue.getName() + "'.",
1183                         e );
1184                 }
1185             }
1186             return queuedBuilds;
1187         }
1188     }
1189 
1190     /**
1191      * @see BuildsManager#getProjectsInCheckoutQueues()
1192      */
1193     public Map<String, List<CheckOutTask>> getProjectsInCheckoutQueues()
1194         throws BuildManagerException
1195     {
1196         synchronized ( overallBuildQueues )
1197         {
1198             Map<String, List<CheckOutTask>> queuedCheckouts = new HashMap<String, List<CheckOutTask>>();
1199             Set<Integer> keySet = overallBuildQueues.keySet();
1200             for ( Integer key : keySet )
1201             {
1202                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1203                 try
1204                 {
1205                     queuedCheckouts.put( overallBuildQueue.getName(), overallBuildQueue.getProjectsInCheckoutQueue() );
1206                 }
1207                 catch ( TaskQueueException e )
1208                 {
1209                     throw new BuildManagerException(
1210                         "Error occurred while getting projects in build queue '" + overallBuildQueue.getName() + "'.",
1211                         e );
1212                 }
1213             }
1214             return queuedCheckouts;
1215         }
1216     }
1217 
1218     /**
1219      * @see BuildsManager#cancelAllPrepareBuilds()
1220      */
1221     public boolean cancelAllPrepareBuilds()
1222         throws BuildManagerException
1223     {
1224         synchronized ( overallBuildQueues )
1225         {
1226             Set<Integer> keySet = overallBuildQueues.keySet();
1227             OverallBuildQueue overallBuildQueue = null;
1228             for ( Integer key : keySet )
1229             {
1230                 overallBuildQueue = overallBuildQueues.get( key );
1231                 overallBuildQueue.cancelCurrentPrepareBuild();
1232             }
1233 
1234             return true;
1235         }
1236     }
1237 
1238     /**
1239      * @see BuildsManager#isBuildInProgress()
1240      */
1241     public boolean isBuildInProgress()
1242     {
1243         synchronized ( overallBuildQueues )
1244         {
1245             Set<Integer> keySet = overallBuildQueues.keySet();
1246             for ( Integer key : keySet )
1247             {
1248                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1249                 if ( overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask() != null )
1250                 {
1251                     return true;
1252                 }
1253             }
1254             return false;
1255         }
1256     }
1257 
1258     public boolean isProjectCurrentlyPreparingBuild( int projectId )
1259         throws BuildManagerException
1260     {
1261         Map<String, PrepareBuildProjectsTask> tasks = getCurrentProjectInPrepareBuild();
1262 
1263         if ( tasks != null )
1264         {
1265             for ( PrepareBuildProjectsTask task : tasks.values() )
1266             {
1267                 Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();
1268 
1269                 if ( map.size() > 0 )
1270                 {
1271                     Set<Integer> projectIds = map.keySet();
1272 
1273                     if ( projectIds.contains( new Integer( projectId ) ) )
1274                     {
1275                         log.info( "Project '{}' is currently preparing build", projectId );
1276                         return true;
1277                     }
1278                 }
1279             }
1280         }
1281 
1282         return false;
1283     }
1284 
1285     public boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId, int scmRootId )
1286         throws BuildManagerException
1287     {
1288         Map<String, PrepareBuildProjectsTask> tasks = getCurrentProjectInPrepareBuild();
1289 
1290         if ( tasks != null )
1291         {
1292             for ( PrepareBuildProjectsTask task : tasks.values() )
1293             {
1294                 if ( task != null && task.getProjectGroupId() == projectGroupId &&
1295                     task.getProjectScmRootId() == scmRootId )
1296                 {
1297                     log.info( "Project group '{}' with scm root '{}' is currently preparing build", projectGroupId,
1298                               scmRootId );
1299                     return true;
1300                 }
1301             }
1302         }
1303 
1304         return false;
1305     }
1306 
1307     public Map<String, PrepareBuildProjectsTask> getCurrentProjectInPrepareBuild()
1308         throws BuildManagerException
1309     {
1310         synchronized ( overallBuildQueues )
1311         {
1312             Map<String, PrepareBuildProjectsTask> currentBuilds = new HashMap<String, PrepareBuildProjectsTask>();
1313             Set<Integer> keys = overallBuildQueues.keySet();
1314             for ( Integer key : keys )
1315             {
1316                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1317                 PrepareBuildProjectsTask task =
1318                     (PrepareBuildProjectsTask) overallBuildQueue.getPrepareBuildTaskQueueExecutor().getCurrentTask();
1319                 if ( task != null )
1320                 {
1321                     currentBuilds.put( overallBuildQueue.getName(), task );
1322                 }
1323             }
1324             return currentBuilds;
1325         }
1326     }
1327 
1328     public Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue()
1329         throws BuildManagerException
1330     {
1331         synchronized ( overallBuildQueues )
1332         {
1333             Map<String, List<PrepareBuildProjectsTask>> queuedPrepareBuilds =
1334                 new HashMap<String, List<PrepareBuildProjectsTask>>();
1335             Set<Integer> keySet = overallBuildQueues.keySet();
1336             for ( Integer key : keySet )
1337             {
1338                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1339                 try
1340                 {
1341                     queuedPrepareBuilds.put( overallBuildQueue.getName(),
1342                                              overallBuildQueue.getProjectsInPrepareBuildQueue() );
1343                 }
1344                 catch ( TaskQueueException e )
1345                 {
1346                     throw new BuildManagerException(
1347                         "Error occurred while getting projects in prepare build queue '" + overallBuildQueue.getName() +
1348                             "'.", e );
1349                 }
1350             }
1351             return queuedPrepareBuilds;
1352         }
1353     }
1354 
1355     public boolean removeProjectFromPrepareBuildQueue( int projectGroupId, int scmRootId )
1356         throws BuildManagerException
1357     {
1358         try
1359         {
1360             OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectGroupIsQueued( projectGroupId,
1361                                                                                                  scmRootId );
1362             if ( overallBuildQueue != null )
1363             {
1364                 overallBuildQueue.removeProjectFromPrepareBuildQueue( projectGroupId, scmRootId );
1365             }
1366             else
1367             {
1368                 log.info( "Project group '{}' with scm '{}' not found in any of the build queues.", projectGroupId,
1369                           scmRootId );
1370             }
1371         }
1372         catch ( TaskQueueException e )
1373         {
1374             throw new BuildManagerException(
1375                 "Error occurred while removing project group from prepare build queue: " + e.getMessage() );
1376         }
1377 
1378         return true;
1379     }
1380 
1381     public void removeProjectsFromPrepareBuildQueueWithHashCodes( int[] hashCodes )
1382         throws BuildManagerException
1383     {
1384         try
1385         {
1386             synchronized ( overallBuildQueues )
1387             {
1388                 Set<Integer> keySet = overallBuildQueues.keySet();
1389                 for ( Integer key : keySet )
1390                 {
1391                     OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1392                     overallBuildQueue.removeProjectsFromPrepareBuildQueueWithHashCodes( hashCodes );
1393                 }
1394             }
1395         }
1396         catch ( TaskQueueException e )
1397         {
1398             throw new BuildManagerException( "Error encountered while removing project group(s) from build queue.", e );
1399         }
1400     }
1401 
1402     private boolean isInQueue( int projectId, int typeOfQueue, int buildDefinitionId )
1403         throws TaskQueueException
1404     {
1405         synchronized ( overallBuildQueues )
1406         {
1407             Set<Integer> keySet = overallBuildQueues.keySet();
1408             for ( Integer key : keySet )
1409             {
1410                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1411                 if ( typeOfQueue == BUILD_QUEUE )
1412                 {
1413                     if ( buildDefinitionId < 0 )
1414                     {
1415                         if ( overallBuildQueue.isInBuildQueue( projectId ) )
1416                         {
1417                             log.info( "Project " + projectId + " is in build queue " + overallBuildQueue.getName() );
1418                             return true;
1419                         }
1420                     }
1421                     else
1422                     {
1423                         if ( overallBuildQueue.isInBuildQueue( projectId, buildDefinitionId ) )
1424                         {
1425                             log.info( "Project " + projectId + " is in build queue " + overallBuildQueue.getName() );
1426                             return true;
1427                         }
1428                     }
1429                 }
1430                 else if ( typeOfQueue == CHECKOUT_QUEUE )
1431                 {
1432                     if ( overallBuildQueue.isInCheckoutQueue( projectId ) )
1433                     {
1434                         log.info( "Project " + projectId + " is in checkout queue " + overallBuildQueue.getName() );
1435                         return true;
1436                     }
1437                 }
1438             }
1439 
1440             return false;
1441         }
1442     }
1443 
1444     // get overall queue where project is queued
1445     private OverallBuildQueue getOverallBuildQueueWhereProjectIsQueued( int projectId, int typeOfQueue )
1446         throws TaskQueueException
1447     {
1448         synchronized ( overallBuildQueues )
1449         {
1450             OverallBuildQueue whereQueued = null;
1451             Set<Integer> keySet = overallBuildQueues.keySet();
1452 
1453             for ( Integer key : keySet )
1454             {
1455                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1456                 if ( typeOfQueue == BUILD_QUEUE )
1457                 {
1458                     if ( overallBuildQueue.isInBuildQueue( projectId ) )
1459                     {
1460                         whereQueued = overallBuildQueue;
1461                         break;
1462                     }
1463                 }
1464                 else if ( typeOfQueue == CHECKOUT_QUEUE )
1465                 {
1466                     if ( overallBuildQueue.isInCheckoutQueue( projectId ) )
1467                     {
1468                         whereQueued = overallBuildQueue;
1469                         break;
1470                     }
1471                 }
1472                 else if ( typeOfQueue == PREPARE_BUILD_QUEUE )
1473                 {
1474                     if ( overallBuildQueue.isInPrepareBuildQueue( projectId ) )
1475                     {
1476                         whereQueued = overallBuildQueue;
1477                         break;
1478                     }
1479                 }
1480             }
1481 
1482             return whereQueued;
1483         }
1484     }
1485 
1486     // get overall queue where project will be queued
1487     private OverallBuildQueue getOverallBuildQueue( int typeOfQueue, List<BuildQueue> buildQueues )
1488         throws BuildManagerException
1489     {
1490         OverallBuildQueue whereToBeQueued = null;
1491         synchronized ( overallBuildQueues )
1492         {
1493             if ( overallBuildQueues == null || overallBuildQueues.isEmpty() )
1494             {
1495                 throw new BuildManagerException( "No build queues configured." );
1496             }
1497 
1498             int size = 0;
1499             int idx = 0;
1500             int allowedBuilds = configurationService.getNumberOfBuildsInParallel();
1501 
1502             try
1503             {
1504                 int count = 1;
1505                 for ( BuildQueue buildQueue : buildQueues )
1506                 {
1507                     if ( count <= allowedBuilds )
1508                     {
1509                         OverallBuildQueue overallBuildQueue = overallBuildQueues.get( buildQueue.getId() );
1510                         if ( overallBuildQueue != null )
1511                         {
1512                             TaskQueue taskQueue = null;
1513                             TaskQueueExecutor taskQueueExecutor = null;
1514                             int tempSize = 0;
1515                             if ( typeOfQueue == BUILD_QUEUE )
1516                             {
1517                                 taskQueue = overallBuildQueue.getBuildQueue();
1518                                 taskQueueExecutor = overallBuildQueue.getBuildTaskQueueExecutor();
1519                             }
1520                             else if ( typeOfQueue == CHECKOUT_QUEUE )
1521                             {
1522                                 taskQueue = overallBuildQueue.getCheckoutQueue();
1523                                 taskQueueExecutor = overallBuildQueue.getCheckoutTaskQueueExecutor();
1524                             }
1525                             else if ( typeOfQueue == PREPARE_BUILD_QUEUE )
1526                             {
1527                                 taskQueue = overallBuildQueue.getPrepareBuildQueue();
1528                                 taskQueueExecutor = overallBuildQueue.getPrepareBuildTaskQueueExecutor();
1529                             }
1530 
1531                             tempSize = taskQueue.getQueueSnapshot().size();
1532                             if ( taskQueueExecutor.getCurrentTask() != null )
1533                             {
1534                                 tempSize++;
1535                             }
1536 
1537                             if ( idx == 0 )
1538                             {
1539                                 whereToBeQueued = overallBuildQueue;
1540                                 size = tempSize;
1541                             }
1542 
1543                             if ( tempSize < size )
1544                             {
1545                                 whereToBeQueued = overallBuildQueue;
1546                                 size = tempSize;
1547                             }
1548 
1549                             idx++;
1550                         }
1551                         else
1552                         {
1553                             log.error( "Build queue not found." );
1554                         }
1555                         count++;
1556                     }
1557                     else
1558                     {
1559                         break;
1560                     }
1561                 }
1562             }
1563             catch ( TaskQueueException e )
1564             {
1565                 throw new BuildManagerException( "Error occurred while retrieving task quueue: " + e.getMessage() );
1566             }
1567         }
1568 
1569         // use default overall build queue if none is configured
1570         if ( whereToBeQueued == null )
1571         {
1572             Set<Integer> keySet = overallBuildQueues.keySet();
1573             for ( Integer key : keySet )
1574             {
1575                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1576                 if ( overallBuildQueue.getName().equals( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) )
1577                 {
1578                     return overallBuildQueue;
1579                 }
1580             }
1581         }
1582 
1583         return whereToBeQueued;
1584     }
1585 
1586     public OverallBuildQueue getOverallBuildQueueWhereProjectsInGroupAreQueued( int projectGroupId )
1587         throws BuildManagerException
1588     {
1589         OverallBuildQueue whereToBeQueued = null;
1590 
1591         try
1592         {
1593             List<Project> projects = projectDao.getProjectsInGroup( projectGroupId );
1594 
1595             if ( projects != null )
1596             {
1597                 for ( Project project : projects )
1598                 {
1599                     whereToBeQueued = getOverallBuildQueueWhereProjectIsQueued( project.getId(), BUILD_QUEUE );
1600 
1601                     if ( whereToBeQueued == null )
1602                     {
1603                         whereToBeQueued = getOverallBuildQueueWhereProjectIsBuilding( project.getId() );
1604                     }
1605 
1606                     if ( whereToBeQueued != null )
1607                     {
1608                         break;
1609                     }
1610                 }
1611             }
1612         }
1613         catch ( ContinuumStoreException e )
1614         {
1615             throw new BuildManagerException(
1616                 "Error while retrieving overall build queue for project: " + e.getMessage() );
1617         }
1618         catch ( TaskQueueException e )
1619         {
1620             throw new BuildManagerException(
1621                 "Error while retrieving overall build queue for project: " + e.getMessage() );
1622         }
1623 
1624         return whereToBeQueued;
1625     }
1626 
1627     private OverallBuildQueue getOverallBuildQueueWhereProjectGroupIsQueued( int projectGroupId, int scmRootId )
1628         throws TaskQueueException
1629     {
1630         synchronized ( overallBuildQueues )
1631         {
1632             OverallBuildQueue whereQueued = null;
1633             Set<Integer> keySet = overallBuildQueues.keySet();
1634 
1635             for ( Integer key : keySet )
1636             {
1637                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1638 
1639                 if ( overallBuildQueue.isInPrepareBuildQueue( projectGroupId, scmRootId ) )
1640                 {
1641                     whereQueued = overallBuildQueue;
1642                 }
1643             }
1644 
1645             return whereQueued;
1646         }
1647     }
1648 
1649     private OverallBuildQueue getOverallBuildQueueWhereProjectGroupIsQueued( int projectGroupId, String scmRootAddress )
1650         throws TaskQueueException
1651     {
1652         synchronized ( overallBuildQueues )
1653         {
1654             OverallBuildQueue whereQueued = null;
1655             Set<Integer> keySet = overallBuildQueues.keySet();
1656 
1657             for ( Integer key : keySet )
1658             {
1659                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1660 
1661                 if ( overallBuildQueue.isInPrepareBuildQueue( projectGroupId, scmRootAddress ) )
1662                 {
1663                     whereQueued = overallBuildQueue;
1664                 }
1665             }
1666 
1667             return whereQueued;
1668         }
1669     }
1670 
1671     private OverallBuildQueue getOverallBuildQueueWhereProjectIsBuilding( int projectId )
1672     {
1673         synchronized ( overallBuildQueues )
1674         {
1675             for ( Integer key : overallBuildQueues.keySet() )
1676             {
1677                 OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
1678                 BuildProjectTask task =
1679                     (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
1680                 if ( task != null && task.getProjectId() == projectId )
1681                 {
1682                     return overallBuildQueue;
1683                 }
1684             }
1685             return null;
1686         }
1687     }
1688 
1689     public boolean isProjectCurrentlyBeingCheckedOut( int projectId )
1690         throws BuildManagerException
1691     {
1692         Map<String, CheckOutTask> checkouts = getCurrentCheckouts();
1693         for ( String key : checkouts.keySet() )
1694         {
1695             CheckOutTask task = checkouts.get( key );
1696             if ( task.getProjectId() == projectId )
1697             {
1698                 return true;
1699             }
1700         }
1701 
1702         return false;
1703     }
1704 
1705     public boolean isAnyProjectCurrentlyBuilding( int[] projectIds )
1706         throws BuildManagerException
1707     {
1708         for ( int i = 0; i < projectIds.length; i++ )
1709         {
1710             if ( isProjectInAnyCurrentBuild( projectIds[i] ) )
1711             {
1712                 return true;
1713             }
1714         }
1715 
1716         return false;
1717     }
1718 
1719     public boolean isAnyProjectCurrentlyPreparingBuild( int[] projectIds )
1720         throws BuildManagerException
1721     {
1722         for ( int i = 0; i < projectIds.length; i++ )
1723         {
1724             if ( isProjectCurrentlyPreparingBuild( projectIds[i] ) )
1725             {
1726                 return true;
1727             }
1728         }
1729 
1730         return false;
1731     }
1732 
1733     public void contextualize( Context context )
1734         throws ContextException
1735     {
1736         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
1737 
1738         synchronized ( overallBuildQueues )
1739         {
1740             try
1741             {
1742                 // create all the build queues configured in the database, not just the default!               
1743                 List<BuildQueue> buildQueues = buildQueueService.getAllBuildQueues();
1744                 for ( BuildQueue buildQueue : buildQueues )
1745                 {
1746                     createOverallBuildQueue( buildQueue );
1747                 }
1748 
1749                 // add default overall build queue if not yet added to the map
1750                 BuildQueue defaultBuildQueue = configurationService.getDefaultBuildQueue();
1751                 if ( overallBuildQueues.get( defaultBuildQueue.getId() ) == null )
1752                 {
1753                     createOverallBuildQueue( defaultBuildQueue );
1754                 }
1755             }
1756             catch ( ComponentLookupException e )
1757             {
1758                 log.error( "Cannot create overall build queue: " + e.getMessage() );
1759             }
1760             catch ( BuildQueueServiceException e )
1761             {
1762                 log.error( "Cannot create overall build queue: " + e.getMessage() );
1763             }
1764         }
1765     }
1766 
1767     public void setContainer( PlexusContainer container )
1768     {
1769         this.container = container;
1770     }
1771 
1772     private void createOverallBuildQueue( BuildQueue defaultBuildQueue )
1773         throws ComponentLookupException
1774     {
1775         OverallBuildQueue overallBuildQueue = (OverallBuildQueue) container.lookup( OverallBuildQueue.class );
1776         overallBuildQueue.setId( defaultBuildQueue.getId() );
1777         overallBuildQueue.setName( defaultBuildQueue.getName() );
1778 
1779         overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue );
1780     }
1781 
1782     // for unit tests.. 
1783 
1784     public void setOverallBuildQueues( Map<Integer, OverallBuildQueue> overallBuildQueues )
1785     {
1786         this.overallBuildQueues = overallBuildQueues;
1787     }
1788 
1789     public void setConfigurationService( ConfigurationService configurationService )
1790     {
1791         this.configurationService = configurationService;
1792     }
1793 
1794     public void setBuildQueueService( BuildQueueService buildQueueService )
1795     {
1796         this.buildQueueService = buildQueueService;
1797     }
1798 
1799     public void setBuildDefinitionDao( BuildDefinitionDao buildDefinitionDao )
1800     {
1801         this.buildDefinitionDao = buildDefinitionDao;
1802     }
1803 
1804     public void setProjectDao( ProjectDao projectDao )
1805     {
1806         this.projectDao = projectDao;
1807     }
1808 }