View Javadoc

1   package org.apache.continuum.release.distributed.manager;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
23  import org.apache.continuum.configuration.BuildAgentConfiguration;
24  import org.apache.continuum.configuration.BuildAgentConfigurationException;
25  import org.apache.continuum.dao.BuildResultDao;
26  import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
27  import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
28  import org.apache.continuum.model.repository.LocalRepository;
29  import org.apache.continuum.release.distributed.DistributedReleaseUtil;
30  import org.apache.continuum.release.model.PreparedRelease;
31  import org.apache.continuum.release.model.PreparedReleaseModel;
32  import org.apache.continuum.release.model.io.stax.ContinuumPrepareReleasesModelStaxReader;
33  import org.apache.continuum.release.model.io.stax.ContinuumPrepareReleasesModelStaxWriter;
34  import org.apache.maven.artifact.ArtifactUtils;
35  import org.apache.maven.continuum.configuration.ConfigurationService;
36  import org.apache.maven.continuum.installation.InstallationService;
37  import org.apache.maven.continuum.model.project.BuildResult;
38  import org.apache.maven.continuum.model.project.Project;
39  import org.apache.maven.continuum.release.ContinuumReleaseException;
40  import org.apache.maven.shared.release.ReleaseResult;
41  import org.codehaus.plexus.util.IOUtil;
42  import org.codehaus.plexus.util.StringUtils;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  import java.io.File;
47  import java.io.FileInputStream;
48  import java.io.FileWriter;
49  import java.io.IOException;
50  import java.io.InputStreamReader;
51  import java.net.MalformedURLException;
52  import java.net.URL;
53  import java.util.ArrayList;
54  import java.util.HashMap;
55  import java.util.LinkedHashMap;
56  import java.util.List;
57  import java.util.Map;
58  import java.util.Properties;
59  import javax.xml.stream.XMLStreamException;
60  
61  /**
62   * @plexus.component role="org.apache.continuum.release.distributed.manager.DistributedReleaseManager"
63   */
64  public class DefaultDistributedReleaseManager
65      implements DistributedReleaseManager
66  {
67      private static final Logger log = LoggerFactory.getLogger( DefaultDistributedReleaseManager.class );
68  
69      public final String PREPARED_RELEASES_FILENAME = "prepared-releases.xml";
70  
71      /**
72       * @plexus.requirement
73       */
74      BuildResultDao buildResultDao;
75  
76      /**
77       * @plexus.requirement
78       */
79      InstallationService installationService;
80  
81      /**
82       * @plexus.requirement
83       */
84      ConfigurationService configurationService;
85  
86      /**
87       * @plexus.requirement
88       */
89      DistributedBuildManager distributedBuildManager;
90  
91      private Map<String, Map<String, Object>> releasesInProgress;
92  
93      public Map getReleasePluginParameters( int projectId, String pomFilename )
94          throws ContinuumReleaseException, BuildAgentConfigurationException
95      {
96          String buildAgentUrl = getDefaultBuildagent( projectId );
97  
98          if ( !checkBuildAgent( buildAgentUrl ) )
99          {
100             throw new BuildAgentConfigurationException( buildAgentUrl );
101         }
102 
103         try
104         {
105             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
106             {
107                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
108                     buildAgentUrl );
109                 return client.getReleasePluginParameters( projectId, pomFilename );
110             }
111 
112             // call reload in case we disable the build agent
113             distributedBuildManager.reload();
114 
115             throw new ContinuumReleaseException(
116                 "Failed to retrieve release plugin parameters because build agent " + buildAgentUrl +
117                     " is not available" );
118         }
119         catch ( MalformedURLException e )
120         {
121             log.error( "Invalid build agent url " + buildAgentUrl );
122             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
123         }
124         catch ( Exception e )
125         {
126             log.error( "Failed to retrieve release plugin parameters", e );
127             throw new ContinuumReleaseException( "Failed to retrieve release plugin parameters", e );
128         }
129     }
130 
131     public List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
132         throws ContinuumReleaseException, BuildAgentConfigurationException
133     {
134         BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId );
135 
136         String buildAgentUrl = buildResult.getBuildUrl();
137 
138         if ( !checkBuildAgent( buildAgentUrl ) )
139         {
140             throw new BuildAgentConfigurationException( buildAgentUrl );
141         }
142 
143         try
144         {
145             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
146             {
147                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
148                     buildAgentUrl );
149                 return client.processProject( projectId, pomFilename, autoVersionSubmodules );
150             }
151 
152             // call reload in case we disable the build agent
153             distributedBuildManager.reload();
154 
155             throw new ContinuumReleaseException(
156                 "Failed to process project for releasing because build agent " + buildAgentUrl + " is unavailable" );
157         }
158         catch ( MalformedURLException e )
159         {
160             log.error( "Invalid build agent url " + buildAgentUrl );
161             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
162         }
163         catch ( Exception e )
164         {
165             log.error( "Failed to process project for releasing", e );
166             throw new ContinuumReleaseException( "Failed to process project for releasing", e );
167         }
168     }
169 
170     public String releasePrepare( Project project, Properties releaseProperties, Map<String, String> releaseVersion,
171                                   Map<String, String> developmentVersion, Map<String, String> environments,
172                                   String username )
173         throws ContinuumReleaseException, BuildAgentConfigurationException
174     {
175         String buildAgentUrl = environments.get( DistributedReleaseUtil.KEY_BUILD_AGENT_URL );
176 
177         if ( !checkBuildAgent( buildAgentUrl ) )
178         {
179             throw new BuildAgentConfigurationException( buildAgentUrl );
180         }
181 
182         try
183         {
184             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
185             {
186                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
187                     buildAgentUrl );
188 
189                 String releaseId = client.releasePrepare( createProjectMap( project ), releaseProperties,
190                                                           releaseVersion, developmentVersion, environments, username );
191 
192                 String key = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
193                 addReleasePrepare( releaseId, buildAgentUrl, releaseVersion.get( key ), "prepare",
194                                    releaseProperties.getProperty( "preparation-goals" ), username );
195 
196                 addReleaseInProgress( releaseId, "prepare", project.getId(), username );
197 
198                 return releaseId;
199             }
200 
201             // call reload in case we disable the build agent
202             distributedBuildManager.reload();
203 
204             throw new ContinuumReleaseException(
205                 "Failed to prepare release project because the build agent " + buildAgentUrl + " is not available" );
206         }
207         catch ( MalformedURLException e )
208         {
209             log.error( "Invalid build agent url " + buildAgentUrl );
210             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
211         }
212         catch ( Exception e )
213         {
214             log.error( "Failed to prepare release project " + project.getName(), e );
215             throw new ContinuumReleaseException( "Failed to prepare release project " + project.getName(), e );
216         }
217     }
218 
219     public ReleaseResult getReleaseResult( String releaseId )
220         throws ContinuumReleaseException, BuildAgentConfigurationException
221     {
222         String buildAgentUrl = getBuildAgentUrl( releaseId );
223 
224         if ( !checkBuildAgent( buildAgentUrl ) )
225         {
226             throw new BuildAgentConfigurationException( buildAgentUrl );
227         }
228 
229         try
230         {
231             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
232             {
233                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
234                     buildAgentUrl );
235                 Map<String, Object> result = client.getReleaseResult( releaseId );
236 
237                 ReleaseResult releaseResult = new ReleaseResult();
238                 releaseResult.setStartTime( DistributedReleaseUtil.getStartTime( result ) );
239                 releaseResult.setEndTime( DistributedReleaseUtil.getEndTime( result ) );
240                 releaseResult.setResultCode( DistributedReleaseUtil.getReleaseResultCode( result ) );
241                 releaseResult.getOutputBuffer().append( DistributedReleaseUtil.getReleaseOutput( result ) );
242 
243                 return releaseResult;
244             }
245 
246             // call reload in case we disable a build agent
247             distributedBuildManager.reload();
248 
249             throw new ContinuumReleaseException( "Failed to get release result of " + releaseId +
250                                                      " because the build agent " + buildAgentUrl +
251                                                      " is not available" );
252         }
253         catch ( MalformedURLException e )
254         {
255             log.error( "Invalid build agent url " + buildAgentUrl );
256             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
257         }
258         catch ( Exception e )
259         {
260             log.error( "Failed to get release result of " + releaseId, e );
261             throw new ContinuumReleaseException( "Failed to get release result of " + releaseId, e );
262         }
263     }
264 
265     public Map<String, Object> getListener( String releaseId )
266         throws ContinuumReleaseException, BuildAgentConfigurationException
267     {
268         String buildAgentUrl = getBuildAgentUrl( releaseId );
269 
270         if ( !checkBuildAgent( buildAgentUrl ) )
271         {
272             throw new BuildAgentConfigurationException( buildAgentUrl );
273         }
274 
275         try
276         {
277             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
278             {
279                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
280                     buildAgentUrl );
281                 return client.getListener( releaseId );
282             }
283 
284             // call reload in case we disable the build agent
285             distributedBuildManager.reload();
286 
287             throw new ContinuumReleaseException( "Failed to get listener for " + releaseId +
288                                                      " because the build agent " + buildAgentUrl +
289                                                      " is not available" );
290         }
291         catch ( MalformedURLException e )
292         {
293             log.error( "Invalid build agent url " + buildAgentUrl );
294             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
295         }
296         catch ( Exception e )
297         {
298             log.error( "Failed to get listener for " + releaseId, e );
299             throw new ContinuumReleaseException( "Failed to get listener for " + releaseId, e );
300         }
301     }
302 
303     public void removeListener( String releaseId )
304         throws ContinuumReleaseException, BuildAgentConfigurationException
305     {
306         String buildAgentUrl = getBuildAgentUrl( releaseId );
307 
308         if ( !checkBuildAgent( buildAgentUrl ) )
309         {
310             throw new BuildAgentConfigurationException( buildAgentUrl );
311         }
312 
313         try
314         {
315             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
316             {
317                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
318                     buildAgentUrl );
319                 client.removeListener( releaseId );
320             }
321 
322             // call reload in case we disable the build agent
323             distributedBuildManager.reload();
324 
325             throw new ContinuumReleaseException( "Failed to remove listener of " + releaseId +
326                                                      " because the build agent " + buildAgentUrl +
327                                                      " is not available" );
328         }
329         catch ( MalformedURLException e )
330         {
331             log.error( "Invalid build agent url " + buildAgentUrl );
332             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
333         }
334         catch ( Exception e )
335         {
336             log.error( "Failed to remove listener of " + releaseId, e );
337             throw new ContinuumReleaseException( "Failed to remove listener of " + releaseId, e );
338         }
339     }
340 
341     public String getPreparedReleaseName( String releaseId )
342         throws ContinuumReleaseException
343     {
344         String buildAgentUrl = getBuildAgentUrl( releaseId );
345 
346         if ( StringUtils.isBlank( buildAgentUrl ) )
347         {
348             log.info( "Unable to get prepared release name because no build agent found for " + releaseId );
349             return null;
350         }
351 
352         try
353         {
354             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
355             {
356                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
357                     buildAgentUrl );
358                 return client.getPreparedReleaseName( releaseId );
359             }
360 
361             // call reload in case we disable the build agent
362             distributedBuildManager.reload();
363 
364             throw new ContinuumReleaseException( "Failed to get prepared release name of " + releaseId +
365                                                      " because the build agent " + buildAgentUrl +
366                                                      " is not available" );
367         }
368         catch ( MalformedURLException e )
369         {
370             log.error( "Invalid build agent url " + buildAgentUrl );
371             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
372         }
373         catch ( Exception e )
374         {
375             log.error( "Failed to get prepared release name of " + releaseId, e );
376             throw new ContinuumReleaseException( "Failed to get prepared release name of " + releaseId, e );
377         }
378     }
379 
380     public Map<String, String> getPreparedReleases( String groupId, String artifactId )
381         throws ContinuumReleaseException
382     {
383         String releaseId = ArtifactUtils.versionlessKey( groupId, artifactId );
384 
385         Map<String, String> projectPreparedReleases = new LinkedHashMap<String, String>();
386         for ( PreparedRelease release : getPreparedReleases() )
387         {
388             // get exact match, or one with a timestamp appended
389             String id = release.getReleaseId();
390             if ( id.equals( releaseId ) || id.startsWith( releaseId + ":" ) )
391             {
392                 projectPreparedReleases.put( id, release.getReleaseName() );
393             }
394         }
395         return projectPreparedReleases;
396     }
397 
398     public void releasePerform( int projectId, String releaseId, String goals, String arguments,
399                                 boolean useReleaseProfile, LocalRepository repository, String username )
400         throws ContinuumReleaseException, BuildAgentConfigurationException
401     {
402         List<PreparedRelease> releases = getPreparedReleases();
403 
404         for ( PreparedRelease release : releases )
405         {
406             if ( release.getReleaseId().equals( releaseId ) )
407             {
408                 release.setReleaseType( "perform" );
409                 savePreparedReleases( releases );
410                 break;
411             }
412         }
413 
414         String buildAgentUrl = getBuildAgentUrl( releaseId );
415 
416         if ( !checkBuildAgent( buildAgentUrl ) )
417         {
418             throw new BuildAgentConfigurationException( buildAgentUrl );
419         }
420 
421         if ( goals == null )
422         {
423             goals = "";
424         }
425 
426         if ( arguments == null )
427         {
428             arguments = "";
429         }
430 
431         Map<String, String> map = new HashMap<String, String>();
432         map.put( DistributedReleaseUtil.KEY_USERNAME, username );
433 
434         if ( repository != null )
435         {
436             map.put( DistributedReleaseUtil.KEY_LOCAL_REPOSITORY_NAME, repository.getName() );
437         }
438 
439         try
440         {
441             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
442             {
443                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
444                     buildAgentUrl );
445                 client.releasePerform( releaseId, goals, arguments, useReleaseProfile, map, username );
446 
447                 addReleaseInProgress( releaseId, "perform", projectId, username );
448             }
449             else
450             {
451                 // call reload in case we disable the build agent
452                 distributedBuildManager.reload();
453 
454                 throw new ContinuumReleaseException( "Failed to perform release of " + releaseId +
455                                                          " because the build agent " + buildAgentUrl +
456                                                          " is not available" );
457             }
458         }
459         catch ( MalformedURLException e )
460         {
461             log.error( "Invalid build agent url " + buildAgentUrl );
462             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
463         }
464         catch ( Exception e )
465         {
466             log.error( "Failed to perform release of " + releaseId, e );
467             throw new ContinuumReleaseException( "Failed to perform release of " + releaseId, e );
468         }
469     }
470 
471     public String releasePerformFromScm( int projectId, String goals, String arguments, boolean useReleaseProfile,
472                                          LocalRepository repository, String scmUrl, String scmUsername,
473                                          String scmPassword, String scmTag, String scmTagBase, Map environments,
474                                          String username )
475         throws ContinuumReleaseException, BuildAgentConfigurationException
476     {
477         String buildAgentUrl = (String) environments.get( DistributedReleaseUtil.KEY_BUILD_AGENT_URL );
478 
479         if ( !checkBuildAgent( buildAgentUrl ) )
480         {
481             throw new BuildAgentConfigurationException( buildAgentUrl );
482         }
483 
484         if ( goals == null )
485         {
486             goals = "";
487         }
488 
489         if ( arguments == null )
490         {
491             arguments = "";
492         }
493 
494         Map<String, String> map = new HashMap<String, String>();
495         map.put( DistributedReleaseUtil.KEY_USERNAME, username );
496 
497         if ( repository != null )
498         {
499             map.put( DistributedReleaseUtil.KEY_LOCAL_REPOSITORY_NAME, repository.getName() );
500         }
501 
502         try
503         {
504             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
505             {
506                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
507                     buildAgentUrl );
508                 String releaseId = client.releasePerformFromScm( goals, arguments, useReleaseProfile, map, scmUrl,
509                                                                  scmUsername, scmPassword, scmTag, scmTagBase,
510                                                                  environments, username );
511 
512                 addReleasePrepare( releaseId, buildAgentUrl, scmTag, "perform", goals, username );
513                 addReleaseInProgress( releaseId, "perform", projectId, username );
514 
515                 return releaseId;
516             }
517 
518             // call reload in case we disable the build agent
519             distributedBuildManager.reload();
520 
521             throw new ContinuumReleaseException(
522                 "Failed to perform release because the build agent " + buildAgentUrl + " is not available" );
523         }
524         catch ( MalformedURLException e )
525         {
526             log.error( "Invalid build agent url " + buildAgentUrl );
527             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
528         }
529         catch ( Exception e )
530         {
531             log.error( "Failed to perform release", e );
532             throw new ContinuumReleaseException( "Failed to perform release", e );
533         }
534     }
535 
536     public void releaseRollback( String releaseId, int projectId )
537         throws ContinuumReleaseException, BuildAgentConfigurationException
538     {
539         String buildAgentUrl = getBuildAgentUrl( releaseId );
540 
541         if ( !checkBuildAgent( buildAgentUrl ) )
542         {
543             throw new BuildAgentConfigurationException( buildAgentUrl );
544         }
545 
546         try
547         {
548             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
549             {
550                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
551                     buildAgentUrl );
552                 client.releaseRollback( releaseId, projectId );
553                 return;
554             }
555 
556             // call reload in case we disable the build agent
557             distributedBuildManager.reload();
558 
559             throw new ContinuumReleaseException( "Unable to rollback release " + releaseId +
560                                                      " because the build agent " + buildAgentUrl +
561                                                      " is not available" );
562         }
563         catch ( MalformedURLException e )
564         {
565             log.error( "Invalid build agent url " + buildAgentUrl );
566             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
567         }
568         catch ( Exception e )
569         {
570             log.error( "Unable to rollback release " + releaseId, e );
571             throw new ContinuumReleaseException( e );
572         }
573     }
574 
575     public String releaseCleanup( String releaseId )
576         throws ContinuumReleaseException, BuildAgentConfigurationException
577     {
578         String buildAgentUrl = getBuildAgentUrl( releaseId );
579 
580         if ( !checkBuildAgent( buildAgentUrl ) )
581         {
582             throw new BuildAgentConfigurationException( buildAgentUrl );
583         }
584 
585         try
586         {
587             if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
588             {
589                 removeFromReleaseInProgress( releaseId );
590                 removeFromPreparedReleases( releaseId );
591 
592                 SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
593                     buildAgentUrl );
594                 String result = client.releaseCleanup( releaseId );
595 
596                 return result;
597             }
598 
599             // call reload in case we disable the build agent
600             distributedBuildManager.reload();
601 
602             throw new ContinuumReleaseException( "Failed to cleanup release of " + releaseId +
603                                                      " because the build agent " + buildAgentUrl +
604                                                      " is not available" );
605         }
606         catch ( MalformedURLException e )
607         {
608             log.error( "Invalid build agent url " + buildAgentUrl );
609             throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
610         }
611         catch ( Exception e )
612         {
613             log.error( "Failed to cleanup release of " + releaseId, e );
614             throw new ContinuumReleaseException( "Failed to cleanup release of " + releaseId, e );
615         }
616     }
617 
618     public List<Map<String, Object>> getAllReleasesInProgress()
619         throws ContinuumReleaseException, BuildAgentConfigurationException
620     {
621         List<Map<String, Object>> releases = new ArrayList<Map<String, Object>>();
622         Map<String, Map<String, Object>> releasesMap = new HashMap<String, Map<String, Object>>();
623 
624         if ( releasesInProgress != null && !releasesInProgress.isEmpty() )
625         {
626             for ( String releaseId : releasesInProgress.keySet() )
627             {
628                 String buildAgentUrl = getBuildAgentUrl( releaseId );
629 
630                 if ( StringUtils.isNotBlank( buildAgentUrl ) )
631                 {
632                     if ( !checkBuildAgent( buildAgentUrl ) )
633                     {
634                         throw new BuildAgentConfigurationException( buildAgentUrl );
635                     }
636 
637                     try
638                     {
639                         if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
640                         {
641                             SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
642                                 buildAgentUrl );
643                             Map map = client.getListener( releaseId );
644 
645                             if ( map != null && !map.isEmpty() )
646                             {
647                                 Map<String, Object> release = releasesInProgress.get( releaseId );
648                                 release.put( DistributedReleaseUtil.KEY_RELEASE_ID, releaseId );
649                                 release.put( DistributedReleaseUtil.KEY_BUILD_AGENT_URL, buildAgentUrl );
650 
651                                 releases.add( release );
652 
653                                 releasesMap.put( releaseId, releasesInProgress.get( releaseId ) );
654                             }
655                         }
656                     }
657                     catch ( MalformedURLException e )
658                     {
659                         log.error( "Invalid build agent url " + buildAgentUrl );
660                         throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
661                     }
662                     catch ( Exception e )
663                     {
664                         log.error( "Failed to get all releases in progress ", e );
665                         throw new ContinuumReleaseException( "Failed to get all releases in progress ", e );
666                     }
667                 }
668             }
669 
670             releasesInProgress = releasesMap;
671         }
672 
673         try
674         {
675             // call reload in case we disable a build agent
676             distributedBuildManager.reload();
677         }
678         catch ( Exception e )
679         {
680             throw new ContinuumReleaseException( e.getMessage(), e );
681         }
682 
683         return releases;
684     }
685 
686     public String getDefaultBuildagent( int projectId )
687     {
688         BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId );
689 
690         return buildResult != null ? buildResult.getBuildUrl() : null;
691     }
692 
693     public PreparedRelease getPreparedRelease( String releaseId, String releaseType )
694         throws ContinuumReleaseException
695     {
696         List<PreparedRelease> releases = getPreparedReleases();
697 
698         for ( PreparedRelease release : releases )
699         {
700             if ( release.getReleaseId().equals( releaseId ) && release.getReleaseType().equals( releaseType ) )
701             {
702                 return release;
703             }
704         }
705 
706         return null;
707     }
708 
709     public SlaveBuildAgentTransportService createSlaveBuildAgentTransportClientConnection( String buildAgentUrl )
710         throws MalformedURLException, Exception
711     {
712         return new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ), "",
713                                                    configurationService.getSharedSecretPassword() );
714     }
715 
716     private Map createProjectMap( Project project )
717     {
718         Map<String, Object> map = new HashMap<String, Object>();
719 
720         map.put( DistributedReleaseUtil.KEY_PROJECT_ID, project.getId() );
721         map.put( DistributedReleaseUtil.KEY_GROUP_ID, project.getGroupId() );
722         map.put( DistributedReleaseUtil.KEY_ARTIFACT_ID, project.getArtifactId() );
723         map.put( DistributedReleaseUtil.KEY_SCM_URL, project.getScmUrl() );
724         if ( project.getProjectGroup().getLocalRepository() != null )
725         {
726             map.put( DistributedReleaseUtil.KEY_LOCAL_REPOSITORY_NAME,
727                      project.getProjectGroup().getLocalRepository().getName() );
728         }
729 
730         return map;
731     }
732 
733     private List<PreparedRelease> getPreparedReleases()
734         throws ContinuumReleaseException
735     {
736         File file = getPreparedReleasesFile();
737 
738         if ( file.exists() )
739         {
740             FileInputStream fis = null;
741             try
742             {
743                 fis = new FileInputStream( file );
744                 ContinuumPrepareReleasesModelStaxReader reader = new ContinuumPrepareReleasesModelStaxReader();
745                 PreparedReleaseModel model = reader.read( new InputStreamReader( fis ) );
746 
747                 return model.getPreparedReleases();
748             }
749             catch ( IOException e )
750             {
751                 log.error( e.getMessage(), e );
752                 throw new ContinuumReleaseException( "Unable to get prepared releases", e );
753             }
754             catch ( XMLStreamException e )
755             {
756                 log.error( e.getMessage(), e );
757                 throw new ContinuumReleaseException( e.getMessage(), e );
758             }
759             finally
760             {
761                 if ( fis != null )
762                 {
763                     IOUtil.close( fis );
764                 }
765             }
766         }
767 
768         return new ArrayList<PreparedRelease>();
769     }
770 
771     private void addReleasePrepare( String releaseId, String buildAgentUrl, String releaseName, String releaseType,
772                                     String releaseGoals, String username )
773         throws ContinuumReleaseException
774     {
775         PreparedRelease release = new PreparedRelease();
776         release.setReleaseId( releaseId );
777         release.setBuildAgentUrl( buildAgentUrl );
778         release.setReleaseName( releaseName );
779         release.setReleaseType( releaseType );
780         release.setReleaseGoals( releaseGoals );
781         release.setReleaseBy( username );
782 
783         List<PreparedRelease> preparedReleases = getPreparedReleases();
784 
785         if ( preparedReleases == null )
786         {
787             preparedReleases = new ArrayList<PreparedRelease>();
788         }
789 
790         for ( PreparedRelease preparedRelease : preparedReleases )
791         {
792             if ( preparedRelease.getReleaseId().equals( release.getReleaseId() ) )
793             {
794                 preparedReleases.remove( preparedRelease );
795                 break;
796             }
797         }
798 
799         preparedReleases.add( release );
800 
801         savePreparedReleases( preparedReleases );
802     }
803 
804     private void addReleaseInProgress( String releaseId, String releaseType, int projectId, String username )
805     {
806         if ( releasesInProgress == null )
807         {
808             releasesInProgress = new HashMap<String, Map<String, Object>>();
809         }
810 
811         Map<String, Object> map = new HashMap<String, Object>();
812         map.put( DistributedReleaseUtil.KEY_RELEASE_GOAL, releaseType );
813         map.put( DistributedReleaseUtil.KEY_PROJECT_ID, projectId );
814         map.put( DistributedReleaseUtil.KEY_USERNAME, username );
815 
816         releasesInProgress.put( releaseId, map );
817     }
818 
819     private void removeFromReleaseInProgress( String releaseId )
820     {
821         if ( releasesInProgress != null && releasesInProgress.containsKey( releaseId ) )
822         {
823             releasesInProgress.remove( releaseId );
824         }
825     }
826 
827     private String getBuildAgentUrl( String releaseId )
828         throws ContinuumReleaseException
829     {
830         List<PreparedRelease> preparedReleases = getPreparedReleases();
831 
832         if ( preparedReleases != null )
833         {
834             for ( PreparedRelease preparedRelease : preparedReleases )
835             {
836                 if ( preparedRelease.getReleaseId().equals( releaseId ) )
837                 {
838                     return preparedRelease.getBuildAgentUrl();
839                 }
840             }
841         }
842 
843         return null;
844     }
845 
846     private File getPreparedReleasesFile()
847     {
848         return new File( System.getProperty( "appserver.base" ) + File.separator + "conf" + File.separator +
849                              PREPARED_RELEASES_FILENAME );
850     }
851 
852     private boolean checkBuildAgent( String buildAgentUrl )
853     {
854         BuildAgentConfiguration buildAgent = configurationService.getBuildAgent( buildAgentUrl );
855 
856         if ( buildAgent != null && buildAgent.isEnabled() )
857         {
858             return true;
859         }
860 
861         log.info( "Build agent: " + buildAgentUrl + " is either disabled or removed" );
862         return false;
863     }
864 
865     private void removeFromPreparedReleases( String releaseId )
866         throws ContinuumReleaseException
867     {
868         List<PreparedRelease> releases = getPreparedReleases();
869 
870         for ( PreparedRelease release : releases )
871         {
872             if ( release.getReleaseId().equals( releaseId ) )
873             {
874                 if ( release.getReleaseType().equals( "perform" ) )
875                 {
876                     releases.remove( release );
877                     savePreparedReleases( releases );
878                     break;
879                 }
880             }
881         }
882     }
883 
884     private void savePreparedReleases( List<PreparedRelease> preparedReleases )
885         throws ContinuumReleaseException
886     {
887         File file = getPreparedReleasesFile();
888 
889         if ( !file.exists() )
890         {
891             file.getParentFile().mkdirs();
892         }
893 
894         PreparedReleaseModel model = new PreparedReleaseModel();
895         model.setPreparedReleases( preparedReleases );
896 
897         FileWriter fileWriter = null;
898         try
899         {
900             ContinuumPrepareReleasesModelStaxWriter writer = new ContinuumPrepareReleasesModelStaxWriter();
901             fileWriter = new FileWriter( file );
902             writer.write( fileWriter, model );
903             fileWriter.flush();
904         }
905         catch ( IOException e )
906         {
907             throw new ContinuumReleaseException( "Failed to write prepared releases in file", e );
908         }
909         catch ( XMLStreamException e )
910         {
911             throw new ContinuumReleaseException( "Failed to write prepared releases in file", e );
912         }
913         finally
914         {
915             IOUtil.close( fileWriter );
916         }
917     }
918 
919     // for unit test
920 
921     public void setBuildResultDao( BuildResultDao buildResultDao )
922     {
923         this.buildResultDao = buildResultDao;
924     }
925 }