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