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 protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant,
318 Map<Object, Object> context )
319 {
320 List<Repository> src = source.getPluginRepositories();
321 if ( !src.isEmpty() )
322 {
323 List<Repository> tgt = target.getPluginRepositories();
324 Map<Object, Repository> merged = new LinkedHashMap<Object, Repository>( ( src.size() + tgt.size() ) * 2 );
325
326 List<Repository> dominant, recessive;
327 if ( sourceDominant )
328 {
329 dominant = src;
330 recessive = tgt;
331 }
332 else
333 {
334 dominant = tgt;
335 recessive = src;
336 }
337
338 for ( Repository element : dominant )
339 {
340 Object key = getRepositoryKey( element );
341 merged.put( key, element );
342 }
343
344 for ( Repository element : recessive )
345 {
346 Object key = getRepositoryKey( element );
347 if ( !merged.containsKey( key ) )
348 {
349 merged.put( key, element );
350 }
351 }
352
353 target.setPluginRepositories( new ArrayList<Repository>( merged.values() ) );
354 }
355 }
356
357
358
359
360 @Override
361 protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boolean sourceDominant,
362 Map<Object, Object> context )
363 {
364 List<String> src = source.getFilters();
365 if ( !src.isEmpty() )
366 {
367 List<String> tgt = target.getFilters();
368 Set<String> excludes = new LinkedHashSet<String>( tgt );
369 List<String> merged = new ArrayList<String>( tgt.size() + src.size() );
370 merged.addAll( tgt );
371 for ( String s : src )
372 {
373 if ( !excludes.contains( s ) )
374 {
375 merged.add( s );
376 }
377 }
378 target.setFilters( merged );
379 }
380 }
381
382 @Override
383 protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant,
384 Map<Object, Object> context )
385 {
386 if ( sourceDominant || target.getResources().isEmpty() )
387 {
388 super.mergeBuildBase_Resources( target, source, sourceDominant, context );
389 }
390 }
391
392 @Override
393 protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant,
394 Map<Object, Object> context )
395 {
396 if ( sourceDominant || target.getTestResources().isEmpty() )
397 {
398 super.mergeBuildBase_TestResources( target, source, sourceDominant, context );
399 }
400 }
401
402 @Override
403 protected void mergeDistributionManagement_Repository( DistributionManagement target,
404 DistributionManagement source, boolean sourceDominant,
405 Map<Object, Object> context )
406 {
407 DeploymentRepository src = source.getRepository();
408 if ( src != null )
409 {
410 DeploymentRepository tgt = target.getRepository();
411 if ( sourceDominant || tgt == null )
412 {
413 tgt = new DeploymentRepository();
414 tgt.setLocation( "", src.getLocation( "" ) );
415 target.setRepository( tgt );
416 mergeDeploymentRepository( tgt, src, sourceDominant, context );
417 }
418 }
419 }
420
421 @Override
422 protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement target,
423 DistributionManagement source,
424 boolean sourceDominant,
425 Map<Object, Object> context )
426 {
427 DeploymentRepository src = source.getSnapshotRepository();
428 if ( src != null )
429 {
430 DeploymentRepository tgt = target.getSnapshotRepository();
431 if ( sourceDominant || tgt == null )
432 {
433 tgt = new DeploymentRepository();
434 tgt.setLocation( "", src.getLocation( "" ) );
435 target.setSnapshotRepository( tgt );
436 mergeDeploymentRepository( tgt, src, sourceDominant, context );
437 }
438 }
439 }
440
441 @Override
442 protected void mergeDistributionManagement_Site( DistributionManagement target, DistributionManagement source,
443 boolean sourceDominant, Map<Object, Object> context )
444 {
445 Site src = source.getSite();
446 if ( src != null )
447 {
448 Site tgt = target.getSite();
449 if ( sourceDominant || tgt == null )
450 {
451 tgt = new Site();
452 tgt.setLocation( "", src.getLocation( "" ) );
453 target.setSite( tgt );
454 mergeSite( tgt, src, sourceDominant, context );
455 }
456 }
457 }
458
459 @Override
460 protected void mergeSite_Url( Site target, Site source, boolean sourceDominant, Map<Object, Object> context )
461 {
462 String src = source.getUrl();
463 if ( src != null )
464 {
465 if ( sourceDominant )
466 {
467 target.setUrl( src );
468 target.setLocation( "url", source.getLocation( "url" ) );
469 }
470 else if ( target.getUrl() == null )
471 {
472 target.setUrl( appendPath( src, context ) );
473 target.setLocation( "url", source.getLocation( "url" ) );
474 }
475 }
476 }
477
478 @Override
479 protected void mergeScm_Url( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
480 {
481 String src = source.getUrl();
482 if ( src != null )
483 {
484 if ( sourceDominant )
485 {
486 target.setUrl( src );
487 target.setLocation( "url", source.getLocation( "url" ) );
488 }
489 else if ( target.getUrl() == null )
490 {
491 target.setUrl( appendPath( src, context ) );
492 target.setLocation( "url", source.getLocation( "url" ) );
493 }
494 }
495 }
496
497 @Override
498 protected void mergeScm_Connection( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
499 {
500 String src = source.getConnection();
501 if ( src != null )
502 {
503 if ( sourceDominant )
504 {
505 target.setConnection( src );
506 target.setLocation( "connection", source.getLocation( "connection" ) );
507 }
508 else if ( target.getConnection() == null )
509 {
510 target.setConnection( appendPath( src, context ) );
511 target.setLocation( "connection", source.getLocation( "connection" ) );
512 }
513 }
514 }
515
516 @Override
517 protected void mergeScm_DeveloperConnection( Scm target, Scm source, boolean sourceDominant,
518 Map<Object, Object> context )
519 {
520 String src = source.getDeveloperConnection();
521 if ( src != null )
522 {
523 if ( sourceDominant )
524 {
525 target.setDeveloperConnection( src );
526 target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) );
527 }
528 else if ( target.getDeveloperConnection() == null )
529 {
530 target.setDeveloperConnection( appendPath( src, context ) );
531 target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) );
532 }
533 }
534 }
535
536 @Override
537 protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant,
538 Map<Object, Object> context )
539 {
540 List<PluginExecution> src = source.getExecutions();
541 if ( !src.isEmpty() )
542 {
543 List<PluginExecution> tgt = target.getExecutions();
544 Map<Object, PluginExecution> merged =
545 new LinkedHashMap<Object, PluginExecution>( ( src.size() + tgt.size() ) * 2 );
546
547 for ( PluginExecution element : src )
548 {
549 if ( sourceDominant
550 || ( element.getInherited() != null ? element.isInherited() : source.isInherited() ) )
551 {
552 Object key = getPluginExecutionKey( element );
553 merged.put( key, element );
554 }
555 }
556
557 for ( PluginExecution element : tgt )
558 {
559 Object key = getPluginExecutionKey( element );
560 PluginExecution existing = merged.get( key );
561 if ( existing != null )
562 {
563 mergePluginExecution( element, existing, sourceDominant, context );
564 }
565 merged.put( key, element );
566 }
567
568 target.setExecutions( new ArrayList<PluginExecution>( merged.values() ) );
569 }
570 }
571
572 @Override
573 protected void mergePluginExecution_Goals( PluginExecution target, PluginExecution source, boolean sourceDominant,
574 Map<Object, Object> context )
575 {
576 List<String> src = source.getGoals();
577 if ( !src.isEmpty() )
578 {
579 List<String> tgt = target.getGoals();
580 Set<String> excludes = new LinkedHashSet<String>( tgt );
581 List<String> merged = new ArrayList<String>( tgt.size() + src.size() );
582 merged.addAll( tgt );
583 for ( String s : src )
584 {
585 if ( !excludes.contains( s ) )
586 {
587 merged.add( s );
588 }
589 }
590 target.setGoals( merged );
591 }
592 }
593
594 @Override
595 protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
596 Map<Object, Object> context )
597 {
598 List<ReportSet> src = source.getReportSets();
599 if ( !src.isEmpty() )
600 {
601 List<ReportSet> tgt = target.getReportSets();
602 Map<Object, ReportSet> merged = new LinkedHashMap<Object, ReportSet>( ( src.size() + tgt.size() ) * 2 );
603
604 for ( ReportSet rset : src )
605 {
606 if ( sourceDominant || ( rset.getInherited() != null ? rset.isInherited() : source.isInherited() ) )
607 {
608 Object key = getReportSetKey( rset );
609 merged.put( key, rset );
610 }
611 }
612
613 for ( ReportSet element : tgt )
614 {
615 Object key = getReportSetKey( element );
616 ReportSet existing = merged.get( key );
617 if ( existing != null )
618 {
619 mergeReportSet( element, existing, sourceDominant, context );
620 }
621 merged.put( key, element );
622 }
623
624 target.setReportSets( new ArrayList<ReportSet>( merged.values() ) );
625 }
626 }
627
628 @Override
629 protected Object getDependencyKey( Dependency dependency )
630 {
631 return dependency.getManagementKey();
632 }
633
634 @Override
635 protected Object getPluginKey( Plugin plugin )
636 {
637 return plugin.getKey();
638 }
639
640 @Override
641 protected Object getPluginExecutionKey( PluginExecution pluginExecution )
642 {
643 return pluginExecution.getId();
644 }
645
646 @Override
647 protected Object getReportPluginKey( ReportPlugin reportPlugin )
648 {
649 return reportPlugin.getKey();
650 }
651
652 @Override
653 protected Object getReportSetKey( ReportSet reportSet )
654 {
655 return reportSet.getId();
656 }
657
658 @Override
659 protected Object getRepositoryBaseKey( RepositoryBase repositoryBase )
660 {
661 return repositoryBase.getId();
662 }
663
664 @Override
665 protected Object getExtensionKey( Extension extension )
666 {
667 return extension.getGroupId() + ':' + extension.getArtifactId();
668 }
669
670 @Override
671 protected Object getExclusionKey( Exclusion exclusion )
672 {
673 return exclusion.getGroupId() + ':' + exclusion.getArtifactId();
674 }
675
676 private String appendPath( String parentPath, Map<Object, Object> context )
677 {
678 Object artifactId = context.get( ARTIFACT_ID );
679 Object childPathAdjustment = context.get( CHILD_PATH_ADJUSTMENT );
680
681 if ( artifactId != null && childPathAdjustment != null )
682 {
683 return appendPath( parentPath, artifactId.toString(), childPathAdjustment.toString() );
684 }
685 else
686 {
687 return parentPath;
688 }
689 }
690
691 private String appendPath( String parentPath, String childPath, String pathAdjustment )
692 {
693 String path = parentPath;
694 path = concatPath( path, pathAdjustment );
695 path = concatPath( path, childPath );
696 return path;
697 }
698
699 private String concatPath( String base, String path )
700 {
701 String result = base;
702
703 if ( path != null && path.length() > 0 )
704 {
705 if ( ( result.endsWith( "/" ) && !path.startsWith( "/" ) )
706 || ( !result.endsWith( "/" ) && path.startsWith( "/" ) ) )
707 {
708 result += path;
709 }
710 else if ( result.endsWith( "/" ) && path.startsWith( "/" ) )
711 {
712 result += path.substring( 1 );
713 }
714 else
715 {
716 result += '/';
717 result += path;
718 }
719 if ( base.endsWith( "/" ) && !result.endsWith( "/" ) )
720 {
721 result += '/';
722 }
723 }
724
725 return result;
726 }
727
728 }