1 package org.apache.maven.model.merge;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.LinkedHashMap;
24 import java.util.LinkedHashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 import org.apache.maven.model.BuildBase;
30 import org.apache.maven.model.CiManagement;
31 import org.apache.maven.model.Contributor;
32 import org.apache.maven.model.Dependency;
33 import org.apache.maven.model.DeploymentRepository;
34 import org.apache.maven.model.Developer;
35 import org.apache.maven.model.DistributionManagement;
36 import org.apache.maven.model.Exclusion;
37 import org.apache.maven.model.Extension;
38 import org.apache.maven.model.InputLocation;
39 import org.apache.maven.model.IssueManagement;
40 import org.apache.maven.model.License;
41 import org.apache.maven.model.MailingList;
42 import org.apache.maven.model.Model;
43 import org.apache.maven.model.ModelBase;
44 import org.apache.maven.model.Organization;
45 import org.apache.maven.model.Plugin;
46 import org.apache.maven.model.PluginExecution;
47 import org.apache.maven.model.ReportPlugin;
48 import org.apache.maven.model.ReportSet;
49 import org.apache.maven.model.Repository;
50 import org.apache.maven.model.RepositoryBase;
51 import org.apache.maven.model.Scm;
52 import org.apache.maven.model.Site;
53
54
55
56
57
58
59
60 public class MavenModelMerger
61 extends ModelMerger
62 {
63
64
65
66
67 public static final String CHILD_PATH_ADJUSTMENT = "child-path-adjustment";
68
69
70
71
72 private static final String ARTIFACT_ID = "artifact-id";
73
74 @Override
75 protected void mergeModel( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
76 {
77 context.put( ARTIFACT_ID, target.getArtifactId() );
78
79 super.mergeModel( target, source, sourceDominant, context );
80 }
81
82 @Override
83 protected void mergeModel_Name( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
84 {
85 String src = source.getName();
86 if ( src != null )
87 {
88 if ( sourceDominant )
89 {
90 target.setName( src );
91 target.setLocation( "name", source.getLocation( "name" ) );
92 }
93 }
94 }
95
96 @Override
97 protected void mergeModel_Url( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
98 {
99 String src = source.getUrl();
100 if ( src != null )
101 {
102 if ( sourceDominant )
103 {
104 target.setUrl( src );
105 target.setLocation( "url", source.getLocation( "url" ) );
106 }
107 else if ( target.getUrl() == null )
108 {
109 target.setUrl( appendPath( src, context ) );
110 target.setLocation( "url", source.getLocation( "url" ) );
111 }
112 }
113 }
114
115
116
117
118
119 @Override
120 protected void mergeModel_Organization( Model target, Model source, boolean sourceDominant,
121 Map<Object, Object> context )
122 {
123 Organization src = source.getOrganization();
124 if ( src != null )
125 {
126 Organization tgt = target.getOrganization();
127 if ( tgt == null )
128 {
129 tgt = new Organization();
130 tgt.setLocation( "", src.getLocation( "" ) );
131 target.setOrganization( tgt );
132 mergeOrganization( tgt, src, sourceDominant, context );
133 }
134 }
135 }
136
137 @Override
138 protected void mergeModel_IssueManagement( Model target, Model source, boolean sourceDominant,
139 Map<Object, Object> context )
140 {
141 IssueManagement src = source.getIssueManagement();
142 if ( src != null )
143 {
144 IssueManagement tgt = target.getIssueManagement();
145 if ( tgt == null )
146 {
147 tgt = new IssueManagement();
148 tgt.setLocation( "", src.getLocation( "" ) );
149 target.setIssueManagement( tgt );
150 mergeIssueManagement( tgt, src, sourceDominant, context );
151 }
152 }
153 }
154
155 @Override
156 protected void mergeModel_CiManagement( Model target, Model source, boolean sourceDominant,
157 Map<Object, Object> context )
158 {
159 CiManagement src = source.getCiManagement();
160 if ( src != null )
161 {
162 CiManagement tgt = target.getCiManagement();
163 if ( tgt == null )
164 {
165 tgt = new CiManagement();
166 tgt.setLocation( "", src.getLocation( "" ) );
167 target.setCiManagement( tgt );
168 mergeCiManagement( tgt, src, sourceDominant, context );
169 }
170 }
171 }
172
173 @Override
174 protected void mergeModel_ModelVersion( Model target, Model source, boolean sourceDominant,
175 Map<Object, Object> context )
176 {
177
178 }
179
180 @Override
181 protected void mergeModel_ArtifactId( Model target, Model source, boolean sourceDominant,
182 Map<Object, Object> context )
183 {
184
185 }
186
187 @Override
188 protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant,
189 Map<Object, Object> context )
190 {
191
192 }
193
194 @Override
195 protected void mergeModel_Prerequisites( Model target, Model source, boolean sourceDominant,
196 Map<Object, Object> context )
197 {
198
199 }
200
201 @Override
202 protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant,
203 Map<Object, Object> context )
204 {
205 if ( target.getLicenses().isEmpty() )
206 {
207 target.setLicenses( new ArrayList<License>( source.getLicenses() ) );
208 }
209 }
210
211 @Override
212 protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant,
213 Map<Object, Object> context )
214 {
215 if ( target.getDevelopers().isEmpty() )
216 {
217 target.setDevelopers( new ArrayList<Developer>( source.getDevelopers() ) );
218 }
219 }
220
221 @Override
222 protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant,
223 Map<Object, Object> context )
224 {
225 if ( target.getContributors().isEmpty() )
226 {
227 target.setContributors( new ArrayList<Contributor>( source.getContributors() ) );
228 }
229 }
230
231 @Override
232 protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant,
233 Map<Object, Object> context )
234 {
235 if ( target.getMailingLists().isEmpty() )
236 {
237 target.setMailingLists( new ArrayList<MailingList>( source.getMailingLists() ) );
238 }
239 }
240
241 @Override
242 protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boolean sourceDominant,
243 Map<Object, Object> context )
244 {
245 List<String> src = source.getModules();
246 if ( !src.isEmpty() && sourceDominant )
247 {
248 List<Integer> indices = new ArrayList<Integer>();
249 List<String> tgt = target.getModules();
250 Set<String> excludes = new LinkedHashSet<String>( tgt );
251 List<String> merged = new ArrayList<String>( tgt.size() + src.size() );
252 merged.addAll( tgt );
253 for ( int i = 0, n = tgt.size(); i < n; i++ )
254 {
255 indices.add( i );
256 }
257 for ( int i = 0, n = src.size(); i < n; i++ )
258 {
259 String s = src.get( i );
260 if ( !excludes.contains( s ) )
261 {
262 merged.add( s );
263 indices.add( ~i );
264 }
265 }
266 target.setModules( merged );
267 target.setLocation( "modules", InputLocation.merge( target.getLocation( "modules" ),
268 source.getLocation( "modules" ), indices ) );
269 }
270 }
271
272
273
274
275
276 @Override
277 protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant,
278 Map<Object, Object> context )
279 {
280 List<Repository> src = source.getRepositories();
281 if ( !src.isEmpty() )
282 {
283 List<Repository> tgt = target.getRepositories();
284 Map<Object, Repository> merged = new LinkedHashMap<Object, Repository>( ( src.size() + tgt.size() ) * 2 );
285
286 List<Repository> dominant, recessive;
287 if ( sourceDominant )
288 {
289 dominant = src;
290 recessive = tgt;
291 }
292 else
293 {
294 dominant = tgt;
295 recessive = src;
296 }
297
298 for ( Repository element : dominant )
299 {
300 Object key = getRepositoryKey( element );
301 merged.put( key, element );
302 }
303
304 for ( Repository element : recessive )
305 {
306 Object key = getRepositoryKey( element );
307 if ( !merged.containsKey( key ) )
308 {
309 merged.put( key, element );
310 }
311 }
312
313 target.setRepositories( new ArrayList<Repository>( merged.values() ) );
314 }
315 }
316
317 @Override
318 protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant,
319 Map<Object, Object> context )
320 {
321 List<Repository> src = source.getPluginRepositories();
322 if ( !src.isEmpty() )
323 {
324 List<Repository> tgt = target.getPluginRepositories();
325 Map<Object, Repository> merged = new LinkedHashMap<Object, Repository>( ( src.size() + tgt.size() ) * 2 );
326
327 List<Repository> dominant, recessive;
328 if ( sourceDominant )
329 {
330 dominant = src;
331 recessive = tgt;
332 }
333 else
334 {
335 dominant = tgt;
336 recessive = src;
337 }
338
339 for ( Repository element : dominant )
340 {
341 Object key = getRepositoryKey( element );
342 merged.put( key, element );
343 }
344
345 for ( Repository element : recessive )
346 {
347 Object key = getRepositoryKey( element );
348 if ( !merged.containsKey( key ) )
349 {
350 merged.put( key, element );
351 }
352 }
353
354 target.setPluginRepositories( new ArrayList<Repository>( merged.values() ) );
355 }
356 }
357
358
359
360
361 @Override
362 protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boolean sourceDominant,
363 Map<Object, Object> context )
364 {
365 List<String> src = source.getFilters();
366 if ( !src.isEmpty() )
367 {
368 List<String> tgt = target.getFilters();
369 Set<String> excludes = new LinkedHashSet<String>( tgt );
370 List<String> merged = new ArrayList<String>( tgt.size() + src.size() );
371 merged.addAll( tgt );
372 for ( String s : src )
373 {
374 if ( !excludes.contains( s ) )
375 {
376 merged.add( s );
377 }
378 }
379 target.setFilters( merged );
380 }
381 }
382
383 @Override
384 protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant,
385 Map<Object, Object> context )
386 {
387 if ( sourceDominant || target.getResources().isEmpty() )
388 {
389 super.mergeBuildBase_Resources( target, source, sourceDominant, context );
390 }
391 }
392
393 @Override
394 protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant,
395 Map<Object, Object> context )
396 {
397 if ( sourceDominant || target.getTestResources().isEmpty() )
398 {
399 super.mergeBuildBase_TestResources( target, source, sourceDominant, context );
400 }
401 }
402
403 @Override
404 protected void mergeDistributionManagement_Repository( DistributionManagement target,
405 DistributionManagement source, boolean sourceDominant,
406 Map<Object, Object> context )
407 {
408 DeploymentRepository src = source.getRepository();
409 if ( src != null )
410 {
411 DeploymentRepository tgt = target.getRepository();
412 if ( sourceDominant || tgt == null )
413 {
414 tgt = new DeploymentRepository();
415 tgt.setLocation( "", src.getLocation( "" ) );
416 target.setRepository( tgt );
417 mergeDeploymentRepository( tgt, src, sourceDominant, context );
418 }
419 }
420 }
421
422 @Override
423 protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement target,
424 DistributionManagement source,
425 boolean sourceDominant,
426 Map<Object, Object> context )
427 {
428 DeploymentRepository src = source.getSnapshotRepository();
429 if ( src != null )
430 {
431 DeploymentRepository tgt = target.getSnapshotRepository();
432 if ( sourceDominant || tgt == null )
433 {
434 tgt = new DeploymentRepository();
435 tgt.setLocation( "", src.getLocation( "" ) );
436 target.setSnapshotRepository( tgt );
437 mergeDeploymentRepository( tgt, src, sourceDominant, context );
438 }
439 }
440 }
441
442 @Override
443 protected void mergeDistributionManagement_Site( DistributionManagement target, DistributionManagement source,
444 boolean sourceDominant, Map<Object, Object> context )
445 {
446 Site src = source.getSite();
447 if ( src != null )
448 {
449 Site tgt = target.getSite();
450 if ( sourceDominant || tgt == null )
451 {
452 tgt = new Site();
453 tgt.setLocation( "", src.getLocation( "" ) );
454 target.setSite( tgt );
455 mergeSite( tgt, src, sourceDominant, context );
456 }
457 }
458 }
459
460 @Override
461 protected void mergeSite_Url( Site target, Site source, boolean sourceDominant, Map<Object, Object> context )
462 {
463 String src = source.getUrl();
464 if ( src != null )
465 {
466 if ( sourceDominant )
467 {
468 target.setUrl( src );
469 target.setLocation( "url", source.getLocation( "url" ) );
470 }
471 else if ( target.getUrl() == null )
472 {
473 target.setUrl( appendPath( src, context ) );
474 target.setLocation( "url", source.getLocation( "url" ) );
475 }
476 }
477 }
478
479 @Override
480 protected void mergeScm_Url( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
481 {
482 String src = source.getUrl();
483 if ( src != null )
484 {
485 if ( sourceDominant )
486 {
487 target.setUrl( src );
488 target.setLocation( "url", source.getLocation( "url" ) );
489 }
490 else if ( target.getUrl() == null )
491 {
492 target.setUrl( appendPath( src, context ) );
493 target.setLocation( "url", source.getLocation( "url" ) );
494 }
495 }
496 }
497
498 @Override
499 protected void mergeScm_Connection( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
500 {
501 String src = source.getConnection();
502 if ( src != null )
503 {
504 if ( sourceDominant )
505 {
506 target.setConnection( src );
507 target.setLocation( "connection", source.getLocation( "connection" ) );
508 }
509 else if ( target.getConnection() == null )
510 {
511 target.setConnection( appendPath( src, context ) );
512 target.setLocation( "connection", source.getLocation( "connection" ) );
513 }
514 }
515 }
516
517 @Override
518 protected void mergeScm_DeveloperConnection( Scm target, Scm source, boolean sourceDominant,
519 Map<Object, Object> context )
520 {
521 String src = source.getDeveloperConnection();
522 if ( src != null )
523 {
524 if ( sourceDominant )
525 {
526 target.setDeveloperConnection( src );
527 target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) );
528 }
529 else if ( target.getDeveloperConnection() == null )
530 {
531 target.setDeveloperConnection( appendPath( src, context ) );
532 target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) );
533 }
534 }
535 }
536
537 @Override
538 protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant,
539 Map<Object, Object> context )
540 {
541 List<PluginExecution> src = source.getExecutions();
542 if ( !src.isEmpty() )
543 {
544 List<PluginExecution> tgt = target.getExecutions();
545 Map<Object, PluginExecution> merged =
546 new LinkedHashMap<Object, PluginExecution>( ( src.size() + tgt.size() ) * 2 );
547
548 for ( PluginExecution element : src )
549 {
550 if ( sourceDominant
551 || ( element.getInherited() != null ? element.isInherited() : source.isInherited() ) )
552 {
553 Object key = getPluginExecutionKey( element );
554 merged.put( key, element );
555 }
556 }
557
558 for ( PluginExecution element : tgt )
559 {
560 Object key = getPluginExecutionKey( element );
561 PluginExecution existing = merged.get( key );
562 if ( existing != null )
563 {
564 mergePluginExecution( element, existing, sourceDominant, context );
565 }
566 merged.put( key, element );
567 }
568
569 target.setExecutions( new ArrayList<PluginExecution>( merged.values() ) );
570 }
571 }
572
573 @Override
574 protected void mergePluginExecution_Goals( PluginExecution target, PluginExecution source, boolean sourceDominant,
575 Map<Object, Object> context )
576 {
577 List<String> src = source.getGoals();
578 if ( !src.isEmpty() )
579 {
580 List<String> tgt = target.getGoals();
581 Set<String> excludes = new LinkedHashSet<String>( tgt );
582 List<String> merged = new ArrayList<String>( tgt.size() + src.size() );
583 merged.addAll( tgt );
584 for ( String s : src )
585 {
586 if ( !excludes.contains( s ) )
587 {
588 merged.add( s );
589 }
590 }
591 target.setGoals( merged );
592 }
593 }
594
595 @Override
596 protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
597 Map<Object, Object> context )
598 {
599 List<ReportSet> src = source.getReportSets();
600 if ( !src.isEmpty() )
601 {
602 List<ReportSet> tgt = target.getReportSets();
603 Map<Object, ReportSet> merged = new LinkedHashMap<Object, ReportSet>( ( src.size() + tgt.size() ) * 2 );
604
605 for ( ReportSet rset : src )
606 {
607 if ( sourceDominant || ( rset.getInherited() != null ? rset.isInherited() : source.isInherited() ) )
608 {
609 Object key = getReportSetKey( rset );
610 merged.put( key, rset );
611 }
612 }
613
614 for ( ReportSet element : tgt )
615 {
616 Object key = getReportSetKey( element );
617 ReportSet existing = merged.get( key );
618 if ( existing != null )
619 {
620 mergeReportSet( element, existing, sourceDominant, context );
621 }
622 merged.put( key, element );
623 }
624
625 target.setReportSets( new ArrayList<ReportSet>( merged.values() ) );
626 }
627 }
628
629 @Override
630 protected Object getDependencyKey( Dependency dependency )
631 {
632 return dependency.getManagementKey();
633 }
634
635 @Override
636 protected Object getPluginKey( Plugin plugin )
637 {
638 return plugin.getKey();
639 }
640
641 @Override
642 protected Object getPluginExecutionKey( PluginExecution pluginExecution )
643 {
644 return pluginExecution.getId();
645 }
646
647 @Override
648 protected Object getReportPluginKey( ReportPlugin reportPlugin )
649 {
650 return reportPlugin.getKey();
651 }
652
653 @Override
654 protected Object getReportSetKey( ReportSet reportSet )
655 {
656 return reportSet.getId();
657 }
658
659 @Override
660 protected Object getRepositoryBaseKey( RepositoryBase repositoryBase )
661 {
662 return repositoryBase.getId();
663 }
664
665 @Override
666 protected Object getExtensionKey( Extension extension )
667 {
668 return extension.getGroupId() + ':' + extension.getArtifactId();
669 }
670
671 @Override
672 protected Object getExclusionKey( Exclusion exclusion )
673 {
674 return exclusion.getGroupId() + ':' + exclusion.getArtifactId();
675 }
676
677 private String appendPath( String parentPath, Map<Object, Object> context )
678 {
679 Object artifactId = context.get( ARTIFACT_ID );
680 Object childPathAdjustment = context.get( CHILD_PATH_ADJUSTMENT );
681
682 if ( artifactId != null && childPathAdjustment != null )
683 {
684 return appendPath( parentPath, artifactId.toString(), childPathAdjustment.toString() );
685 }
686 else
687 {
688 return parentPath;
689 }
690 }
691
692 private String appendPath( String parentPath, String childPath, String pathAdjustment )
693 {
694 String path = parentPath;
695 path = concatPath( path, pathAdjustment );
696 path = concatPath( path, childPath );
697 return path;
698 }
699
700 private String concatPath( String base, String path )
701 {
702 String result = base;
703
704 if ( path != null && path.length() > 0 )
705 {
706 if ( ( result.endsWith( "/" ) && !path.startsWith( "/" ) )
707 || ( !result.endsWith( "/" ) && path.startsWith( "/" ) ) )
708 {
709 result += path;
710 }
711 else if ( result.endsWith( "/" ) && path.startsWith( "/" ) )
712 {
713 result += path.substring( 1 );
714 }
715 else
716 {
717 result += '/';
718 result += path;
719 }
720 if ( base.endsWith( "/" ) && !result.endsWith( "/" ) )
721 {
722 result += '/';
723 }
724 }
725
726 return result;
727 }
728
729 }