Package org.apache.continuum.buildmanager

Source Code of org.apache.continuum.buildmanager.ParallelBuildsManager

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 javax.annotation.Resource;

import org.apache.commons.lang.ArrayUtils;
import org.apache.continuum.buildqueue.BuildQueueService;
import org.apache.continuum.buildqueue.BuildQueueServiceException;
import org.apache.continuum.dao.BuildDefinitionDao;
import org.apache.continuum.dao.ProjectDao;
import org.apache.continuum.taskqueue.BuildProjectTask;
import org.apache.continuum.taskqueue.CheckOutTask;
import org.apache.continuum.taskqueue.OverallBuildQueue;
import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor;
import org.apache.maven.continuum.configuration.ConfigurationService;
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.scm.ScmResult;
import org.apache.maven.continuum.store.ContinuumStoreException;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
import org.codehaus.plexus.taskqueue.Task;
import org.codehaus.plexus.taskqueue.TaskQueue;
import org.codehaus.plexus.taskqueue.TaskQueueException;
import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
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>
* @version $Id$
*/
public class ParallelBuildsManager
    implements BuildsManager, Contextualizable
{
    private static final 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;

    @Resource
    private BuildDefinitionDao buildDefinitionDao;

    @Resource
    private ProjectDao projectDao;

    private TaskQueue prepareBuildQueue;

    @Resource
    private ConfigurationService configurationService;

    @Resource
    private BuildQueueService buildQueueService;

    private PlexusContainer container;

    /**
     * @see BuildsManager#buildProject(int, BuildDefinition, String, int, ScmResult, int)
     */
    public void buildProject( int projectId, BuildDefinition buildDefinition, String projectName, int trigger,
                              ScmResult scmResult, int projectGroupId )
        throws BuildManagerException
    {
        try
        {
            if ( isInQueue( projectId, BUILD_QUEUE, -1 ) )
            {
                log.warn( "Project already queued." );
                return;
            }
            else if ( isProjectInAnyCurrentBuild( projectId ) )
            {
                log.warn( "Project is already building." );
                return;
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException(
                "Error occurred while checking if the project is already in queue: " + e.getMessage() );
        }

        OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectsInGroupAreQueued( projectGroupId );

        if ( overallBuildQueue == null )
        {
            overallBuildQueue = getOverallBuildQueue( BUILD_QUEUE, buildDefinition.getSchedule().getBuildQueues() );
        }

        if ( overallBuildQueue != null )
        {
            String buildDefinitionLabel = buildDefinition.getDescription();

            if ( StringUtils.isEmpty( buildDefinitionLabel ) )
            {
                buildDefinitionLabel = buildDefinition.getGoals();
            }
   
            BuildProjectTask buildTask =
                new BuildProjectTask( projectId, buildDefinition.getId(), trigger, projectName, buildDefinitionLabel,
                                      scmResult, projectGroupId );
            try
            {
                log.info(
                    "Project '" + projectName + "' added to overall build queue '" + overallBuildQueue.getName() + "'." );
                overallBuildQueue.addToBuildQueue( buildTask );
            }
            catch ( TaskQueueException e )
            {
                throw new BuildManagerException( "Error occurred while adding project to build queue: " + e.getMessage() );
            }
        }
        else
        {
            log.warn( "No build queue configured. Not building." );
        }
    }

    /**
     * @see BuildsManager#buildProjects(List, Map, int, Map, int)
     */
    public void buildProjects( List<Project> projects, Map<Integer, BuildDefinition> projectsBuildDefinitionsMap,
                               int trigger, Map<Integer, ScmResult> scmResultMap, int projectGroupId )
        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, -1 ) && !isProjectInAnyCurrentBuild( project.getId() ) )
                {
                    firstProjectId = project.getId();
                    break;
                }
            }
            catch ( TaskQueueException e )
            {
                log.warn( "Error occurred while verifying if project is already queued." );
            }
        }

        if ( firstProjectId != 0 )
        {
            BuildDefinition buildDef = projectsBuildDefinitionsMap.get( firstProjectId );
            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectsInGroupAreQueued( projectGroupId );

            if ( overallBuildQueue == null )
            {
                overallBuildQueue = getOverallBuildQueue( BUILD_QUEUE, buildDef.getSchedule().getBuildQueues() );
            }

            if ( overallBuildQueue != null )
            {
                for ( Project project : projects )
                {
                    try
                    {
                        if ( isInQueue( project.getId(), BUILD_QUEUE,
                                        projectsBuildDefinitionsMap.get( project.getId() ).getId() ) )
                        {
                            log.warn( "Project '" + project.getId() + "' - '" + project.getName() +
                                "' is already in build queue." );
                            continue;
                        }
                        else if ( isProjectInAnyCurrentBuild( project.getId() ) )
                        {
                            log.warn( "Project '" + project.getId() + "' - '" + project.getName() +
                                      "' is already building." );
                            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();
                    }

                    ScmResult scmResult = scmResultMap.get( project.getId() );
                    BuildProjectTask buildTask =
                        new BuildProjectTask( project.getId(), buildDefinition.getId(), trigger, project.getName(),
                                              buildDefinitionLabel, scmResult, projectGroupId );
                    buildTask.setMaxExecutionTime( buildDefinition.getSchedule().getMaxJobExecutionTime() * 1000 );

                    try
                    {
                        log.info( "Project '" + project.getId() + "' - '" + project.getName() +
                            "' added to overall build queue '" + overallBuildQueue.getName() + "'." );

                        overallBuildQueue.addToBuildQueue( buildTask );
                    }
                    catch ( TaskQueueException e )
                    {
                        throw new BuildManagerException(
                            "Error occurred while adding project to build queue: " + e.getMessage() );
                    }
                }
            }
            else
            {
                log.warn( "No build queue configured. Not building" );
            }
        }
        else
        {
            log.error( "Projects are already in build queue." );
        }
    }

    /**
     * @see BuildsManager#cancelBuildInQueue(int)
     */
    public boolean cancelBuildInQueue( int buildQueueId )
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            OverallBuildQueue overallBuildQueue;
            overallBuildQueue = overallBuildQueues.get( buildQueueId );
            if ( overallBuildQueue != null )
            {
                overallBuildQueue.cancelCurrentBuild();
            }
            else
            {
                log.warn( "Project not found in any of the build queues." );
            }

            return true;
        }
    }

    /**
     * @see BuildsManager#cancelAllBuilds()
     */
    public boolean cancelAllBuilds()
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            Set<Integer> keySet = overallBuildQueues.keySet();
            OverallBuildQueue overallBuildQueue = null;
            for ( Integer key : keySet )
            {
                overallBuildQueue = overallBuildQueues.get( key );
                overallBuildQueue.cancelCurrentBuild();
            }

            return true;
        }
    }

    /**
     * @see BuildsManager#cancelAllCheckouts()
     */
    public boolean cancelAllCheckouts()
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            Set<Integer> keySet = overallBuildQueues.keySet();
            OverallBuildQueue overallBuildQueue;
            for ( Integer key : keySet )
            {
                overallBuildQueue = overallBuildQueues.get( key );
                overallBuildQueue.cancelCurrentCheckout();
            }

            return true;
        }
    }

    /**
     * @see BuildsManager#cancelBuild(int)
     */
    public boolean cancelBuild( int projectId )
        throws BuildManagerException
    {
        try
        {
            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
            if ( overallBuildQueue != null )
            {
                overallBuildQueue.cancelBuildTask( projectId );
            }
            else
            {
                synchronized ( overallBuildQueues )
                {
                    Set<Integer> keySet = overallBuildQueues.keySet();
                    for ( Integer key : keySet )
                    {
                        overallBuildQueue = overallBuildQueues.get( key );
                        BuildProjectTask buildTask =
                            (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
                        if ( buildTask != null && buildTask.getProjectId() == projectId )
                        {
                            overallBuildQueue.cancelBuildTask( projectId );
                            return true;
                        }
                    }
                    log.error( "Project '" + projectId + "' not found in any of the builds queues." );
                }
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
        }

        return true;
    }

    /**
     * @see BuildsManager#cancelCheckout(int)
     */
    public boolean cancelCheckout( int projectId )
        throws BuildManagerException
    {
        try
        {
            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE );
            if ( overallBuildQueue != null )
            {
                overallBuildQueue.cancelCheckoutTask( projectId );
            }
            else
            {
                synchronized ( overallBuildQueues )
                {
                    Set<Integer> keySet = overallBuildQueues.keySet();
                    for ( Integer key : keySet )
                    {
                        overallBuildQueue = overallBuildQueues.get( key );
                        CheckOutTask checkoutTask =
                            (CheckOutTask) overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask();
                        if ( checkoutTask != null && checkoutTask.getProjectId() == projectId )
                        {
                            overallBuildQueue.cancelCheckoutTask( projectId );
                            return true;
                        }
                    }
                    log.info( "Project '" + projectId + "' not found in any of the checkout queues." );
                }
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
        }

        return true;
    }

    /**
     * @see BuildsManager#checkoutProject(int, String, File, String, String, BuildDefinition)
     */
    public void checkoutProject( int projectId, String projectName, File workingDirectory, String scmUsername,
                                 String scmPassword, BuildDefinition defaultBuildDefinition )
        throws BuildManagerException
    {
        try
        {
            if ( isInQueue( projectId, CHECKOUT_QUEUE, -1 ) )
            {
                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( CHECKOUT_QUEUE, defaultBuildDefinition.getSchedule().getBuildQueues() );
        CheckOutTask checkoutTask =
            new CheckOutTask( projectId, workingDirectory, projectName, scmUsername, scmPassword );
        try
        {
            if ( overallBuildQueue != null )
            {
                log.info( "Project '" + projectName + "' added to overall build queue '" + overallBuildQueue.getName() +
                    "'." );
                overallBuildQueue.addToCheckoutQueue( checkoutTask );
            }
            else
            {
                throw new BuildManagerException(
                    "Unable to add project to checkout queue. No overall build queue configured." );
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException(
                "Error occurred while adding project to checkout queue: " + e.getMessage() );
        }
    }

    /**
     * @see BuildsManager#isInAnyBuildQueue(int)
     */
    public boolean isInAnyBuildQueue( int projectId )
        throws BuildManagerException
    {
        try
        {
            return isInQueue( projectId, BUILD_QUEUE, -1 );
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( e.getMessage() );
        }
    }

    /**
     * @see BuildsManager#isInAnyBuildQueue(int, int)
     */
    public boolean isInAnyBuildQueue( int projectId, int buildDefinitionId )
        throws BuildManagerException
    {
        try
        {
            return isInQueue( projectId, BUILD_QUEUE, buildDefinitionId );
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( e.getMessage() );
        }
    }

    /**
     * @see BuildsManager#isInAnyCheckoutQueue(int)
     */
    public boolean isInAnyCheckoutQueue( int projectId )
        throws BuildManagerException
    {
        try
        {
            return isInQueue( projectId, CHECKOUT_QUEUE, -1 );
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( e.getMessage() );
        }
    }

    /**
     * @see BuildsManager#isAnyProjectCurrentlyBeingCheckedOut(int[])
     */
    public boolean isAnyProjectCurrentlyBeingCheckedOut( int[] projectIds )
        throws BuildManagerException
    {
        for ( int projectId : projectIds )
        {
            Map<String, CheckOutTask> checkouts = getCurrentCheckouts();
            Set<String> keySet = checkouts.keySet();
            for ( String key : keySet )
            {
                CheckOutTask task = checkouts.get( key );
                if ( task.getProjectId() == projectId )
                {
                    log.info( "Project " + projectId + " is currently being checked out" );
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @see BuildsManager#isInPrepareBuildQueue(int)
     */
    public boolean isInPrepareBuildQueue( int projectId )
        throws BuildManagerException
    {
        try
        {
            List<PrepareBuildProjectsTask> queue = prepareBuildQueue.getQueueSnapshot();
            for ( PrepareBuildProjectsTask task : queue )
            {
                if ( task != null )
                {
                    Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();

                    if ( map.size() > 0 )
                    {
                        Set<Integer> projectIds = map.keySet();

                        if ( projectIds.contains( new Integer( projectId ) ) )
                        {
                            log.info( "Project " + projectId + " is in prepare build queue" );
                            return true;
                        }
                    }
                }
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( e.getMessage() );
        }

        return false;
    }

    /**
     * @see BuildsManager#isProjectInAnyCurrentBuild(int)
     */
    public boolean isProjectInAnyCurrentBuild( int projectId )
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            Set<Integer> keys = overallBuildQueues.keySet();
            for ( Integer key : keys )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                BuildProjectTask task =
                    (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
                if ( task != null && task.getProjectId() == projectId )
                {
                    log.info( "Project " + projectId + " is currently building in " + overallBuildQueue.getName() );
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * @see BuildsManager#prepareBuildProjects(Map, int, int, String, String, int)
     */
    public void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, int trigger,
                                      int projectGroupId, String projectGroupName, String scmRootAddress,
                                      int scmRootId )
        throws BuildManagerException
    {
        try
        {
            PrepareBuildProjectsTask task =
                new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, trigger, projectGroupId, projectGroupName,
                                              scmRootAddress, scmRootId );

            log.info( "Queueing prepare-build-project task '" + task + "' to prepare-build queue." );
            prepareBuildQueue.put( task );
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException(
                "Error occurred while creating prepare-build-project task: " + e.getMessage() );
        }
    }

    /**
     * @see BuildsManager#removeProjectFromBuildQueue(int)
     */
    public void removeProjectFromBuildQueue( int projectId )
        throws BuildManagerException
    {
        try
        {
            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
            if ( overallBuildQueue != null )
            {
                overallBuildQueue.removeProjectFromBuildQueue( projectId );
            }
            else
            {
                log.info( "Project '" + projectId + "' not found in any of the build queues." );
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException(
                "Error occurred while removing project from build queue: " + e.getMessage() );
        }
    }

    /**
     * @see BuildsManager#removeProjectFromBuildQueue(int, int, int, String)
     */
    public void removeProjectFromBuildQueue( int projectId, int buildDefinitionId, int trigger, String projectName,
                                             int projectGroupId )
        throws BuildManagerException
    {
        try
        {
            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
            if ( overallBuildQueue != null )
            {
                overallBuildQueue.removeProjectFromBuildQueue( projectId, buildDefinitionId, trigger, projectName,
                                                               projectGroupId );
            }
            else
            {
                log.info( "Project '" + projectId + "' not found in any of the build queues." );
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException(
                "Error occurred while removing project from build queue: " + e.getMessage() );
        }
    }

    /**
     * @see BuildsManager#removeProjectFromCheckoutQueue(int)
     */
    public void removeProjectFromCheckoutQueue( int projectId )
        throws BuildManagerException
    {
        try
        {
            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE );
            if ( overallBuildQueue != null )
            {
                overallBuildQueue.removeProjectFromCheckoutQueue( projectId );
            }
            else
            {
                log.info( "Project '" + projectId + "' not found in any of the checkout queues." );
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException(
                "Error occurred while removing project from checkout queue: " + e.getMessage() );
        }
    }

    /**
     * @see BuildsManager#removeProjectsFromBuildQueue(int[])
     */
    public void removeProjectsFromBuildQueue( int[] projectIds )
    {
        for ( int projectId : projectIds )
        {
            try
            {
                OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE )
                    ;
                if ( overallBuildQueue != null )
                {
                    overallBuildQueue.removeProjectFromBuildQueue( projectId );
                }
                else
                {
                    log.error( "Project '" + projectId + "' not found in any of the build queues." );
                }
            }
            catch ( TaskQueueException e )
            {
                log.error( "Error occurred while removing project '" + projectId + "' from build queue." );
            }
        }
    }

    /**
     * @see BuildsManager#removeProjectsFromCheckoutQueue(int[])
     */
    public void removeProjectsFromCheckoutQueue( int[] projectIds )
    {
        for ( int projectId : projectIds )
        {
            try
            {
                OverallBuildQueue overallBuildQueue =
                    getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE );
                if ( overallBuildQueue != null )
                {
                    overallBuildQueue.removeProjectFromCheckoutQueue( projectId );
                }
                else
                {
                    log.error( "Project '" + projectId + "' not found in any of the checkout queues." );
                }
            }
            catch ( TaskQueueException e )
            {
                log.error( "Error occurred while removing project '" + projectId + "' from checkout queue." );
            }
        }
    }

    /**
     * @see BuildsManager#removeProjectsFromCheckoutQueueWithHashcodes(int[])
     */
    public void removeProjectsFromCheckoutQueueWithHashcodes( int[] hashcodes )
        throws BuildManagerException
    {
        try
        {
            synchronized ( overallBuildQueues )
            {
                Set<Integer> keySet = overallBuildQueues.keySet();
                for ( Integer key : keySet )
                {
                    OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                    overallBuildQueue.removeTasksFromCheckoutQueueWithHashCodes( hashcodes );
                }
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( "Error encountered while removing project(s) from checkout queue.", e );
        }
    }

    /**
     * @see BuildsManager#removeProjectsFromBuildQueueWithHashcodes(int[])
     */
    public void removeProjectsFromBuildQueueWithHashcodes( int[] hashcodes )
        throws BuildManagerException
    {
        try
        {
            synchronized ( overallBuildQueues )
            {
                Set<Integer> keySet = overallBuildQueues.keySet();
                for ( Integer key : keySet )
                {
                    OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                    overallBuildQueue.removeProjectsFromBuildQueueWithHashCodes( hashcodes );
                }
            }
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( "Error encountered while removing project(s) from build queue.", e );
        }
    }

    public boolean removeProjectGroupFromPrepareBuildQueue( int projectGroupId, String scmRootAddress )
        throws BuildManagerException
    {
        try
        {
            List<PrepareBuildProjectsTask> queue = prepareBuildQueue.getQueueSnapshot();

            for ( PrepareBuildProjectsTask task : queue )
            {
                if ( task != null && task.getProjectGroupId() == projectGroupId &&
                    task.getScmRootAddress().equals( scmRootAddress ) )
                {
                    return prepareBuildQueue.remove( task );
                }
            }
            return false;
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( "Error while getting the prepare build projects task in queue", e );
        }
    }

    /**
     * @see BuildsManager#addOverallBuildQueue(BuildQueue)
     */
    public void addOverallBuildQueue( BuildQueue buildQueue )
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            try
            {
                OverallBuildQueue overallBuildQueue = (OverallBuildQueue) container.lookup( OverallBuildQueue.class );
                overallBuildQueue.setId( buildQueue.getId() );
                overallBuildQueue.setName( buildQueue.getName() );

                if ( overallBuildQueues.get( buildQueue.getId() ) == null )
                {
                    log.info( "Adding overall build queue to map : " + overallBuildQueue.getName() );
                    overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue );
                }
                else
                {
                    log.warn( "Overall build queue already in the map." );
                }
            }
            catch ( ComponentLookupException e )
            {
                throw new BuildManagerException( "Error creating overall build queue.", e );
            }
        }
    }

    /**
     * @see BuildsManager#removeOverallBuildQueue(int)
     */
    public void removeOverallBuildQueue( int overallBuildQueueId )
        throws BuildManagerException
    {
        List<BuildProjectTask> tasks;
        List<CheckOutTask> checkoutTasks;

        synchronized ( overallBuildQueues )
        {
            OverallBuildQueue overallBuildQueue = overallBuildQueues.get( overallBuildQueueId );
            if ( overallBuildQueue.getName().equals( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) )
            {
                throw new BuildManagerException( "Cannot remove default build queue." );
            }

            try
            {
                if ( overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask() != null ||
                    overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask() != null )
                {
                    throw new BuildManagerException( "Cannot remove build queue. A task is currently executing." );
                }

                tasks = overallBuildQueue.getProjectsInBuildQueue();
                checkoutTasks = overallBuildQueue.getProjectsInCheckoutQueue();

                overallBuildQueue.getBuildQueue().removeAll( tasks );
                overallBuildQueue.getCheckoutQueue().removeAll( checkoutTasks );

                ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getBuildTaskQueueExecutor() ).stop();
                ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getCheckoutTaskQueueExecutor() ).stop();
                container.release( overallBuildQueue );
            }
            catch ( TaskQueueException e )
            {
                throw new BuildManagerException(
                    "Cannot remove build queue. An error occurred while retrieving queued tasks." );
            }
            catch ( ComponentLifecycleException e )
            {
                throw new BuildManagerException(
                    "Cannot remove build queue. An error occurred while destroying the build queue: " +
                        e.getMessage() );
            }
            catch ( StoppingException e )
            {
                throw new BuildManagerException(
                    "Cannot remove build queue. An error occurred while stopping the build queue: " + e.getMessage() );
            }

            this.overallBuildQueues.remove( overallBuildQueueId );
            log.info( "Removed overall build queue '" + overallBuildQueueId + "' from build queues map." );
        }

        for ( BuildProjectTask buildTask : tasks )
        {
            try
            {
                BuildDefinition buildDefinition =
                    buildDefinitionDao.getBuildDefinition( buildTask.getBuildDefinitionId() );

                buildProject( buildTask.getProjectId(), buildDefinition, buildTask.getProjectName(),
                              buildTask.getTrigger(), buildTask.getScmResult(), buildTask.getProjectGroupId() );
            }
            catch ( ContinuumStoreException e )
            {
                log.error( "Unable to queue build task for project '" + buildTask.getProjectName() + "'" );
            }
        }

        for ( CheckOutTask task : checkoutTasks )
        {
            try
            {
                BuildDefinition buildDefinition = buildDefinitionDao.getDefaultBuildDefinition( task.getProjectId() );
                checkoutProject( task.getProjectId(), task.getProjectName(), task.getWorkingDirectory(),
                                 task.getScmUserName(), task.getScmPassword(), buildDefinition );
            }
            catch ( ContinuumStoreException e )
            {
                log.error( "Unable to queue checkout task for project '" + task.getProjectName() + "'" );
            }
        }
    }

    public Map<Integer, OverallBuildQueue> getOverallBuildQueues()
    {
        return overallBuildQueues;
    }

    /**
     * @see BuildsManager#getCurrentBuilds()
     */
    public Map<String, BuildProjectTask> getCurrentBuilds()
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            Map<String, BuildProjectTask> currentBuilds = new HashMap<String, BuildProjectTask>();
            Set<Integer> keys = overallBuildQueues.keySet();
            for ( Integer key : keys )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                BuildProjectTask task =
                    (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
                if ( task != null )
                {
                    currentBuilds.put( overallBuildQueue.getName(), task );
                }
            }
            return currentBuilds;
        }
    }

    /**
     * @see BuildsManager#getCurrentCheckouts()
     */
    public Map<String, CheckOutTask> getCurrentCheckouts()
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            Map<String, CheckOutTask> currentCheckouts = new HashMap<String, CheckOutTask>();
            Set<Integer> keys = overallBuildQueues.keySet();
            for ( Integer key : keys )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                CheckOutTask task = (CheckOutTask) overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask();
                if ( task != null )
                {
                    currentCheckouts.put( overallBuildQueue.getName(), task );
                }
            }
            return currentCheckouts;
        }
    }

    /**
     * @see BuildsManager#getProjectsInBuildQueues()
     */
    public Map<String, List<BuildProjectTask>> getProjectsInBuildQueues()
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            Map<String, List<BuildProjectTask>> queuedBuilds = new HashMap<String, List<BuildProjectTask>>();
            Set<Integer> keySet = overallBuildQueues.keySet();
            for ( Integer key : keySet )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                try
                {
                    queuedBuilds.put( overallBuildQueue.getName(), overallBuildQueue.getProjectsInBuildQueue() );
                }
                catch ( TaskQueueException e )
                {
                    throw new BuildManagerException(
                        "Error occurred while getting projects in build queue '" + overallBuildQueue.getName() + "'.",
                        e );
                }
            }
            return queuedBuilds;
        }
    }

    /**
     * @see BuildsManager#getProjectsInCheckoutQueues()
     */
    public Map<String, List<CheckOutTask>> getProjectsInCheckoutQueues()
        throws BuildManagerException
    {
        synchronized ( overallBuildQueues )
        {
            Map<String, List<CheckOutTask>> queuedCheckouts = new HashMap<String, List<CheckOutTask>>();
            Set<Integer> keySet = overallBuildQueues.keySet();
            for ( Integer key : keySet )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                try
                {
                    queuedCheckouts.put( overallBuildQueue.getName(), overallBuildQueue.getProjectsInCheckoutQueue() );
                }
                catch ( TaskQueueException e )
                {
                    throw new BuildManagerException(
                        "Error occurred while getting projects in build queue '" + overallBuildQueue.getName() + "'.",
                        e );
                }
            }
            return queuedCheckouts;
        }
    }

    /**
     * @see BuildsManager#cancelAllPrepareBuilds()
     */
    public boolean cancelAllPrepareBuilds()
        throws BuildManagerException
    {
        try
        {
            TaskQueueExecutor executor =
                (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "prepare-build-project" );
            Task task = executor.getCurrentTask();
            if ( task != null )
            {
                executor.cancelTask( task );
            }
        }
        catch ( ComponentLookupException e )
        {
            throw new BuildManagerException( "Error looking up prepare-build-queue.", e );
        }

        return false;
    }

    /**
     * @see BuildsManager#isBuildInProgress()
     */
    public boolean isBuildInProgress()
    {
        synchronized ( overallBuildQueues )
        {
            Set<Integer> keySet = overallBuildQueues.keySet();
            for ( Integer key : keySet )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                if ( overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask() != null )
                {
                    return true;
                }
            }
            return false;
        }
    }

    public boolean isProjectCurrentlyPreparingBuild( int projectId )
        throws BuildManagerException
    {
        PrepareBuildProjectsTask task = getCurrentProjectInPrepareBuild();

        if ( task != null )
        {
            Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();

            if ( map.size() > 0 )
            {
                Set<Integer> projectIds = map.keySet();

                if ( projectIds.contains( new Integer( projectId ) ) )
                {
                    log.info( "Project " + projectId + " is currently preparing build" );
                    return true;
                }
            }
        }

        return false;
    }

    public PrepareBuildProjectsTask getCurrentProjectInPrepareBuild()
        throws BuildManagerException
    {
        Task task = getPrepareBuildTaskQueueExecutor().getCurrentTask();

        if ( task != null )
        {
            return (PrepareBuildProjectsTask) task;
        }
        else
        {
            return null;
        }
    }

    public List<PrepareBuildProjectsTask> getProjectsInPrepareBuildQueue()
        throws BuildManagerException
    {
        try
        {
            return getPrepareBuildQueue().getQueueSnapshot();
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( "Error occurred while retrieving projects in prepare build queue", e );
        }
    }

    public boolean removeProjectFromPrepareBuildQueue( int projectGroupId, int scmRootId )
        throws BuildManagerException
    {
        List<PrepareBuildProjectsTask> tasks = getProjectsInPrepareBuildQueue();

        if ( tasks != null )
        {
            for ( PrepareBuildProjectsTask task : tasks )
            {
                if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
                {
                    return getPrepareBuildQueue().remove( task );
                }
            }
        }

        return false;
    }

    public void removeProjectsFromPrepareBuildQueueWithHashCodes( int[] hashCodes )
        throws BuildManagerException
    {
        List<PrepareBuildProjectsTask> tasks = getProjectsInPrepareBuildQueue();

        if ( tasks != null )
        {
            for ( PrepareBuildProjectsTask task : tasks )
            {
                if ( ArrayUtils.contains( hashCodes, task.getHashCode() ) )
                {
                    getPrepareBuildQueue().remove( task );
                }
            }
        }
    }

    private boolean isInQueue( int projectId, int typeOfQueue, int buildDefinitionId )
        throws TaskQueueException
    {
        synchronized ( overallBuildQueues )
        {
            Set<Integer> keySet = overallBuildQueues.keySet();
            for ( Integer key : keySet )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                if ( typeOfQueue == BUILD_QUEUE )
                {
                    if ( buildDefinitionId < 0 )
                    {
                        if ( overallBuildQueue.isInBuildQueue( projectId ) )
                        {
                            log.info( "Project " + projectId + " is in build queue " + overallBuildQueue.getName() );
                            return true;
                        }
                    }
                    else
                    {
                        if ( overallBuildQueue.isInBuildQueue( projectId, buildDefinitionId ) )
                        {
                            log.info( "Project " + projectId + " is in build queue " + overallBuildQueue.getName() );
                            return true;
                        }
                    }
                }
                else if ( typeOfQueue == CHECKOUT_QUEUE )
                {
                    if ( overallBuildQueue.isInCheckoutQueue( projectId ) )
                    {
                        log.info( "Project " + projectId + " is in checkout queue " + overallBuildQueue.getName() );
                        return true;
                    }
                }
            }

            return false;
        }
    }

    // get overall queue where project is queued
    private OverallBuildQueue getOverallBuildQueueWhereProjectIsQueued( 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;
                    }
                }
            }

            return whereQueued;
        }
    }

    // get overall queue where project will be queued
    private OverallBuildQueue getOverallBuildQueue( 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;
            int allowedBuilds = configurationService.getNumberOfBuildsInParallel();

            try
            {
                int count = 1;
                for ( BuildQueue buildQueue : buildQueues )
                {
                    if ( count <= allowedBuilds )
                    {
                        OverallBuildQueue overallBuildQueue = overallBuildQueues.get( buildQueue.getId() );
                        if ( overallBuildQueue != null )
                        {
                            TaskQueue taskQueue = null;
                            TaskQueueExecutor taskQueueExecutor = null;
                            int tempSize = 0;
                            if ( typeOfQueue == BUILD_QUEUE )
                            {
                                taskQueue = overallBuildQueue.getBuildQueue();
                                taskQueueExecutor = overallBuildQueue.getBuildTaskQueueExecutor();
                            }
                            else if ( typeOfQueue == CHECKOUT_QUEUE )
                            {
                                taskQueue = overallBuildQueue.getCheckoutQueue();
                                taskQueueExecutor = overallBuildQueue.getCheckoutTaskQueueExecutor();
                            }

                            tempSize = taskQueue.getQueueSnapshot().size();
                            if ( taskQueueExecutor.getCurrentTask() != null )
                            {
                                tempSize++;
                            }

                            if ( idx == 0 )
                            {
                                whereToBeQueued = overallBuildQueue;
                                size = tempSize;
                            }

                            if ( tempSize < size )
                            {
                                whereToBeQueued = overallBuildQueue;
                                size = tempSize;
                            }

                            idx++;
                        }
                        else
                        {
                            log.error( "Build queue not found." );
                        }
                        count++;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            catch ( TaskQueueException e )
            {
                throw new BuildManagerException( "Error occurred while retrieving task quueue: " + e.getMessage() );
            }
        }

        // use default overall build queue if none is configured
        if ( whereToBeQueued == null )
        {
            Set<Integer> keySet = overallBuildQueues.keySet();
            for ( Integer key : keySet )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                if ( overallBuildQueue.getName().equals( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) )
                {
                    return overallBuildQueue;
                }
            }
        }

        return whereToBeQueued;
    }

    public OverallBuildQueue getOverallBuildQueueWhereProjectsInGroupAreQueued( int projectGroupId )
        throws BuildManagerException
    {
        OverallBuildQueue whereToBeQueued = null;

        try
        {
            List<Project> projects = projectDao.getProjectsInGroup( projectGroupId );

            if ( projects != null )
            {
                for ( Project project : projects )
                {
                    whereToBeQueued = getOverallBuildQueueWhereProjectIsQueued( project.getId(), BUILD_QUEUE );

                    if ( whereToBeQueued == null )
                    {
                        whereToBeQueued = getOverallBuildQueueWhereProjectIsBuilding( project.getId() );
                    }

                    if ( whereToBeQueued != null )
                    {
                        break;
                    }
                }
            }
        }
        catch ( ContinuumStoreException e )
        {
            throw new BuildManagerException( "Error while retrieving overall build queue for project: " + e.getMessage() );
        }
        catch ( TaskQueueException e )
        {
            throw new BuildManagerException( "Error while retrieving overall build queue for project: " + e.getMessage() );
        }

        return whereToBeQueued;
    }

    private OverallBuildQueue getOverallBuildQueueWhereProjectIsBuilding( int projectId )
    {
        synchronized ( overallBuildQueues )
        {
            for ( Integer key : overallBuildQueues.keySet() )
            {
                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
                BuildProjectTask task =
                    (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
                if ( task != null && task.getProjectId() == projectId )
                {
                    return overallBuildQueue;
                }
            }
            return null;
        }
    }

    public TaskQueueExecutor getPrepareBuildTaskQueueExecutor()
        throws BuildManagerException
    {
        try
        {
            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "prepare-build-project" );
        }
        catch ( ComponentLookupException e )
        {
            throw new BuildManagerException( e.getMessage(), e );
        }
    }

    public boolean isProjectCurrentlyBeingCheckedOut( int projectId )
        throws BuildManagerException
    {
        Map<String, CheckOutTask> checkouts = getCurrentCheckouts();
        for( String key : checkouts.keySet() )
        {
            CheckOutTask task = checkouts.get( key );
            if( task.getProjectId() == projectId )
            {
                return true;
            }
        }

        return false;
    }

    public boolean isAnyProjectCurrentlyBuilding( int[] projectIds )
        throws BuildManagerException
    {
        for ( int i = 0; i < projectIds.length; i++ )
        {
            if ( isProjectInAnyCurrentBuild( projectIds[i] ) )
            {
                return true;
            }
        }

        return false;
    }

    public void contextualize( Context context )
        throws ContextException
    {
        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );

        synchronized ( overallBuildQueues )
        {
            try
            {
                // create all the build queues configured in the database, not just the default!              
                List<BuildQueue> buildQueues = buildQueueService.getAllBuildQueues();
                for ( BuildQueue buildQueue : buildQueues )
                {
                    createOverallBuildQueue( buildQueue );
                }

                // add default overall build queue if not yet added to the map
                BuildQueue defaultBuildQueue = configurationService.getDefaultBuildQueue();
                if ( overallBuildQueues.get( defaultBuildQueue.getId() ) == null )
                {
                    createOverallBuildQueue( defaultBuildQueue );
                }
            }
            catch ( ComponentLookupException e )
            {
                log.error( "Cannot create overall build queue: " + e.getMessage() );
            }
            catch ( BuildQueueServiceException e )
            {
                log.error( "Cannot create overall build queue: " + e.getMessage() );
            }
        }
    }

    public void setContainer( PlexusContainer container )
    {
        this.container = container;
    }

    private void createOverallBuildQueue( BuildQueue defaultBuildQueue )
        throws ComponentLookupException
    {
        OverallBuildQueue overallBuildQueue = (OverallBuildQueue) container.lookup( OverallBuildQueue.class );
        overallBuildQueue.setId( defaultBuildQueue.getId() );
        overallBuildQueue.setName( defaultBuildQueue.getName() );

        overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue );
    }

    public TaskQueue getPrepareBuildQueue()
    {
        return prepareBuildQueue;
    }

    public void setPrepareBuildQueue( TaskQueue prepareBuildQueue )
    {
        this.prepareBuildQueue = prepareBuildQueue;
    }

    // for unit tests..

    public void setOverallBuildQueues( Map<Integer, OverallBuildQueue> overallBuildQueues )
    {
        this.overallBuildQueues = overallBuildQueues;
    }

    public void setConfigurationService( ConfigurationService configurationService )
    {
        this.configurationService = configurationService;
    }

    public void setBuildQueueService( BuildQueueService buildQueueService )
    {
        this.buildQueueService = buildQueueService;
    }

    public void setBuildDefinitionDao( BuildDefinitionDao buildDefinitionDao )
    {
        this.buildDefinitionDao = buildDefinitionDao;
    }

    public void setProjectDao( ProjectDao projectDao )
    {
        this.projectDao = projectDao;
    }
}
TOP

Related Classes of org.apache.continuum.buildmanager.ParallelBuildsManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.