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 && project.getOriginalModel().getBuild().getFinalName() != null )
302 {
303 return project.getOriginalModel().getBuild().getFinalName();
304 }
305 else if( project.hasParent() )
306 {
307 return findOriginalFinalName( project.getParent() );
308 }
309 else
310 {
311 return null;
312 }
313 }
314
315 public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
316 List<MavenProject> reactorProjects )
317 throws ReleaseExecutionException, ReleaseFailureException
318 {
319 return execute( releaseDescriptor, releaseEnvironment, reactorProjects, true );
320 }
321
322 protected Map<String, String> getOriginalVersionMap( ReleaseDescriptor releaseDescriptor,
323 List<MavenProject> reactorProjects )
324 {
325 return releaseDescriptor.getOriginalVersions( reactorProjects );
326 }
327
328 @SuppressWarnings( "unchecked" )
329 protected Map<String, String> getNextVersionMap( ReleaseDescriptor releaseDescriptor )
330 {
331 return releaseDescriptor.getReleaseVersions();
332 }
333
334 private String getNextVersion( Map<String, String> mappedVersions, String groupId, String artifactId, String version )
335 throws ReleaseFailureException
336 {
337
338
339 String id = ArtifactUtils.versionlessKey( groupId, artifactId );
340
341 String nextVersion = mappedVersions.get( id );
342
343 if ( nextVersion == null )
344 {
345 throw new ReleaseFailureException( "Version for '" + id + "' was not mapped" );
346 }
347
348 return nextVersion;
349 }
350
351 private ScmTranslator getScmTranslator( ScmRepository scmRepository )
352 {
353 return scmTranslators.get( scmRepository.getProvider() );
354 }
355
356 private Scm createReleaseScm( Scm scm, ScmTranslator scmTranslator, ReleaseDescriptor releaseDescriptor )
357 {
358
359
360 String tag = releaseDescriptor.getScmReleaseLabel();
361 String tagBase = releaseDescriptor.getScmTagBase();
362
363 Scm releaseScm = new Scm();
364
365 if ( scm.getConnection() != null )
366 {
367 String value = scmTranslator.translateTagUrl( scm.getConnection(), tag, tagBase );
368 releaseScm.setConnection( value );
369 }
370
371 if ( scm.getDeveloperConnection() != null )
372 {
373 String value = scmTranslator.translateTagUrl( scm.getDeveloperConnection(), tag, tagBase );
374 releaseScm.setDeveloperConnection( value );
375 }
376
377 if ( scm.getUrl() != null )
378 {
379 String value = scmTranslator.translateTagUrl( scm.getUrl(), tag, tagBase );
380 releaseScm.setUrl( value );
381 }
382
383 if ( scm.getTag() != null )
384 {
385 String value = scmTranslator.resolveTag( scm.getTag() );
386 releaseScm.setTag( value );
387 }
388
389 return releaseScm;
390 }
391
392 private List<Dependency> createReleaseDependencies( Map<String, String> originalVersions,
393 Map<String, String> mappedVersions, MavenProject project )
394 throws ReleaseFailureException
395 {
396 @SuppressWarnings( "unchecked" )
397 Set<Artifact> artifacts = project.getArtifacts();
398
399 List<Dependency> releaseDependencies = null;
400
401 if ( artifacts != null )
402 {
403
404 List<Artifact> orderedArtifacts = new ArrayList<Artifact>();
405 orderedArtifacts.addAll( artifacts );
406 Collections.sort( orderedArtifacts );
407
408 releaseDependencies = new ArrayList<Dependency>();
409
410 for ( Artifact artifact : orderedArtifacts )
411 {
412 Dependency releaseDependency = new Dependency();
413
414 releaseDependency.setGroupId( artifact.getGroupId() );
415 releaseDependency.setArtifactId( artifact.getArtifactId() );
416
417 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
418
419 releaseDependency.setVersion( version );
420 releaseDependency.setType( artifact.getType() );
421 releaseDependency.setScope( artifact.getScope() );
422 releaseDependency.setClassifier( artifact.getClassifier() );
423
424 releaseDependencies.add( releaseDependency );
425 }
426 }
427
428 return releaseDependencies;
429 }
430
431 private String getReleaseVersion( Map<String, String> originalVersions, Map<String, String> mappedVersions, Artifact artifact )
432 throws ReleaseFailureException
433 {
434 String key = ArtifactUtils.versionlessKey( artifact );
435
436 String originalVersion = originalVersions.get( key );
437 String mappedVersion = mappedVersions.get( key );
438
439 String version = artifact.getVersion();
440
441 if ( version.equals( originalVersion ) )
442 {
443 if ( mappedVersion != null )
444 {
445 version = mappedVersion;
446 }
447 else
448 {
449 throw new ReleaseFailureException( "Version '" + version + "' for '" + key + "' was not mapped" );
450 }
451 }
452 else
453 {
454 if ( !ArtifactUtils.isSnapshot( version ) )
455 {
456 version = artifact.getBaseVersion();
457 }
458 }
459
460 return version;
461 }
462
463 private List<Plugin> createReleasePlugins( Map<String, String> originalVersions, Map<String, String> mappedVersions, MavenProject project )
464 throws ReleaseFailureException
465 {
466 List<Plugin> releasePlugins = null;
467
468
469 Build build = project.getOriginalModel().getBuild();
470
471 if ( build != null )
472 {
473 List<Plugin> plugins = build.getPlugins();
474
475 if ( plugins != null )
476 {
477 @SuppressWarnings( "unchecked" )
478 Map<String, Artifact> artifactsById = project.getPluginArtifactMap();
479
480 releasePlugins = new ArrayList<Plugin>();
481
482 for ( Plugin plugin : plugins )
483 {
484 String id = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
485 Artifact artifact = artifactsById.get( id );
486 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
487
488 Plugin releasePlugin = new Plugin();
489 releasePlugin.setGroupId( plugin.getGroupId() );
490 releasePlugin.setArtifactId( plugin.getArtifactId() );
491 releasePlugin.setVersion( version );
492 releasePlugin.setExtensions( plugin.isExtensions() );
493 releasePlugin.setExecutions( plugin.getExecutions() );
494 releasePlugin.setDependencies( plugin.getDependencies() );
495 releasePlugin.setGoals( plugin.getGoals() );
496 releasePlugin.setInherited( plugin.getInherited() );
497 releasePlugin.setConfiguration( plugin.getConfiguration() );
498
499 releasePlugins.add( releasePlugin );
500 }
501 }
502 }
503
504 return releasePlugins;
505 }
506
507 private List<ReportPlugin> createReleaseReportPlugins( Map<String, String> originalVersions, Map<String, String> mappedVersions,
508 MavenProject project )
509 throws ReleaseFailureException
510 {
511 List<ReportPlugin> releaseReportPlugins = null;
512
513 Reporting reporting = project.getModel().getReporting();
514
515 if ( reporting != null )
516 {
517 List<ReportPlugin> reportPlugins = reporting.getPlugins();
518
519 if ( reportPlugins != null )
520 {
521 @SuppressWarnings( "unchecked" )
522 Map<String, Artifact> artifactsById = project.getReportArtifactMap();
523
524 releaseReportPlugins = new ArrayList<ReportPlugin>();
525
526 for ( ReportPlugin reportPlugin : reportPlugins )
527 {
528 String id = ArtifactUtils.versionlessKey( reportPlugin.getGroupId(), reportPlugin.getArtifactId() );
529 Artifact artifact = artifactsById.get( id );
530 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
531
532 ReportPlugin releaseReportPlugin = new ReportPlugin();
533 releaseReportPlugin.setGroupId( reportPlugin.getGroupId() );
534 releaseReportPlugin.setArtifactId( reportPlugin.getArtifactId() );
535 releaseReportPlugin.setVersion( version );
536 releaseReportPlugin.setInherited( reportPlugin.getInherited() );
537 releaseReportPlugin.setConfiguration( reportPlugin.getConfiguration() );
538 releaseReportPlugin.setReportSets( reportPlugin.getReportSets() );
539
540 releaseReportPlugins.add( releaseReportPlugin );
541 }
542 }
543 }
544
545 return releaseReportPlugins;
546 }
547
548 private List<Extension> createReleaseExtensions( Map<String, String> originalVersions, Map<String, String> mappedVersions, MavenProject project )
549 throws ReleaseFailureException
550 {
551 List<Extension> releaseExtensions = null;
552
553
554 Build build = project.getOriginalModel().getBuild();
555
556 if ( build != null )
557 {
558 List<Extension> extensions = build.getExtensions();
559
560 if ( extensions != null )
561 {
562 releaseExtensions = new ArrayList<Extension>();
563
564 for ( Extension extension : extensions )
565 {
566 String id = ArtifactUtils.versionlessKey( extension.getGroupId(), extension.getArtifactId() );
567 Artifact artifact = (Artifact) project.getExtensionArtifactMap().get( id );
568 String version = getReleaseVersion( originalVersions, mappedVersions, artifact );
569
570 Extension releaseExtension = new Extension();
571 releaseExtension.setGroupId( extension.getGroupId() );
572 releaseExtension.setArtifactId( extension.getArtifactId() );
573 releaseExtension.setVersion( version );
574
575 releaseExtensions.add( releaseExtension );
576 }
577 }
578 }
579
580 return releaseExtensions;
581 }
582
583
584
585
586 public ReleaseResult clean( List<MavenProject> reactorProjects )
587 {
588 ReleaseResult result = new ReleaseResult();
589
590 for ( MavenProject project : reactorProjects )
591 {
592 File releasePom = ReleaseUtil.getReleasePom( project );
593
594
595 if ( releasePom != null && releasePom.exists() )
596 {
597 logInfo( result, "Deleting release POM for '" + project.getName() + "'..." );
598
599 if ( !releasePom.delete() )
600 {
601 logWarn( result, "Cannot delete release POM: " + releasePom );
602 }
603 }
604 }
605
606 result.setResultCode( ReleaseResult.SUCCESS );
607
608 return result;
609 }
610 }