1 package org.apache.maven.shared.release.phase;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.Writer;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30
31 import org.apache.maven.artifact.Artifact;
32 import org.apache.maven.artifact.ArtifactUtils;
33 import org.apache.maven.model.Build;
34 import org.apache.maven.model.Dependency;
35 import org.apache.maven.model.Extension;
36 import org.apache.maven.model.Model;
37 import org.apache.maven.model.Plugin;
38 import org.apache.maven.model.Profile;
39 import org.apache.maven.model.ReportPlugin;
40 import org.apache.maven.model.Reporting;
41 import org.apache.maven.model.Scm;
42 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
43 import org.apache.maven.project.MavenProject;
44 import org.apache.maven.project.path.PathTranslator;
45 import org.apache.maven.scm.ScmException;
46 import org.apache.maven.scm.ScmFileSet;
47 import org.apache.maven.scm.command.add.AddScmResult;
48 import org.apache.maven.scm.provider.ScmProvider;
49 import org.apache.maven.scm.repository.ScmRepository;
50 import org.apache.maven.shared.release.ReleaseExecutionException;
51 import org.apache.maven.shared.release.ReleaseFailureException;
52 import org.apache.maven.shared.release.ReleaseResult;
53 import org.apache.maven.shared.release.config.ReleaseDescriptor;
54 import org.apache.maven.shared.release.env.ReleaseEnvironment;
55 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
56 import org.apache.maven.shared.release.scm.ScmTranslator;
57 import org.apache.maven.shared.release.util.ReleaseUtil;
58 import org.codehaus.plexus.util.IOUtil;
59 import org.codehaus.plexus.util.WriterFactory;
60
61
62
63
64
65
66
67
68 public class GenerateReleasePomsPhase
69 extends AbstractReleasePomsPhase
70 {
71 private static final String FINALNAME_EXPRESSION = "${project.artifactId}-${project.version}";
72
73
74
75
76
77
78 private PathTranslator pathTranslator;
79
80
81
82
83
84
85 private Map<String, ScmTranslator> scmTranslators;
86
87
88
89
90
91 public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
92 List<MavenProject> reactorProjects )
93 throws ReleaseExecutionException, ReleaseFailureException
94 {
95 return execute( releaseDescriptor, releaseEnvironment, reactorProjects, false );
96 }
97
98 private ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
99 List<MavenProject> reactorProjects, boolean simulate )
100 throws ReleaseExecutionException, ReleaseFailureException
101 {
102 ReleaseResult result = new ReleaseResult();
103
104 if ( releaseDescriptor.isGenerateReleasePoms() )
105 {
106 logInfo( result, "Generating release POMs..." );
107
108 generateReleasePoms( releaseDescriptor, releaseEnvironment, reactorProjects, simulate, result );
109 }
110 else
111 {
112 logInfo( result, "Not generating release POMs" );
113 }
114
115 result.setResultCode( ReleaseResult.SUCCESS );
116
117 return result;
118 }
119
120 private void generateReleasePoms( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
121 List<MavenProject> reactorProjects, boolean simulate, ReleaseResult result )
122 throws ReleaseExecutionException, ReleaseFailureException
123 {
124 List<File> releasePoms = new ArrayList<File>();
125
126 for ( MavenProject project : reactorProjects )
127 {
128 logInfo( result, "Generating release POM for '" + project.getName() + "'..." );
129
130 releasePoms.add( generateReleasePom( project, releaseDescriptor, releaseEnvironment, reactorProjects,
131 simulate, result ) );
132 }
133
134 addReleasePomsToScm( releaseDescriptor, releaseEnvironment, reactorProjects, simulate, result, releasePoms );
135 }
136
137 private File generateReleasePom( MavenProject project, ReleaseDescriptor releaseDescriptor,
138 ReleaseEnvironment releaseEnvironment, List<MavenProject> reactorProjects,
139 boolean simulate, ReleaseResult result )
140 throws ReleaseExecutionException, ReleaseFailureException
141 {
142
143
144 Model releasePom = createReleaseModel( project, releaseDescriptor, releaseEnvironment, reactorProjects, result );
145
146
147
148 MavenXpp3Writer pomWriter = new MavenXpp3Writer();
149
150 File releasePomFile = ReleaseUtil.getReleasePom( project );
151
152
153 if ( releasePomFile == null )
154 {
155 throw new ReleaseExecutionException( "Cannot generate release POM : pom file is null" );
156 }
157
158 Writer fileWriter = null;
159
160 try
161 {
162 fileWriter = WriterFactory.newXmlWriter( releasePomFile );
163
164 pomWriter.write( fileWriter, releasePom );
165 }
166 catch ( IOException exception )
167 {
168 throw new ReleaseExecutionException( "Cannot generate release POM", exception );
169 }
170 finally
171 {
172 IOUtil.close( fileWriter );
173 }
174
175 return releasePomFile;
176 }
177
178 private void addReleasePomsToScm( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
179 List<MavenProject> reactorProjects, boolean simulate, ReleaseResult result,
180 List<File> releasePoms )
181 throws ReleaseFailureException, ReleaseExecutionException
182 {
183 if ( simulate )
184 {
185 logInfo( result, "Full run would be adding " + releasePoms );
186 }
187 else
188 {
189 ScmRepository scmRepository = getScmRepository( releaseDescriptor, releaseEnvironment );
190 ScmProvider scmProvider = getScmProvider( scmRepository );
191
192 MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
193 ScmFileSet scmFileSet = new ScmFileSet( rootProject.getFile().getParentFile(), releasePoms );
194
195 try
196 {
197 AddScmResult scmResult = scmProvider.add( scmRepository, scmFileSet );
198
199 if ( !scmResult.isSuccess() )
200 {
201 throw new ReleaseScmCommandException( "Cannot add release POM to SCM", scmResult );
202 }
203 }
204 catch ( ScmException exception )
205 {
206 throw new ReleaseExecutionException( "Cannot add release POM to SCM: " + exception.getMessage(),
207 exception );
208 }
209 }
210 }
211
212 private Model createReleaseModel( MavenProject project, ReleaseDescriptor releaseDescriptor,
213 ReleaseEnvironment releaseEnvironment, List<MavenProject> reactorProjects,
214 ReleaseResult result )
215 throws ReleaseFailureException, ReleaseExecutionException
216 {
217 Map<String, String> originalVersions = getOriginalVersionMap( releaseDescriptor, reactorProjects );
218 Map<String, String> mappedVersions = getNextVersionMap( releaseDescriptor );
219
220 MavenProject releaseProject = new MavenProject( project );
221 Model releaseModel = releaseProject.getModel();
222
223
224
225 releaseModel.setParent( null );
226 releaseModel.setProfiles( Collections.<Profile>emptyList() );
227 releaseModel.setDependencyManagement( null );
228 releaseProject.getBuild().setPluginManagement( null );
229
230
231 String projectVersion = releaseModel.getVersion();
232 String releaseVersion =
233 getNextVersion( mappedVersions, project.getGroupId(), project.getArtifactId(), projectVersion );
234 releaseModel.setVersion( releaseVersion );
235
236
237 if ( !FINALNAME_EXPRESSION.equals( releaseModel.getBuild().getFinalName() ) )
238 {
239 String originalFinalName = findOriginalFinalName( project );
240
241 if ( originalFinalName == null )
242 {
243
244 originalFinalName = FINALNAME_EXPRESSION;
245 }
246 String finalName = ReleaseUtil.interpolate( originalFinalName, releaseModel );
247
248
249 if ( finalName.indexOf( Artifact.SNAPSHOT_VERSION ) != -1 )
250 {
251 throw new ReleaseFailureException( "Cannot reliably adjust the finalName of project: "
252 + releaseProject.getId() );
253 }
254
255 releaseModel.getBuild().setFinalName( finalName );
256 }
257
258
259 Scm scm = releaseModel.getScm();
260
261 if ( scm != null )
262 {
263 ScmRepository scmRepository = getScmRepository( releaseDescriptor, releaseEnvironment );
264 ScmTranslator scmTranslator = getScmTranslator( scmRepository );
265
266 if ( scmTranslator != null )
267 {
268 releaseModel.setScm( createReleaseScm( releaseModel.getScm(), scmTranslator, releaseDescriptor ) );
269 }
270 else
271 {
272 String message = "No SCM translator found - skipping rewrite";
273
274 result.appendDebug( message );
275
276 getLogger().debug( message );
277 }
278 }
279
280
281 releaseModel.setDependencies( createReleaseDependencies( originalVersions, mappedVersions, releaseProject ) );
282
283
284 releaseModel.getBuild().setPlugins( createReleasePlugins( originalVersions, mappedVersions, releaseProject ) );
285
286
287 releaseModel.getReporting().setPlugins( createReleaseReportPlugins( originalVersions, mappedVersions,
288 releaseProject ) );
289
290
291 releaseModel.getBuild().setExtensions( createReleaseExtensions( originalVersions, mappedVersions,
292 releaseProject ) );
293
294 pathTranslator.unalignFromBaseDirectory( releaseProject.getModel(), project.getFile().getParentFile() );
295
296 return releaseModel;
297 }
298
299 private String findOriginalFinalName( MavenProject project )
300 {
301 if ( project.getOriginalModel().getBuild() != null
302 && project.getOriginalModel().getBuild().getFinalName() != null )
303 {
304 return project.getOriginalModel().getBuild().getFinalName();
305 }
306 else if ( project.hasParent() )
307 {
308 return findOriginalFinalName( project.getParent() );
309 }
310 else
311 {
312 return null;
313 }
314 }
315
316 public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
317 List<MavenProject> reactorProjects )
318 throws ReleaseExecutionException, ReleaseFailureException
319 {
320 return execute( releaseDescriptor, releaseEnvironment, reactorProjects, true );
321 }
322
323 protected Map<String, String> getOriginalVersionMap( ReleaseDescriptor releaseDescriptor,
324 List<MavenProject> reactorProjects )
325 {
326 return releaseDescriptor.getOriginalVersions( reactorProjects );
327 }
328
329 @SuppressWarnings( "unchecked" )
330 protected Map<String, String> getNextVersionMap( ReleaseDescriptor releaseDescriptor )
331 {
332 return releaseDescriptor.getReleaseVersions();
333 }
334
335 private String getNextVersion( Map<String, String> mappedVersions, String groupId, String artifactId, String version )
336 throws ReleaseFailureException
337 {
338
339
340 String id = ArtifactUtils.versionlessKey( groupId, artifactId );
341
342 String nextVersion = mappedVersions.get( id );
343
344 if ( nextVersion == null )
345 {
346 throw new ReleaseFailureException( "Version for '" + id + "' was not mapped" );
347 }
348
349 return nextVersion;
350 }
351
352 private ScmTranslator getScmTranslator( ScmRepository scmRepository )
353 {
354 return scmTranslators.get( scmRepository.getProvider() );
355 }
356
357 private Scm createReleaseScm( Scm scm, ScmTranslator scmTranslator, ReleaseDescriptor releaseDescriptor )
358 {
359
360
361 String tag = releaseDescriptor.getScmReleaseLabel();
362 String tagBase = releaseDescriptor.getScmTagBase();
363
364 Scm releaseScm = new Scm();
365
366 if ( scm.getConnection() != null )
367 {
368 String value = scmTranslator.translateTagUrl( scm.getConnection(), tag, tagBase );
369 releaseScm.setConnection( value );
370 }
371
372 if ( scm.getDeveloperConnection() != null )
373 {
374 String value = scmTranslator.translateTagUrl( scm.getDeveloperConnection(), tag, tagBase );
375 releaseScm.setDeveloperConnection( value );
376 }
377
378 if ( scm.getUrl() != null )
379 {
380 String value = scmTranslator.translateTagUrl( scm.getUrl(), tag, tagBase );
381 releaseScm.setUrl( value );
382 }
383
384 if ( scm.getTag() != null )
385 {
386 String value = scmTranslator.resolveTag( scm.getTag() );
387 releaseScm.setTag( value );
388 }
389
390 return releaseScm;
391 }
392
393 private List<Dependency> createReleaseDependencies( Map<String, String> originalVersions,
394 Map<String, String> mappedVersions, MavenProject project )
395 throws ReleaseFailureException
396 {
397 @SuppressWarnings( "unchecked" )
398 Set<Artifact> artifacts = project.getArtifacts();
399
400 List<Dependency> releaseDependencies = null;
401
402 if ( artifacts != null )
403 {
404
405 List<Artifact> orderedArtifacts = new ArrayList<Artifact>();
406 orderedArtifacts.addAll( artifacts );
407 Collections.sort( orderedArtifacts );
408
409 releaseDependencies = new ArrayList<Dependency>();
410
411 for ( Artifact artifact : orderedArtifacts )
412 {
413 Dependency releaseDependency = new Dependency();
414
415 releaseDependency.setGroupId( artifact.getGroupId() );
416 releaseDependency.setArtifactId( artifact.getArtifactId() );
417
418 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
419
420 releaseDependency.setVersion( version );
421 releaseDependency.setType( artifact.getType() );
422 releaseDependency.setScope( artifact.getScope() );
423 releaseDependency.setClassifier( artifact.getClassifier() );
424
425 releaseDependencies.add( releaseDependency );
426 }
427 }
428
429 return releaseDependencies;
430 }
431
432 private String getReleaseVersion( Map<String, String> originalVersions, Map<String, String> mappedVersions, Artifact artifact )
433 throws ReleaseFailureException
434 {
435 String key = ArtifactUtils.versionlessKey( artifact );
436
437 String originalVersion = originalVersions.get( key );
438 String mappedVersion = mappedVersions.get( key );
439
440 String version = artifact.getVersion();
441
442 if ( version.equals( originalVersion ) )
443 {
444 if ( mappedVersion != null )
445 {
446 version = mappedVersion;
447 }
448 else
449 {
450 throw new ReleaseFailureException( "Version '" + version + "' for '" + key + "' was not mapped" );
451 }
452 }
453 else
454 {
455 if ( !ArtifactUtils.isSnapshot( version ) )
456 {
457 version = artifact.getBaseVersion();
458 }
459 }
460
461 return version;
462 }
463
464 private List<Plugin> createReleasePlugins( Map<String, String> originalVersions, Map<String, String> mappedVersions, MavenProject project )
465 throws ReleaseFailureException
466 {
467 List<Plugin> releasePlugins = null;
468
469
470 Build build = project.getOriginalModel().getBuild();
471
472 if ( build != null )
473 {
474 List<Plugin> plugins = build.getPlugins();
475
476 if ( plugins != null )
477 {
478 @SuppressWarnings( "unchecked" )
479 Map<String, Artifact> artifactsById = project.getPluginArtifactMap();
480
481 releasePlugins = new ArrayList<Plugin>();
482
483 for ( Plugin plugin : plugins )
484 {
485 String id = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
486 Artifact artifact = artifactsById.get( id );
487 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
488
489 Plugin releasePlugin = new Plugin();
490 releasePlugin.setGroupId( plugin.getGroupId() );
491 releasePlugin.setArtifactId( plugin.getArtifactId() );
492 releasePlugin.setVersion( version );
493 releasePlugin.setExtensions( plugin.isExtensions() );
494 releasePlugin.setExecutions( plugin.getExecutions() );
495 releasePlugin.setDependencies( plugin.getDependencies() );
496 releasePlugin.setGoals( plugin.getGoals() );
497 releasePlugin.setInherited( plugin.getInherited() );
498 releasePlugin.setConfiguration( plugin.getConfiguration() );
499
500 releasePlugins.add( releasePlugin );
501 }
502 }
503 }
504
505 return releasePlugins;
506 }
507
508 private List<ReportPlugin> createReleaseReportPlugins( Map<String, String> originalVersions, Map<String, String> mappedVersions,
509 MavenProject project )
510 throws ReleaseFailureException
511 {
512 List<ReportPlugin> releaseReportPlugins = null;
513
514 Reporting reporting = project.getModel().getReporting();
515
516 if ( reporting != null )
517 {
518 List<ReportPlugin> reportPlugins = reporting.getPlugins();
519
520 if ( reportPlugins != null )
521 {
522 @SuppressWarnings( "unchecked" )
523 Map<String, Artifact> artifactsById = project.getReportArtifactMap();
524
525 releaseReportPlugins = new ArrayList<ReportPlugin>();
526
527 for ( ReportPlugin reportPlugin : reportPlugins )
528 {
529 String id = ArtifactUtils.versionlessKey( reportPlugin.getGroupId(), reportPlugin.getArtifactId() );
530 Artifact artifact = artifactsById.get( id );
531 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
532
533 ReportPlugin releaseReportPlugin = new ReportPlugin();
534 releaseReportPlugin.setGroupId( reportPlugin.getGroupId() );
535 releaseReportPlugin.setArtifactId( reportPlugin.getArtifactId() );
536 releaseReportPlugin.setVersion( version );
537 releaseReportPlugin.setInherited( reportPlugin.getInherited() );
538 releaseReportPlugin.setConfiguration( reportPlugin.getConfiguration() );
539 releaseReportPlugin.setReportSets( reportPlugin.getReportSets() );
540
541 releaseReportPlugins.add( releaseReportPlugin );
542 }
543 }
544 }
545
546 return releaseReportPlugins;
547 }
548
549 private List<Extension> createReleaseExtensions( Map<String, String> originalVersions, Map<String, String> mappedVersions, MavenProject project )
550 throws ReleaseFailureException
551 {
552 List<Extension> releaseExtensions = null;
553
554
555 Build build = project.getOriginalModel().getBuild();
556
557 if ( build != null )
558 {
559 List<Extension> extensions = build.getExtensions();
560
561 if ( extensions != null )
562 {
563 releaseExtensions = new ArrayList<Extension>();
564
565 for ( Extension extension : extensions )
566 {
567 String id = ArtifactUtils.versionlessKey( extension.getGroupId(), extension.getArtifactId() );
568 Artifact artifact = (Artifact) project.getExtensionArtifactMap().get( id );
569 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
570
571 Extension releaseExtension = new Extension();
572 releaseExtension.setGroupId( extension.getGroupId() );
573 releaseExtension.setArtifactId( extension.getArtifactId() );
574 releaseExtension.setVersion( version );
575
576 releaseExtensions.add( releaseExtension );
577 }
578 }
579 }
580
581 return releaseExtensions;
582 }
583
584
585
586
587 public ReleaseResult clean( List<MavenProject> reactorProjects )
588 {
589 ReleaseResult result = new ReleaseResult();
590
591 for ( MavenProject project : reactorProjects )
592 {
593 File releasePom = ReleaseUtil.getReleasePom( project );
594
595
596 if ( releasePom != null && releasePom.exists() )
597 {
598 logInfo( result, "Deleting release POM for '" + project.getName() + "'..." );
599
600 if ( !releasePom.delete() )
601 {
602 logWarn( result, "Cannot delete release POM: " + releasePom );
603 }
604 }
605 }
606
607 result.setResultCode( ReleaseResult.SUCCESS );
608
609 return result;
610 }
611 }