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