View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.shared.release.phase;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.io.Writer;
28  import java.nio.file.Path;
29  import java.util.ArrayList;
30  import java.util.Collections;
31  import java.util.LinkedHashMap;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.Properties;
35  import java.util.Set;
36  
37  import org.apache.maven.artifact.Artifact;
38  import org.apache.maven.artifact.ArtifactUtils;
39  import org.apache.maven.model.Build;
40  import org.apache.maven.model.Dependency;
41  import org.apache.maven.model.Extension;
42  import org.apache.maven.model.Model;
43  import org.apache.maven.model.Plugin;
44  import org.apache.maven.model.ReportPlugin;
45  import org.apache.maven.model.Reporting;
46  import org.apache.maven.model.Resource;
47  import org.apache.maven.model.Scm;
48  import org.apache.maven.model.building.DefaultModelBuildingRequest;
49  import org.apache.maven.model.building.ModelBuildingRequest;
50  import org.apache.maven.model.interpolation.ModelInterpolator;
51  import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
52  import org.apache.maven.model.superpom.SuperPomProvider;
53  import org.apache.maven.project.MavenProject;
54  import org.apache.maven.scm.ScmException;
55  import org.apache.maven.scm.ScmFileSet;
56  import org.apache.maven.scm.command.add.AddScmResult;
57  import org.apache.maven.scm.provider.ScmProvider;
58  import org.apache.maven.scm.repository.ScmRepository;
59  import org.apache.maven.shared.release.ReleaseExecutionException;
60  import org.apache.maven.shared.release.ReleaseFailureException;
61  import org.apache.maven.shared.release.ReleaseResult;
62  import org.apache.maven.shared.release.config.ReleaseDescriptor;
63  import org.apache.maven.shared.release.env.ReleaseEnvironment;
64  import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
65  import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
66  import org.apache.maven.shared.release.scm.ScmTranslator;
67  import org.apache.maven.shared.release.util.ReleaseUtil;
68  import org.codehaus.plexus.util.WriterFactory;
69  
70  import static java.util.Objects.requireNonNull;
71  
72  /**
73   * Generate release POMs.
74   *
75   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
76   * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
77   */
78  @Singleton
79  @Named("generate-release-poms")
80  public class GenerateReleasePomsPhase extends AbstractReleasePomsPhase implements ResourceGenerator {
81      private static final String FINALNAME_EXPRESSION = "${project.artifactId}-${project.version}";
82  
83      private final SuperPomProvider superPomProvider;
84  
85      private final ModelInterpolator modelInterpolator;
86  
87      /**
88       * SCM URL translators mapped by provider name.
89       */
90      private final Map<String, ScmTranslator> scmTranslators;
91  
92      @Inject
93      public GenerateReleasePomsPhase(
94              ScmRepositoryConfigurator scmRepositoryConfigurator,
95              SuperPomProvider superPomProvider,
96              ModelInterpolator modelInterpolator,
97              Map<String, ScmTranslator> scmTranslators) {
98          super(scmRepositoryConfigurator);
99          this.superPomProvider = requireNonNull(superPomProvider);
100         this.modelInterpolator = requireNonNull(modelInterpolator);
101         this.scmTranslators = requireNonNull(scmTranslators);
102     }
103 
104     /*
105      * @see org.apache.maven.shared.release.phase.ReleasePhase#execute(org.apache.maven.shared.release.config.ReleaseDescriptor,
106      *      org.apache.maven.settings.Settings, java.util.List)
107      */
108     @Override
109     public ReleaseResult execute(
110             ReleaseDescriptor releaseDescriptor,
111             ReleaseEnvironment releaseEnvironment,
112             List<MavenProject> reactorProjects)
113             throws ReleaseExecutionException, ReleaseFailureException {
114         return execute(releaseDescriptor, releaseEnvironment, reactorProjects, false);
115     }
116 
117     private ReleaseResult execute(
118             ReleaseDescriptor releaseDescriptor,
119             ReleaseEnvironment releaseEnvironment,
120             List<MavenProject> reactorProjects,
121             boolean simulate)
122             throws ReleaseExecutionException, ReleaseFailureException {
123         ReleaseResult result = new ReleaseResult();
124 
125         if (releaseDescriptor.isGenerateReleasePoms()) {
126             logInfo(result, "Generating release POMs...");
127 
128             generateReleasePoms(releaseDescriptor, releaseEnvironment, reactorProjects, simulate, result);
129         } else {
130             logInfo(result, "Not generating release POMs");
131         }
132 
133         result.setResultCode(ReleaseResult.SUCCESS);
134 
135         return result;
136     }
137 
138     private void generateReleasePoms(
139             ReleaseDescriptor releaseDescriptor,
140             ReleaseEnvironment releaseEnvironment,
141             List<MavenProject> reactorProjects,
142             boolean simulate,
143             ReleaseResult result)
144             throws ReleaseExecutionException, ReleaseFailureException {
145         List<File> releasePoms = new ArrayList<>();
146 
147         for (MavenProject project : reactorProjects) {
148             logInfo(result, "Generating release POM for '" + project.getName() + "'...");
149 
150             releasePoms.add(generateReleasePom(project, releaseDescriptor, releaseEnvironment, result));
151         }
152 
153         addReleasePomsToScm(releaseDescriptor, releaseEnvironment, reactorProjects, simulate, result, releasePoms);
154     }
155 
156     private File generateReleasePom(
157             MavenProject project,
158             ReleaseDescriptor releaseDescriptor,
159             ReleaseEnvironment releaseEnvironment,
160             ReleaseResult result)
161             throws ReleaseExecutionException, ReleaseFailureException {
162         // create release pom
163 
164         Model releasePom = createReleaseModel(project, releaseDescriptor, releaseEnvironment, result);
165 
166         // write release pom to file
167 
168         MavenXpp3Writer pomWriter = new MavenXpp3Writer();
169 
170         File releasePomFile = ReleaseUtil.getReleasePom(project);
171 
172         // MRELEASE-273 : A release pom can be null
173         if (releasePomFile == null) {
174             throw new ReleaseExecutionException("Cannot generate release POM : pom file is null");
175         }
176 
177         try (Writer fileWriter = WriterFactory.newXmlWriter(releasePomFile)) {
178             pomWriter.write(fileWriter, releasePom);
179         } catch (IOException exception) {
180             throw new ReleaseExecutionException("Cannot generate release POM", exception);
181         }
182 
183         return releasePomFile;
184     }
185 
186     private void addReleasePomsToScm(
187             ReleaseDescriptor releaseDescriptor,
188             ReleaseEnvironment releaseEnvironment,
189             List<MavenProject> reactorProjects,
190             boolean simulate,
191             ReleaseResult result,
192             List<File> releasePoms)
193             throws ReleaseFailureException, ReleaseExecutionException {
194         if (simulate) {
195             logInfo(result, "Full run would be adding " + releasePoms);
196         } else {
197             ScmRepository scmRepository = getScmRepository(releaseDescriptor, releaseEnvironment);
198             ScmProvider scmProvider = getScmProvider(scmRepository);
199 
200             MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
201             ScmFileSet scmFileSet = new ScmFileSet(rootProject.getFile().getParentFile(), releasePoms);
202 
203             try {
204                 AddScmResult scmResult = scmProvider.add(scmRepository, scmFileSet);
205 
206                 if (!scmResult.isSuccess()) {
207                     throw new ReleaseScmCommandException("Cannot add release POM to SCM", scmResult);
208                 }
209             } catch (ScmException exception) {
210                 throw new ReleaseExecutionException(
211                         "Cannot add release POM to SCM: " + exception.getMessage(), exception);
212             }
213         }
214     }
215 
216     private Model createReleaseModel(
217             MavenProject project,
218             ReleaseDescriptor releaseDescriptor,
219             ReleaseEnvironment releaseEnvironment,
220             ReleaseResult result)
221             throws ReleaseFailureException, ReleaseExecutionException {
222         MavenProject releaseProject = project.clone();
223         Model releaseModel = releaseProject.getModel();
224 
225         // the release POM should reflect bits of these which were injected at build time...
226         // we don't need these polluting the POM.
227         releaseModel.setParent(null);
228         releaseModel.setProfiles(Collections.emptyList());
229         releaseModel.setDependencyManagement(null);
230         releaseProject.getBuild().setPluginManagement(null);
231 
232         // update project version
233         String releaseVersion = getNextVersion(releaseDescriptor, project.getGroupId(), project.getArtifactId());
234         releaseModel.setVersion(releaseVersion);
235 
236         String originalFinalName = releaseModel.getBuild().getFinalName();
237         // update final name if implicit
238         if (!FINALNAME_EXPRESSION.equals(originalFinalName)) {
239             originalFinalName = findOriginalFinalName(project);
240 
241             if (originalFinalName == null) {
242                 // as defined in super-pom
243                 originalFinalName = FINALNAME_EXPRESSION;
244             }
245         }
246 
247         // make finalName always explicit
248         String finalName = ReleaseUtil.interpolate(originalFinalName, releaseModel);
249 
250         // still required?
251         if (finalName.contains(Artifact.SNAPSHOT_VERSION)) {
252             throw new ReleaseFailureException(
253                     "Cannot reliably adjust the finalName of project: " + releaseProject.getId());
254         }
255         releaseModel.getBuild().setFinalName(finalName);
256 
257         // update scm
258         Scm scm = releaseModel.getScm();
259 
260         if (scm != null) {
261             ScmRepository scmRepository = getScmRepository(releaseDescriptor, releaseEnvironment);
262             ScmTranslator scmTranslator = getScmTranslator(scmRepository);
263 
264             if (scmTranslator != null) {
265                 releaseModel.setScm(createReleaseScm(releaseModel.getScm(), scmTranslator, releaseDescriptor));
266             } else {
267                 String message = "No SCM translator found - skipping rewrite";
268 
269                 result.appendDebug(message);
270 
271                 getLogger().debug(message);
272             }
273         }
274 
275         // rewrite dependencies
276         releaseModel.setDependencies(createReleaseDependencies(releaseDescriptor, releaseProject));
277 
278         // rewrite plugins
279         releaseModel.getBuild().setPlugins(createReleasePlugins(releaseDescriptor, releaseProject));
280 
281         // rewrite reports
282         releaseModel.getReporting().setPlugins(createReleaseReportPlugins(releaseDescriptor, releaseProject));
283 
284         // rewrite extensions
285         releaseModel.getBuild().setExtensions(createReleaseExtensions(releaseDescriptor, releaseProject));
286 
287         unalignFromBaseDirectory(releaseModel, project.getBasedir());
288 
289         return releaseModel;
290     }
291 
292     private void unalignFromBaseDirectory(Model releaseModel, File basedir) {
293         Model rawSuperModel = superPomProvider.getSuperModel(releaseModel.getModelVersion());
294 
295         ModelBuildingRequest buildingRequest = new DefaultModelBuildingRequest();
296         buildingRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_STRICT);
297 
298         // inject proper values used by project.build.finalName
299         Properties properties = new Properties();
300         properties.put("project.version", releaseModel.getVersion());
301         properties.put("project.artifactId", releaseModel.getArtifactId());
302         buildingRequest.setUserProperties(properties);
303 
304         Model interpolatedSuperModel =
305                 modelInterpolator.interpolateModel(rawSuperModel.clone(), basedir, buildingRequest, null);
306 
307         Build currentBuild = releaseModel.getBuild();
308         Build interpolatedSuperBuild = interpolatedSuperModel.getBuild();
309         Build rawSuperBuild = rawSuperModel.getBuild();
310 
311         currentBuild.setSourceDirectory(resolvePath(
312                 basedir.toPath(),
313                 currentBuild.getSourceDirectory(),
314                 interpolatedSuperBuild.getSourceDirectory(),
315                 rawSuperBuild.getSourceDirectory()));
316         currentBuild.setScriptSourceDirectory(resolvePath(
317                 basedir.toPath(),
318                 currentBuild.getScriptSourceDirectory(),
319                 interpolatedSuperBuild.getScriptSourceDirectory(),
320                 rawSuperBuild.getScriptSourceDirectory()));
321         currentBuild.setTestSourceDirectory(resolvePath(
322                 basedir.toPath(),
323                 currentBuild.getTestSourceDirectory(),
324                 interpolatedSuperBuild.getTestSourceDirectory(),
325                 rawSuperBuild.getTestSourceDirectory()));
326         currentBuild.setOutputDirectory(resolvePath(
327                 basedir.toPath(),
328                 currentBuild.getOutputDirectory(),
329                 interpolatedSuperBuild.getOutputDirectory(),
330                 rawSuperBuild.getOutputDirectory()));
331         currentBuild.setTestOutputDirectory(resolvePath(
332                 basedir.toPath(),
333                 currentBuild.getTestOutputDirectory(),
334                 interpolatedSuperBuild.getTestOutputDirectory(),
335                 rawSuperBuild.getTestOutputDirectory()));
336         currentBuild.setDirectory(resolvePath(
337                 basedir.toPath(),
338                 currentBuild.getDirectory(),
339                 interpolatedSuperBuild.getDirectory(),
340                 rawSuperBuild.getDirectory()));
341 
342         for (Resource currentResource : currentBuild.getResources()) {
343             Map<String, String> superResourceDirectories =
344                     new LinkedHashMap<>(interpolatedSuperBuild.getResources().size());
345             for (int i = 0; i < interpolatedSuperBuild.getResources().size(); i++) {
346                 superResourceDirectories.put(
347                         interpolatedSuperBuild.getResources().get(i).getDirectory(),
348                         rawSuperBuild.getResources().get(i).getDirectory());
349             }
350             currentResource.setDirectory(
351                     resolvePath(basedir.toPath(), currentResource.getDirectory(), superResourceDirectories));
352         }
353 
354         for (Resource currentResource : currentBuild.getTestResources()) {
355             Map<String, String> superResourceDirectories = new LinkedHashMap<>(
356                     interpolatedSuperBuild.getTestResources().size());
357             for (int i = 0; i < interpolatedSuperBuild.getTestResources().size(); i++) {
358                 superResourceDirectories.put(
359                         interpolatedSuperBuild.getTestResources().get(i).getDirectory(),
360                         rawSuperBuild.getTestResources().get(i).getDirectory());
361             }
362             currentResource.setDirectory(
363                     resolvePath(basedir.toPath(), currentResource.getDirectory(), superResourceDirectories));
364         }
365 
366         releaseModel
367                 .getReporting()
368                 .setOutputDirectory(resolvePath(
369                         basedir.toPath(),
370                         releaseModel.getReporting().getOutputDirectory(),
371                         interpolatedSuperModel.getReporting().getOutputDirectory(),
372                         rawSuperModel.getReporting().getOutputDirectory()));
373     }
374 
375     private String resolvePath(Path basedir, String current, String superInterpolated, String superRaw) {
376         return basedir.resolve(current).equals(basedir.resolve(superInterpolated)) ? superRaw : current;
377     }
378 
379     private String resolvePath(
380             Path basedir, String current, Map<String /* interpolated */, String /* raw */> superValues) {
381         for (Map.Entry<String, String> superValue : superValues.entrySet()) {
382             if (basedir.resolve(current).equals(basedir.resolve(superValue.getKey()))) {
383                 return superValue.getValue();
384             }
385         }
386         return current;
387     }
388 
389     private String findOriginalFinalName(MavenProject project) {
390         if (project.getOriginalModel().getBuild() != null
391                 && project.getOriginalModel().getBuild().getFinalName() != null) {
392             return project.getOriginalModel().getBuild().getFinalName();
393         } else if (project.hasParent()) {
394             return findOriginalFinalName(project.getParent());
395         } else {
396             return null;
397         }
398     }
399 
400     @Override
401     public ReleaseResult simulate(
402             ReleaseDescriptor releaseDescriptor,
403             ReleaseEnvironment releaseEnvironment,
404             List<MavenProject> reactorProjects)
405             throws ReleaseExecutionException, ReleaseFailureException {
406         return execute(releaseDescriptor, releaseEnvironment, reactorProjects, true);
407     }
408 
409     private String getNextVersion(ReleaseDescriptor releaseDescriptor, String groupId, String artifactId)
410             throws ReleaseFailureException {
411         // TODO: share with RewritePomsForReleasePhase.rewriteVersion
412 
413         String id = ArtifactUtils.versionlessKey(groupId, artifactId);
414 
415         String nextVersion = releaseDescriptor.getProjectReleaseVersion(id);
416 
417         if (nextVersion == null) {
418             throw new ReleaseFailureException("Version for '" + id + "' was not mapped");
419         }
420 
421         return nextVersion;
422     }
423 
424     private ScmTranslator getScmTranslator(ScmRepository scmRepository) {
425         return scmTranslators.get(scmRepository.getProvider());
426     }
427 
428     private Scm createReleaseScm(Scm scm, ScmTranslator scmTranslator, ReleaseDescriptor releaseDescriptor) {
429         // TODO: share with RewritePomsForReleasePhase.translateScm
430 
431         String tag = releaseDescriptor.getScmReleaseLabel();
432         String tagBase = releaseDescriptor.getScmTagBase();
433 
434         Scm releaseScm = new Scm();
435 
436         if (scm.getConnection() != null) {
437             String value = scmTranslator.translateTagUrl(scm.getConnection(), tag, tagBase);
438             releaseScm.setConnection(value);
439         }
440 
441         if (scm.getDeveloperConnection() != null) {
442             String value = scmTranslator.translateTagUrl(scm.getDeveloperConnection(), tag, tagBase);
443             releaseScm.setDeveloperConnection(value);
444         }
445 
446         if (scm.getUrl() != null) {
447             String value = scmTranslator.translateTagUrl(scm.getUrl(), tag, tagBase);
448             releaseScm.setUrl(value);
449         }
450 
451         if (scm.getTag() != null) {
452             String value = scmTranslator.resolveTag(scm.getTag());
453             releaseScm.setTag(value);
454         }
455 
456         return releaseScm;
457     }
458 
459     private List<Dependency> createReleaseDependencies(ReleaseDescriptor releaseDescriptor, MavenProject project)
460             throws ReleaseFailureException {
461         Set<Artifact> artifacts = project.getDependencyArtifacts();
462 
463         List<Dependency> releaseDependencies = null;
464 
465         if (artifacts != null) {
466             // make dependency order deterministic for tests (related to MNG-1412)
467             List<Artifact> orderedArtifacts = new ArrayList<>(artifacts);
468             Collections.sort(orderedArtifacts);
469 
470             releaseDependencies = new ArrayList<>();
471 
472             for (Artifact artifact : orderedArtifacts) {
473                 if (artifact.getVersion() == null) {
474                     artifact.setVersion(project.getArtifactMap()
475                             .get(ArtifactUtils.versionlessKey(artifact))
476                             .getVersion());
477                 }
478 
479                 Dependency releaseDependency = new Dependency();
480 
481                 releaseDependency.setGroupId(artifact.getGroupId());
482                 releaseDependency.setArtifactId(artifact.getArtifactId());
483 
484                 String version = getReleaseVersion(releaseDescriptor, artifact);
485 
486                 releaseDependency.setVersion(version);
487                 releaseDependency.setType(artifact.getType());
488                 releaseDependency.setScope(artifact.getScope());
489                 releaseDependency.setClassifier(artifact.getClassifier());
490 
491                 releaseDependencies.add(releaseDependency);
492             }
493         }
494 
495         return releaseDependencies;
496     }
497 
498     private String getReleaseVersion(ReleaseDescriptor releaseDescriptor, Artifact artifact)
499             throws ReleaseFailureException {
500         String key = ArtifactUtils.versionlessKey(artifact);
501 
502         String originalVersion = releaseDescriptor.getProjectOriginalVersion(key);
503         String mappedVersion = releaseDescriptor.getProjectReleaseVersion(key);
504 
505         String version = artifact.getVersion();
506 
507         if (version.equals(originalVersion)) {
508             if (mappedVersion != null) {
509                 version = mappedVersion;
510             } else {
511                 throw new ReleaseFailureException("Version '" + version + "' for '" + key + "' was not mapped");
512             }
513         } else {
514             if (!ArtifactUtils.isSnapshot(version)) {
515                 version = artifact.getBaseVersion();
516             }
517         }
518 
519         return version;
520     }
521 
522     private List<Plugin> createReleasePlugins(ReleaseDescriptor releaseDescriptor, MavenProject project)
523             throws ReleaseFailureException {
524         List<Plugin> releasePlugins = null;
525 
526         // Use original - don't want the lifecycle introduced ones
527         Build build = project.getOriginalModel().getBuild();
528 
529         if (build != null) {
530             List<Plugin> plugins = build.getPlugins();
531 
532             if (plugins != null) {
533                 Map<String, Artifact> artifactsById = project.getPluginArtifactMap();
534 
535                 releasePlugins = new ArrayList<>();
536 
537                 for (Plugin plugin : plugins) {
538                     String id = ArtifactUtils.versionlessKey(plugin.getGroupId(), plugin.getArtifactId());
539                     Artifact artifact = artifactsById.get(id);
540                     String version = getReleaseVersion(releaseDescriptor, artifact);
541 
542                     Plugin releasePlugin = new Plugin();
543                     releasePlugin.setGroupId(plugin.getGroupId());
544                     releasePlugin.setArtifactId(plugin.getArtifactId());
545                     releasePlugin.setVersion(version);
546                     if (plugin.getExtensions() != null) {
547                         releasePlugin.setExtensions(plugin.isExtensions());
548                     }
549                     releasePlugin.setExecutions(plugin.getExecutions());
550                     releasePlugin.setDependencies(plugin.getDependencies());
551                     releasePlugin.setInherited(plugin.getInherited());
552                     if (plugin.getConfiguration() != null) {
553                         releasePlugin.setConfiguration(plugin.getConfiguration());
554                     }
555 
556                     releasePlugins.add(releasePlugin);
557                 }
558             }
559         }
560 
561         return releasePlugins;
562     }
563 
564     private List<ReportPlugin> createReleaseReportPlugins(ReleaseDescriptor releaseDescriptor, MavenProject project)
565             throws ReleaseFailureException {
566         List<ReportPlugin> releaseReportPlugins = null;
567 
568         Reporting reporting = project.getModel().getReporting();
569 
570         if (reporting != null) {
571             List<ReportPlugin> reportPlugins = reporting.getPlugins();
572 
573             if (reportPlugins != null) {
574                 Map<String, Artifact> artifactsById = project.getReportArtifactMap();
575 
576                 releaseReportPlugins = new ArrayList<>();
577 
578                 for (ReportPlugin reportPlugin : reportPlugins) {
579                     String id = ArtifactUtils.versionlessKey(reportPlugin.getGroupId(), reportPlugin.getArtifactId());
580                     Artifact artifact = artifactsById.get(id);
581                     String version = getReleaseVersion(releaseDescriptor, artifact);
582 
583                     ReportPlugin releaseReportPlugin = new ReportPlugin();
584                     releaseReportPlugin.setGroupId(reportPlugin.getGroupId());
585                     releaseReportPlugin.setArtifactId(reportPlugin.getArtifactId());
586                     releaseReportPlugin.setVersion(version);
587                     releaseReportPlugin.setInherited(reportPlugin.getInherited());
588                     releaseReportPlugin.setConfiguration(reportPlugin.getConfiguration());
589                     releaseReportPlugin.setReportSets(reportPlugin.getReportSets());
590 
591                     releaseReportPlugins.add(releaseReportPlugin);
592                 }
593             }
594         }
595 
596         return releaseReportPlugins;
597     }
598 
599     private List<Extension> createReleaseExtensions(ReleaseDescriptor releaseDescriptor, MavenProject project)
600             throws ReleaseFailureException {
601         List<Extension> releaseExtensions = null;
602 
603         // Use original - don't want the lifecycle introduced ones
604         Build build = project.getOriginalModel().getBuild();
605 
606         if (build != null) {
607             List<Extension> extensions = build.getExtensions();
608 
609             if (extensions != null) {
610                 releaseExtensions = new ArrayList<>();
611 
612                 for (Extension extension : extensions) {
613                     String id = ArtifactUtils.versionlessKey(extension.getGroupId(), extension.getArtifactId());
614                     Artifact artifact = project.getExtensionArtifactMap().get(id);
615                     String version = getReleaseVersion(releaseDescriptor, artifact);
616 
617                     Extension releaseExtension = new Extension();
618                     releaseExtension.setGroupId(extension.getGroupId());
619                     releaseExtension.setArtifactId(extension.getArtifactId());
620                     releaseExtension.setVersion(version);
621 
622                     releaseExtensions.add(releaseExtension);
623                 }
624             }
625         }
626 
627         return releaseExtensions;
628     }
629 
630     /*
631      * @see org.apache.maven.shared.release.phase.AbstractReleasePhase#clean(java.util.List)
632      */
633     @Override
634     public ReleaseResult clean(List<MavenProject> reactorProjects) {
635         ReleaseResult result = new ReleaseResult();
636 
637         for (MavenProject project : reactorProjects) {
638             File releasePom = ReleaseUtil.getReleasePom(project);
639 
640             // MRELEASE-273 : A release pom can be null
641             if (releasePom != null && releasePom.exists()) {
642                 logInfo(result, "Deleting release POM for '" + project.getName() + "'...");
643 
644                 if (!releasePom.delete()) {
645                     logWarn(result, "Cannot delete release POM: " + releasePom);
646                 }
647             }
648         }
649 
650         result.setResultCode(ReleaseResult.SUCCESS);
651 
652         return result;
653     }
654 }