EMMA Coverage Report (generated Sun Sep 18 11:34:27 PHT 2011)
[all classes][org.apache.maven.continuum.scm.queue]

COVERAGE SUMMARY FOR SOURCE FILE [PrepareBuildProjectsTaskExecutor.java]

nameclass, %method, %block, %line, %
PrepareBuildProjectsTaskExecutor.java100% (1/1)75%  (12/16)48%  (415/857)54%  (106/196)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class PrepareBuildProjectsTaskExecutor100% (1/1)75%  (12/16)48%  (415/857)54%  (106/196)
cleanWorkingDirectory (Map): void 0%   (0/1)0%   (0/5)0%   (0/2)
convertScmResultToError (ScmResult): String 0%   (0/1)0%   (0/121)0%   (0/16)
getOldScmResults (int, long, long): ScmResult 0%   (0/1)0%   (0/63)0%   (0/15)
updateProjectScmRoot (Map, String): void 0%   (0/1)0%   (0/25)0%   (0/9)
mergeScmResults (Map): void 100% (1/1)23%  (10/44)33%  (4/12)
performAction (String, Map): void 100% (1/1)26%  (17/66)23%  (3/13)
updateWorkingDirectory (Map): void 100% (1/1)48%  (23/48)57%  (8/14)
endProjectPrepareBuild (Map): void 100% (1/1)56%  (10/18)60%  (3/5)
buildProjects (int, Map, int, Map): void 100% (1/1)73%  (89/122)71%  (22/31)
startPrepareBuild (Map): void 100% (1/1)74%  (20/27)78%  (7/9)
executeTask (Task): void 100% (1/1)75%  (133/178)83%  (28.3/34)
endPrepareBuild (Map): void 100% (1/1)77%  (23/30)80%  (8/10)
initializeContext (int, int): Map 100% (1/1)79%  (73/92)85%  (18.8/22)
checkProjectScmRoot (Map): boolean 100% (1/1)91%  (10/11)95%  (1.9/2)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
PrepareBuildProjectsTaskExecutor (): void 100% (1/1)100% (3/3)100% (1/1)

