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