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.StringReader;
25 import java.io.StringWriter;
26 import java.io.Writer;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36
37 import org.apache.maven.artifact.Artifact;
38 import org.apache.maven.artifact.ArtifactUtils;
39 import org.apache.maven.model.Model;
40 import org.apache.maven.model.Scm;
41 import org.apache.maven.project.MavenProject;
42 import org.apache.maven.scm.ScmException;
43 import org.apache.maven.scm.ScmFileSet;
44 import org.apache.maven.scm.command.edit.EditScmResult;
45 import org.apache.maven.scm.manager.NoSuchScmProviderException;
46 import org.apache.maven.scm.provider.ScmProvider;
47 import org.apache.maven.scm.repository.ScmRepository;
48 import org.apache.maven.scm.repository.ScmRepositoryException;
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.IdentifiedScm;
55 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
56 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
57 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
58 import org.apache.maven.shared.release.util.ReleaseUtil;
59 import org.codehaus.plexus.interpolation.InterpolationException;
60 import org.codehaus.plexus.interpolation.MapBasedValueSource;
61 import org.codehaus.plexus.interpolation.ObjectBasedValueSource;
62 import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
63 import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
64 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
65 import org.codehaus.plexus.util.IOUtil;
66 import org.codehaus.plexus.util.WriterFactory;
67 import org.jdom.CDATA;
68 import org.jdom.Comment;
69 import org.jdom.Document;
70 import org.jdom.Element;
71 import org.jdom.JDOMException;
72 import org.jdom.Namespace;
73 import org.jdom.Text;
74 import org.jdom.filter.ContentFilter;
75 import org.jdom.filter.ElementFilter;
76 import org.jdom.input.SAXBuilder;
77 import org.jdom.output.Format;
78 import org.jdom.output.XMLOutputter;
79
80
81
82
83
84
85 public abstract class AbstractRewritePomsPhase
86 extends AbstractReleasePhase
87 {
88
89
90
91 private ScmRepositoryConfigurator scmRepositoryConfigurator;
92
93
94
95
96 private String pomSuffix;
97
98 private String ls = ReleaseUtil.LS;
99
100 public void setLs( String ls )
101 {
102 this.ls = ls;
103 }
104
105 public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
106 List<MavenProject> reactorProjects )
107 throws ReleaseExecutionException, ReleaseFailureException
108 {
109 ReleaseResult result = new ReleaseResult();
110
111 transform( releaseDescriptor, releaseEnvironment, reactorProjects, false, result );
112
113 result.setResultCode( ReleaseResult.SUCCESS );
114
115 return result;
116 }
117
118 private void transform( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
119 List<MavenProject> reactorProjects, boolean simulate, ReleaseResult result )
120 throws ReleaseExecutionException, ReleaseFailureException
121 {
122 for ( MavenProject project : reactorProjects )
123 {
124 logInfo( result, "Transforming '" + project.getName() + "'..." );
125
126 transformProject( project, releaseDescriptor, releaseEnvironment, reactorProjects, simulate, result );
127 }
128 }
129
130 private void transformProject( MavenProject project, ReleaseDescriptor releaseDescriptor,
131 ReleaseEnvironment releaseEnvironment, List<MavenProject> reactorProjects,
132 boolean simulate, ReleaseResult result )
133 throws ReleaseExecutionException, ReleaseFailureException
134 {
135 Document document;
136 String intro = null;
137 String outtro = null;
138 try
139 {
140 String content = ReleaseUtil.readXmlFile( ReleaseUtil.getStandardPom( project ), ls );
141
142 content = content.replaceAll( "<([^!][^>]*?)\\s{2,}([^>]*?)>", "<$1 $2>" );
143 content = content.replaceAll( "(\\s{2,}|[^\\s])/>", "$1 />" );
144
145 SAXBuilder builder = new SAXBuilder();
146 document = builder.build( new StringReader( content ) );
147
148
149
150 normaliseLineEndings( document );
151
152
153 StringWriter w = new StringWriter();
154 Format format = Format.getRawFormat();
155 format.setLineSeparator( ls );
156 XMLOutputter out = new XMLOutputter( format );
157 out.output( document.getRootElement(), w );
158
159 int index = content.indexOf( w.toString() );
160 if ( index >= 0 )
161 {
162 intro = content.substring( 0, index );
163 outtro = content.substring( index + w.toString().length() );
164 }
165 else
166 {
167
168
169
170
171
172 final String SPACE = "\\s++";
173 final String XML = "<\\?(?:(?:[^\"'>]++)|(?:\"[^\"]*+\")|(?:'[^\']*+'))*+>";
174 final String INTSUB = "\\[(?:(?:[^\"'\\]]++)|(?:\"[^\"]*+\")|(?:'[^\']*+'))*+\\]";
175 final String DOCTYPE =
176 "<!DOCTYPE(?:(?:[^\"'\\[>]++)|(?:\"[^\"]*+\")|(?:'[^\']*+')|(?:" + INTSUB + "))*+>";
177 final String PI = XML;
178 final String COMMENT = "<!--(?:[^-]|(?:-[^-]))*+-->";
179
180 final String INTRO =
181 "(?:(?:" + SPACE + ")|(?:" + XML + ")|(?:" + DOCTYPE + ")|(?:" + COMMENT + ")|(?:" + PI + "))*";
182 final String OUTRO = "(?:(?:" + SPACE + ")|(?:" + COMMENT + ")|(?:" + PI + "))*";
183 final String POM = "(?s)(" + INTRO + ")(.*?)(" + OUTRO + ")";
184
185 Matcher matcher = Pattern.compile( POM ).matcher( content );
186 if ( matcher.matches() )
187 {
188 intro = matcher.group( 1 );
189 outtro = matcher.group( matcher.groupCount() );
190 }
191 }
192 }
193 catch ( JDOMException e )
194 {
195 throw new ReleaseExecutionException( "Error reading POM: " + e.getMessage(), e );
196 }
197 catch ( IOException e )
198 {
199 throw new ReleaseExecutionException( "Error reading POM: " + e.getMessage(), e );
200 }
201
202 ScmRepository scmRepository;
203 ScmProvider provider;
204 try
205 {
206 scmRepository = scmRepositoryConfigurator.getConfiguredRepository( releaseDescriptor,
207 releaseEnvironment.getSettings() );
208
209 provider = scmRepositoryConfigurator.getRepositoryProvider( scmRepository );
210 }
211 catch ( ScmRepositoryException e )
212 {
213 throw new ReleaseScmRepositoryException( e.getMessage(), e.getValidationMessages() );
214 }
215 catch ( NoSuchScmProviderException e )
216 {
217 throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
218 }
219
220 transformDocument( project, document.getRootElement(), releaseDescriptor, reactorProjects, scmRepository,
221 result, simulate );
222
223 File pomFile = ReleaseUtil.getStandardPom( project );
224
225 if ( simulate )
226 {
227 File outputFile = new File( pomFile.getParentFile(), pomFile.getName() + "." + pomSuffix );
228 writePom( outputFile, document, releaseDescriptor, project.getModelVersion(), intro, outtro );
229 }
230 else
231 {
232 writePom( pomFile, document, releaseDescriptor, project.getModelVersion(), intro, outtro, scmRepository,
233 provider );
234 }
235 }
236
237 private void normaliseLineEndings( Document document )
238 {
239 for ( Iterator<?> i = document.getDescendants( new ContentFilter( ContentFilter.COMMENT ) ); i.hasNext(); )
240 {
241 Comment c = (Comment) i.next();
242 c.setText( ReleaseUtil.normalizeLineEndings( c.getText(), ls ) );
243 }
244 for ( Iterator<?> i = document.getDescendants( new ContentFilter( ContentFilter.CDATA ) ); i.hasNext(); )
245 {
246 CDATA c = (CDATA) i.next();
247 c.setText( ReleaseUtil.normalizeLineEndings( c.getText(), ls ) );
248 }
249 }
250
251 private void transformDocument( MavenProject project, Element rootElement, ReleaseDescriptor releaseDescriptor,
252 List<MavenProject> reactorProjects, ScmRepository scmRepository, ReleaseResult result,
253 boolean simulate )
254 throws ReleaseExecutionException, ReleaseFailureException
255 {
256 Namespace namespace = rootElement.getNamespace();
257 Map<String, String> mappedVersions = getNextVersionMap( releaseDescriptor );
258 Map<String, String> originalVersions = getOriginalVersionMap( releaseDescriptor, reactorProjects, simulate );
259 @SuppressWarnings("unchecked")
260 Map<String, Map<String, String>> resolvedSnapshotDependencies = releaseDescriptor.getResolvedSnapshotDependencies();
261 Model model = project.getModel();
262 Element properties = rootElement.getChild( "properties", namespace );
263
264 String parentVersion = rewriteParent( project, rootElement, namespace, mappedVersions,
265 resolvedSnapshotDependencies, originalVersions );
266
267 String projectId = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
268
269 rewriteVersion( rootElement, namespace, mappedVersions, projectId, project, parentVersion );
270
271 List<Element> roots = new ArrayList<Element>();
272 roots.add( rootElement );
273 roots.addAll( getChildren( rootElement, "profiles", "profile" ) );
274
275 for ( Element root : roots )
276 {
277 rewriteArtifactVersions( getChildren( root, "dependencies", "dependency" ), mappedVersions,
278 resolvedSnapshotDependencies, originalVersions, model, properties, result,
279 releaseDescriptor );
280
281 rewriteArtifactVersions( getChildren( root, "dependencyManagement", "dependencies", "dependency" ),
282 mappedVersions, resolvedSnapshotDependencies, originalVersions, model, properties,
283 result, releaseDescriptor );
284
285 rewriteArtifactVersions( getChildren( root, "build", "extensions", "extension" ), mappedVersions,
286 resolvedSnapshotDependencies, originalVersions, model, properties, result,
287 releaseDescriptor );
288
289 List<Element> pluginElements = new ArrayList<Element>();
290 pluginElements.addAll( getChildren( root, "build", "plugins", "plugin" ) );
291 pluginElements.addAll( getChildren( root, "build", "pluginManagement", "plugins", "plugin" ) );
292
293 rewriteArtifactVersions( pluginElements, mappedVersions, resolvedSnapshotDependencies, originalVersions,
294 model, properties, result, releaseDescriptor );
295
296 for ( Element pluginElement : pluginElements )
297 {
298 rewriteArtifactVersions( getChildren( pluginElement, "dependencies", "dependency" ), mappedVersions,
299 resolvedSnapshotDependencies, originalVersions, model, properties, result,
300 releaseDescriptor );
301 }
302
303 rewriteArtifactVersions( getChildren( root, "reporting", "plugins", "plugin" ), mappedVersions,
304 resolvedSnapshotDependencies, originalVersions, model, properties, result,
305 releaseDescriptor );
306 }
307
308 String commonBasedir;
309 try
310 {
311 commonBasedir = ReleaseUtil.getCommonBasedir( reactorProjects );
312 }
313 catch ( IOException e )
314 {
315 throw new ReleaseExecutionException( "Exception occurred while calculating common basedir: "
316 + e.getMessage(), e );
317 }
318 transformScm( project, rootElement, namespace, releaseDescriptor, projectId, scmRepository, result,
319 commonBasedir );
320 }
321
322 @SuppressWarnings( "unchecked" )
323 private List<Element> getChildren( Element root, String... names )
324 {
325 Element parent = root;
326 for ( int i = 0; i < names.length - 1 && parent != null; i++ )
327 {
328 parent = parent.getChild( names[i], parent.getNamespace() );
329 }
330 if ( parent == null )
331 {
332 return Collections.emptyList();
333 }
334 return parent.getChildren( names[names.length - 1], parent.getNamespace() );
335 }
336
337
338
339
340
341
342
343
344 private void rewriteValue( Element element, String value )
345 {
346 Text text = null;
347 if ( element.getContent() != null )
348 {
349 for ( Iterator<?> it = element.getContent().iterator(); it.hasNext(); )
350 {
351 Object content = it.next();
352 if ( ( content instanceof Text ) && ( (Text) content ).getTextTrim().length() > 0 )
353 {
354 text = (Text) content;
355 while ( it.hasNext() )
356 {
357 content = it.next();
358 if ( content instanceof Text )
359 {
360 text.append( (Text) content );
361 it.remove();
362 }
363 else
364 {
365 break;
366 }
367 }
368 break;
369 }
370 }
371 }
372 if ( text == null )
373 {
374 element.addContent( value );
375 }
376 else
377 {
378 String chars = text.getText();
379 String trimmed = text.getTextTrim();
380 int idx = chars.indexOf( trimmed );
381 String leadingWhitespace = chars.substring( 0, idx );
382 String trailingWhitespace = chars.substring( idx + trimmed.length() );
383 text.setText( leadingWhitespace + value + trailingWhitespace );
384 }
385 }
386
387 private void rewriteVersion( Element rootElement, Namespace namespace, Map<String, String> mappedVersions, String projectId,
388 MavenProject project, String parentVersion )
389 throws ReleaseFailureException
390 {
391 Element versionElement = rootElement.getChild( "version", namespace );
392 String version = mappedVersions.get( projectId );
393 if ( version == null )
394 {
395 throw new ReleaseFailureException( "Version for '" + project.getName() + "' was not mapped" );
396 }
397
398 if ( versionElement == null )
399 {
400 if ( !version.equals( parentVersion ) )
401 {
402
403 Element artifactIdElement = rootElement.getChild( "artifactId", namespace );
404 int index = rootElement.indexOf( artifactIdElement );
405
406 versionElement = new Element( "version", namespace );
407 versionElement.setText( version );
408 rootElement.addContent( index + 1, new Text( "\n " ) );
409 rootElement.addContent( index + 2, versionElement );
410 }
411 }
412 else
413 {
414 rewriteValue( versionElement, version );
415 }
416 }
417
418 private String rewriteParent( MavenProject project, Element rootElement, Namespace namespace, Map<String, String> mappedVersions,
419 Map<String, Map<String, String>> resolvedSnapshotDependencies, Map<String, String> originalVersions )
420 throws ReleaseFailureException
421 {
422 String parentVersion = null;
423 if ( project.hasParent() )
424 {
425 Element parentElement = rootElement.getChild( "parent", namespace );
426 Element versionElement = parentElement.getChild( "version", namespace );
427 MavenProject parent = project.getParent();
428 String key = ArtifactUtils.versionlessKey( parent.getGroupId(), parent.getArtifactId() );
429 parentVersion = mappedVersions.get( key );
430 if ( parentVersion == null )
431 {
432
433 parentVersion = getResolvedSnapshotVersion( key, resolvedSnapshotDependencies );
434 }
435 if ( parentVersion == null )
436 {
437 if ( parent.getVersion().equals( originalVersions.get( key ) ) )
438 {
439 throw new ReleaseFailureException( "Version for parent '" + parent.getName() + "' was not mapped" );
440 }
441 }
442 else
443 {
444 rewriteValue( versionElement, parentVersion );
445 }
446 }
447 return parentVersion;
448 }
449
450 private void rewriteArtifactVersions( Collection<Element> elements, Map<String, String> mappedVersions,
451 Map<String, Map<String, String>> resolvedSnapshotDependencies, Map<String, String> originalVersions,
452 Model projectModel, Element properties, ReleaseResult result,
453 ReleaseDescriptor releaseDescriptor )
454 throws ReleaseExecutionException, ReleaseFailureException
455 {
456 if ( elements == null )
457 {
458 return;
459 }
460 String projectId = ArtifactUtils.versionlessKey( projectModel.getGroupId(), projectModel.getArtifactId() );
461 for ( Element element : elements )
462 {
463 Element versionElement = element.getChild( "version", element.getNamespace() );
464 if ( versionElement == null )
465 {
466
467 continue;
468 }
469 String rawVersion = versionElement.getTextTrim();
470
471 Element groupIdElement = element.getChild( "groupId", element.getNamespace() );
472 if ( groupIdElement == null )
473 {
474 if ( "plugin".equals( element.getName() ) )
475 {
476 groupIdElement = new Element( "groupId", element.getNamespace() );
477 groupIdElement.setText( "org.apache.maven.plugins" );
478 }
479 else
480 {
481
482 continue;
483 }
484 }
485 String groupId = interpolate( groupIdElement.getTextTrim(), projectModel );
486
487 Element artifactIdElement = element.getChild( "artifactId", element.getNamespace() );
488 if ( artifactIdElement == null )
489 {
490
491 continue;
492 }
493 String artifactId = interpolate( artifactIdElement.getTextTrim(), projectModel);
494
495 String key = ArtifactUtils.versionlessKey( groupId, artifactId );
496 String resolvedSnapshotVersion = getResolvedSnapshotVersion( key, resolvedSnapshotDependencies );
497 String mappedVersion = mappedVersions.get( key );
498 String originalVersion = originalVersions.get( key );
499 if ( originalVersion == null )
500 {
501 originalVersion = getOriginalResolvedSnapshotVersion( key, resolvedSnapshotDependencies );
502 }
503
504
505 if ( mappedVersion != null && mappedVersion.endsWith( Artifact.SNAPSHOT_VERSION )
506 && !rawVersion.endsWith( Artifact.SNAPSHOT_VERSION ) && !releaseDescriptor.isUpdateDependencies() )
507 {
508 continue;
509 }
510
511 if ( mappedVersion != null )
512 {
513 if ( rawVersion.equals( originalVersion ) )
514 {
515 logInfo( result, " Updating " + artifactId + " to " + mappedVersion );
516 rewriteValue( versionElement, mappedVersion );
517 }
518 else if ( rawVersion.matches( "\\$\\{.+\\}" ) )
519 {
520 String expression = rawVersion.substring( 2, rawVersion.length() - 1 );
521
522 if ( expression.startsWith( "project." ) || expression.startsWith( "pom." )
523 || "version".equals( expression ) )
524 {
525 if ( !mappedVersion.equals( mappedVersions.get( projectId ) ) )
526 {
527 logInfo( result, " Updating " + artifactId + " to " + mappedVersion );
528 rewriteValue( versionElement, mappedVersion );
529 }
530 else
531 {
532 logInfo( result, " Ignoring artifact version update for expression " + rawVersion );
533 }
534 }
535 else if ( properties != null )
536 {
537
538 Element property = properties.getChild( expression, properties.getNamespace() );
539 if ( property != null )
540 {
541 String propertyValue = property.getTextTrim();
542
543 if ( propertyValue.equals( originalVersion ) )
544 {
545 logInfo( result, " Updating " + rawVersion + " to " + mappedVersion );
546
547 rewriteValue( property, mappedVersion );
548 }
549 else if ( mappedVersion.equals( propertyValue ) )
550 {
551
552 logInfo( result, " Ignoring artifact version update for expression " + rawVersion
553 + " because it is already updated" );
554 }
555 else if ( !mappedVersion.equals( rawVersion ) )
556 {
557 if ( mappedVersion.matches( "\\$\\{project.+\\}" )
558 || mappedVersion.matches( "\\$\\{pom.+\\}" ) || "${version}".equals( mappedVersion ) )
559 {
560 logInfo( result, " Ignoring artifact version update for expression "
561 + mappedVersion );
562
563 }
564 else
565 {
566
567 throw new ReleaseFailureException( "The artifact (" + key + ") requires a "
568 + "different version (" + mappedVersion + ") than what is found ("
569 + propertyValue + ") for the expression (" + expression + ") in the "
570 + "project (" + projectId + ")." );
571 }
572 }
573 }
574 else
575 {
576
577
578 throw new ReleaseFailureException( "The version could not be updated: " + rawVersion );
579 }
580 }
581 }
582 else
583 {
584
585 }
586 }
587 else if ( resolvedSnapshotVersion != null )
588 {
589 logInfo( result, " Updating " + artifactId + " to " + resolvedSnapshotVersion );
590
591 rewriteValue( versionElement, resolvedSnapshotVersion );
592 }
593 else
594 {
595
596 }
597 }
598 }
599
600 private String interpolate( String value, Model model )
601 throws ReleaseExecutionException
602 {
603 if ( value != null && value.contains( "${" ) )
604 {
605 StringSearchInterpolator interpolator = new StringSearchInterpolator();
606 List<String> pomPrefixes = Arrays.asList( "pom.", "project." );
607 interpolator.addValueSource( new PrefixedObjectValueSource( pomPrefixes, model, false ) );
608 interpolator.addValueSource( new MapBasedValueSource( model.getProperties() ) );
609 interpolator.addValueSource( new ObjectBasedValueSource( model ) );
610 try
611 {
612 value = interpolator.interpolate( value, new PrefixAwareRecursionInterceptor( pomPrefixes ) );
613 }
614 catch ( InterpolationException e )
615 {
616 throw new ReleaseExecutionException(
617 "Failed to interpolate " + value + " for project " + model.getId(),
618 e );
619 }
620 }
621 return value;
622 }
623
624 private void writePom( File pomFile, Document document, ReleaseDescriptor releaseDescriptor, String modelVersion,
625 String intro, String outtro, ScmRepository repository, ScmProvider provider )
626 throws ReleaseExecutionException, ReleaseScmCommandException
627 {
628 try
629 {
630 if ( releaseDescriptor.isScmUseEditMode() || provider.requiresEditMode() )
631 {
632 EditScmResult result = provider.edit( repository, new ScmFileSet(
633 new File( releaseDescriptor.getWorkingDirectory() ), pomFile ) );
634
635 if ( !result.isSuccess() )
636 {
637 throw new ReleaseScmCommandException( "Unable to enable editing on the POM", result );
638 }
639 }
640 }
641 catch ( ScmException e )
642 {
643 throw new ReleaseExecutionException( "An error occurred enabling edit mode: " + e.getMessage(), e );
644 }
645
646 writePom( pomFile, document, releaseDescriptor, modelVersion, intro, outtro );
647 }
648
649 private void writePom( File pomFile, Document document, ReleaseDescriptor releaseDescriptor, String modelVersion,
650 String intro, String outtro )
651 throws ReleaseExecutionException
652 {
653 Element rootElement = document.getRootElement();
654
655 if ( releaseDescriptor.isAddSchema() )
656 {
657 Namespace pomNamespace = Namespace.getNamespace( "", "http://maven.apache.org/POM/" + modelVersion );
658 rootElement.setNamespace( pomNamespace );
659 Namespace xsiNamespace = Namespace.getNamespace( "xsi", "http://www.w3.org/2001/XMLSchema-instance" );
660 rootElement.addNamespaceDeclaration( xsiNamespace );
661
662 if ( rootElement.getAttribute( "schemaLocation", xsiNamespace ) == null )
663 {
664 rootElement.setAttribute( "schemaLocation", "http://maven.apache.org/POM/" + modelVersion
665 + " http://maven.apache.org/maven-v" + modelVersion.replace( '.', '_' ) + ".xsd", xsiNamespace );
666 }
667
668
669 ElementFilter elementFilter = new ElementFilter( Namespace.getNamespace( "" ) );
670 for ( Iterator<?> i = rootElement.getDescendants( elementFilter ); i.hasNext(); )
671 {
672 Element e = (Element) i.next();
673 e.setNamespace( pomNamespace );
674 }
675 }
676
677 Writer writer = null;
678 try
679 {
680 writer = WriterFactory.newXmlWriter( pomFile );
681
682 if ( intro != null )
683 {
684 writer.write( intro );
685 }
686
687 Format format = Format.getRawFormat();
688 format.setLineSeparator( ls );
689 XMLOutputter out = new XMLOutputter( format );
690 out.output( document.getRootElement(), writer );
691
692 if ( outtro != null )
693 {
694 writer.write( outtro );
695 }
696 }
697 catch ( IOException e )
698 {
699 throw new ReleaseExecutionException( "Error writing POM: " + e.getMessage(), e );
700 }
701 finally
702 {
703 IOUtil.close( writer );
704 }
705 }
706
707 public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
708 List<MavenProject> reactorProjects )
709 throws ReleaseExecutionException, ReleaseFailureException
710 {
711 ReleaseResult result = new ReleaseResult();
712
713 transform( releaseDescriptor, releaseEnvironment, reactorProjects, true, result );
714
715 result.setResultCode( ReleaseResult.SUCCESS );
716
717 return result;
718 }
719
720 public ReleaseResult clean( List<MavenProject> reactorProjects )
721 {
722 ReleaseResult result = new ReleaseResult();
723
724 super.clean( reactorProjects );
725
726 if ( reactorProjects != null )
727 {
728 for ( MavenProject project : reactorProjects )
729 {
730 File pomFile = ReleaseUtil.getStandardPom( project );
731
732 if ( pomFile != null )
733 {
734 File file = new File( pomFile.getParentFile(), pomFile.getName() + "." + pomSuffix );
735 if ( file.exists() )
736 {
737 file.delete();
738 }
739 }
740 }
741 }
742
743 result.setResultCode( ReleaseResult.SUCCESS );
744
745 return result;
746 }
747
748 protected abstract String getResolvedSnapshotVersion( String artifactVersionlessKey, Map<String, Map<String,String>> resolvedSnapshots );
749
750 protected abstract Map<String, String> getOriginalVersionMap( ReleaseDescriptor releaseDescriptor, List<MavenProject> reactorProjects,
751 boolean simulate );
752
753 protected abstract Map<String,String> getNextVersionMap( ReleaseDescriptor releaseDescriptor );
754
755 protected abstract void transformScm( MavenProject project, Element rootElement, Namespace namespace,
756 ReleaseDescriptor releaseDescriptor, String projectId,
757 ScmRepository scmRepository, ReleaseResult result, String commonBasedir )
758 throws ReleaseExecutionException;
759
760 protected String getOriginalResolvedSnapshotVersion( String artifactVersionlessKey, Map<String, Map<String, String>> resolvedSnapshots )
761 {
762 Map<String, String> versionsMap = resolvedSnapshots.get( artifactVersionlessKey );
763
764 if ( versionsMap != null )
765 {
766 return versionsMap.get( ReleaseDescriptor.ORIGINAL_VERSION );
767 }
768 else
769 {
770 return null;
771 }
772 }
773
774 protected Element rewriteElement( String name, String value, Element root, Namespace namespace )
775 {
776 Element tagElement = root.getChild( name, namespace );
777 if ( tagElement != null )
778 {
779 if ( value != null )
780 {
781 rewriteValue( tagElement, value );
782 }
783 else
784 {
785 int index = root.indexOf( tagElement );
786 root.removeContent( index );
787 for ( int i = index - 1; i >= 0; i-- )
788 {
789 if ( root.getContent( i ) instanceof Text )
790 {
791 root.removeContent( i );
792 }
793 else
794 {
795 break;
796 }
797 }
798 }
799 }
800 else
801 {
802 if ( value != null )
803 {
804 Element element = new Element( name, namespace );
805 element.setText( value );
806 root.addContent( " " ).addContent( element ).addContent( "\n " );
807 tagElement = element;
808 }
809 }
810 return tagElement;
811 }
812
813 protected Scm buildScm( MavenProject project )
814 {
815 IdentifiedScm scm;
816 if ( project.getOriginalModel().getScm() == null )
817 {
818 scm = null;
819 }
820 else
821 {
822 scm = new IdentifiedScm();
823 scm.setConnection( project.getOriginalModel().getScm().getConnection() );
824 scm.setDeveloperConnection( project.getOriginalModel().getScm().getDeveloperConnection() );
825 scm.setTag( project.getOriginalModel().getScm().getTag() );
826 scm.setUrl( project.getOriginalModel().getScm().getUrl() );
827 scm.setId( project.getProperties().getProperty( "project.scm.id" ) );
828 }
829 return scm;
830 }
831 }