View Javadoc
1   package org.apache.maven.shared.release;
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 javax.inject.Inject;
23  import javax.inject.Named;
24  import javax.inject.Singleton;
25  
26  import java.io.File;
27  import java.util.ArrayList;
28  import java.util.Collections;
29  import java.util.LinkedHashSet;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Set;
33  import java.util.concurrent.atomic.AtomicReference;
34  
35  import org.apache.commons.lang3.BooleanUtils;
36  import org.apache.maven.shared.release.config.ReleaseDescriptor;
37  import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder;
38  import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder.BuilderReleaseDescriptor;
39  import org.apache.maven.shared.release.config.ReleaseDescriptorStore;
40  import org.apache.maven.shared.release.config.ReleaseDescriptorStoreException;
41  import org.apache.maven.shared.release.config.ReleaseUtils;
42  import org.apache.maven.shared.release.phase.ReleasePhase;
43  import org.apache.maven.shared.release.phase.ResourceGenerator;
44  import org.apache.maven.shared.release.strategy.Strategy;
45  import org.codehaus.plexus.util.StringUtils;
46  import org.slf4j.Logger;
47  import org.slf4j.LoggerFactory;
48  
49  import static java.util.Objects.requireNonNull;
50  
51  /**
52   * Implementation of the release manager.
53   *
54   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
55   */
56  @Singleton
57  @Named
58  public class DefaultReleaseManager
59      implements ReleaseManager
60  {
61      private final Logger logger = LoggerFactory.getLogger( getClass() );
62  
63      private final Map<String, Strategy> strategies;
64  
65      /**
66       * The available phases.
67       */
68      private final Map<String, ReleasePhase> releasePhases;
69  
70      /**
71       * The configuration storage.
72       */
73      private final AtomicReference<ReleaseDescriptorStore> configStore;
74  
75      @Inject
76      public DefaultReleaseManager( Map<String, Strategy> strategies,
77                                    Map<String, ReleasePhase> releasePhases,
78                                    @Named( "properties" ) ReleaseDescriptorStore configStore )
79      {
80          this.strategies = requireNonNull( strategies );
81          this.releasePhases = requireNonNull( releasePhases );
82          this.configStore = new AtomicReference<>( requireNonNull( configStore ) );
83      }
84  
85      /**
86       * For easier testing only!
87       */
88      public void setConfigStore( ReleaseDescriptorStore configStore )
89      {
90          this.configStore.set( configStore );
91      }
92  
93      @Override
94      public ReleaseResult prepareWithResult( ReleasePrepareRequest prepareRequest )
95      {
96          ReleaseResult result = new ReleaseResult();
97  
98          result.setStartTime( System.currentTimeMillis() );
99  
100         try
101         {
102             prepare( prepareRequest, result );
103 
104             result.setResultCode( ReleaseResult.SUCCESS );
105         }
106         catch ( ReleaseExecutionException | ReleaseFailureException e )
107         {
108             captureException( result, prepareRequest.getReleaseManagerListener(), e );
109         }
110         finally
111         {
112             result.setEndTime( System.currentTimeMillis() );
113         }
114 
115         return result;
116     }
117 
118     @Override
119     public void prepare( ReleasePrepareRequest prepareRequest )
120         throws ReleaseExecutionException, ReleaseFailureException
121     {
122         prepare( prepareRequest, new ReleaseResult() );
123     }
124 
125     private void prepare( ReleasePrepareRequest prepareRequest, ReleaseResult result )
126         throws ReleaseExecutionException, ReleaseFailureException
127     {
128 
129         final ReleaseDescriptorBuilder builder = prepareRequest.getReleaseDescriptorBuilder();
130 
131         // Create a config containing values from the session properties (ie command line properties with cli).
132         ReleaseUtils.copyPropertiesToReleaseDescriptor( prepareRequest.getUserProperties(),
133                 new ReleaseDescriptorBuilder()
134                 {
135                     public ReleaseDescriptorBuilder addDevelopmentVersion( String key,
136                                                                            String value )
137                     {
138                         builder.addDevelopmentVersion( key, value );
139                         return this;
140                     }
141 
142                     public ReleaseDescriptorBuilder addReleaseVersion( String key,
143                                                                        String value )
144                     {
145                         builder.addReleaseVersion( key, value );
146                         return this;
147                     }
148 
149                     public ReleaseDescriptorBuilder addDependencyReleaseVersion( String dependencyKey,
150                                                                                 String version )
151                     {
152                         builder.addDependencyReleaseVersion( dependencyKey, version );
153                         return this;
154                     }
155 
156                     public ReleaseDescriptorBuilder addDependencyDevelopmentVersion( String dependencyKey,
157                                                                                     String version )
158                     {
159                         builder.addDependencyDevelopmentVersion( dependencyKey, version );
160                         return this;
161                     }
162                 } );
163 
164         BuilderReleaseDescriptor config;
165         if ( BooleanUtils.isNotFalse( prepareRequest.getResume() ) )
166         {
167             config = loadReleaseDescriptor( builder, prepareRequest.getReleaseManagerListener() );
168         }
169         else
170         {
171             config = ReleaseUtils.buildReleaseDescriptor( builder );
172         }
173 
174         Strategy releaseStrategy = getStrategy( config.getReleaseStrategyId() );
175 
176         List<String> preparePhases = getGoalPhases( releaseStrategy, "prepare" );
177 
178         goalStart( prepareRequest.getReleaseManagerListener(), "prepare", preparePhases );
179 
180         // Later, it would be a good idea to introduce a proper workflow tool so that the release can be made up of a
181         // more flexible set of steps.
182 
183         String completedPhase = config.getCompletedPhase();
184         int index = preparePhases.indexOf( completedPhase );
185 
186         for ( int idx = 0; idx <= index; idx++ )
187         {
188             phaseSkip( prepareRequest.getReleaseManagerListener(), preparePhases.get( idx ) );
189         }
190 
191         if ( index == preparePhases.size() - 1 )
192         {
193             logInfo( result, "Release preparation already completed. You can now continue with release:perform, "
194                 + "or start again using the -Dresume=false flag" );
195         }
196         else if ( index >= 0 )
197         {
198             logInfo( result, "Resuming release from phase '" + preparePhases.get( index + 1 ) + "'" );
199         }
200 
201         // start from next phase
202         for ( int i = index + 1; i < preparePhases.size(); i++ )
203         {
204             String name = preparePhases.get( i );
205 
206             ReleasePhase phase = releasePhases.get( name );
207 
208             if ( phase == null )
209             {
210                 throw new ReleaseExecutionException( "Unable to find phase '" + name + "' to execute" );
211             }
212 
213             phaseStart( prepareRequest.getReleaseManagerListener(), name );
214 
215             ReleaseResult phaseResult = null;
216             try
217             {
218                 if ( BooleanUtils.isTrue( prepareRequest.getDryRun() ) )
219                 {
220                     phaseResult = phase.simulate( config,
221                                                   prepareRequest.getReleaseEnvironment(),
222                                                   prepareRequest.getReactorProjects() );
223                 }
224                 else
225                 {
226                     phaseResult = phase.execute( config,
227                                                  prepareRequest.getReleaseEnvironment(),
228                                                  prepareRequest.getReactorProjects() );
229                 }
230             }
231             finally
232             {
233                 if ( result != null && phaseResult != null )
234                 {
235                     result.appendOutput(  phaseResult.getOutput() );
236                 }
237             }
238 
239             config.setCompletedPhase( name );
240             try
241             {
242                 configStore.get().write( config );
243             }
244             catch ( ReleaseDescriptorStoreException e )
245             {
246                 // TODO: rollback?
247                 throw new ReleaseExecutionException( "Error writing release properties after completing phase", e );
248             }
249 
250             phaseEnd( prepareRequest.getReleaseManagerListener() );
251         }
252 
253         goalEnd( prepareRequest.getReleaseManagerListener() );
254     }
255 
256     @Override
257     public void rollback( ReleaseRollbackRequest rollbackRequest )
258         throws ReleaseExecutionException, ReleaseFailureException
259     {
260         ReleaseDescriptor releaseDescriptor =
261             loadReleaseDescriptor( rollbackRequest.getReleaseDescriptorBuilder(), null );
262 
263         Strategy releaseStrategy = getStrategy( releaseDescriptor.getReleaseStrategyId() );
264 
265         List<String> rollbackPhases = getGoalPhases( releaseStrategy, "rollback" );
266 
267         goalStart( rollbackRequest.getReleaseManagerListener(), "rollback", rollbackPhases );
268 
269         for ( String name : rollbackPhases )
270         {
271             ReleasePhase phase = releasePhases.get( name );
272 
273             if ( phase == null )
274             {
275                 throw new ReleaseExecutionException( "Unable to find phase '" + name + "' to execute" );
276             }
277 
278             phaseStart( rollbackRequest.getReleaseManagerListener(), name );
279             phase.execute( releaseDescriptor,
280                            rollbackRequest.getReleaseEnvironment(),
281                            rollbackRequest.getReactorProjects() );
282             phaseEnd( rollbackRequest.getReleaseManagerListener() );
283         }
284 
285         //call release:clean so that resume will not be possible anymore after a rollback
286         clean( rollbackRequest );
287         goalEnd( rollbackRequest.getReleaseManagerListener() );
288     }
289 
290     @Override
291     public ReleaseResult performWithResult( ReleasePerformRequest performRequest )
292     {
293         ReleaseResult result = new ReleaseResult();
294 
295         try
296         {
297             result.setStartTime( System.currentTimeMillis() );
298 
299             perform( performRequest, result );
300 
301             result.setResultCode( ReleaseResult.SUCCESS );
302         }
303         catch ( ReleaseExecutionException | ReleaseFailureException e )
304         {
305             captureException( result, performRequest.getReleaseManagerListener(), e );
306         }
307         finally
308         {
309             result.setEndTime( System.currentTimeMillis() );
310         }
311 
312         return result;
313     }
314 
315     @Override
316     public void perform( ReleasePerformRequest performRequest )
317         throws ReleaseExecutionException, ReleaseFailureException
318     {
319         perform( performRequest, new ReleaseResult() );
320     }
321 
322     private void perform( ReleasePerformRequest performRequest, ReleaseResult result )
323         throws ReleaseExecutionException, ReleaseFailureException
324     {
325         List<String> specificProfiles =
326             ReleaseUtils.buildReleaseDescriptor( performRequest.getReleaseDescriptorBuilder() )
327             .getActivateProfiles();
328 
329         ReleaseDescriptorBuilder builder =
330             loadReleaseDescriptorBuilder( performRequest.getReleaseDescriptorBuilder(),
331                                           performRequest.getReleaseManagerListener() );
332 
333         if ( specificProfiles != null && !specificProfiles.isEmpty() )
334         {
335             List<String> allProfiles =
336                     new ArrayList<>( ReleaseUtils.buildReleaseDescriptor( builder ).getActivateProfiles() );
337             for ( String specificProfile : specificProfiles )
338             {
339                 if ( !allProfiles.contains( specificProfile ) )
340                 {
341                     allProfiles.add( specificProfile );
342                 }
343             }
344             builder.setActivateProfiles( allProfiles );
345         }
346 
347         ReleaseDescriptor releaseDescriptor = ReleaseUtils.buildReleaseDescriptor( builder );
348 
349         Strategy releaseStrategy = getStrategy( releaseDescriptor.getReleaseStrategyId() );
350 
351         List<String> performPhases = getGoalPhases( releaseStrategy, "perform" );
352 
353         goalStart( performRequest.getReleaseManagerListener(), "perform", performPhases );
354 
355         for ( String name : performPhases )
356         {
357             ReleasePhase phase = releasePhases.get( name );
358 
359             if ( phase == null )
360             {
361                 throw new ReleaseExecutionException( "Unable to find phase '" + name + "' to execute" );
362             }
363 
364             phaseStart( performRequest.getReleaseManagerListener(), name );
365 
366             ReleaseResult phaseResult = null;
367             try
368             {
369                 if ( BooleanUtils.isTrue( performRequest.getDryRun() ) )
370                 {
371                     phaseResult = phase.simulate( releaseDescriptor,
372                                                  performRequest.getReleaseEnvironment(),
373                                                  performRequest.getReactorProjects() );
374                 }
375                 else
376                 {
377                     phaseResult = phase.execute( releaseDescriptor,
378                                                  performRequest.getReleaseEnvironment(),
379                                                  performRequest.getReactorProjects() );
380                 }
381             }
382             finally
383             {
384                 if ( result != null && phaseResult != null )
385                 {
386                     result.appendOutput( phaseResult.getOutput() );
387                 }
388             }
389 
390             phaseEnd( performRequest.getReleaseManagerListener() );
391         }
392 
393         if ( BooleanUtils.isNotFalse( performRequest.getClean() ) )
394         {
395             // call release:clean so that resume will not be possible anymore after a perform
396             clean( performRequest );
397         }
398 
399         goalEnd( performRequest.getReleaseManagerListener() );
400     }
401 
402     @Override
403     public void branch( ReleaseBranchRequest branchRequest )
404         throws ReleaseExecutionException, ReleaseFailureException
405     {
406         final ReleaseDescriptorBuilder builder = branchRequest.getReleaseDescriptorBuilder();
407         
408         ReleaseUtils.copyPropertiesToReleaseDescriptor( branchRequest.getUserProperties(),
409                     new ReleaseDescriptorBuilder()
410                     {
411                         public ReleaseDescriptorBuilder addDevelopmentVersion( String key,
412                                                                                String value )
413                         {
414                             builder.addDevelopmentVersion( key, value );
415                             return this;
416                         }
417 
418                         public ReleaseDescriptorBuilder addReleaseVersion( String key,
419                                                                            String value )
420                         {
421                             builder.addReleaseVersion( key, value );
422                             return this;
423                         }
424                     } );
425         
426         ReleaseDescriptor releaseDescriptor =
427             loadReleaseDescriptor( builder, branchRequest.getReleaseManagerListener() );
428 
429         boolean dryRun = BooleanUtils.isTrue( branchRequest.getDryRun() );
430 
431         Strategy releaseStrategy = getStrategy( releaseDescriptor.getReleaseStrategyId() );
432 
433         List<String> branchPhases = getGoalPhases( releaseStrategy, "branch" );
434 
435         goalStart( branchRequest.getReleaseManagerListener(), "branch", branchPhases );
436 
437         for ( String name : branchPhases )
438         {
439             ReleasePhase phase = releasePhases.get( name );
440 
441             if ( phase == null )
442             {
443                 throw new ReleaseExecutionException( "Unable to find phase '" + name + "' to execute" );
444             }
445 
446             phaseStart( branchRequest.getReleaseManagerListener(), name );
447 
448             if ( dryRun )
449             {
450                 phase.simulate( releaseDescriptor,
451                                 branchRequest.getReleaseEnvironment(),
452                                 branchRequest.getReactorProjects() );
453             }
454             else // getDryRun is null or FALSE
455             {
456                 phase.execute( releaseDescriptor,
457                                branchRequest.getReleaseEnvironment(),
458                                branchRequest.getReactorProjects() );
459             }
460 
461             phaseEnd( branchRequest.getReleaseManagerListener() );
462         }
463 
464         if ( !dryRun )
465         {
466             clean( branchRequest );
467         }
468 
469         goalEnd( branchRequest.getReleaseManagerListener() );
470     }
471 
472     @Override
473     public void updateVersions( ReleaseUpdateVersionsRequest updateVersionsRequest )
474         throws ReleaseExecutionException, ReleaseFailureException
475     {
476         final ReleaseDescriptorBuilder builder = updateVersionsRequest.getReleaseDescriptorBuilder();
477         
478         // Create a config containing values from the session properties (ie command line properties with cli).
479         ReleaseUtils.copyPropertiesToReleaseDescriptor( updateVersionsRequest.getUserProperties(),
480                                     new ReleaseDescriptorBuilder()
481                                     {
482                                         public ReleaseDescriptorBuilder addDevelopmentVersion( String key,
483                                                                                                String value )
484                                         {
485                                             builder.addDevelopmentVersion( key, value );
486                                             return this;
487                                         }
488 
489                                         public ReleaseDescriptorBuilder addReleaseVersion( String key,
490                                                                                            String value )
491                                         {
492                                             builder.addReleaseVersion( key, value );
493                                             return this;
494                                         }
495                                     } );
496 
497         ReleaseDescriptor releaseDescriptor =
498             loadReleaseDescriptor( builder, updateVersionsRequest.getReleaseManagerListener() );
499 
500         Strategy releaseStrategy = getStrategy( releaseDescriptor.getReleaseStrategyId() );
501 
502         List<String> updateVersionsPhases = getGoalPhases( releaseStrategy, "updateVersions" );
503 
504         goalStart( updateVersionsRequest.getReleaseManagerListener(), "updateVersions", updateVersionsPhases );
505 
506         for ( String name : updateVersionsPhases )
507         {
508             ReleasePhase phase = releasePhases.get( name );
509 
510             if ( phase == null )
511             {
512                 throw new ReleaseExecutionException( "Unable to find phase '" + name + "' to execute" );
513             }
514 
515             phaseStart( updateVersionsRequest.getReleaseManagerListener(), name );
516             phase.execute( releaseDescriptor,
517                            updateVersionsRequest.getReleaseEnvironment(),
518                            updateVersionsRequest.getReactorProjects() );
519             phaseEnd( updateVersionsRequest.getReleaseManagerListener() );
520         }
521 
522         clean( updateVersionsRequest );
523 
524         goalEnd( updateVersionsRequest.getReleaseManagerListener() );
525     }
526 
527     /**
528      * Determines the path of the working directory. By default, this is the
529      * checkout directory. For some SCMs, the project root directory is not the
530      * checkout directory itself, but a SCM-specific subdirectory.
531      *
532      * @param checkoutDirectory            The checkout directory as java.io.File
533      * @param relativePathProjectDirectory The relative path of the project directory within the checkout
534      *                                     directory or ""
535      * @return The working directory
536      */
537     protected File determineWorkingDirectory( File checkoutDirectory, String relativePathProjectDirectory )
538     {
539         if ( StringUtils.isNotEmpty( relativePathProjectDirectory ) )
540         {
541             return new File( checkoutDirectory, relativePathProjectDirectory );
542         }
543         else
544         {
545             return checkoutDirectory;
546         }
547     }
548 
549     private BuilderReleaseDescriptor loadReleaseDescriptor( ReleaseDescriptorBuilder builder,
550                                                      ReleaseManagerListener listener )
551         throws ReleaseExecutionException
552     {
553         return ReleaseUtils.buildReleaseDescriptor( loadReleaseDescriptorBuilder( builder, listener ) );
554     }
555 
556     private ReleaseDescriptorBuilder loadReleaseDescriptorBuilder( ReleaseDescriptorBuilder builder,
557                                                      ReleaseManagerListener listener )
558         throws ReleaseExecutionException
559     {
560         try
561         {
562             return configStore.get().read( builder );
563         }
564         catch ( ReleaseDescriptorStoreException e )
565         {
566             throw new ReleaseExecutionException( "Error reading stored configuration: " + e.getMessage(), e );
567         }
568     }
569 
570     /**
571      * <p>clean.</p>
572      *
573      * @param releaseRequest a {@link org.apache.maven.shared.release.AbstractReleaseRequest} object
574      * @throws org.apache.maven.shared.release.ReleaseFailureException if any.
575      */
576     protected void clean( AbstractReleaseRequest releaseRequest  ) throws ReleaseFailureException
577     {
578         ReleaseCleanRequest cleanRequest = new ReleaseCleanRequest();
579         cleanRequest.setReleaseDescriptorBuilder( releaseRequest.getReleaseDescriptorBuilder() );
580         cleanRequest.setReleaseManagerListener( releaseRequest.getReleaseManagerListener() );
581         cleanRequest.setReactorProjects( releaseRequest.getReactorProjects() );
582 
583         clean( cleanRequest );
584     }
585 
586     @Override
587     public void clean( ReleaseCleanRequest cleanRequest ) throws ReleaseFailureException
588     {
589         logger.info( "Cleaning up after release..." );
590 
591         ReleaseDescriptor releaseDescriptor =
592             ReleaseUtils.buildReleaseDescriptor( cleanRequest.getReleaseDescriptorBuilder() );
593 
594         configStore.get().delete( releaseDescriptor );
595 
596         Strategy releaseStrategy = getStrategy( releaseDescriptor.getReleaseStrategyId() );
597 
598         Set<String> phases = new LinkedHashSet<>();
599         phases.addAll( getGoalPhases( releaseStrategy, "prepare" ) );
600         phases.addAll( getGoalPhases( releaseStrategy, "branch" ) );
601 
602         for ( String name : phases )
603         {
604             ReleasePhase phase = releasePhases.get( name );
605             
606             if ( phase instanceof ResourceGenerator )
607             {
608                 ( (ResourceGenerator) phase ).clean( cleanRequest.getReactorProjects() );
609             }
610         }
611     }
612 
613     void goalStart( ReleaseManagerListener listener, String goal, List<String> phases )
614     {
615         if ( listener != null )
616         {
617             listener.goalStart( goal, phases );
618         }
619     }
620 
621     void goalEnd( ReleaseManagerListener listener )
622     {
623         if ( listener != null )
624         {
625             listener.goalEnd();
626         }
627     }
628 
629     void phaseSkip( ReleaseManagerListener listener, String name )
630     {
631         if ( listener != null )
632         {
633             listener.phaseSkip( name );
634         }
635     }
636 
637     void phaseStart( ReleaseManagerListener listener, String name )
638     {
639         if ( listener != null )
640         {
641             listener.phaseStart( name );
642         }
643     }
644 
645     void phaseEnd( ReleaseManagerListener listener )
646     {
647         if ( listener != null )
648         {
649             listener.phaseEnd();
650         }
651     }
652 
653     void error( ReleaseManagerListener listener, String name )
654     {
655         if ( listener != null )
656         {
657             listener.error( name );
658         }
659     }
660 
661     private Strategy getStrategy( String strategyId ) throws ReleaseFailureException
662     {
663         Strategy strategy = strategies.get( strategyId );
664         if ( strategy == null )
665         {
666             throw new ReleaseFailureException( "Unknown strategy: " + strategyId );
667         }
668         return strategy;
669     }
670 
671     private List<String> getGoalPhases( Strategy strategy, String goal )
672     {
673         List<String> phases;
674 
675         if ( "prepare".equals( goal ) )
676         {
677             phases = strategy.getPreparePhases();
678             if ( phases  == null )
679             {
680                 phases = strategies.get( "default" ).getPreparePhases();
681             }
682         }
683         else if ( "perform".equals( goal ) )
684         {
685             phases = strategy.getPerformPhases();
686             if ( phases  == null )
687             {
688                 phases = strategies.get( "default" ).getPerformPhases();
689             }
690         }
691         else if ( "rollback".equals( goal ) )
692         {
693             phases = strategy.getRollbackPhases();
694             if ( phases  == null )
695             {
696                 phases = strategies.get( "default" ).getRollbackPhases();
697             }
698         }
699         else if ( "branch".equals( goal ) )
700         {
701             phases = strategy.getBranchPhases();
702             if ( phases  == null )
703             {
704                 phases = strategies.get( "default" ).getBranchPhases();
705             }
706         }
707         else if ( "updateVersions".equals( goal ) )
708         {
709             phases = strategy.getUpdateVersionsPhases();
710             if ( phases  == null )
711             {
712                 phases = strategies.get( "default" ).getUpdateVersionsPhases();
713             }
714         }
715         else
716         {
717             phases = null;
718         }
719 
720         return Collections.unmodifiableList( phases ); // TODO: NPE here in phases=null above!
721     }
722 
723     private void logInfo( ReleaseResult result, String message )
724     {
725         if ( result != null )
726         {
727             result.appendInfo( message );
728         }
729 
730         logger.info( message );
731     }
732 
733     private void captureException( ReleaseResult result, ReleaseManagerListener listener, Exception e )
734     {
735         if ( listener != null )
736         {
737             listener.error( e.getMessage() );
738         }
739 
740         result.appendError( e );
741 
742         result.setResultCode( ReleaseResult.ERROR );
743     }
744 }