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