1package org.apache.maven.continuum.scm.queue;
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 
22import java.util.ArrayList;
23import java.util.HashMap;
24import java.util.List;
25import java.util.Map;
26import java.util.Set;
27 
28import org.apache.continuum.dao.BuildDefinitionDao;
29import org.apache.continuum.dao.BuildResultDao;
30import org.apache.continuum.dao.ProjectDao;
31import org.apache.continuum.dao.ProjectScmRootDao;
32import org.apache.continuum.model.project.ProjectScmRoot;
33import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
34import org.apache.continuum.utils.ContinuumUtils;
35import org.apache.continuum.utils.ProjectSorter;
36import org.apache.maven.continuum.core.action.AbstractContinuumAction;
37import org.apache.maven.continuum.core.action.CheckWorkingDirectoryAction;
38import org.apache.maven.continuum.core.action.CheckoutProjectContinuumAction;
39import org.apache.maven.continuum.core.action.UpdateWorkingDirectoryFromScmContinuumAction;
40import org.apache.maven.continuum.model.project.BuildDefinition;
41import org.apache.maven.continuum.model.project.BuildResult;
42import org.apache.maven.continuum.model.project.Project;
43import org.apache.maven.continuum.model.project.ProjectGroup;
44import org.apache.maven.continuum.model.scm.ChangeSet;
45import org.apache.maven.continuum.model.scm.ScmResult;
46import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
47import org.apache.maven.continuum.project.ContinuumProjectState;
48import org.apache.maven.continuum.store.ContinuumStoreException;
49import org.apache.maven.continuum.utils.WorkingDirectoryService;
50import org.codehaus.plexus.action.ActionManager;
51import org.codehaus.plexus.action.ActionNotFoundException;
52import org.codehaus.plexus.taskqueue.Task;
53import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
54import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
55import org.codehaus.plexus.util.StringUtils;
56import org.slf4j.Logger;
57import org.slf4j.LoggerFactory;
58 
59/**
60 * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
61 * @version $Id: PrepareBuildProjectsTaskExecutor.java 819456 2009-09-28 05:50:03Z ctan $
62 * @plexus.component role="org.codehaus.plexus.taskqueue.execution.TaskExecutor"
63 * role-hint="prepare-build-project"
64 */
65public class PrepareBuildProjectsTaskExecutor
66    implements TaskExecutor
67{
68    private static final Logger log = LoggerFactory.getLogger( PrepareBuildProjectsTaskExecutor.class );
69 
70    /**
71     * @plexus.requirement
72     */
73    private ActionManager actionManager;
74 
75    /**
76     * @plexus.requirement
77     */
78    private ProjectDao projectDao;
79 
80    /**
81     * @plexus.requirement
82     */
83    private BuildDefinitionDao buildDefinitionDao;
84 
85    /**
86     * @plexus.requirement
87     */
88    private ProjectScmRootDao projectScmRootDao;
89 
90    /**
91     * @plexus.requirement
92     */
93    private BuildResultDao buildResultDao;
94 
95    /**
96     * @plexus.requirement
97     */
98    private WorkingDirectoryService workingDirectoryService;
99 
100    /**
101     * @plexus.requirement
102     */
103    private ContinuumNotificationDispatcher notifierDispatcher;
104 
105    public void executeTask( Task task )
106        throws TaskExecutionException
107    {
108        PrepareBuildProjectsTask prepareTask = (PrepareBuildProjectsTask) task;
109 
110        Map<Integer, Integer> projectsBuildDefinitionsMap = prepareTask.getProjectsBuildDefinitionsMap();
111        int trigger = prepareTask.getTrigger();
112        Set<Integer> projectsId = projectsBuildDefinitionsMap.keySet();
113        Map<String, Object> context = new HashMap<String, Object>();
114        Map<Integer, ScmResult> scmResultMap = new HashMap<Integer, ScmResult>();
115 
116        try
117        {
118            for ( Integer projectId : projectsId )
119            {
120                int buildDefinitionId = projectsBuildDefinitionsMap.get( projectId );
121 
122                log.info( "Initializing prepare build" );
123                context = initializeContext( projectId, buildDefinitionId );
124 
125                log.info(
126                    "Starting prepare build of project: " + AbstractContinuumAction.getProject( context ).getName() );
127                startPrepareBuild( context );
128 
129                if ( !checkProjectScmRoot( context ) )
130                {
131                    break;
132                }
133 
134                try
135                {
136                    if ( AbstractContinuumAction.getBuildDefinition( context ).isBuildFresh() )
137                    {
138                        log.info( "Purging existing working copy" );
139                        cleanWorkingDirectory( context );
140                    }
141 
142                    // ----------------------------------------------------------------------
143                    // TODO: Centralize the error handling from the SCM related actions.
144                    // ContinuumScmResult should return a ContinuumScmResult from all
145                    // methods, even in a case of failure.
146                    // ----------------------------------------------------------------------
147                    log.info( "Updating working dir" );
148                    updateWorkingDirectory( context );
149 
150                    log.info( "Merging SCM results" );
151                    //CONTINUUM-1393
152                    if ( !AbstractContinuumAction.getBuildDefinition( context ).isBuildFresh() )
153                    {
154                        mergeScmResults( context );
155                    }
156                }
157                finally
158                {
159                    log.info(
160                        "Ending prepare build of project: " + AbstractContinuumAction.getProject( context ).getName() );
161                    scmResultMap.put( AbstractContinuumAction.getProjectId( context ),
162                                      AbstractContinuumAction.getScmResult( context, new ScmResult() ) );
163                    endProjectPrepareBuild( context );
164                }
165            }
166        }
167        finally
168        {
169            log.info( "Ending prepare build" );
170            endPrepareBuild( context );
171        }
172 
173        if ( checkProjectScmRoot( context ) )
174        {
175            int projectGroupId = AbstractContinuumAction.getProjectGroupId( context );
176            buildProjects( projectGroupId, projectsBuildDefinitionsMap, trigger, scmResultMap );
177        }
178    }
179 
180    private Map<String, Object> initializeContext( int projectId, int buildDefinitionId )
181        throws TaskExecutionException
182    {
183        Map<String, Object> context = new HashMap<String, Object>();
184 
185        try
186        {
187            Project project = projectDao.getProject( projectId );
188            ProjectGroup projectGroup = project.getProjectGroup();
189 
190            List<ProjectScmRoot> scmRoots = projectScmRootDao.getProjectScmRootByProjectGroup( projectGroup.getId() );
191            String projectScmUrl = project.getScmUrl();
192 
193            for ( ProjectScmRoot projectScmRoot : scmRoots )
194            {
195                if ( projectScmUrl.startsWith( projectScmRoot.getScmRootAddress() ) )
196                {
197                    AbstractContinuumAction.setProjectScmRoot( context, projectScmRoot );
198                    break;
199                }
200            }
201 
202            AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
203            AbstractContinuumAction.setProjectId( context, projectId );
204            AbstractContinuumAction.setProject( context, project );
205 
206            AbstractContinuumAction.setBuildDefinitionId( context, buildDefinitionId );
207            AbstractContinuumAction.setBuildDefinition( context,
208                                                        buildDefinitionDao.getBuildDefinition( buildDefinitionId ) );
209 
210            BuildResult oldBuildResult =
211                buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
212 
213            if ( oldBuildResult != null )
214            {
215                AbstractContinuumAction.setOldScmResult( context,
216                                                         getOldScmResults( projectId, oldBuildResult.getBuildNumber(),
217                                                                           oldBuildResult.getEndTime() ) );
218            }
219            else
220            {
221                AbstractContinuumAction.setOldScmResult( context, null );
222            }
223        }
224        catch ( ContinuumStoreException e )
225        {
226            throw new TaskExecutionException( "Error initializing pre-build context", e );
227        }
228 
229        return context;
230    }
231 
232    private void cleanWorkingDirectory( Map<String, Object> context )
233        throws TaskExecutionException
234    {
235        performAction( "clean-working-directory", context );
236    }
237 
238    private void updateWorkingDirectory( Map<String, Object> context )
239        throws TaskExecutionException
240    {
241        performAction( "check-working-directory", context );
242 
243        boolean workingDirectoryExists = CheckWorkingDirectoryAction.isWorkingDirectoryExist( context );
244 
245        ScmResult scmResult;
246 
247        if ( workingDirectoryExists )
248        {
249            performAction( "update-working-directory-from-scm", context );
250 
251            scmResult = UpdateWorkingDirectoryFromScmContinuumAction.getUpdateScmResult( context );
252        }
253        else
254        {
255            Project project = AbstractContinuumAction.getProject( context );
256 
257            AbstractContinuumAction.setWorkingDirectory( context, workingDirectoryService.getWorkingDirectory(
258                project ).getAbsolutePath() );
259 
260            performAction( "checkout-project", context );
261 
262            scmResult = CheckoutProjectContinuumAction.getCheckoutResult( context, null );
263        }
264 
265        // [CONTINUUM-2207] when returned scmResult is null, this causes a problem when building the project 
266        if ( scmResult == null )
267        {
268            log.debug( "Returned ScmResult is null when updating the working directory" );
269            scmResult = new ScmResult();
270        }
271 
272        AbstractContinuumAction.setScmResult( context, scmResult );
273    }
274 
275    private boolean checkProjectScmRoot( Map<String, Object> context )
276        throws TaskExecutionException
277    {
278        ProjectScmRoot projectScmRoot = AbstractContinuumAction.getProjectScmRoot( context );
279 
280        // check state of scm root
281        return projectScmRoot.getState() != ContinuumProjectState.ERROR;
282 
283    }
284 
285    private void startPrepareBuild( Map<String, Object> context )
286        throws TaskExecutionException
287    {
288        ProjectScmRoot projectScmRoot = AbstractContinuumAction.getProjectScmRoot( context );
289        if ( projectScmRoot.getState() != ContinuumProjectState.UPDATING )
290        {
291            try
292            {
293                projectScmRoot.setOldState( projectScmRoot.getState() );
294                projectScmRoot.setState( ContinuumProjectState.UPDATING );
295                projectScmRootDao.updateProjectScmRoot( projectScmRoot );
296            }
297            catch ( ContinuumStoreException e )
298            {
299                throw new TaskExecutionException( "Error persisting projectScmRoot", e );
300            }
301        }
302    }
303 
304    private void endPrepareBuild( Map<String, Object> context )
305        throws TaskExecutionException
306    {
307        ProjectScmRoot projectScmRoot = AbstractContinuumAction.getProjectScmRoot( context );
308 
309        if ( projectScmRoot.getState() != ContinuumProjectState.ERROR )
310        {
311            projectScmRoot.setState( ContinuumProjectState.UPDATED );
312            projectScmRoot.setError( null );
313 
314            try
315            {
316                projectScmRootDao.updateProjectScmRoot( projectScmRoot );
317            }
318            catch ( ContinuumStoreException e )
319            {
320                throw new TaskExecutionException( "Error persisting projectScmRoot", e );
321            }
322        }
323 
324        notifierDispatcher.prepareBuildComplete( projectScmRoot );
325    }
326 
327    /**
328     * @param context
329     * @throws TaskExecutionException
330     */
331    private void endProjectPrepareBuild( Map<String, Object> context )
332        throws TaskExecutionException
333    {
334        ScmResult scmResult = AbstractContinuumAction.getScmResult( context, null );
335 
336        if ( scmResult == null || !scmResult.isSuccess() )
337        {
338            String error = convertScmResultToError( scmResult );
339 
340            updateProjectScmRoot( context, error );
341        }
342    }
343 
344    private ScmResult getOldScmResults( int projectId, long startId, long fromDate )
345        throws ContinuumStoreException
346    {
347        List<BuildResult> results = buildResultDao.getBuildResultsForProjectFromId( projectId, startId );
348 
349        ScmResult res = new ScmResult();
350 
351        if ( results != null && results.size() > 0 )
352        {
353            for ( BuildResult result : results )
354            {
355                ScmResult scmResult = result.getScmResult();
356 
357                if ( scmResult != null )
358                {
359                    List<ChangeSet> changes = scmResult.getChanges();
360 
361                    if ( changes != null )
362                    {
363                        for ( ChangeSet changeSet : changes )
364                        {
365                            if ( changeSet.getDate() < fromDate )
366                            {
367                                continue;
368                            }
369                            if ( !res.getChanges().contains( changeSet ) )
370                            {
371                                res.addChange( changeSet );
372                            }
373                        }
374                    }
375                }
376            }
377        }
378 
379        return res;
380    }
381 
382    /**
383     * Merges scm results so we'll have all changes since last execution of current build definition
384     *
385     * @param context The build context
386     */
387    private void mergeScmResults( Map<String, Object> context )
388    {
389        ScmResult oldScmResult = AbstractContinuumAction.getOldScmResult( context );
390        ScmResult newScmResult = AbstractContinuumAction.getScmResult( context, null );
391 
392        if ( oldScmResult != null )
393        {
394            if ( newScmResult == null )
395            {
396                AbstractContinuumAction.setScmResult( context, oldScmResult );
397            }
398            else
399            {
400                List<ChangeSet> oldChanges = oldScmResult.getChanges();
401 
402                List<ChangeSet> newChanges = newScmResult.getChanges();
403 
404                for ( ChangeSet change : newChanges )
405                {
406                    if ( !oldChanges.contains( change ) )
407                    {
408                        oldChanges.add( change );
409                    }
410                }
411 
412                newScmResult.setChanges( oldChanges );
413            }
414        }
415    }
416 
417    private void performAction( String actionName, Map<String, Object> context )
418        throws TaskExecutionException
419    {
420        TaskExecutionException exception;
421 
422        try
423        {
424            log.info( "Performing action " + actionName );
425            actionManager.lookup( actionName ).execute( context );
426            return;
427        }
428        catch ( ActionNotFoundException e )
429        {
430            exception = new TaskExecutionException( "Error looking up action '" + actionName + "'", e );
431        }
432        catch ( Exception e )
433        {
434            exception = new TaskExecutionException( "Error executing action '" + actionName + "'", e );
435        }
436 
437        ScmResult result = new ScmResult();
438 
439        result.setSuccess( false );
440 
441        result.setException( ContinuumUtils.throwableToString( exception ) );
442 
443        AbstractContinuumAction.setScmResult( context, result );
444 
445        throw exception;
446    }
447 
448    private String convertScmResultToError( ScmResult result )
449    {
450        String error = "";
451 
452        if ( result == null )
453        {
454            error = "Scm result is null.";
455        }
456        else
457        {
458            if ( result.getCommandLine() != null )
459            {
460                error = "Command line: " + StringUtils.clean( result.getCommandLine() ) +
461                    System.getProperty( "line.separator" );
462            }
463 
464            if ( result.getProviderMessage() != null )
465            {
466                error = "Provider message: " + StringUtils.clean( result.getProviderMessage() ) +
467                    System.getProperty( "line.separator" );
468            }
469 
470            if ( result.getCommandOutput() != null )
471            {
472                error += "Command output: " + System.getProperty( "line.separator" );
473                error += "-------------------------------------------------------------------------------" +
474                    System.getProperty( "line.separator" );
475                error += StringUtils.clean( result.getCommandOutput() ) + System.getProperty( "line.separator" );
476                error += "-------------------------------------------------------------------------------" +
477                    System.getProperty( "line.separator" );
478            }
479 
480            if ( result.getException() != null )
481            {
482                error += "Exception:" + System.getProperty( "line.separator" );
483                error += result.getException();
484            }
485        }
486 
487        return error;
488    }
489 
490    private void updateProjectScmRoot( Map<String, Object> context, String error )
491        throws TaskExecutionException
492    {
493        ProjectScmRoot projectScmRoot = AbstractContinuumAction.getProjectScmRoot( context );
494 
495        try
496        {
497            projectScmRoot.setState( ContinuumProjectState.ERROR );
498            projectScmRoot.setError( error );
499 
500            projectScmRootDao.updateProjectScmRoot( projectScmRoot );
501 
502            AbstractContinuumAction.setProjectScmRoot( context, projectScmRoot );
503        }
504        catch ( ContinuumStoreException e )
505        {
506            throw new TaskExecutionException( "Error storing project scm root", e );
507        }
508    }
509 
510    private void buildProjects( int projectGroupId, Map<Integer, Integer> projectsAndBuildDefinitionsMap, int trigger,
511                                Map<Integer, ScmResult> scmResultMap )
512        throws TaskExecutionException
513    {
514        List<Project> projects = projectDao.getProjectsWithDependenciesByGroupId( projectGroupId );
515        List<Project> projectList;
516 
517        projectList = ProjectSorter.getSortedProjects( projects, log );
518 
519        List<Project> projectsToBeBuilt = new ArrayList<Project>();
520        Map<Integer, BuildDefinition> projectsBuildDefinitionsMap = new HashMap<Integer, BuildDefinition>();
521 
522        for ( Project project : projectList )
523        {
524            int buildDefinitionId;
525 
526            if ( projectsAndBuildDefinitionsMap.get( project.getId() ) != null )
527            {
528                buildDefinitionId = projectsAndBuildDefinitionsMap.get( project.getId() );
529 
530                try
531                {
532                    BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
533                    projectsBuildDefinitionsMap.put( project.getId(), buildDefinition );
534                    projectsToBeBuilt.add( project );
535                }
536                catch ( ContinuumStoreException e )
537                {
538                    log.error( "Error while creating build object", e );
539                    throw new TaskExecutionException( "Error while creating build object", e );
540                }
541            }
542        }
543 
544        try
545        {
546            Map<String, Object> context = new HashMap<String, Object>();
547            AbstractContinuumAction.setListOfProjects( context, projectsToBeBuilt );
548            AbstractContinuumAction.setProjectsBuildDefinitionsMap( context, projectsBuildDefinitionsMap );
549            AbstractContinuumAction.setTrigger( context, trigger );
550            AbstractContinuumAction.setScmResultMap( context, scmResultMap );
551            AbstractContinuumAction.setProjectGroupId( context, projectGroupId );
552 
553            log.info( "Performing action create-build-project-task" );
554            actionManager.lookup( "create-build-project-task" ).execute( context );
555        }
556        catch ( ActionNotFoundException e )
557        {
558            log.error( "Error looking up action 'build-project'" );
559            throw new TaskExecutionException( "Error looking up action 'build-project'", e );
560        }
561        catch ( Exception e )
562        {
563            log.error( e.getMessage(), e );
564            throw new TaskExecutionException( "Error executing action 'build-project'", e );
565        }
566    }
567}

[all classes][org.apache.maven.continuum.scm.queue]
EMMA 2.0.5312 (C) Vladimir Roubtsov