1 package org.apache.maven.continuum;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
23 import org.apache.continuum.buildmanager.BuildManagerException;
24 import org.apache.continuum.buildmanager.BuildsManager;
25 import org.apache.continuum.buildqueue.BuildQueueService;
26 import org.apache.continuum.buildqueue.BuildQueueServiceException;
27 import org.apache.continuum.configuration.ContinuumConfigurationException;
28 import org.apache.continuum.dao.BuildDefinitionDao;
29 import org.apache.continuum.dao.BuildResultDao;
30 import org.apache.continuum.dao.ContinuumReleaseResultDao;
31 import org.apache.continuum.dao.DaoUtils;
32 import org.apache.continuum.dao.NotifierDao;
33 import org.apache.continuum.dao.ProjectDao;
34 import org.apache.continuum.dao.ProjectGroupDao;
35 import org.apache.continuum.dao.ProjectScmRootDao;
36 import org.apache.continuum.dao.ScheduleDao;
37 import org.apache.continuum.model.project.ProjectGroupSummary;
38 import org.apache.continuum.model.project.ProjectScmRoot;
39 import org.apache.continuum.model.release.ContinuumReleaseResult;
40 import org.apache.continuum.purge.ContinuumPurgeManager;
41 import org.apache.continuum.purge.PurgeConfigurationService;
42 import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
43 import org.apache.continuum.repository.RepositoryService;
44 import org.apache.continuum.taskqueue.manager.TaskQueueManager;
45 import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
46 import org.apache.continuum.utils.ProjectSorter;
47 import org.apache.maven.continuum.build.settings.SchedulesActivationException;
48 import org.apache.maven.continuum.build.settings.SchedulesActivator;
49 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
50 import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
51 import org.apache.maven.continuum.configuration.ConfigurationException;
52 import org.apache.maven.continuum.configuration.ConfigurationLoadingException;
53 import org.apache.maven.continuum.configuration.ConfigurationService;
54 import org.apache.maven.continuum.core.action.AbstractContinuumAction;
55 import org.apache.maven.continuum.core.action.CheckoutProjectContinuumAction;
56 import org.apache.maven.continuum.core.action.CreateProjectsFromMetadataAction;
57 import org.apache.maven.continuum.core.action.StoreProjectAction;
58 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
59 import org.apache.maven.continuum.execution.manager.BuildExecutorManager;
60 import org.apache.maven.continuum.initialization.ContinuumInitializationException;
61 import org.apache.maven.continuum.initialization.ContinuumInitializer;
62 import org.apache.maven.continuum.installation.InstallationService;
63 import org.apache.maven.continuum.model.project.BuildDefinition;
64 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
65 import org.apache.maven.continuum.model.project.BuildQueue;
66 import org.apache.maven.continuum.model.project.BuildResult;
67 import org.apache.maven.continuum.model.project.Project;
68 import org.apache.maven.continuum.model.project.ProjectGroup;
69 import org.apache.maven.continuum.model.project.ProjectNotifier;
70 import org.apache.maven.continuum.model.project.Schedule;
71 import org.apache.maven.continuum.model.scm.ChangeSet;
72 import org.apache.maven.continuum.model.scm.ScmResult;
73 import org.apache.maven.continuum.profile.ProfileService;
74 import org.apache.maven.continuum.project.ContinuumProjectState;
75 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
76 import org.apache.maven.continuum.project.builder.maven.MavenOneContinuumProjectBuilder;
77 import org.apache.maven.continuum.project.builder.maven.MavenTwoContinuumProjectBuilder;
78 import org.apache.maven.continuum.release.ContinuumReleaseManager;
79 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
80 import org.apache.maven.continuum.store.ContinuumStoreException;
81 import org.apache.maven.continuum.utils.ContinuumUrlValidator;
82 import org.apache.maven.continuum.utils.WorkingDirectoryService;
83 import org.codehaus.plexus.action.Action;
84 import org.codehaus.plexus.action.ActionManager;
85 import org.codehaus.plexus.action.ActionNotFoundException;
86 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
87 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
88 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Startable;
89 import org.codehaus.plexus.personality.plexus.lifecycle.phase.StartingException;
90 import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
91 import org.codehaus.plexus.util.FileUtils;
92 import org.codehaus.plexus.util.IOUtil;
93 import org.codehaus.plexus.util.StringUtils;
94 import org.slf4j.Logger;
95 import org.slf4j.LoggerFactory;
96 import org.springframework.beans.BeanUtils;
97
98 import java.io.File;
99 import java.io.IOException;
100 import java.io.InputStream;
101 import java.util.ArrayList;
102 import java.util.Collection;
103 import java.util.Collections;
104 import java.util.HashMap;
105 import java.util.Iterator;
106 import java.util.List;
107 import java.util.Map;
108 import java.util.Properties;
109 import java.util.regex.Matcher;
110 import java.util.regex.Pattern;
111
112
113
114
115
116
117
118 public class DefaultContinuum
119 implements Continuum, Initializable, Startable
120 {
121 private static final Logger log = LoggerFactory.getLogger( DefaultContinuum.class );
122
123
124
125
126 private ActionManager actionManager;
127
128
129
130
131 private ConfigurationService configurationService;
132
133
134
135
136 private DaoUtils daoUtils;
137
138
139
140
141 private BuildDefinitionDao buildDefinitionDao;
142
143
144
145
146 private BuildResultDao buildResultDao;
147
148
149
150
151 private NotifierDao notifierDao;
152
153
154
155
156 private ProjectDao projectDao;
157
158
159
160
161 private ProjectGroupDao projectGroupDao;
162
163
164
165
166 private ScheduleDao scheduleDao;
167
168
169
170
171 private ContinuumReleaseResultDao releaseResultDao;
172
173
174
175
176 private ProjectScmRootDao projectScmRootDao;
177
178
179
180
181 private ContinuumInitializer initializer;
182
183
184
185
186 private SchedulesActivator schedulesActivator;
187
188
189
190
191 private InstallationService installationService;
192
193
194
195
196 private ProfileService profileService;
197
198
199
200
201 private BuildDefinitionService buildDefinitionService;
202
203
204
205
206
207
208
209
210 private ContinuumReleaseManager releaseManager;
211
212
213
214
215 private WorkingDirectoryService workingDirectoryService;
216
217
218
219
220 private BuildExecutorManager executorManager;
221
222
223
224
225 private ContinuumUrlValidator urlValidator;
226
227 private boolean stopped = false;
228
229
230
231
232 private ContinuumPurgeManager purgeManager;
233
234
235
236
237 private RepositoryService repositoryService;
238
239
240
241
242 private PurgeConfigurationService purgeConfigurationService;
243
244
245
246
247 private TaskQueueManager taskQueueManager;
248
249
250
251
252 private BuildsManager parallelBuildsManager;
253
254
255
256
257 private BuildQueueService buildQueueService;
258
259
260
261
262 private DistributedBuildManager distributedBuildManager;
263
264
265
266
267 private DistributedReleaseManager distributedReleaseManager;
268
269 public DefaultContinuum()
270 {
271 Runtime.getRuntime().addShutdownHook( new Thread()
272 {
273 @Override
274 public void run()
275 {
276 stopContinuum();
277 }
278 } );
279 }
280
281 public ContinuumReleaseManager getReleaseManager()
282 {
283 return releaseManager;
284 }
285
286 public ContinuumPurgeManager getPurgeManager()
287 {
288 return purgeManager;
289 }
290
291 public RepositoryService getRepositoryService()
292 {
293 return repositoryService;
294 }
295
296 public TaskQueueManager getTaskQueueManager()
297 {
298 return taskQueueManager;
299 }
300
301 public PurgeConfigurationService getPurgeConfigurationService()
302 {
303 return purgeConfigurationService;
304 }
305
306 public BuildsManager getBuildsManager()
307 {
308 return parallelBuildsManager;
309 }
310
311 public DistributedReleaseManager getDistributedReleaseManager()
312 {
313 return distributedReleaseManager;
314 }
315
316
317
318
319 public ProjectGroup getProjectGroup( int projectGroupId )
320 throws ContinuumException
321 {
322 try
323 {
324 return projectGroupDao.getProjectGroup( projectGroupId );
325 }
326 catch ( ContinuumObjectNotFoundException e )
327 {
328 throw new ContinuumException( "invalid group id", e );
329 }
330 catch ( ContinuumStoreException e )
331 {
332 throw new ContinuumException( "Error while querying for project group.", e );
333 }
334 }
335
336 public ProjectGroup getProjectGroupWithProjects( int projectGroupId )
337 throws ContinuumException
338 {
339 try
340 {
341 return projectGroupDao.getProjectGroupWithProjects( projectGroupId );
342 }
343 catch ( ContinuumStoreException e )
344 {
345 throw new ContinuumException( "could not find project group containing " + projectGroupId );
346 }
347 }
348
349 public ProjectGroup getProjectGroupByProjectId( int projectId )
350 throws ContinuumException
351 {
352 try
353 {
354 return projectGroupDao.getProjectGroupByProjectId( projectId );
355 }
356 catch ( ContinuumObjectNotFoundException e )
357 {
358 throw new ContinuumException( "could not find project group containing " + projectId );
359 }
360 }
361
362 public void removeProjectGroup( int projectGroupId )
363 throws ContinuumException
364 {
365 ProjectGroup projectGroup = getProjectGroupWithProjects( projectGroupId );
366
367 if ( projectGroup != null )
368 {
369 List<Project> projects = projectGroup.getProjects();
370 int[] projectIds = new int[projects.size()];
371
372 int idx = 0;
373 for ( Project project : projects )
374 {
375 projectIds[idx] = project.getId();
376 idx++;
377 }
378
379
380
381 try
382 {
383 if ( parallelBuildsManager.isAnyProjectCurrentlyBeingCheckedOut( projectIds ) )
384 {
385 throw new ContinuumException(
386 "Unable to delete group. At least one project in group is still being checked out." );
387 }
388
389 if ( parallelBuildsManager.isAnyProjectCurrentlyBuilding( projectIds ) )
390 {
391 throw new ContinuumException(
392 "Unable to delete group. At least one project in group is still building." );
393 }
394
395 if ( isAnyProjectsInReleaseStage( projects ) )
396 {
397 throw new ContinuumException(
398 "Unable to delete group. At least one project in group is in release stage" );
399 }
400 }
401 catch ( BuildManagerException e )
402 {
403 throw new ContinuumException( "Unable to delete group.", e );
404 }
405
406 for ( int projectId : projectIds )
407 {
408 removeProject( projectId );
409 }
410
411
412 List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( projectGroupId );
413
414 for ( ProjectScmRoot scmRoot : scmRoots )
415 {
416 removeProjectScmRoot( scmRoot );
417 }
418
419 log.info( "Remove project group " + projectGroup.getName() + "(" + projectGroup.getId() + ")" );
420
421 Map<String, Object> context = new HashMap<String, Object>();
422 AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
423 executeAction( "remove-assignable-roles", context );
424
425 projectGroupDao.removeProjectGroup( projectGroup );
426 }
427 }
428
429 public void addProjectGroup( ProjectGroup projectGroup )
430 throws ContinuumException
431 {
432 ProjectGroup pg = null;
433
434 try
435 {
436 pg = projectGroupDao.getProjectGroupByGroupId( projectGroup.getGroupId() );
437 }
438 catch ( ContinuumObjectNotFoundException e )
439 {
440
441
442 }
443 catch ( ContinuumStoreException e )
444 {
445 throw new ContinuumException( "Unable to add the requested project group", e );
446 }
447
448 if ( pg == null )
449 {
450
451 projectGroup.setName( projectGroup.getName().trim() );
452 try
453 {
454 ProjectGroup new_pg = projectGroupDao.addProjectGroup( projectGroup );
455
456 buildDefinitionService.addBuildDefinitionTemplateToProjectGroup( new_pg.getId(),
457 buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate() );
458
459 Map<String, Object> context = new HashMap<String, Object>();
460 AbstractContinuumAction.setProjectGroupId( context, new_pg.getId() );
461 executeAction( "add-assignable-roles", context );
462
463 log.info( "Added new project group: " + new_pg.getName() );
464 }
465 catch ( BuildDefinitionServiceException e )
466 {
467 throw new ContinuumException( e.getMessage(), e );
468 }
469 catch ( ContinuumObjectNotFoundException e )
470 {
471 throw new ContinuumException( e.getMessage(), e );
472 }
473
474 }
475 else
476 {
477 throw new ContinuumException( "Unable to add the requested project group: groupId already exists." );
478 }
479
480 }
481
482 public List<ProjectGroup> getAllProjectGroups()
483 {
484 return new ArrayList<ProjectGroup>( projectGroupDao.getAllProjectGroups() );
485 }
486
487 public ProjectGroup getProjectGroupByGroupId( String groupId )
488 throws ContinuumException
489 {
490 try
491 {
492 return projectGroupDao.getProjectGroupByGroupId( groupId );
493 }
494 catch ( ContinuumObjectNotFoundException e )
495 {
496 throw new ContinuumException( "Unable to find project group", e );
497 }
498 catch ( ContinuumStoreException e )
499 {
500 throw new ContinuumException( "Error retrieving", e );
501 }
502 }
503
504 public ProjectGroup getProjectGroupByGroupIdWithBuildDetails( String groupId )
505 throws ContinuumException
506 {
507 try
508 {
509 return projectGroupDao.getProjectGroupByGroupIdWithBuildDetails( groupId );
510 }
511 catch ( ContinuumObjectNotFoundException e )
512 {
513 throw new ContinuumException( "Unable to find project group", e );
514 }
515 catch ( ContinuumStoreException e )
516 {
517 throw new ContinuumException( "Error retrieving", e );
518 }
519 }
520
521 public List<ProjectGroup> getAllProjectGroupsWithRepository( int repositoryId )
522 {
523 return projectGroupDao.getProjectGroupByRepository( repositoryId );
524 }
525
526
527
528
529
530
531
532
533 public Collection<Project> getProjects()
534 throws ContinuumException
535 {
536 return projectDao.getAllProjectsByName();
537 }
538
539
540
541
542 public Collection<Project> getProjectsWithDependencies()
543 throws ContinuumException
544 {
545 return projectDao.getAllProjectsByNameWithDependencies();
546 }
547
548 public Map<Integer, BuildResult> getLatestBuildResults( int projectGroupId )
549 {
550 Map<Integer, BuildResult> result = buildResultDao.getLatestBuildResultsByProjectGroupId( projectGroupId );
551
552 if ( result == null )
553 {
554 result = new HashMap<Integer, BuildResult>();
555 }
556
557 return result;
558 }
559
560 public Map<Integer, BuildResult> getBuildResultsInSuccess( int projectGroupId )
561 {
562 Map<Integer, BuildResult> result = buildResultDao.getBuildResultsInSuccessByProjectGroupId( projectGroupId );
563
564 if ( result == null )
565 {
566 result = new HashMap<Integer, BuildResult>();
567 }
568
569 return result;
570 }
571
572 public BuildResult getLatestBuildResultForProject( int projectId )
573 {
574 return buildResultDao.getLatestBuildResultForProject( projectId );
575 }
576
577 public BuildResult getBuildResultByBuildNumber( int projectId, int buildNumber )
578 throws ContinuumException
579 {
580 List<BuildResult> builds = buildResultDao.getBuildResultByBuildNumber( projectId, buildNumber );
581
582 return ( builds.isEmpty() ? null : builds.get( 0 ) );
583 }
584
585
586
587
588
589 public void removeProject( int projectId )
590 throws ContinuumException
591 {
592 try
593 {
594 Project project = getProject( projectId );
595
596 try
597 {
598 if ( parallelBuildsManager.isProjectCurrentlyBeingCheckedOut( projectId ) )
599 {
600 throw new ContinuumException(
601 "Unable to remove project " + projectId + " because it is currently being checked out" );
602 }
603
604 if ( parallelBuildsManager.isProjectInAnyCurrentBuild( projectId ) )
605 {
606 throw new ContinuumException(
607 "Unable to remove project " + projectId + " because it is currently building" );
608 }
609 }
610 catch ( BuildManagerException e )
611 {
612 throw new ContinuumException( e.getMessage(), e );
613 }
614
615 if ( isProjectInReleaseStage( project ) )
616 {
617 throw new ContinuumException(
618 "Unable to remove project " + projectId + " because it is in release stage" );
619 }
620
621 try
622 {
623 parallelBuildsManager.removeProjectFromCheckoutQueue( projectId );
624
625 parallelBuildsManager.removeProjectFromBuildQueue( projectId );
626 }
627 catch ( BuildManagerException e )
628 {
629 throw new ContinuumException( e.getMessage(), e );
630 }
631
632 List<ContinuumReleaseResult> releaseResults =
633 releaseResultDao.getContinuumReleaseResultsByProject( projectId );
634
635 ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
636
637 try
638 {
639 for ( ContinuumReleaseResult releaseResult : releaseResults )
640 {
641 releaseResultDao.removeContinuumReleaseResult( releaseResult );
642 }
643
644 File releaseOutputDirectory =
645 configurationService.getReleaseOutputDirectory( project.getProjectGroup().getId() );
646
647 if ( releaseOutputDirectory != null )
648 {
649 FileUtils.deleteDirectory( releaseOutputDirectory );
650 }
651 }
652 catch ( ContinuumStoreException e )
653 {
654 throw new ContinuumException( "Error while deleting continuum release result of project group", e );
655 }
656 catch ( IOException e )
657 {
658 throw logAndCreateException( "Error while deleting project group release output directory.", e );
659 }
660
661 log.info( "Remove project " + project.getName() + "(" + projectId + ")" );
662
663
664 project = projectDao.getProjectWithDependencies( projectId );
665 project.setParent( null );
666 project.getDependencies().clear();
667 projectDao.updateProject( project );
668
669 Collection<BuildResult> buildResults = getBuildResultsForProject( projectId );
670
671 for ( BuildResult br : buildResults )
672 {
673 br.setBuildDefinition( null );
674
675 br.getModifiedDependencies().clear();
676 buildResultDao.updateBuildResult( br );
677 removeBuildResult( br );
678 }
679
680 File workingDirectory = getWorkingDirectory( projectId );
681
682 FileUtils.deleteDirectory( workingDirectory );
683
684 File buildOutputDirectory = configurationService.getBuildOutputDirectory( projectId );
685
686 FileUtils.deleteDirectory( buildOutputDirectory );
687
688 projectDao.removeProject( projectDao.getProject( projectId ) );
689
690 removeProjectScmRoot( scmRoot );
691 }
692 catch ( ContinuumStoreException ex )
693 {
694 throw logAndCreateException( "Error while removing project in database.", ex );
695 }
696 catch ( IOException e )
697 {
698 throw logAndCreateException( "Error while deleting project working directory.", e );
699 }
700 }
701
702
703
704
705 public void checkoutProject( int projectId )
706 throws ContinuumException
707 {
708 Map<String, Object> context = new HashMap<String, Object>();
709
710 AbstractContinuumAction.setProjectId( context, projectId );
711
712 try
713 {
714 BuildDefinition buildDefinition = buildDefinitionDao.getDefaultBuildDefinition( projectId );
715 AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
716
717 executeAction( "add-project-to-checkout-queue", context );
718 }
719 catch ( ContinuumStoreException e )
720 {
721 throw new ContinuumException( e.getMessage(), e );
722 }
723 }
724
725 public Project getProject( int projectId )
726 throws ContinuumException
727 {
728 try
729 {
730 return projectDao.getProject( projectId );
731 }
732 catch ( ContinuumStoreException ex )
733 {
734 throw logAndCreateException( "Exception while getting project '" + projectId + "'.", ex );
735 }
736 }
737
738 public Project getProjectWithBuildDetails( int projectId )
739 throws ContinuumException
740 {
741 try
742 {
743 return projectDao.getProjectWithBuildDetails( projectId );
744 }
745 catch ( ContinuumStoreException ex )
746 {
747 throw logAndCreateException( "Exception while getting project '" + projectId + "'.", ex );
748 }
749 }
750
751 public Map<Integer, ProjectGroupSummary> getProjectsSummaryByGroups()
752 {
753 return projectDao.getProjectsSummary();
754 }
755
756
757
758
759
760
761
762
763 public void buildProjects()
764 throws ContinuumException
765 {
766 buildProjects( ContinuumProjectState.TRIGGER_FORCED );
767 }
768
769 public void buildProjectsWithBuildDefinition( List<Project> projects, List<BuildDefinition> bds )
770 throws ContinuumException
771 {
772 Collection<Project> filteredProjectsList = getProjectsNotInReleaseStage( projects );
773
774 prepareBuildProjects( filteredProjectsList, bds, true, ContinuumProjectState.TRIGGER_FORCED );
775 }
776
777 public void buildProjectsWithBuildDefinition( List<Project> projects, int buildDefinitionId )
778 throws ContinuumException
779 {
780 Collection<Project> filteredProjectsList = getProjectsNotInReleaseStage( projects );
781
782 prepareBuildProjects( filteredProjectsList, buildDefinitionId, ContinuumProjectState.TRIGGER_FORCED );
783 }
784
785
786
787
788
789
790
791
792 public void buildProjects( int trigger )
793 throws ContinuumException
794 {
795 Collection<Project> projectsList = getProjectsInBuildOrder();
796
797 Collection<Project> filteredProjectsList = getProjectsNotInReleaseStage( projectsList );
798
799 prepareBuildProjects( filteredProjectsList, null, true, trigger );
800 }
801
802
803
804
805
806
807
808 public void buildProjectGroup( int projectGroupId )
809 throws ContinuumException
810 {
811 List<BuildDefinition> groupDefaultBDs;
812
813 if ( !isAnyProjectInGroupInReleaseStage( projectGroupId ) )
814 {
815 groupDefaultBDs = getDefaultBuildDefinitionsForProjectGroup( projectGroupId );
816
817 buildProjectGroupWithBuildDefinition( projectGroupId, groupDefaultBDs, true );
818 }
819 }
820
821
822
823
824
825
826
827
828 public void buildProjectGroupWithBuildDefinition( int projectGroupId, int buildDefinitionId )
829 throws ContinuumException
830 {
831 if ( !isAnyProjectInGroupInReleaseStage( projectGroupId ) )
832 {
833 List<BuildDefinition> bds = new ArrayList<BuildDefinition>();
834 BuildDefinition bd = getBuildDefinition( buildDefinitionId );
835 if ( bd != null )
836 {
837 bds.add( bd );
838 }
839 buildProjectGroupWithBuildDefinition( projectGroupId, bds, false );
840 }
841 }
842
843
844
845
846
847
848
849 private void buildProjectGroupWithBuildDefinition( int projectGroupId, List<BuildDefinition> bds,
850 boolean checkDefaultBuildDefinitionForProject )
851 throws ContinuumException
852 {
853 if ( !isAnyProjectInGroupInReleaseStage( projectGroupId ) )
854 {
855 Collection<Project> projectsList;
856
857 projectsList = getProjectsInBuildOrder( projectDao.getProjectsWithDependenciesByGroupId( projectGroupId ) );
858
859 prepareBuildProjects( projectsList, bds, checkDefaultBuildDefinitionForProject,
860 ContinuumProjectState.TRIGGER_FORCED );
861 }
862 }
863
864
865
866
867
868
869
870
871
872 public void buildProjects( Schedule schedule )
873 throws ContinuumException
874 {
875 Collection<Project> projectsList;
876
877 Map<Integer, Object> projectsMap;
878
879 try
880 {
881 projectsMap = daoUtils.getAggregatedProjectIdsAndBuildDefinitionIdsBySchedule( schedule.getId() );
882
883 if ( projectsMap == null || projectsMap.size() == 0 )
884 {
885 log.debug( "no builds attached to schedule" );
886 try
887 {
888 schedulesActivator.unactivateOrphanBuildSchedule( schedule );
889 }
890 catch ( SchedulesActivationException e )
891 {
892 log.debug( "Can't unactivate orphan shcedule for buildDefinitions" );
893 }
894
895
896 return;
897 }
898
899
900
901 projectsList = getProjectsInBuildOrder();
902 }
903 catch ( ContinuumStoreException e )
904 {
905 throw new ContinuumException( "Can't get project list for schedule " + schedule.getName(), e );
906 }
907
908 Map<ProjectScmRoot, Map<Integer, Integer>> map = new HashMap<ProjectScmRoot, Map<Integer, Integer>>();
909 List<ProjectScmRoot> sortedScmRoot = new ArrayList<ProjectScmRoot>();
910
911 for ( Project project : projectsList )
912 {
913 List<Integer> buildDefIds = (List<Integer>) projectsMap.get( project.getId() );
914
915 if ( buildDefIds != null && !buildDefIds.isEmpty() )
916 {
917 for ( Integer buildDefId : buildDefIds )
918 {
919 try
920 {
921 if ( buildDefId != null &&
922 !parallelBuildsManager.isInAnyBuildQueue( project.getId(), buildDefId ) &&
923 !parallelBuildsManager.isInAnyCheckoutQueue( project.getId() ) &&
924 !parallelBuildsManager.isInPrepareBuildQueue( project.getId() ) &&
925 !parallelBuildsManager.isProjectCurrentlyPreparingBuild( project.getId() ) )
926 {
927 ProjectScmRoot scmRoot = getProjectScmRootByProject( project.getId() );
928
929 Map<Integer, Integer> projectsAndBuildDefinitionsMap = map.get( scmRoot );
930
931 if ( projectsAndBuildDefinitionsMap == null )
932 {
933 projectsAndBuildDefinitionsMap = new HashMap<Integer, Integer>();
934 }
935
936 projectsAndBuildDefinitionsMap.put( project.getId(), buildDefId );
937
938 map.put( scmRoot, projectsAndBuildDefinitionsMap );
939
940 if ( !sortedScmRoot.contains( scmRoot ) )
941 {
942 sortedScmRoot.add( scmRoot );
943 }
944 }
945 }
946 catch ( BuildManagerException e )
947 {
948 throw new ContinuumException( e.getMessage(), e );
949 }
950 }
951 }
952 }
953
954 prepareBuildProjects( map, ContinuumProjectState.TRIGGER_SCHEDULED, sortedScmRoot );
955 }
956
957 public void buildProject( int projectId )
958 throws ContinuumException
959 {
960 buildProject( projectId, ContinuumProjectState.TRIGGER_FORCED );
961 }
962
963 public void buildProjectWithBuildDefinition( int projectId, int buildDefinitionId )
964 throws ContinuumException
965 {
966 buildProject( projectId, buildDefinitionId, ContinuumProjectState.TRIGGER_FORCED );
967 }
968
969 public void buildProject( int projectId, int trigger )
970 throws ContinuumException
971 {
972 Project project = getProject( projectId );
973 if ( isProjectInReleaseStage( project ) )
974 {
975 throw new ContinuumException( "Project (id=" + projectId + ") is currently in release stage." );
976 }
977
978 BuildDefinition buildDef = getDefaultBuildDefinition( projectId );
979
980 if ( buildDef == null )
981 {
982 throw new ContinuumException( "Project (id=" + projectId + " doens't have a default build definition." );
983 }
984
985 try
986 {
987 if ( parallelBuildsManager.isInAnyBuildQueue( projectId, buildDef.getId() ) ||
988 parallelBuildsManager.isInAnyCheckoutQueue( projectId ) ||
989 parallelBuildsManager.isInPrepareBuildQueue( projectId ) )
990 {
991 return;
992 }
993 }
994 catch ( BuildManagerException e )
995 {
996 throw new ContinuumException( e.getMessage(), e );
997 }
998
999 Map<Integer, Integer> projectsBuildDefinitionsMap = new HashMap<Integer, Integer>();
1000 projectsBuildDefinitionsMap.put( projectId, buildDef.getId() );
1001
1002 ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
1003 prepareBuildProjects( projectsBuildDefinitionsMap, trigger, scmRoot.getScmRootAddress(),
1004 scmRoot.getProjectGroup().getId(), scmRoot.getId() );
1005 }
1006
1007 public void buildProject( int projectId, int buildDefinitionId, int trigger )
1008 throws ContinuumException
1009 {
1010 Project project = getProject( projectId );
1011 if ( isProjectInReleaseStage( project ) )
1012 {
1013 throw new ContinuumException( "Project (id=" + projectId + ") is currently in release stage." );
1014 }
1015
1016 try
1017 {
1018 if ( parallelBuildsManager.isInAnyBuildQueue( projectId, buildDefinitionId ) ||
1019 parallelBuildsManager.isInAnyCheckoutQueue( projectId ) ||
1020 parallelBuildsManager.isInPrepareBuildQueue( projectId ) )
1021 {
1022 return;
1023 }
1024 }
1025 catch ( BuildManagerException e )
1026 {
1027 throw new ContinuumException( e.getMessage(), e );
1028 }
1029
1030 Map<Integer, Integer> projectsBuildDefinitionsMap = new HashMap<Integer, Integer>();
1031 projectsBuildDefinitionsMap.put( projectId, buildDefinitionId );
1032
1033 ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
1034 prepareBuildProjects( projectsBuildDefinitionsMap, trigger, scmRoot.getScmRootAddress(),
1035 scmRoot.getProjectGroup().getId(), scmRoot.getId() );
1036 }
1037
1038 public BuildResult getBuildResult( int buildId )
1039 throws ContinuumException
1040 {
1041 try
1042 {
1043 return buildResultDao.getBuildResult( buildId );
1044 }
1045 catch ( ContinuumStoreException e )
1046 {
1047 throw logAndCreateException( "Exception while getting build result for project.", e );
1048 }
1049 }
1050
1051 public void removeBuildResult( int buildId )
1052 throws ContinuumException
1053 {
1054 BuildResult buildResult = getBuildResult( buildId );
1055
1056
1057 Project project = buildResult.getProject();
1058 BuildResult bResult = getLatestBuildResultForProject( project.getId() );
1059
1060 try
1061 {
1062 if ( bResult != null && buildResult.getId() == bResult.getId() &&
1063 parallelBuildsManager.isProjectInAnyCurrentBuild( project.getId() ) )
1064 {
1065 throw new ContinuumException(
1066 "Unable to remove build result because it is currently being used by" + "a building project " +
1067 project.getId() );
1068 }
1069 }
1070 catch ( BuildManagerException e )
1071 {
1072 throw new ContinuumException( e.getMessage(), e );
1073 }
1074
1075 buildResult.getModifiedDependencies().clear();
1076 buildResult.setBuildDefinition( null );
1077
1078 try
1079 {
1080 buildResultDao.updateBuildResult( buildResult );
1081 }
1082 catch ( ContinuumStoreException e )
1083 {
1084 throw logAndCreateException( "Error while removing build result in database.", e );
1085 }
1086 removeBuildResult( buildResult );
1087 }
1088
1089
1090 private void removeBuildResult( BuildResult buildResult )
1091 {
1092 buildResultDao.removeBuildResult( buildResult );
1093
1094
1095 try
1096 {
1097 File buildOutputDirectory = getConfiguration().getBuildOutputDirectory( buildResult.getProject().getId() );
1098 File buildDirectory = new File( buildOutputDirectory, Integer.toString( buildResult.getId() ) );
1099
1100 if ( buildDirectory.exists() )
1101 {
1102 FileUtils.deleteDirectory( buildDirectory );
1103 }
1104 File buildOutputFile =
1105 getConfiguration().getBuildOutputFile( buildResult.getId(), buildResult.getProject().getId() );
1106 if ( buildOutputFile.exists() )
1107 {
1108 FileUtils.forceDelete( buildOutputFile );
1109 }
1110 }
1111 catch ( ConfigurationException e )
1112 {
1113 log.info( "skip error during cleanup build files " + e.getMessage(), e );
1114 }
1115 catch ( IOException e )
1116 {
1117 log.info( "skip IOException during cleanup build files " + e.getMessage(), e );
1118 }
1119
1120 }
1121
1122 public String getBuildOutput( int projectId, int buildId )
1123 throws ContinuumException
1124 {
1125 try
1126 {
1127 return configurationService.getBuildOutput( buildId, projectId );
1128 }
1129 catch ( ConfigurationException e )
1130 {
1131 throw logAndCreateException( "Exception while getting build result for project.", e );
1132 }
1133 }
1134
1135
1136
1137
1138 public List<ChangeSet> getChangesSinceLastSuccess( int projectId, int buildResultId )
1139 throws ContinuumException
1140 {
1141 BuildResult previousBuildResult = null;
1142 try
1143 {
1144 previousBuildResult = buildResultDao.getPreviousBuildResultInSuccess( projectId, buildResultId );
1145 }
1146 catch ( ContinuumStoreException e )
1147 {
1148
1149 }
1150 long startTime = previousBuildResult == null ? 0 : previousBuildResult.getStartTime();
1151 ArrayList<BuildResult> buildResults = new ArrayList<BuildResult>(
1152 buildResultDao.getBuildResultsForProjectWithDetails( projectId, startTime, buildResultId ) );
1153
1154 Collections.reverse( buildResults );
1155
1156 Iterator<BuildResult> buildResultsIterator = buildResults.iterator();
1157
1158 boolean stop = false;
1159
1160
1161 while ( !stop )
1162 {
1163 if ( buildResultsIterator.hasNext() )
1164 {
1165 BuildResult buildResult = buildResultsIterator.next();
1166
1167 if ( buildResult.getId() == buildResultId )
1168 {
1169 stop = true;
1170 }
1171 }
1172 else
1173 {
1174 stop = true;
1175 }
1176 }
1177
1178 if ( !buildResultsIterator.hasNext() )
1179 {
1180 return null;
1181 }
1182
1183 BuildResult buildResult = buildResultsIterator.next();
1184
1185 List<ChangeSet> changes = null;
1186
1187 while ( buildResult.getState() != ContinuumProjectState.OK )
1188 {
1189 if ( changes == null )
1190 {
1191 changes = new ArrayList<ChangeSet>();
1192 }
1193
1194 ScmResult scmResult = buildResult.getScmResult();
1195
1196 if ( scmResult != null )
1197 {
1198 changes.addAll( scmResult.getChanges() );
1199 }
1200
1201 if ( !buildResultsIterator.hasNext() )
1202 {
1203 return changes;
1204 }
1205
1206 buildResult = buildResultsIterator.next();
1207 }
1208
1209 if ( changes == null )
1210 {
1211 changes = Collections.EMPTY_LIST;
1212 }
1213
1214 return changes;
1215 }
1216
1217
1218
1219
1220
1221
1222
1223
1224 private List<Project> getProjectsInBuildOrder()
1225 throws ContinuumException
1226 {
1227 return getProjectsInBuildOrder( getProjectsWithDependencies() );
1228 }
1229
1230
1231
1232
1233
1234
1235
1236 public List<Project> getProjectsInBuildOrder( Collection<Project> projects )
1237 {
1238 if ( projects == null || projects.isEmpty() )
1239 {
1240 return new ArrayList<Project>();
1241 }
1242
1243 return ProjectSorter.getSortedProjects( projects, log );
1244 }
1245
1246
1247
1248
1249
1250 public ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl, int projectGroupId )
1251 throws ContinuumException
1252 {
1253 return addMavenOneProject( metadataUrl, projectGroupId, true );
1254 }
1255
1256 public ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl, int projectGroupId,
1257 boolean checkProtocol )
1258 throws ContinuumException
1259 {
1260 return addMavenOneProject( metadataUrl, projectGroupId, checkProtocol, false );
1261 }
1262
1263 public ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl, int projectGroupId,
1264 boolean checkProtocol, boolean useCredentialsCache )
1265 throws ContinuumException
1266 {
1267 try
1268 {
1269 return addMavenOneProject( metadataUrl, projectGroupId, checkProtocol, useCredentialsCache,
1270 buildDefinitionService.getDefaultMavenOneBuildDefinitionTemplate().getId() );
1271 }
1272 catch ( BuildDefinitionServiceException e )
1273 {
1274 throw new ContinuumException( e.getMessage(), e );
1275 }
1276 }
1277
1278 public ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl, int projectGroupId,
1279 boolean checkProtocol, boolean useCredentialsCache,
1280 int buildDefinitionTemplateId )
1281 throws ContinuumException
1282 {
1283 return executeAddProjectsFromMetadataActivity( metadataUrl, MavenOneContinuumProjectBuilder.ID, projectGroupId,
1284 checkProtocol, useCredentialsCache, true,
1285 buildDefinitionTemplateId );
1286 }
1287
1288
1289
1290
1291
1292 public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl )
1293 throws ContinuumException
1294 {
1295 return addMavenTwoProject( metadataUrl, true );
1296 }
1297
1298 public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl, boolean checkProtocol )
1299 throws ContinuumException
1300 {
1301 try
1302 {
1303 return executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID, -1,
1304 checkProtocol,
1305 buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate().getId() );
1306 }
1307 catch ( BuildDefinitionServiceException e )
1308 {
1309 throw new ContinuumException( e.getMessage(), e );
1310 }
1311 }
1312
1313 public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl, int projectGroupId )
1314 throws ContinuumException
1315 {
1316 return addMavenTwoProject( metadataUrl, projectGroupId, true );
1317 }
1318
1319 public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl, int projectGroupId,
1320 boolean checkProtocol )
1321 throws ContinuumException
1322 {
1323 return addMavenTwoProject( metadataUrl, projectGroupId, checkProtocol, false );
1324 }
1325
1326 public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl, int projectGroupId,
1327 boolean checkProtocol, boolean useCredentialsCache )
1328 throws ContinuumException
1329 {
1330 try
1331 {
1332 return executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID,
1333 projectGroupId, checkProtocol, useCredentialsCache, true,
1334 buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate().getId() );
1335 }
1336 catch ( BuildDefinitionServiceException e )
1337 {
1338 throw new ContinuumException( e.getMessage(), e );
1339 }
1340 }
1341
1342 public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl, int projectGroupId,
1343 boolean checkProtocol, boolean useCredentialsCache,
1344 boolean recursiveProjects )
1345 throws ContinuumException
1346 {
1347 try
1348 {
1349 return executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID,
1350 projectGroupId, checkProtocol, useCredentialsCache,
1351 recursiveProjects,
1352 buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate().getId() );
1353 }
1354 catch ( BuildDefinitionServiceException e )
1355 {
1356 throw new ContinuumException( e.getMessage(), e );
1357 }
1358 }
1359
1360 public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl, int projectGroupId,
1361 boolean checkProtocol, boolean useCredentialsCache,
1362 boolean recursiveProjects, int buildDefinitionTemplateId )
1363 throws ContinuumException
1364 {
1365 return executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID, projectGroupId,
1366 checkProtocol, useCredentialsCache, recursiveProjects,
1367 buildDefinitionTemplateId );
1368 }
1369
1370
1371
1372
1373
1374 public int addProject( Project project, String executorId, int groupId )
1375 throws ContinuumException
1376 {
1377 return addProject( project, executorId, groupId, -1 );
1378 }
1379
1380
1381
1382
1383 public int addProject( Project project, String executorId, int groupId, int buildDefinitionTemplateId )
1384 throws ContinuumException
1385 {
1386 project.setExecutorId( executorId );
1387
1388 return executeAddProjectFromScmActivity( project, groupId, buildDefinitionTemplateId );
1389 }
1390
1391
1392
1393
1394
1395 private int executeAddProjectFromScmActivity( Project project, int groupId, int buildDefinitionTemplateId )
1396 throws ContinuumException
1397 {
1398 String executorId = project.getExecutorId();
1399
1400 ProjectGroup projectGroup = getProjectGroupWithBuildDetails( groupId );
1401
1402 Map<String, Object> context = new HashMap<String, Object>();
1403
1404 String scmUrl = project.getScmUrl();
1405
1406 List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( groupId );
1407
1408 boolean found = false;
1409
1410 for ( ProjectScmRoot scmRoot : scmRoots )
1411 {
1412 if ( scmUrl.startsWith( scmRoot.getScmRootAddress() ) )
1413 {
1414 found = true;
1415 break;
1416 }
1417 }
1418
1419 if ( !found )
1420 {
1421 createProjectScmRoot( projectGroup, scmUrl );
1422 }
1423
1424
1425
1426
1427
1428 AbstractContinuumAction.setWorkingDirectory( context, getWorkingDirectory() );
1429
1430 AbstractContinuumAction.setUnvalidatedProject( context, project );
1431
1432 AbstractContinuumAction.setUnvalidatedProjectGroup( context, projectGroup );
1433
1434 AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
1435
1436 StoreProjectAction.setUseScmCredentialsCache( context, project.isScmUseCache() );
1437
1438
1439 String scmUsername = project.getScmUsername();
1440 String scmPassword = project.getScmPassword();
1441
1442 if( scmUsername != null && !StringUtils.isEmpty( scmUsername ) )
1443 {
1444 CheckoutProjectContinuumAction.setScmUsername( context, scmUsername );
1445 }
1446
1447 if( scmPassword != null && !StringUtils.isEmpty( scmPassword ) )
1448 {
1449 CheckoutProjectContinuumAction.setScmPassword( context, scmPassword );
1450 }
1451
1452 executeAction( "validate-project", context );
1453
1454 executeAction( "store-project", context );
1455
1456 try
1457 {
1458 BuildDefinitionTemplate bdt;
1459
1460 if ( executorId.equalsIgnoreCase( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR ) )
1461 {
1462 if ( buildDefinitionTemplateId <= 0 )
1463 {
1464 bdt = buildDefinitionService.getDefaultAntBuildDefinitionTemplate();
1465 }
1466 else
1467 {
1468 bdt = buildDefinitionService.getBuildDefinitionTemplate( buildDefinitionTemplateId );
1469 }
1470 }
1471 else
1472 {
1473
1474 if ( buildDefinitionTemplateId <= 0 )
1475 {
1476 bdt = buildDefinitionService.getDefaultShellBuildDefinitionTemplate();
1477 }
1478 else
1479 {
1480 bdt = buildDefinitionService.getBuildDefinitionTemplate( buildDefinitionTemplateId );
1481 }
1482 }
1483
1484 buildDefinitionService.addTemplateInProject( bdt.getId(), getProject(
1485 AbstractContinuumAction.getProjectId( context ) ) );
1486 }
1487 catch ( BuildDefinitionServiceException e )
1488 {
1489 throw new ContinuumException( e.getMessage(), e );
1490 }
1491
1492 if ( !configurationService.isDistributedBuildEnabled() )
1493 {
1494
1495 BuildDefinition bd = (BuildDefinition) getProjectWithBuildDetails(
1496 AbstractContinuumAction.getProjectId( context ) ).getBuildDefinitions().get( 0 );
1497 AbstractContinuumAction.setBuildDefinition( context, bd );
1498
1499 executeAction( "add-project-to-checkout-queue", context );
1500 }
1501
1502 executeAction( "add-assignable-roles", context );
1503
1504 return AbstractContinuumAction.getProjectId( context );
1505 }
1506
1507 private ContinuumProjectBuildingResult executeAddProjectsFromMetadataActivity( String metadataUrl,
1508 String projectBuilderId,
1509 int projectGroupId,
1510 boolean checkProtocol,
1511 int buildDefinitionTemplateId )
1512 throws ContinuumException
1513 {
1514 return executeAddProjectsFromMetadataActivity( metadataUrl, projectBuilderId, projectGroupId, checkProtocol,
1515 false, false, buildDefinitionTemplateId );
1516 }
1517
1518
1519 protected ContinuumProjectBuildingResult executeAddProjectsFromMetadataActivity( String metadataUrl,
1520 String projectBuilderId,
1521 int projectGroupId,
1522 boolean checkProtocol,
1523 boolean useCredentialsCache,
1524 boolean loadRecursiveProjects,
1525 int buildDefinitionTemplateId,
1526 boolean addAssignableRoles )
1527 throws ContinuumException
1528 {
1529 if ( checkProtocol )
1530 {
1531 if ( !urlValidator.validate( metadataUrl ) )
1532 {
1533 ContinuumProjectBuildingResult res = new ContinuumProjectBuildingResult();
1534 res.addError( ContinuumProjectBuildingResult.ERROR_PROTOCOL_NOT_ALLOWED );
1535 return res;
1536 }
1537 }
1538
1539 Map<String, Object> context = new HashMap<String, Object>();
1540
1541 CreateProjectsFromMetadataAction.setProjectBuilderId( context, projectBuilderId );
1542
1543 CreateProjectsFromMetadataAction.setUrl( context, metadataUrl );
1544
1545 CreateProjectsFromMetadataAction.setLoadRecursiveProject( context, loadRecursiveProjects );
1546
1547 StoreProjectAction.setUseScmCredentialsCache( context, useCredentialsCache );
1548
1549 AbstractContinuumAction.setWorkingDirectory( context, getWorkingDirectory() );
1550
1551
1552 if ( buildDefinitionTemplateId > 0 )
1553 {
1554 try
1555 {
1556 AbstractContinuumAction.setBuildDefinitionTemplate( context,
1557 buildDefinitionService.getBuildDefinitionTemplate(
1558 buildDefinitionTemplateId ) );
1559 }
1560 catch ( BuildDefinitionServiceException e )
1561 {
1562 throw new ContinuumException( e.getMessage(), e );
1563 }
1564 }
1565
1566
1567
1568
1569 executeAction( "create-projects-from-metadata", context );
1570
1571 ContinuumProjectBuildingResult result = CreateProjectsFromMetadataAction.getProjectBuildingResult( context );
1572
1573 if ( log.isInfoEnabled() )
1574 {
1575 if ( result.getProjects() != null )
1576 {
1577 log.info( "Created " + result.getProjects().size() + " projects." );
1578 }
1579 if ( result.getProjectGroups() != null )
1580 {
1581 log.info( "Created " + result.getProjectGroups().size() + " project groups." );
1582 }
1583 log.info( result.getErrors().size() + " errors." );
1584
1585
1586
1587
1588
1589 if ( result.hasErrors() )
1590 {
1591 log.info( result.getErrors().size() + " errors during project add: " );
1592 log.info( result.getErrorsAsString() );
1593 return result;
1594 }
1595 }
1596
1597
1598
1599
1600
1601
1602 if ( result.getProjectGroups().size() != 1 )
1603 {
1604 throw new ContinuumException( "The project building result has to contain exactly one project group." );
1605 }
1606
1607 ProjectGroup projectGroup = result.getProjectGroups().iterator().next();
1608
1609 boolean projectGroupCreation = false;
1610
1611 try
1612 {
1613 if ( projectGroupId == -1 )
1614 {
1615 try
1616 {
1617 projectGroup = projectGroupDao.getProjectGroupByGroupId( projectGroup.getGroupId() );
1618
1619 projectGroupId = projectGroup.getId();
1620
1621 log.info( "Using existing project group with the group id: '" + projectGroup.getGroupId() + "'." );
1622 }
1623 catch ( ContinuumObjectNotFoundException e )
1624 {
1625 log.info( "Creating project group with the group id: '" + projectGroup.getGroupId() + "'." );
1626
1627 Map<String, Object> pgContext = new HashMap<String, Object>();
1628
1629 AbstractContinuumAction.setWorkingDirectory( pgContext, getWorkingDirectory() );
1630
1631 AbstractContinuumAction.setUnvalidatedProjectGroup( pgContext, projectGroup );
1632
1633 executeAction( "validate-project-group", pgContext );
1634
1635 executeAction( "store-project-group", pgContext );
1636
1637 projectGroupId = AbstractContinuumAction.getProjectGroupId( pgContext );
1638
1639 projectGroupCreation = true;
1640 }
1641 }
1642
1643 projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
1644
1645 String url = CreateProjectsFromMetadataAction.getUrl( context );
1646
1647 List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( projectGroup.getId() );
1648
1649 boolean found = false;
1650
1651 for ( ProjectScmRoot scmRoot : scmRoots )
1652 {
1653 if ( url.startsWith( scmRoot.getScmRootAddress() ) )
1654 {
1655 found = true;
1656 break;
1657 }
1658 }
1659
1660 if ( !found )
1661 {
1662 createProjectScmRoot( projectGroup, url );
1663 }
1664
1665
1666 result.getProjectGroups().remove( 0 );
1667 result.getProjectGroups().add( projectGroup );
1668 }
1669 catch ( ContinuumStoreException e )
1670 {
1671 throw new ContinuumException( "Error while querying for project group.", e );
1672 }
1673
1674
1675
1676
1677
1678
1679 List<Project> projects = result.getProjects();
1680
1681 String scmUserName = null;
1682 String scmPassword = null;
1683
1684 for ( Project project : projects )
1685 {
1686 checkForDuplicateProjectInGroup( projectGroup, project, result );
1687
1688 if ( result.hasErrors() )
1689 {
1690 log.info( result.getErrors().size() + " errors during project add: " );
1691 log.info( result.getErrorsAsString() );
1692 return result;
1693 }
1694
1695 project.setScmUseCache( useCredentialsCache );
1696
1697
1698 scmUserName = project.getScmUsername();
1699 scmPassword = project.getScmPassword();
1700
1701 if ( useCredentialsCache )
1702 {
1703 project.setScmUsername( null );
1704 project.setScmPassword( null );
1705 }
1706
1707 projectGroup.addProject( project );
1708 }
1709
1710 try
1711 {
1712 projectGroupDao.updateProjectGroup( projectGroup );
1713
1714 for ( Project project : projects )
1715 {
1716 context = new HashMap<String, Object>();
1717
1718
1719
1720 if ( !projectGroupCreation && buildDefinitionTemplateId > 0 )
1721 {
1722 buildDefinitionService.addTemplateInProject( buildDefinitionTemplateId,
1723 projectDao.getProject( project.getId() ) );
1724 }
1725
1726 AbstractContinuumAction.setUnvalidatedProject( context, project );
1727
1728
1729
1730
1731
1732 AbstractContinuumAction.setProjectId( context, project.getId() );
1733
1734 if ( !StringUtils.isEmpty( scmUserName ) )
1735 {
1736 project.setScmUsername( scmUserName );
1737 CheckoutProjectContinuumAction.setScmUsername( context, scmUserName );
1738 }
1739 if ( !StringUtils.isEmpty( scmPassword ) )
1740 {
1741 project.setScmPassword( scmPassword );
1742 CheckoutProjectContinuumAction.setScmPassword( context, scmPassword );
1743 }
1744
1745
1746
1747 AbstractContinuumAction.setProject( context, projectDao.getProject( project.getId() ) );
1748
1749 BuildDefinition defaultBuildDefinition = null;
1750 BuildDefinitionTemplate template = null;
1751 if ( projectBuilderId.equals( MavenTwoContinuumProjectBuilder.ID ) )
1752 {
1753 template = buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate();
1754
1755 if( template != null && template.getBuildDefinitions().size() > 0 )
1756 {
1757 defaultBuildDefinition = template.getBuildDefinitions().get( 0 );
1758 }
1759 }
1760 else if ( projectBuilderId.equals( MavenOneContinuumProjectBuilder.ID ) )
1761 {
1762 template = buildDefinitionService.getDefaultMavenOneBuildDefinitionTemplate();
1763
1764 if ( template != null && template.getBuildDefinitions().size() > 0 )
1765 {
1766 defaultBuildDefinition = template.getBuildDefinitions().get( 0 );
1767 }
1768 }
1769
1770 if ( defaultBuildDefinition == null )
1771 {
1772
1773
1774 log.warn( "No default build definition found in the template. Project cannot be checked out." );
1775 }
1776 else
1777 {
1778
1779 AbstractContinuumAction.setBuildDefinition( context, defaultBuildDefinition );
1780
1781 if ( !configurationService.isDistributedBuildEnabled() )
1782 {
1783 executeAction( "add-project-to-checkout-queue", context );
1784 }
1785 }
1786 }
1787 }
1788 catch ( BuildDefinitionServiceException e )
1789 {
1790 throw new ContinuumException( "Error attaching buildDefintionTemplate to project ", e );
1791 }
1792 catch ( ContinuumStoreException e )
1793 {
1794 throw new ContinuumException( "Error adding projects from modules", e );
1795 }
1796
1797 AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
1798
1799 if ( addAssignableRoles )
1800 {
1801 executeAction( "add-assignable-roles", context );
1802 }
1803 return result;
1804 }
1805
1806 private ContinuumProjectBuildingResult executeAddProjectsFromMetadataActivity( String metadataUrl,
1807 String projectBuilderId,
1808 int projectGroupId,
1809 boolean checkProtocol,
1810 boolean useCredentialsCache,
1811 boolean loadRecursiveProjects,
1812 int buildDefinitionTemplateId )
1813 throws ContinuumException
1814 {
1815 return executeAddProjectsFromMetadataActivity( metadataUrl, projectBuilderId, projectGroupId, checkProtocol,
1816 useCredentialsCache, loadRecursiveProjects,
1817 buildDefinitionTemplateId, true );
1818 }
1819
1820
1821
1822
1823
1824
1825
1826
1827 public ProjectNotifier getNotifier( int projectId, int notifierId )
1828 throws ContinuumException
1829 {
1830 Project project = getProjectWithAllDetails( projectId );
1831
1832 List<ProjectNotifier> notifiers = project.getNotifiers();
1833
1834 ProjectNotifier notifier = null;
1835
1836 for ( ProjectNotifier notif : notifiers )
1837 {
1838 notifier = notif;
1839
1840 if ( notifier.getId() == notifierId )
1841 {
1842 break;
1843 }
1844 }
1845
1846 return notifier;
1847 }
1848
1849 public ProjectNotifier getGroupNotifier( int projectGroupId, int notifierId )
1850 throws ContinuumException
1851 {
1852 ProjectGroup projectGroup = getProjectGroupWithBuildDetails( projectGroupId );
1853
1854 List<ProjectNotifier> notifiers = projectGroup.getNotifiers();
1855
1856 ProjectNotifier notifier = null;
1857
1858 for ( ProjectNotifier notif : notifiers )
1859 {
1860 notifier = notif;
1861
1862 if ( notifier.getId() == notifierId )
1863 {
1864 break;
1865 }
1866 }
1867
1868 return notifier;
1869 }
1870
1871 public ProjectNotifier updateNotifier( int projectId, ProjectNotifier notifier )
1872 throws ContinuumException
1873 {
1874 Project project = getProjectWithAllDetails( projectId );
1875
1876 ProjectNotifier notif = getNotifier( projectId, notifier.getId() );
1877
1878
1879 project.removeNotifier( notif );
1880
1881 updateProject( project );
1882
1883 return addNotifier( projectId, notifier );
1884 }
1885
1886 public ProjectNotifier updateGroupNotifier( int projectGroupId, ProjectNotifier notifier )
1887 throws ContinuumException
1888 {
1889 ProjectGroup projectGroup = getProjectGroupWithBuildDetails( projectGroupId );
1890
1891 ProjectNotifier notif = getGroupNotifier( projectGroupId, notifier.getId() );
1892
1893
1894 projectGroup.removeNotifier( notif );
1895
1896 try
1897 {
1898 projectGroupDao.updateProjectGroup( projectGroup );
1899 }
1900 catch ( ContinuumStoreException cse )
1901 {
1902 throw new ContinuumException( "Unable to update project group.", cse );
1903 }
1904
1905 return addGroupNotifier( projectGroupId, notifier );
1906 }
1907
1908 public ProjectNotifier addNotifier( int projectId, ProjectNotifier notifier )
1909 throws ContinuumException
1910 {
1911 ProjectNotifier notif = new ProjectNotifier();
1912
1913 notif.setSendOnSuccess( notifier.isSendOnSuccess() );
1914
1915 notif.setSendOnFailure( notifier.isSendOnFailure() );
1916
1917 notif.setSendOnError( notifier.isSendOnError() );
1918
1919 notif.setSendOnWarning( notifier.isSendOnWarning() );
1920
1921 notif.setSendOnScmFailure( notifier.isSendOnScmFailure() );
1922
1923 notif.setConfiguration( notifier.getConfiguration() );
1924
1925 notif.setType( notifier.getType() );
1926
1927 notif.setFrom( ProjectNotifier.FROM_USER );
1928
1929 Project project = getProjectWithAllDetails( projectId );
1930
1931 project.addNotifier( notif );
1932
1933 updateProject( project );
1934
1935 return notif;
1936 }
1937
1938 public ProjectNotifier addGroupNotifier( int projectGroupId, ProjectNotifier notifier )
1939 throws ContinuumException
1940 {
1941 ProjectNotifier notif = new ProjectNotifier();
1942
1943 notif.setSendOnSuccess( notifier.isSendOnSuccess() );
1944
1945 notif.setSendOnFailure( notifier.isSendOnFailure() );
1946
1947 notif.setSendOnError( notifier.isSendOnError() );
1948
1949 notif.setSendOnWarning( notifier.isSendOnWarning() );
1950
1951 notif.setSendOnScmFailure( notifier.isSendOnScmFailure() );
1952
1953 notif.setConfiguration( notifier.getConfiguration() );
1954
1955 notif.setType( notifier.getType() );
1956
1957 notif.setFrom( ProjectNotifier.FROM_USER );
1958
1959 ProjectGroup projectGroup = getProjectGroupWithBuildDetails( projectGroupId );
1960
1961 projectGroup.addNotifier( notif );
1962 try
1963 {
1964 projectGroupDao.updateProjectGroup( projectGroup );
1965 }
1966 catch ( ContinuumStoreException cse )
1967 {
1968 throw new ContinuumException( "unable to add notifier to project group", cse );
1969 }
1970
1971 return notif;
1972 }
1973
1974 public void removeNotifier( int projectId, int notifierId )
1975 throws ContinuumException
1976 {
1977 Project project = getProjectWithAllDetails( projectId );
1978
1979 ProjectNotifier n = getNotifier( projectId, notifierId );
1980
1981 if ( n != null )
1982 {
1983 if ( n.isFromProject() )
1984 {
1985 n.setEnabled( false );
1986
1987 storeNotifier( n );
1988 }
1989 else
1990 {
1991 project.removeNotifier( n );
1992
1993 updateProject( project );
1994 }
1995 }
1996 }
1997
1998 public void removeGroupNotifier( int projectGroupId, int notifierId )
1999 throws ContinuumException
2000 {
2001 ProjectGroup projectGroup = getProjectGroupWithBuildDetails( projectGroupId );
2002
2003 ProjectNotifier n = getGroupNotifier( projectGroupId, notifierId );
2004
2005 if ( n != null )
2006 {
2007 if ( n.isFromProject() )
2008 {
2009 n.setEnabled( false );
2010
2011 storeNotifier( n );
2012 }
2013 else
2014 {
2015 projectGroup.removeNotifier( n );
2016
2017 try
2018 {
2019 projectGroupDao.updateProjectGroup( projectGroup );
2020 }
2021 catch ( ContinuumStoreException cse )
2022 {
2023 throw new ContinuumException( "Unable to remove notifer from project group.", cse );
2024 }
2025 }
2026 }
2027 }
2028
2029
2030
2031
2032
2033 public List<BuildDefinition> getBuildDefinitions( int projectId )
2034 throws ContinuumException
2035 {
2036 Project project = getProjectWithAllDetails( projectId );
2037
2038 return project.getBuildDefinitions();
2039 }
2040
2041 public BuildDefinition getBuildDefinition( int projectId, int buildDefinitionId )
2042 throws ContinuumException
2043 {
2044 List<BuildDefinition> buildDefinitions = getBuildDefinitions( projectId );
2045
2046 BuildDefinition buildDefinition = null;
2047
2048 for ( BuildDefinition bd : buildDefinitions )
2049 {
2050 if ( bd.getId() == buildDefinitionId )
2051 {
2052 buildDefinition = bd;
2053 break;
2054 }
2055 }
2056
2057 return buildDefinition;
2058 }
2059
2060 public BuildDefinition getDefaultBuildDefinition( int projectId )
2061 throws ContinuumException
2062 {
2063 try
2064 {
2065 return buildDefinitionDao.getDefaultBuildDefinition( projectId );
2066 }
2067 catch ( ContinuumObjectNotFoundException cne )
2068 {
2069 throw new ContinuumException( "no default build definition for project", cne );
2070 }
2071 catch ( ContinuumStoreException cse )
2072 {
2073 throw new ContinuumException(
2074 "error attempting to access default build definition for project " + projectId, cse );
2075 }
2076 }
2077
2078 public List<BuildDefinition> getDefaultBuildDefinitionsForProjectGroup( int projectGroupId )
2079 throws ContinuumException
2080 {
2081 try
2082 {
2083 return buildDefinitionDao.getDefaultBuildDefinitionsForProjectGroup( projectGroupId );
2084 }
2085 catch ( ContinuumObjectNotFoundException cne )
2086 {
2087 throw new ContinuumException( "Project Group (id=" + projectGroupId +
2088 " doens't have a default build definition, this should be impossible, it should always have a default definition set." );
2089 }
2090 catch ( ContinuumStoreException cse )
2091 {
2092 throw new ContinuumException( "Project Group (id=" + projectGroupId +
2093 " doens't have a default build definition, this should be impossible, it should always have a default definition set." );
2094 }
2095 }
2096
2097 public BuildDefinition getBuildDefinition( int buildDefinitionId )
2098 throws ContinuumException
2099 {
2100 try
2101 {
2102 return buildDefinitionDao.getBuildDefinition( buildDefinitionId );
2103 }
2104 catch ( ContinuumObjectNotFoundException cne )
2105 {
2106 throw new ContinuumException( "no build definition found", cne );
2107 }
2108 catch ( ContinuumStoreException cse )
2109 {
2110 throw new ContinuumException( "error attempting to access build definition", cse );
2111 }
2112 }
2113
2114 public List<BuildDefinition> getBuildDefinitionsForProject( int projectId )
2115 throws ContinuumException
2116 {
2117 Project project = getProjectWithAllDetails( projectId );
2118
2119 return project.getBuildDefinitions();
2120 }
2121
2122 public List<BuildDefinition> getBuildDefinitionsForProjectGroup( int projectGroupId )
2123 throws ContinuumException
2124 {
2125
2126 ProjectGroup projectGroup = getProjectGroupWithBuildDetails( projectGroupId );
2127
2128 return projectGroup.getBuildDefinitions();
2129 }
2130
2131 public BuildDefinition addBuildDefinitionToProject( int projectId, BuildDefinition buildDefinition )
2132 throws ContinuumException
2133 {
2134 HashMap<String, Object> context = new HashMap<String, Object>();
2135 Schedule schedule = buildDefinition.getSchedule();
2136
2137 AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
2138 AbstractContinuumAction.setProjectId( context, projectId );
2139
2140 executeAction( "add-build-definition-to-project", context );
2141
2142 activeBuildDefinitionSchedule( schedule );
2143
2144 return AbstractContinuumAction.getBuildDefinition( context );
2145 }
2146
2147 public void removeBuildDefinitionFromProject( int projectId, int buildDefinitionId )
2148 throws ContinuumException
2149 {
2150 HashMap<String, Object> context = new HashMap<String, Object>();
2151 BuildDefinition buildDefinition = getBuildDefinition( buildDefinitionId );
2152
2153 AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
2154 AbstractContinuumAction.setProjectId( context, projectId );
2155
2156 executeAction( "remove-build-definition-from-project", context );
2157 }
2158
2159 public BuildDefinition updateBuildDefinitionForProject( int projectId, BuildDefinition buildDefinition )
2160 throws ContinuumException
2161 {
2162 HashMap<String, Object> context = new HashMap<String, Object>();
2163 Schedule schedule = buildDefinition.getSchedule();
2164
2165 AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
2166 AbstractContinuumAction.setProjectId( context, projectId );
2167
2168 executeAction( "update-build-definition-from-project", context );
2169
2170 activeBuildDefinitionSchedule( schedule );
2171
2172 return AbstractContinuumAction.getBuildDefinition( context );
2173 }
2174
2175 public BuildDefinition addBuildDefinitionToProjectGroup( int projectGroupId, BuildDefinition buildDefinition )
2176 throws ContinuumException
2177 {
2178 HashMap<String, Object> context = new HashMap<String, Object>();
2179 Schedule schedule = buildDefinition.getSchedule();
2180
2181 AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
2182 AbstractContinuumAction.setProjectGroupId( context, projectGroupId );
2183
2184 executeAction( "add-build-definition-to-project-group", context );
2185
2186 activeBuildDefinitionSchedule( schedule );
2187
2188 return AbstractContinuumAction.getBuildDefinition( context );
2189 }
2190
2191 public void removeBuildDefinitionFromProjectGroup( int projectGroupId, int buildDefinitionId )
2192 throws ContinuumException
2193 {
2194 HashMap<String, Object> context = new HashMap<String, Object>();
2195
2196 AbstractContinuumAction.setBuildDefinition( context, getBuildDefinition( buildDefinitionId ) );
2197 AbstractContinuumAction.setProjectGroupId( context, projectGroupId );
2198
2199 executeAction( "remove-build-definition-from-project-group", context );
2200 }
2201
2202 public BuildDefinition updateBuildDefinitionForProjectGroup( int projectGroupId, BuildDefinition buildDefinition )
2203 throws ContinuumException
2204 {
2205 HashMap<String, Object> context = new HashMap<String, Object>();
2206 Schedule schedule = buildDefinition.getSchedule();
2207
2208 AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
2209 AbstractContinuumAction.setProjectGroupId( context, projectGroupId );
2210
2211 executeAction( "update-build-definition-from-project-group", context );
2212
2213 activeBuildDefinitionSchedule( schedule );
2214
2215 return AbstractContinuumAction.getBuildDefinition( context );
2216 }
2217
2218 public void removeBuildDefinition( int projectId, int buildDefinitionId )
2219 throws ContinuumException
2220 {
2221 Project project = getProjectWithAllDetails( projectId );
2222
2223 BuildDefinition buildDefinition = getBuildDefinition( projectId, buildDefinitionId );
2224
2225 if ( buildDefinition != null )
2226 {
2227 project.removeBuildDefinition( buildDefinition );
2228
2229 updateProject( project );
2230 }
2231 }
2232
2233
2234
2235
2236
2237 public Schedule getSchedule( int scheduleId )
2238 throws ContinuumException
2239 {
2240 try
2241 {
2242 return scheduleDao.getSchedule( scheduleId );
2243 }
2244 catch ( Exception ex )
2245 {
2246 throw logAndCreateException( "Error while getting schedule.", ex );
2247 }
2248 }
2249
2250 public Schedule getScheduleByName( String scheduleName )
2251 throws ContinuumException
2252 {
2253 try
2254 {
2255 return scheduleDao.getScheduleByName( scheduleName );
2256 }
2257 catch ( ContinuumStoreException e )
2258 {
2259 throw logAndCreateException( "Error while accessing the store.", e );
2260 }
2261 }
2262
2263 public Collection<Schedule> getSchedules()
2264 throws ContinuumException
2265 {
2266 return scheduleDao.getAllSchedulesByName();
2267 }
2268
2269 public void addSchedule( Schedule schedule )
2270 throws ContinuumException
2271 {
2272 Schedule s;
2273
2274 s = getScheduleByName( schedule.getName() );
2275
2276 if ( s != null )
2277 {
2278 throw logAndCreateException( "Can't create schedule. A schedule with the same name already exists.", null );
2279 }
2280
2281 s = scheduleDao.addSchedule( schedule );
2282
2283 try
2284 {
2285 schedulesActivator.activateSchedule( s, this );
2286 }
2287 catch ( SchedulesActivationException e )
2288 {
2289 throw new ContinuumException( "Error activating schedule " + s.getName() + ".", e );
2290 }
2291 }
2292
2293 public void updateSchedule( Schedule schedule )
2294 throws ContinuumException
2295 {
2296 updateSchedule( schedule, true );
2297 }
2298
2299 private void updateSchedule( Schedule schedule, boolean updateScheduler )
2300 throws ContinuumException
2301 {
2302
2303 Schedule old = getSchedule( schedule.getId() );
2304
2305 storeSchedule( schedule );
2306
2307 if ( updateScheduler )
2308 {
2309 try
2310 {
2311 if ( schedule.isActive() )
2312 {
2313
2314 schedulesActivator.unactivateSchedule( old, this );
2315
2316 schedulesActivator.activateSchedule( schedule, this );
2317 }
2318 else
2319 {
2320
2321 schedulesActivator.unactivateSchedule( old, this );
2322 }
2323 }
2324 catch ( SchedulesActivationException e )
2325 {
2326 log.error( "Can't unactivate schedule. You need to restart Continuum.", e );
2327 }
2328 }
2329 }
2330
2331 public void updateSchedule( int scheduleId, Map<String, String> configuration )
2332 throws ContinuumException
2333 {
2334 Schedule schedule = getSchedule( scheduleId );
2335
2336 schedule.setName( configuration.get( "schedule.name" ) );
2337
2338 schedule.setDescription( configuration.get( "schedule.description" ) );
2339
2340 schedule.setCronExpression( configuration.get( "schedule.cronExpression" ) );
2341
2342 schedule.setDelay( Integer.parseInt( configuration.get( "schedule.delay" ) ) );
2343
2344 schedule.setActive( Boolean.valueOf( configuration.get( "schedule.active" ) ) );
2345
2346 updateSchedule( schedule, true );
2347 }
2348
2349 public void removeSchedule( int scheduleId )
2350 throws ContinuumException
2351 {
2352 Schedule schedule = getSchedule( scheduleId );
2353
2354 try
2355 {
2356 schedulesActivator.unactivateSchedule( schedule, this );
2357 }
2358 catch ( SchedulesActivationException e )
2359 {
2360 log.error( "Can't unactivate the schedule. You need to restart Continuum.", e );
2361 }
2362
2363 try
2364 {
2365 scheduleDao.removeSchedule( schedule );
2366 }
2367 catch ( Exception e )
2368 {
2369 log.error( "Can't remove the schedule.", e );
2370
2371 try
2372 {
2373 schedulesActivator.activateSchedule( schedule, this );
2374 }
2375 catch ( SchedulesActivationException sae )
2376 {
2377 log.error( "Can't reactivate the schedule. You need to restart Continuum.", e );
2378 }
2379 throw new ContinuumException( "Can't remove the schedule", e );
2380 }
2381 }
2382
2383 private Schedule storeSchedule( Schedule schedule )
2384 throws ContinuumException
2385 {
2386 try
2387 {
2388 return scheduleDao.storeSchedule( schedule );
2389 }
2390 catch ( ContinuumStoreException ex )
2391 {
2392 throw logAndCreateException( "Error while storing schedule.", ex );
2393 }
2394 }
2395
2396 public void activePurgeSchedule( Schedule schedule )
2397 {
2398 try
2399 {
2400 schedulesActivator.activatePurgeSchedule( schedule, this );
2401 }
2402 catch ( SchedulesActivationException e )
2403 {
2404 log.error( "Can't activate schedule for purgeConfiguration" );
2405 }
2406 }
2407
2408 public void activeBuildDefinitionSchedule( Schedule schedule )
2409 {
2410 try
2411 {
2412 schedulesActivator.activateBuildSchedule( schedule, this );
2413 }
2414 catch ( SchedulesActivationException e )
2415 {
2416 log.error( "Can't activate schedule for buildDefinition" );
2417 }
2418 }
2419
2420
2421
2422
2423 public File getWorkingDirectory( int projectId )
2424 throws ContinuumException
2425 {
2426 try
2427 {
2428 return workingDirectoryService.getWorkingDirectory( projectDao.getProject( projectId ) );
2429 }
2430 catch ( ContinuumStoreException e )
2431 {
2432 throw new ContinuumException( "Can't get files list.", e );
2433 }
2434 }
2435
2436 public String getFileContent( int projectId, String directory, String filename )
2437 throws ContinuumException
2438 {
2439 String relativePath = "\\.\\./";
2440 Pattern pattern = Pattern.compile( relativePath );
2441 Matcher matcher = pattern.matcher( directory );
2442 String filteredDirectory = matcher.replaceAll( "" );
2443
2444 matcher = pattern.matcher( filename );
2445 String filteredFilename = matcher.replaceAll( "" );
2446
2447 File workingDirectory = getWorkingDirectory( projectId );
2448
2449 File fileDirectory = new File( workingDirectory, filteredDirectory );
2450
2451 File userFile = new File( fileDirectory, filteredFilename );
2452
2453 try
2454 {
2455 return FileUtils.fileRead( userFile );
2456 }
2457 catch ( IOException e )
2458 {
2459 throw new ContinuumException( "Can't read file " + filename, e );
2460 }
2461 }
2462
2463 public List<File> getFiles( int projectId, String userDirectory )
2464 throws ContinuumException
2465 {
2466 File workingDirectory = getWorkingDirectory( projectId );
2467
2468 return getFiles( workingDirectory, null, userDirectory );
2469 }
2470
2471 private List<File> getFiles( File baseDirectory, String currentSubDirectory, String userDirectory )
2472 {
2473 List<File> dirs = new ArrayList<File>();
2474
2475 File workingDirectory;
2476
2477 if ( currentSubDirectory != null )
2478 {
2479 workingDirectory = new File( baseDirectory, currentSubDirectory );
2480 }
2481 else
2482 {
2483 workingDirectory = baseDirectory;
2484 }
2485
2486 String[] files = workingDirectory.list();
2487
2488 if ( files != null )
2489 {
2490 for ( String file : files )
2491 {
2492 File current = new File( workingDirectory, file );
2493
2494 String currentFile;
2495
2496 if ( currentSubDirectory == null )
2497 {
2498 currentFile = file;
2499 }
2500 else
2501 {
2502 currentFile = currentSubDirectory + "/" + file;
2503 }
2504
2505 if ( userDirectory != null && current.isDirectory() && userDirectory.startsWith( currentFile ) )
2506 {
2507 dirs.add( current );
2508
2509 dirs.addAll( getFiles( baseDirectory, currentFile, userDirectory ) );
2510 }
2511 else
2512 {
2513 dirs.add( current );
2514 }
2515 }
2516 }
2517
2518 return dirs;
2519 }
2520
2521
2522
2523
2524
2525 public ConfigurationService getConfiguration()
2526 {
2527 return configurationService;
2528 }
2529
2530 public void reloadConfiguration()
2531 throws ContinuumException
2532 {
2533 try
2534 {
2535 configurationService.reload();
2536 }
2537 catch ( Exception e )
2538 {
2539 throw new ContinuumException( "Can't reload configuration.", e );
2540 }
2541 }
2542
2543
2544
2545
2546
2547 public void initialize()
2548 throws InitializationException
2549 {
2550 log.info( "Initializing Continuum." );
2551
2552 log.info( "Showing all groups:" );
2553 try
2554 {
2555 for ( ProjectGroup group : projectGroupDao.getAllProjectGroups() )
2556 {
2557 createProjectScmRootForProjectGroup( group );
2558 }
2559 }
2560 catch ( ContinuumException e )
2561 {
2562 throw new InitializationException( "Error while creating project scm root for the project group", e );
2563 }
2564
2565 log.info( "Showing all projects: " );
2566
2567 for ( Project project : projectDao.getAllProjectsByNameWithBuildDetails() )
2568 {
2569 for ( ProjectNotifier notifier : (List<ProjectNotifier>) project.getNotifiers() )
2570 {
2571 if ( StringUtils.isEmpty( notifier.getType() ) )
2572 {
2573 try
2574 {
2575 removeNotifier( project.getId(), notifier.getId() );
2576 }
2577 catch ( ContinuumException e )
2578 {
2579 throw new InitializationException( "Database is corrupted.", e );
2580 }
2581 }
2582 }
2583
2584 if ( project.getState() != ContinuumProjectState.NEW &&
2585 project.getState() != ContinuumProjectState.CHECKEDOUT &&
2586 project.getState() != ContinuumProjectState.OK && project.getState() != ContinuumProjectState.FAILED &&
2587 project.getState() != ContinuumProjectState.ERROR )
2588 {
2589 int state = project.getState();
2590
2591 project.setState( project.getOldState() );
2592
2593 project.setOldState( 0 );
2594
2595 try
2596 {
2597 log.info( "Fix project state for project " + project.getId() + ":" + project.getName() + ":" +
2598 project.getVersion() );
2599
2600 projectDao.updateProject( project );
2601
2602 Project p = projectDao.getProject( project.getId() );
2603
2604 if ( state == p.getState() )
2605 {
2606 log.info( "Can't fix the project state." );
2607 }
2608 }
2609 catch ( ContinuumStoreException e )
2610 {
2611 throw new InitializationException( "Database is corrupted.", e );
2612 }
2613 }
2614
2615 log.info( " " + project.getId() + ":" + project.getName() + ":" + project.getVersion() + ":" +
2616 project.getExecutorId() );
2617 }
2618
2619 for ( ProjectScmRoot projectScmRoot : projectScmRootDao.getAllProjectScmRoots() )
2620 {
2621 if ( projectScmRoot.getState() == ContinuumProjectState.UPDATING )
2622 {
2623 projectScmRoot.setState( projectScmRoot.getOldState() );
2624
2625 projectScmRoot.setOldState( 0 );
2626
2627 try
2628 {
2629 log.info( "Fix state for projectScmRoot " + projectScmRoot.getScmRootAddress() );
2630
2631 projectScmRootDao.updateProjectScmRoot( projectScmRoot );
2632 }
2633 catch ( ContinuumStoreException e )
2634 {
2635 throw new InitializationException( "Database is corrupted.", e );
2636 }
2637 }
2638 }
2639 }
2640
2641
2642
2643
2644 public void start()
2645 throws StartingException
2646 {
2647 startMessage();
2648
2649 try
2650 {
2651 initializer.initialize();
2652
2653 configurationService.reload();
2654 }
2655 catch ( ConfigurationLoadingException e )
2656 {
2657 throw new StartingException( "Error loading the Continuum configuration.", e );
2658 }
2659 catch ( ContinuumConfigurationException e )
2660 {
2661 throw new StartingException( "Error loading the Continuum configuration.", e );
2662 }
2663 catch ( ContinuumInitializationException e )
2664 {
2665 throw new StartingException( "Cannot initializing Continuum for the first time.", e );
2666 }
2667
2668 try
2669 {
2670
2671
2672
2673 schedulesActivator.activateSchedules( this );
2674 }
2675 catch ( SchedulesActivationException e )
2676 {
2677
2678 log.error( "Error activating schedules.", e );
2679 }
2680 }
2681
2682 public void stop()
2683 throws StoppingException
2684 {
2685 stopContinuum();
2686 }
2687
2688 private void closeStore()
2689 {
2690 if ( daoUtils != null )
2691 {
2692 daoUtils.closeStore();
2693 }
2694 }
2695
2696
2697 public void startup()
2698 throws ContinuumException
2699 {
2700 try
2701 {
2702 this.start();
2703 }
2704 catch ( StartingException e )
2705 {
2706 throw new ContinuumException( e.getMessage(), e );
2707 }
2708 }
2709
2710 private void stopContinuum()
2711 {
2712
2713 if ( stopped )
2714 {
2715 return;
2716 }
2717
2718 try
2719 {
2720 if ( configurationService != null )
2721 {
2722 configurationService.store();
2723 }
2724 }
2725 catch ( Exception e )
2726 {
2727 log.info( "Error storing the Continuum configuration.", e );
2728 }
2729
2730 closeStore();
2731
2732 stopMessage();
2733
2734 stopped = true;
2735 }
2736
2737 public long getNbBuildResultsForProject( int projectId )
2738 {
2739 return buildResultDao.getNbBuildResultsForProject( projectId );
2740 }
2741
2742 public Collection<BuildResult> getBuildResultsForProject( int projectId )
2743 throws ContinuumException
2744 {
2745 return buildResultDao.getBuildResultsForProject( projectId );
2746 }
2747
2748
2749
2750
2751
2752 protected void executeAction( String actionName, Map<String, Object> context )
2753 throws ContinuumException
2754 {
2755 try
2756 {
2757 Action action = actionManager.lookup( actionName );
2758
2759 action.execute( context );
2760 }
2761 catch ( ActionNotFoundException e )
2762 {
2763 e.printStackTrace();
2764 throw new ContinuumException( "Error while executing the action '" + actionName + "'.", e );
2765 }
2766 catch ( ContinuumException e )
2767 {
2768 throw e;
2769 }
2770 catch ( Exception e )
2771 {
2772 log.info( "exception", e );
2773 throw new ContinuumException( "Error while executing the action '" + actionName + "'.", e );
2774 }
2775 }
2776
2777
2778
2779
2780
2781 private ContinuumException logAndCreateException( String message, Throwable cause )
2782 {
2783 if ( cause instanceof ContinuumObjectNotFoundException )
2784 {
2785 return new ContinuumException( "No such object.", cause );
2786 }
2787
2788 log.error( message, cause );
2789
2790 return new ContinuumException( message, cause );
2791 }
2792
2793
2794
2795
2796
2797
2798
2799 public void updateProject( Project project )
2800 throws ContinuumException
2801 {
2802 try
2803 {
2804 boolean removeWorkingDirectory = false;
2805
2806 Project p = projectDao.getProject( project.getId() );
2807 ProjectScmRoot projectScmRoot = null;
2808
2809 if ( !p.getScmUrl().equals( project.getScmUrl() ) )
2810 {
2811 removeWorkingDirectory = true;
2812 projectScmRoot = getProjectScmRootByProject( project.getId() );
2813 }
2814
2815 if ( !p.getProjectGroup().equals( project.getProjectGroup() ) )
2816 {
2817 projectScmRoot = getProjectScmRootByProject( project.getId() );
2818 }
2819
2820 if ( StringUtils.isEmpty( p.getScmTag() ) && !StringUtils.isEmpty( project.getScmTag() ) )
2821 {
2822 removeWorkingDirectory = true;
2823 }
2824 else if ( !StringUtils.isEmpty( p.getScmTag() ) && StringUtils.isEmpty( project.getScmTag() ) )
2825 {
2826 removeWorkingDirectory = true;
2827 }
2828 else if ( !StringUtils.isEmpty( p.getScmTag() ) && !p.getScmTag().equals( project.getScmTag() ) )
2829 {
2830 removeWorkingDirectory = true;
2831 }
2832
2833 if ( removeWorkingDirectory )
2834 {
2835 File workingDirectory = getWorkingDirectory( project.getId() );
2836
2837 FileUtils.deleteDirectory( workingDirectory );
2838 }
2839
2840 if ( StringUtils.isEmpty( project.getScmTag() ) )
2841 {
2842 project.setScmTag( null );
2843 }
2844
2845 projectDao.updateProject( project );
2846
2847 if ( projectScmRoot != null )
2848 {
2849 updateProjectScmRoot( projectScmRoot, project );
2850 }
2851 }
2852 catch ( ContinuumStoreException ex )
2853 {
2854 throw logAndCreateException( "Error while updating project.", ex );
2855 }
2856 catch ( IOException ex )
2857 {
2858 throw logAndCreateException( "Error while updating project.", ex );
2859 }
2860 }
2861
2862 public void updateProjectGroup( ProjectGroup projectGroup )
2863 throws ContinuumException
2864 {
2865
2866 projectGroup.setName( projectGroup.getName().trim() );
2867 try
2868 {
2869 projectGroupDao.updateProjectGroup( projectGroup );
2870 }
2871 catch ( ContinuumStoreException cse )
2872 {
2873 throw logAndCreateException( "Error while updating project group.", cse );
2874 }
2875 }
2876
2877 private ProjectNotifier storeNotifier( ProjectNotifier notifier )
2878 throws ContinuumException
2879 {
2880 try
2881 {
2882 return notifierDao.storeNotifier( notifier );
2883 }
2884 catch ( ContinuumStoreException ex )
2885 {
2886 throw logAndCreateException( "Error while storing notifier.", ex );
2887 }
2888 }
2889
2890 private String getWorkingDirectory()
2891 {
2892 return configurationService.getWorkingDirectory().getAbsolutePath();
2893 }
2894
2895 public Project getProjectWithCheckoutResult( int projectId )
2896 throws ContinuumException
2897 {
2898 try
2899 {
2900 return projectDao.getProjectWithCheckoutResult( projectId );
2901 }
2902 catch ( ContinuumObjectNotFoundException e )
2903 {
2904 throw new ContinuumException( "Unable to find the requested project", e );
2905 }
2906 catch ( ContinuumStoreException e )
2907 {
2908 throw new ContinuumException( "Error retrieving the requested project", e );
2909 }
2910 }
2911
2912 public Project getProjectWithAllDetails( int projectId )
2913 throws ContinuumException
2914 {
2915 try
2916 {
2917 return projectDao.getProjectWithAllDetails( projectId );
2918 }
2919 catch ( ContinuumObjectNotFoundException e )
2920 {
2921 throw new ContinuumException( "Unable to find the requested project", e );
2922 }
2923 catch ( ContinuumStoreException e )
2924 {
2925 throw new ContinuumException( "Error retrieving the requested project", e );
2926 }
2927 }
2928
2929 public ProjectGroup getProjectGroupWithBuildDetails( int projectGroupId )
2930 throws ContinuumException
2931 {
2932 try
2933 {
2934 return projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
2935 }
2936 catch ( ContinuumObjectNotFoundException e )
2937 {
2938 throw new ContinuumException( "Unable to find the requested project", e );
2939 }
2940 catch ( ContinuumStoreException e )
2941 {
2942 throw new ContinuumException( "Error retrieving the requested project", e );
2943 }
2944 }
2945
2946 public Project getProjectWithBuilds( int projectId )
2947 throws ContinuumException
2948 {
2949 try
2950 {
2951 return projectDao.getProjectWithBuilds( projectId );
2952 }
2953 catch ( ContinuumObjectNotFoundException e )
2954 {
2955 throw new ContinuumException( "Unable to find the requested project", e );
2956 }
2957 catch ( ContinuumStoreException e )
2958 {
2959 throw new ContinuumException( "Error retrieving the requested project", e );
2960 }
2961 }
2962
2963 public List<ProjectGroup> getAllProjectGroupsWithBuildDetails()
2964 {
2965 return projectGroupDao.getAllProjectGroupsWithBuildDetails();
2966 }
2967
2968 public Collection<Project> getProjectsInGroup( int projectGroupId )
2969 throws ContinuumException
2970 {
2971 try
2972 {
2973 return projectDao.getProjectsInGroup( projectGroupId );
2974 }
2975 catch ( ContinuumObjectNotFoundException e )
2976 {
2977 throw new ContinuumException( "Unable to find the requested project", e );
2978 }
2979 catch ( ContinuumStoreException e )
2980 {
2981 throw new ContinuumException( "Error retrieving the requested project", e );
2982 }
2983 }
2984
2985 public Collection<Project> getProjectsInGroupWithDependencies( int projectGroupId )
2986 throws ContinuumException
2987 {
2988 try
2989 {
2990 return projectDao.getProjectsInGroupWithDependencies( projectGroupId );
2991 }
2992 catch ( ContinuumObjectNotFoundException e )
2993 {
2994 throw new ContinuumException( "Unable to find the requested project", e );
2995 }
2996 catch ( ContinuumStoreException e )
2997 {
2998 throw new ContinuumException( "Error retrieving the requested project", e );
2999 }
3000 }
3001
3002
3003
3004
3005
3006 private void startMessage()
3007 {
3008 log.info( "Starting Continuum." );
3009
3010
3011
3012
3013
3014 String banner = StringUtils.repeat( "-", getVersion().length() );
3015
3016 log.info( "" );
3017 log.info( "" );
3018 log.info( "< Continuum " + getVersion() + " started! >" );
3019 log.info( "-----------------------" + banner );
3020 log.info( " \\ ^__^" );
3021 log.info( " \\ (oo)\\_______" );
3022 log.info( " (__)\\ )\\/\\" );
3023 log.info( " ||----w |" );
3024 log.info( " || ||" );
3025 log.info( "" );
3026 log.info( "" );
3027 }
3028
3029 private void stopMessage()
3030 {
3031
3032 if ( log != null )
3033 {
3034 log.info( "Stopping Continuum." );
3035
3036 log.info( "Continuum stopped." );
3037 }
3038 }
3039
3040 private String getVersion()
3041 {
3042 InputStream resourceAsStream = null;
3043 try
3044 {
3045 Properties properties = new Properties();
3046
3047 String name = "META-INF/maven/org.apache.continuum/continuum-core/pom.properties";
3048
3049 resourceAsStream = getClass().getClassLoader().getResourceAsStream( name );
3050
3051 if ( resourceAsStream == null )
3052 {
3053 return "unknown";
3054 }
3055
3056 properties.load( resourceAsStream );
3057
3058 return properties.getProperty( "version", "unknown" );
3059 }
3060 catch ( IOException e )
3061 {
3062 return "unknown";
3063 }
3064 finally
3065 {
3066 if ( resourceAsStream != null )
3067 {
3068 IOUtil.close( resourceAsStream );
3069 }
3070 }
3071 }
3072
3073 public InstallationService getInstallationService()
3074 {
3075 return installationService;
3076 }
3077
3078 public ProfileService getProfileService()
3079 {
3080 return profileService;
3081 }
3082
3083 public BuildDefinitionService getBuildDefinitionService()
3084 {
3085 return buildDefinitionService;
3086 }
3087
3088 public ContinuumReleaseResult addContinuumReleaseResult( ContinuumReleaseResult releaseResult )
3089 throws ContinuumException
3090 {
3091 try
3092 {
3093 return releaseResultDao.addContinuumReleaseResult( releaseResult );
3094 }
3095 catch ( ContinuumStoreException e )
3096 {
3097 throw new ContinuumException( "Error while adding continuumReleaseResult", e );
3098 }
3099 }
3100
3101 public void removeContinuumReleaseResult( int releaseResultId )
3102 throws ContinuumException
3103 {
3104 ContinuumReleaseResult releaseResult = getContinuumReleaseResult( releaseResultId );
3105
3106 try
3107 {
3108 releaseResultDao.removeContinuumReleaseResult( releaseResult );
3109 }
3110 catch ( ContinuumStoreException e )
3111 {
3112 throw new ContinuumException( "Error while deleting continuumReleaseResult: " + releaseResultId, e );
3113 }
3114
3115 try
3116 {
3117 int projectGroupId = releaseResult.getProjectGroup().getId();
3118
3119 String name = "releases-" + releaseResult.getStartTime();
3120
3121 File releaseFile = getConfiguration().getReleaseOutputFile( projectGroupId, name );
3122
3123 if ( releaseFile.exists() )
3124 {
3125 try
3126 {
3127 FileUtils.forceDelete( releaseFile );
3128 }
3129 catch ( IOException e )
3130 {
3131 throw new ContinuumException( "Can't delete " + releaseFile.getAbsolutePath(), e );
3132 }
3133 }
3134 }
3135 catch ( ConfigurationException e )
3136 {
3137 log.info( "skip error during cleanup release files " + e.getMessage(), e );
3138 }
3139 }
3140
3141 public ContinuumReleaseResult getContinuumReleaseResult( int releaseResultId )
3142 throws ContinuumException
3143 {
3144 try
3145 {
3146 return releaseResultDao.getContinuumReleaseResult( releaseResultId );
3147 }
3148 catch ( ContinuumObjectNotFoundException e )
3149 {
3150 throw new ContinuumException( "No continuumReleaseResult found: " + releaseResultId );
3151 }
3152 catch ( ContinuumStoreException e )
3153 {
3154 throw new ContinuumException( "Error while retrieving continuumReleaseResult: " + releaseResultId, e );
3155 }
3156 }
3157
3158 public List<ContinuumReleaseResult> getAllContinuumReleaseResults()
3159 {
3160 return releaseResultDao.getAllContinuumReleaseResults();
3161 }
3162
3163 public List<ContinuumReleaseResult> getContinuumReleaseResultsByProjectGroup( int projectGroupId )
3164 {
3165 return releaseResultDao.getContinuumReleaseResultsByProjectGroup( projectGroupId );
3166 }
3167
3168 public ContinuumReleaseResult getContinuumReleaseResult( int projectId, String releaseGoal, long startTime,
3169 long endTime )
3170 throws ContinuumException
3171 {
3172 try
3173 {
3174 return releaseResultDao.getContinuumReleaseResult( projectId, releaseGoal, startTime, endTime );
3175 }
3176 catch ( ContinuumStoreException e )
3177 {
3178 throw new ContinuumException(
3179 "Error while retrieving continuumReleaseResult of projectId " + projectId + " with releaseGoal: " +
3180 releaseGoal, e );
3181 }
3182 }
3183
3184 public String getReleaseOutput( int releaseResultId )
3185 throws ContinuumException
3186 {
3187 ContinuumReleaseResult releaseResult = getContinuumReleaseResult( releaseResultId );
3188
3189 ProjectGroup projectGroup = releaseResult.getProjectGroup();
3190
3191 try
3192 {
3193 return configurationService.getReleaseOutput( projectGroup.getId(),
3194 "releases-" + releaseResult.getStartTime() );
3195 }
3196 catch ( ConfigurationException e )
3197 {
3198 throw new ContinuumException( "Error while retrieving release output for release: " + releaseResultId );
3199 }
3200 }
3201
3202 public List<ProjectScmRoot> getProjectScmRootByProjectGroup( int projectGroupId )
3203 {
3204 return projectScmRootDao.getProjectScmRootByProjectGroup( projectGroupId );
3205 }
3206
3207 public ProjectScmRoot getProjectScmRoot( int projectScmRootId )
3208 throws ContinuumException
3209 {
3210 try
3211 {
3212 return projectScmRootDao.getProjectScmRoot( projectScmRootId );
3213 }
3214 catch ( ContinuumObjectNotFoundException e )
3215 {
3216 throw new ContinuumException( "No projectScmRoot found with the given id: " + projectScmRootId );
3217 }
3218 catch ( ContinuumStoreException e )
3219 {
3220 throw new ContinuumException( "Error while retrieving projectScmRoot ", e );
3221 }
3222 }
3223
3224 public ProjectScmRoot getProjectScmRootByProject( int projectId )
3225 throws ContinuumException
3226 {
3227 Project project = getProject( projectId );
3228 ProjectGroup group = getProjectGroupByProjectId( projectId );
3229
3230 List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( group.getId() );
3231
3232 for ( ProjectScmRoot scmRoot : scmRoots )
3233 {
3234 if ( project.getScmUrl() != null && project.getScmUrl().startsWith( scmRoot.getScmRootAddress() ) )
3235 {
3236 return scmRoot;
3237 }
3238 }
3239 return null;
3240 }
3241
3242 public ProjectScmRoot getProjectScmRootByProjectGroupAndScmRootAddress( int projectGroupId, String scmRootAddress )
3243 throws ContinuumException
3244 {
3245 try
3246 {
3247 return projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId, scmRootAddress );
3248 }
3249 catch ( ContinuumStoreException e )
3250 {
3251 throw new ContinuumException( "Error while retrieving project scm root for " + projectGroupId, e );
3252 }
3253 }
3254
3255 private void removeProjectScmRoot( ProjectScmRoot projectScmRoot )
3256 throws ContinuumException
3257 {
3258 if ( projectScmRoot == null )
3259 {
3260 return;
3261 }
3262
3263
3264 ProjectGroup group = getProjectGroupWithProjects( projectScmRoot.getProjectGroup().getId() );
3265
3266 List<Project> projects = group.getProjects();
3267
3268 boolean found = false;
3269 for ( Project project : projects )
3270 {
3271 if ( project.getScmUrl() != null && project.getScmUrl().startsWith( projectScmRoot.getScmRootAddress() ) )
3272 {
3273 found = true;
3274 break;
3275 }
3276 }
3277
3278 if ( !found )
3279 {
3280 log.info( "Removing project scm root '" + projectScmRoot.getScmRootAddress() + "'" );
3281 try
3282 {
3283 projectScmRootDao.removeProjectScmRoot( projectScmRoot );
3284 }
3285 catch ( ContinuumStoreException e )
3286 {
3287 log.error( "Failed to remove project scm root '" + projectScmRoot.getScmRootAddress() + "'", e );
3288 throw new ContinuumException(
3289 "Error while removing project scm root '" + projectScmRoot.getScmRootAddress() + "'", e );
3290 }
3291 }
3292 else
3293 {
3294 log.info(
3295 "Project scm root '" + projectScmRoot.getScmRootAddress() + "' still has projects, not removing" );
3296 }
3297 }
3298
3299 public BuildQueue addBuildQueue( BuildQueue buildQueue )
3300 throws ContinuumException
3301 {
3302 try
3303 {
3304 return buildQueueService.addBuildQueue( buildQueue );
3305 }
3306 catch ( BuildQueueServiceException e )
3307 {
3308 throw new ContinuumException( "Error adding build queue to the database.", e );
3309 }
3310 }
3311
3312 public BuildQueue getBuildQueue( int buildQueueId )
3313 throws ContinuumException
3314 {
3315 try
3316 {
3317 return buildQueueService.getBuildQueue( buildQueueId );
3318 }
3319 catch ( BuildQueueServiceException e )
3320 {
3321 throw new ContinuumException( "Error retrieving build queue.", e );
3322 }
3323 }
3324
3325 public BuildQueue getBuildQueueByName( String buildQueueName )
3326 throws ContinuumException
3327 {
3328 try
3329 {
3330 return buildQueueService.getBuildQueueByName( buildQueueName );
3331 }
3332 catch ( BuildQueueServiceException e )
3333 {
3334 throw new ContinuumException( "Error retrieving build queue.", e );
3335 }
3336 }
3337
3338 public void removeBuildQueue( BuildQueue buildQueue )
3339 throws ContinuumException
3340 {
3341 try
3342 {
3343 buildQueueService.removeBuildQueue( buildQueue );
3344 }
3345 catch ( BuildQueueServiceException e )
3346 {
3347 throw new ContinuumException( "Error deleting build queue from database.", e );
3348 }
3349 }
3350
3351 public BuildQueue storeBuildQueue( BuildQueue buildQueue )
3352 throws ContinuumException
3353 {
3354 try
3355 {
3356 return buildQueueService.updateBuildQueue( buildQueue );
3357 }
3358 catch ( BuildQueueServiceException e )
3359 {
3360 throw new ContinuumException( "Error updating build queue.", e );
3361 }
3362 }
3363
3364 public List<BuildQueue> getAllBuildQueues()
3365 throws ContinuumException
3366 {
3367 try
3368 {
3369 return buildQueueService.getAllBuildQueues();
3370 }
3371 catch ( BuildQueueServiceException e )
3372 {
3373 throw new ContinuumException( "Error adding build queue.", e );
3374 }
3375 }
3376
3377 private void prepareBuildProjects( Collection<Project> projects, List<BuildDefinition> bds,
3378 boolean checkDefaultBuildDefinitionForProject, int trigger )
3379 throws ContinuumException
3380 {
3381 Map<ProjectScmRoot, Map<Integer, Integer>> map = new HashMap<ProjectScmRoot, Map<Integer, Integer>>();
3382 List<ProjectScmRoot> sortedScmRoot = new ArrayList<ProjectScmRoot>();
3383
3384 for ( Project project : projects )
3385 {
3386 int projectId = project.getId();
3387
3388 try
3389 {
3390
3391 if ( parallelBuildsManager.isInAnyBuildQueue( projectId ) ||
3392 parallelBuildsManager.isProjectInAnyCurrentBuild( projectId ) ||
3393 parallelBuildsManager.isInPrepareBuildQueue( projectId ) ||
3394 parallelBuildsManager.isProjectCurrentlyPreparingBuild( projectId ) )
3395 {
3396 continue;
3397 }
3398
3399 if ( parallelBuildsManager.isInAnyCheckoutQueue( projectId ) )
3400 {
3401 parallelBuildsManager.removeProjectFromCheckoutQueue( projectId );
3402 }
3403 }
3404 catch ( BuildManagerException e )
3405 {
3406 throw new ContinuumException( e.getMessage(), e );
3407 }
3408
3409 int buildDefId = -1;
3410
3411 if ( bds != null )
3412 {
3413 for ( BuildDefinition bd : bds )
3414 {
3415 if ( project.getExecutorId().equals( bd.getType() ) || ( StringUtils.isEmpty( bd.getType() ) &&
3416 ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR.equals( project.getExecutorId() ) ) )
3417 {
3418 buildDefId = bd.getId();
3419 break;
3420 }
3421 }
3422 }
3423
3424 if ( checkDefaultBuildDefinitionForProject )
3425 {
3426 BuildDefinition projectDefaultBD = null;
3427 try
3428 {
3429 projectDefaultBD = buildDefinitionDao.getDefaultBuildDefinitionForProject( projectId );
3430 }
3431 catch ( ContinuumObjectNotFoundException e )
3432 {
3433 log.debug( e.getMessage() );
3434 }
3435 catch ( ContinuumStoreException e )
3436 {
3437 log.debug( e.getMessage() );
3438 }
3439
3440 if ( projectDefaultBD != null )
3441 {
3442 buildDefId = projectDefaultBD.getId();
3443 log.debug( "Project " + project.getId() +
3444 " has own default build definition, will use it instead of group's." );
3445 }
3446 }
3447
3448 if ( buildDefId == -1 )
3449 {
3450 log.info( "Project " + projectId +
3451 " don't have a default build definition defined in the project or project group, will not be included in group prepare." );
3452 continue;
3453 }
3454
3455 ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
3456
3457 Map<Integer, Integer> projectsAndBuildDefinitionsMap = map.get( scmRoot );
3458
3459 if ( projectsAndBuildDefinitionsMap == null )
3460 {
3461 projectsAndBuildDefinitionsMap = new HashMap<Integer, Integer>();
3462 }
3463
3464 projectsAndBuildDefinitionsMap.put( projectId, buildDefId );
3465
3466 map.put( scmRoot, projectsAndBuildDefinitionsMap );
3467
3468 if ( !sortedScmRoot.contains( scmRoot ) )
3469 {
3470 sortedScmRoot.add( scmRoot );
3471 }
3472 }
3473
3474 prepareBuildProjects( map, trigger, sortedScmRoot );
3475 }
3476
3477 private void prepareBuildProjects( Collection<Project> projects, int buildDefinitionId, int trigger )
3478 throws ContinuumException
3479 {
3480 Map<ProjectScmRoot, Map<Integer, Integer>> map = new HashMap<ProjectScmRoot, Map<Integer, Integer>>();
3481 List<ProjectScmRoot> sortedScmRoot = new ArrayList<ProjectScmRoot>();
3482
3483 for ( Project project : projects )
3484 {
3485 int projectId = project.getId();
3486
3487 try
3488 {
3489
3490 if ( parallelBuildsManager.isInAnyBuildQueue( projectId ) ||
3491 parallelBuildsManager.isProjectInAnyCurrentBuild( projectId ) ||
3492 parallelBuildsManager.isInPrepareBuildQueue( projectId ) ||
3493 parallelBuildsManager.isProjectCurrentlyPreparingBuild( projectId ) )
3494 {
3495 log.info( "not building" );
3496 continue;
3497 }
3498
3499 if ( parallelBuildsManager.isInAnyCheckoutQueue( projectId ) )
3500 {
3501 parallelBuildsManager.removeProjectFromCheckoutQueue( projectId );
3502 }
3503
3504 ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
3505
3506 Map<Integer, Integer> projectsAndBuildDefinitionsMap = map.get( scmRoot );
3507
3508 if ( projectsAndBuildDefinitionsMap == null )
3509 {
3510 projectsAndBuildDefinitionsMap = new HashMap<Integer, Integer>();
3511 }
3512
3513 projectsAndBuildDefinitionsMap.put( projectId, buildDefinitionId );
3514
3515 map.put( scmRoot, projectsAndBuildDefinitionsMap );
3516
3517 if ( !sortedScmRoot.contains( scmRoot ) )
3518 {
3519 sortedScmRoot.add( scmRoot );
3520 }
3521 }
3522 catch ( BuildManagerException e )
3523 {
3524 throw new ContinuumException( e.getMessage(), e );
3525 }
3526 }
3527
3528 prepareBuildProjects( map, trigger, sortedScmRoot );
3529 }
3530
3531 private void prepareBuildProjects( Map<ProjectScmRoot, Map<Integer, Integer>> map, int trigger,
3532 List<ProjectScmRoot> scmRoots )
3533 throws ContinuumException
3534 {
3535 for ( ProjectScmRoot scmRoot : scmRoots )
3536 {
3537 prepareBuildProjects( map.get( scmRoot ), trigger, scmRoot.getScmRootAddress(),
3538 scmRoot.getProjectGroup().getId(), scmRoot.getId() );
3539 }
3540 }
3541
3542 private void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, int trigger,
3543 String scmRootAddress, int projectGroupId, int scmRootId )
3544 throws ContinuumException
3545 {
3546 ProjectGroup group = getProjectGroup( projectGroupId );
3547
3548 try
3549 {
3550 if ( configurationService.isDistributedBuildEnabled() )
3551 {
3552 distributedBuildManager.prepareBuildProjects( projectsBuildDefinitionsMap, trigger, projectGroupId,
3553 group.getName(), scmRootAddress, scmRootId );
3554 }
3555 else
3556 {
3557 parallelBuildsManager.prepareBuildProjects( projectsBuildDefinitionsMap, trigger, projectGroupId,
3558 group.getName(), scmRootAddress, scmRootId );
3559 }
3560 }
3561 catch ( BuildManagerException e )
3562 {
3563 throw logAndCreateException( "Error while creating enqueuing object.", e );
3564 }
3565 }
3566
3567 private void createProjectScmRootForProjectGroup( ProjectGroup projectGroup )
3568 throws ContinuumException
3569 {
3570 List<Project> projectsList;
3571
3572 projectsList =
3573 getProjectsInBuildOrder( projectDao.getProjectsWithDependenciesByGroupId( projectGroup.getId() ) );
3574
3575 String url = "";
3576
3577 for ( Project project : projectsList )
3578 {
3579 if ( StringUtils.isEmpty( url ) || !project.getScmUrl().startsWith( url ) )
3580 {
3581
3582 url = project.getScmUrl();
3583 createProjectScmRoot( projectGroup, url );
3584 }
3585 }
3586 }
3587
3588 private ProjectScmRoot createProjectScmRoot( ProjectGroup projectGroup, String url )
3589 throws ContinuumException
3590 {
3591 try
3592 {
3593 ProjectScmRoot scmRoot =
3594 projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroup.getId(), url );
3595
3596 if ( scmRoot != null )
3597 {
3598 return null;
3599 }
3600
3601 ProjectScmRoot projectScmRoot = new ProjectScmRoot();
3602
3603 projectScmRoot.setProjectGroup( projectGroup );
3604
3605 projectScmRoot.setScmRootAddress( url );
3606
3607 return projectScmRootDao.addProjectScmRoot( projectScmRoot );
3608 }
3609 catch ( ContinuumStoreException e )
3610 {
3611 throw new ContinuumException( "Error while creating project scm root with scm root address:" + url );
3612 }
3613 }
3614
3615 private void updateProjectScmRoot( ProjectScmRoot oldScmRoot, Project project )
3616 throws ContinuumException
3617 {
3618 try
3619 {
3620 removeProjectScmRoot( oldScmRoot );
3621 ProjectScmRoot scmRoot =
3622 projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( project.getProjectGroup().getId(),
3623 project.getScmUrl() );
3624 if ( scmRoot == null )
3625 {
3626 ProjectScmRoot newScmRoot = new ProjectScmRoot();
3627 if ( project.getScmUrl().equals( oldScmRoot.getScmRootAddress() ) )
3628 {
3629 BeanUtils.copyProperties( oldScmRoot, newScmRoot, new String[]{"id", "projectGroup"} );
3630 }
3631 else
3632 {
3633 newScmRoot.setScmRootAddress( project.getScmUrl() );
3634 }
3635 newScmRoot.setProjectGroup( project.getProjectGroup() );
3636 projectScmRootDao.addProjectScmRoot( newScmRoot );
3637 }
3638 }
3639 catch ( ContinuumStoreException ex )
3640 {
3641 throw logAndCreateException( "Error while updating project.", ex );
3642 }
3643 }
3644
3645 private boolean isProjectInReleaseStage( Project project )
3646 throws ContinuumException
3647 {
3648 String releaseId = project.getGroupId() + ":" + project.getArtifactId();
3649 try
3650 {
3651 return taskQueueManager.isProjectInReleaseStage( releaseId );
3652 }
3653 catch ( TaskQueueManagerException e )
3654 {
3655 throw new ContinuumException( "Error occurred while checking if project is currently being released.", e );
3656 }
3657 }
3658
3659 private boolean isAnyProjectInGroupInReleaseStage( int projectGroupId )
3660 throws ContinuumException
3661 {
3662 Collection<Project> projects = getProjectsInGroup( projectGroupId );
3663 for ( Project project : projects )
3664 {
3665 if ( isProjectInReleaseStage( project ) )
3666 {
3667 throw new ContinuumException( "Cannot build project group. Project (id=" + project.getId() +
3668 ") in group is currently in release stage." );
3669 }
3670 }
3671 return false;
3672 }
3673
3674 private boolean isAnyProjectsInReleaseStage( List<Project> projects )
3675 throws ContinuumException
3676 {
3677 for ( Project project : projects )
3678 {
3679 if ( isProjectInReleaseStage( project ) )
3680 {
3681 return true;
3682 }
3683 }
3684
3685 return false;
3686 }
3687
3688 private Collection<Project> getProjectsNotInReleaseStage( Collection<Project> projectsList )
3689 throws ContinuumException
3690 {
3691
3692
3693 Collection<Project> filteredProjectsList = new ArrayList<Project>();
3694 for ( Project project : projectsList )
3695 {
3696 if ( !isProjectInReleaseStage( project ) )
3697 {
3698 filteredProjectsList.add( project );
3699 }
3700 else
3701 {
3702 log.warn(
3703 "Project (id=" + project.getId() + ") will not be built. It is currently in the release stage." );
3704 }
3705 }
3706 return filteredProjectsList;
3707 }
3708
3709 private void checkForDuplicateProjectInGroup( ProjectGroup projectGroup, Project projectToCheck,
3710 ContinuumProjectBuildingResult result )
3711 {
3712 List<Project> projectsInGroup = projectGroup.getProjects();
3713
3714 if ( projectsInGroup == null )
3715 {
3716 return;
3717 }
3718
3719 for ( Project project : projectGroup.getProjects() )
3720 {
3721
3722
3723 if ( projectToCheck.getGroupId().equals( project.getGroupId() ) && projectToCheck.getArtifactId().equals(
3724 project.getArtifactId() ) && projectToCheck.getVersion().equals( project.getVersion() ) )
3725 {
3726 result.addError( ContinuumProjectBuildingResult.ERROR_DUPLICATE_PROJECTS );
3727 return;
3728 }
3729 }
3730 }
3731
3732 void setTaskQueueManager( TaskQueueManager taskQueueManager )
3733 {
3734 this.taskQueueManager = taskQueueManager;
3735 }
3736
3737 void setProjectDao( ProjectDao projectDao )
3738 {
3739 this.projectDao = projectDao;
3740 }
3741
3742 public DistributedBuildManager getDistributedBuildManager()
3743 {
3744 return distributedBuildManager;
3745 }
3746 }