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