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,
145 result );
146
147
148
149 MavenXpp3Writer pomWriter = new MavenXpp3Writer();
150
151 File releasePomFile = ReleaseUtil.getReleasePom( project );
152
153
154 if ( releasePomFile == null )
155 {
156 throw new ReleaseExecutionException( "Cannot generate release POM : pom file is null" );
157 }
158
159 Writer fileWriter = null;
160
161 try
162 {
163 fileWriter = WriterFactory.newXmlWriter( releasePomFile );
164
165 pomWriter.write( fileWriter, releasePom );
166 }
167 catch ( IOException exception )
168 {
169 throw new ReleaseExecutionException( "Cannot generate release POM", exception );
170 }
171 finally
172 {
173 IOUtil.close( fileWriter );
174 }
175
176 return releasePomFile;
177 }
178
179 private void addReleasePomsToScm( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
180 List<MavenProject> reactorProjects, boolean simulate, ReleaseResult result,
181 List<File> releasePoms )
182 throws ReleaseFailureException, ReleaseExecutionException
183 {
184 if ( simulate )
185 {
186 logInfo( result, "Full run would be adding " + releasePoms );
187 }
188 else
189 {
190 ScmRepository scmRepository = getScmRepository( releaseDescriptor, releaseEnvironment );
191 ScmProvider scmProvider = getScmProvider( scmRepository );
192
193 MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
194 ScmFileSet scmFileSet = new ScmFileSet( rootProject.getFile().getParentFile(), releasePoms );
195
196 try
197 {
198 AddScmResult scmResult = scmProvider.add( scmRepository, scmFileSet );
199
200 if ( !scmResult.isSuccess() )
201 {
202 throw new ReleaseScmCommandException( "Cannot add release POM to SCM", scmResult );
203 }
204 }
205 catch ( ScmException exception )
206 {
207 throw new ReleaseExecutionException( "Cannot add release POM to SCM: " + exception.getMessage(),
208 exception );
209 }
210 }
211 }
212
213 private Model createReleaseModel( MavenProject project, ReleaseDescriptor releaseDescriptor,
214 ReleaseEnvironment releaseEnvironment, List<MavenProject> reactorProjects,
215 ReleaseResult result )
216 throws ReleaseFailureException, ReleaseExecutionException
217 {
218 Map<String, String> originalVersions = getOriginalVersionMap( releaseDescriptor, reactorProjects );
219 Map<String, String> mappedVersions = getNextVersionMap( releaseDescriptor );
220
221 MavenProject releaseProject = new MavenProject( project );
222 Model releaseModel = releaseProject.getModel();
223
224
225
226 releaseModel.setParent( null );
227 releaseModel.setProfiles( Collections.<Profile>emptyList() );
228 releaseModel.setDependencyManagement( null );
229 releaseProject.getBuild().setPluginManagement( null );
230
231
232 String projectVersion = releaseModel.getVersion();
233 String releaseVersion =
234 getNextVersion( mappedVersions, project.getGroupId(), project.getArtifactId(), projectVersion );
235 releaseModel.setVersion( releaseVersion );
236
237
238 if ( !FINALNAME_EXPRESSION.equals( releaseModel.getBuild().getFinalName() ) )
239 {
240 String originalFinalName = findOriginalFinalName( project );
241
242 if ( originalFinalName == null )
243 {
244
245 originalFinalName = FINALNAME_EXPRESSION;
246 }
247 String finalName = ReleaseUtil.interpolate( originalFinalName, releaseModel );
248
249
250 if ( finalName.indexOf( Artifact.SNAPSHOT_VERSION ) != -1 )
251 {
252 throw new ReleaseFailureException( "Cannot reliably adjust the finalName of project: "
253 + releaseProject.getId() );
254 }
255
256 releaseModel.getBuild().setFinalName( finalName );
257 }
258
259
260 Scm scm = releaseModel.getScm();
261
262 if ( scm != null )
263 {
264 ScmRepository scmRepository = getScmRepository( releaseDescriptor, releaseEnvironment );
265 ScmTranslator scmTranslator = getScmTranslator( scmRepository );
266
267 if ( scmTranslator != null )
268 {
269 releaseModel.setScm( createReleaseScm( releaseModel.getScm(), scmTranslator, releaseDescriptor ) );
270 }
271 else
272 {
273 String message = "No SCM translator found - skipping rewrite";
274
275 result.appendDebug( message );
276
277 getLogger().debug( message );
278 }
279 }
280
281
282 releaseModel.setDependencies( createReleaseDependencies( originalVersions, mappedVersions, releaseProject ) );
283
284
285 releaseModel.getBuild().setPlugins( createReleasePlugins( originalVersions, mappedVersions, releaseProject ) );
286
287
288 releaseModel.getReporting().setPlugins( createReleaseReportPlugins( originalVersions, mappedVersions,
289 releaseProject ) );
290
291
292 releaseModel.getBuild().setExtensions( createReleaseExtensions( originalVersions, mappedVersions,
293 releaseProject ) );
294
295 pathTranslator.unalignFromBaseDirectory( releaseProject.getModel(), project.getFile().getParentFile() );
296
297 return releaseModel;
298 }
299
300 private String findOriginalFinalName( MavenProject project )
301 {
302 if ( project.getOriginalModel().getBuild() != null
303 && project.getOriginalModel().getBuild().getFinalName() != null )
304 {
305 return project.getOriginalModel().getBuild().getFinalName();
306 }
307 else if ( project.hasParent() )
308 {
309 return findOriginalFinalName( project.getParent() );
310 }
311 else
312 {
313 return null;
314 }
315 }
316
317 public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
318 List<MavenProject> reactorProjects )
319 throws ReleaseExecutionException, ReleaseFailureException
320 {
321 return execute( releaseDescriptor, releaseEnvironment, reactorProjects, true );
322 }
323
324 protected Map<String, String> getOriginalVersionMap( ReleaseDescriptor releaseDescriptor,
325 List<MavenProject> reactorProjects )
326 {
327 return releaseDescriptor.getOriginalVersions( reactorProjects );
328 }
329
330 @SuppressWarnings( "unchecked" )
331 protected Map<String, String> getNextVersionMap( ReleaseDescriptor releaseDescriptor )
332 {
333 return releaseDescriptor.getReleaseVersions();
334 }
335
336 private String getNextVersion( Map<String, String> mappedVersions, String groupId, String artifactId,
337 String version )
338 throws ReleaseFailureException
339 {
340
341
342 String id = ArtifactUtils.versionlessKey( groupId, artifactId );
343
344 String nextVersion = mappedVersions.get( id );
345
346 if ( nextVersion == null )
347 {
348 throw new ReleaseFailureException( "Version for '" + id + "' was not mapped" );
349 }
350
351 return nextVersion;
352 }
353
354 private ScmTranslator getScmTranslator( ScmRepository scmRepository )
355 {
356 return scmTranslators.get( scmRepository.getProvider() );
357 }
358
359 private Scm createReleaseScm( Scm scm, ScmTranslator scmTranslator, ReleaseDescriptor releaseDescriptor )
360 {
361
362
363 String tag = releaseDescriptor.getScmReleaseLabel();
364 String tagBase = releaseDescriptor.getScmTagBase();
365
366 Scm releaseScm = new Scm();
367
368 if ( scm.getConnection() != null )
369 {
370 String value = scmTranslator.translateTagUrl( scm.getConnection(), tag, tagBase );
371 releaseScm.setConnection( value );
372 }
373
374 if ( scm.getDeveloperConnection() != null )
375 {
376 String value = scmTranslator.translateTagUrl( scm.getDeveloperConnection(), tag, tagBase );
377 releaseScm.setDeveloperConnection( value );
378 }
379
380 if ( scm.getUrl() != null )
381 {
382 String value = scmTranslator.translateTagUrl( scm.getUrl(), tag, tagBase );
383 releaseScm.setUrl( value );
384 }
385
386 if ( scm.getTag() != null )
387 {
388 String value = scmTranslator.resolveTag( scm.getTag() );
389 releaseScm.setTag( value );
390 }
391
392 return releaseScm;
393 }
394
395 private List<Dependency> createReleaseDependencies( Map<String, String> originalVersions,
396 Map<String, String> mappedVersions, MavenProject project )
397 throws ReleaseFailureException
398 {
399 @SuppressWarnings( "unchecked" )
400 Set<Artifact> artifacts = project.getArtifacts();
401
402 List<Dependency> releaseDependencies = null;
403
404 if ( artifacts != null )
405 {
406
407 List<Artifact> orderedArtifacts = new ArrayList<Artifact>();
408 orderedArtifacts.addAll( artifacts );
409 Collections.sort( orderedArtifacts );
410
411 releaseDependencies = new ArrayList<Dependency>();
412
413 for ( Artifact artifact : orderedArtifacts )
414 {
415 Dependency releaseDependency = new Dependency();
416
417 releaseDependency.setGroupId( artifact.getGroupId() );
418 releaseDependency.setArtifactId( artifact.getArtifactId() );
419
420 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
421
422 releaseDependency.setVersion( version );
423 releaseDependency.setType( artifact.getType() );
424 releaseDependency.setScope( artifact.getScope() );
425 releaseDependency.setClassifier( artifact.getClassifier() );
426
427 releaseDependencies.add( releaseDependency );
428 }
429 }
430
431 return releaseDependencies;
432 }
433
434 private String getReleaseVersion( Map<String, String> originalVersions, Map<String, String> mappedVersions,
435 Artifact artifact )
436 throws ReleaseFailureException
437 {
438 String key = ArtifactUtils.versionlessKey( artifact );
439
440 String originalVersion = originalVersions.get( key );
441 String mappedVersion = mappedVersions.get( key );
442
443 String version = artifact.getVersion();
444
445 if ( version.equals( originalVersion ) )
446 {
447 if ( mappedVersion != null )
448 {
449 version = mappedVersion;
450 }
451 else
452 {
453 throw new ReleaseFailureException( "Version '" + version + "' for '" + key + "' was not mapped" );
454 }
455 }
456 else
457 {
458 if ( !ArtifactUtils.isSnapshot( version ) )
459 {
460 version = artifact.getBaseVersion();
461 }
462 }
463
464 return version;
465 }
466
467 private List<Plugin> createReleasePlugins( Map<String, String> originalVersions,
468 Map<String, String> mappedVersions, MavenProject project )
469 throws ReleaseFailureException
470 {
471 List<Plugin> releasePlugins = null;
472
473
474 Build build = project.getOriginalModel().getBuild();
475
476 if ( build != null )
477 {
478 List<Plugin> plugins = build.getPlugins();
479
480 if ( plugins != null )
481 {
482 @SuppressWarnings( "unchecked" )
483 Map<String, Artifact> artifactsById = project.getPluginArtifactMap();
484
485 releasePlugins = new ArrayList<Plugin>();
486
487 for ( Plugin plugin : plugins )
488 {
489 String id = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
490 Artifact artifact = artifactsById.get( id );
491 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
492
493 Plugin releasePlugin = new Plugin();
494 releasePlugin.setGroupId( plugin.getGroupId() );
495 releasePlugin.setArtifactId( plugin.getArtifactId() );
496 releasePlugin.setVersion( version );
497 releasePlugin.setExtensions( plugin.isExtensions() );
498 releasePlugin.setExecutions( plugin.getExecutions() );
499 releasePlugin.setDependencies( plugin.getDependencies() );
500 releasePlugin.setGoals( plugin.getGoals() );
501 releasePlugin.setInherited( plugin.getInherited() );
502 releasePlugin.setConfiguration( plugin.getConfiguration() );
503
504 releasePlugins.add( releasePlugin );
505 }
506 }
507 }
508
509 return releasePlugins;
510 }
511
512 private List<ReportPlugin> createReleaseReportPlugins( Map<String, String> originalVersions,
513 Map<String, String> mappedVersions, MavenProject project )
514 throws ReleaseFailureException
515 {
516 List<ReportPlugin> releaseReportPlugins = null;
517
518 Reporting reporting = project.getModel().getReporting();
519
520 if ( reporting != null )
521 {
522 List<ReportPlugin> reportPlugins = reporting.getPlugins();
523
524 if ( reportPlugins != null )
525 {
526 @SuppressWarnings( "unchecked" )
527 Map<String, Artifact> artifactsById = project.getReportArtifactMap();
528
529 releaseReportPlugins = new ArrayList<ReportPlugin>();
530
531 for ( ReportPlugin reportPlugin : reportPlugins )
532 {
533 String id = ArtifactUtils.versionlessKey( reportPlugin.getGroupId(), reportPlugin.getArtifactId() );
534 Artifact artifact = artifactsById.get( id );
535 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
536
537 ReportPlugin releaseReportPlugin = new ReportPlugin();
538 releaseReportPlugin.setGroupId( reportPlugin.getGroupId() );
539 releaseReportPlugin.setArtifactId( reportPlugin.getArtifactId() );
540 releaseReportPlugin.setVersion( version );
541 releaseReportPlugin.setInherited( reportPlugin.getInherited() );
542 releaseReportPlugin.setConfiguration( reportPlugin.getConfiguration() );
543 releaseReportPlugin.setReportSets( reportPlugin.getReportSets() );
544
545 releaseReportPlugins.add( releaseReportPlugin );
546 }
547 }
548 }
549
550 return releaseReportPlugins;
551 }
552
553 private List<Extension> createReleaseExtensions( Map<String, String> originalVersions,
554 Map<String, String> mappedVersions, MavenProject project )
555 throws ReleaseFailureException
556 {
557 List<Extension> releaseExtensions = null;
558
559
560 Build build = project.getOriginalModel().getBuild();
561
562 if ( build != null )
563 {
564 List<Extension> extensions = build.getExtensions();
565
566 if ( extensions != null )
567 {
568 releaseExtensions = new ArrayList<Extension>();
569
570 for ( Extension extension : extensions )
571 {
572 String id = ArtifactUtils.versionlessKey( extension.getGroupId(), extension.getArtifactId() );
573 Artifact artifact = (Artifact) project.getExtensionArtifactMap().get( id );
574 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
575
576 Extension releaseExtension = new Extension();
577 releaseExtension.setGroupId( extension.getGroupId() );
578 releaseExtension.setArtifactId( extension.getArtifactId() );
579 releaseExtension.setVersion( version );
580
581 releaseExtensions.add( releaseExtension );
582 }
583 }
584 }
585
586 return releaseExtensions;
587 }
588
589
590
591
592 public ReleaseResult clean( List<MavenProject> reactorProjects )
593 {
594 ReleaseResult result = new ReleaseResult();
595
596 for ( MavenProject project : reactorProjects )
597 {
598 File releasePom = ReleaseUtil.getReleasePom( project );
599
600
601 if ( releasePom != null && releasePom.exists() )
602 {
603 logInfo( result, "Deleting release POM for '" + project.getName() + "'..." );
604
605 if ( !releasePom.delete() )
606 {
607 logWarn( result, "Cannot delete release POM: " + releasePom );
608 }
609 }
610 }
611
612 result.setResultCode( ReleaseResult.SUCCESS );
613
614 return result;
615 }
616 }