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 ( source.getOrganization() != null )
124 {
125 Organization tgt = target.getOrganization();
126 if ( tgt == null )
127 {
128 tgt = new Organization();
129 target.setOrganization( tgt );
130 mergeOrganization( tgt, src, sourceDominant, context );
131 }
132 }
133 }
134
135 @Override
136 protected void mergeModel_IssueManagement( Model target, Model source, boolean sourceDominant,
137 Map<Object, Object> context )
138 {
139 IssueManagement src = source.getIssueManagement();
140 if ( source.getIssueManagement() != null )
141 {
142 IssueManagement tgt = target.getIssueManagement();
143 if ( tgt == null )
144 {
145 tgt = new IssueManagement();
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 ( source.getCiManagement() != null )
158 {
159 CiManagement tgt = target.getCiManagement();
160 if ( tgt == null )
161 {
162 tgt = new CiManagement();
163 target.setCiManagement( tgt );
164 mergeCiManagement( tgt, src, sourceDominant, context );
165 }
166 }
167 }
168
169 @Override
170 protected void mergeModel_ModelVersion( Model target, Model source, boolean sourceDominant,
171 Map<Object, Object> context )
172 {
173
174 }
175
176 @Override
177 protected void mergeModel_ArtifactId( Model target, Model source, boolean sourceDominant,
178 Map<Object, Object> context )
179 {
180
181 }
182
183 @Override
184 protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant,
185 Map<Object, Object> context )
186 {
187
188 }
189
190 @Override
191 protected void mergeModel_Prerequisites( Model target, Model source, boolean sourceDominant,
192 Map<Object, Object> context )
193 {
194
195 }
196
197 @Override
198 protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant,
199 Map<Object, Object> context )
200 {
201 if ( target.getLicenses().isEmpty() )
202 {
203 target.setLicenses( new ArrayList<License>( source.getLicenses() ) );
204 }
205 }
206
207 @Override
208 protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant,
209 Map<Object, Object> context )
210 {
211 if ( target.getDevelopers().isEmpty() )
212 {
213 target.setDevelopers( new ArrayList<Developer>( source.getDevelopers() ) );
214 }
215 }
216
217 @Override
218 protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant,
219 Map<Object, Object> context )
220 {
221 if ( target.getContributors().isEmpty() )
222 {
223 target.setContributors( new ArrayList<Contributor>( source.getContributors() ) );
224 }
225 }
226
227 @Override
228 protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant,
229 Map<Object, Object> context )
230 {
231 if ( target.getMailingLists().isEmpty() )
232 {
233 target.setMailingLists( new ArrayList<MailingList>( source.getMailingLists() ) );
234 }
235 }
236
237 @Override
238 protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boolean sourceDominant,
239 Map<Object, Object> context )
240 {
241 List<String> src = source.getModules();
242 if ( !src.isEmpty() && sourceDominant )
243 {
244 List<Integer> indices = new ArrayList<Integer>();
245 List<String> tgt = target.getModules();
246 Set<String> excludes = new LinkedHashSet<String>( tgt );
247 List<String> merged = new ArrayList<String>( tgt.size() + src.size() );
248 merged.addAll( tgt );
249 for ( int i = 0, n = tgt.size(); i < n; i++ )
250 {
251 indices.add( Integer.valueOf( i ) );
252 }
253 for ( int i = 0, n = src.size(); i < n; i++ )
254 {
255 String s = src.get( i );
256 if ( !excludes.contains( s ) )
257 {
258 merged.add( s );
259 indices.add( Integer.valueOf( ~i ) );
260 }
261 }
262 target.setModules( merged );
263 target.setLocation( "modules", InputLocation.merge( target.getLocation( "modules" ),
264 source.getLocation( "modules" ), indices ) );
265 }
266 }
267
268
269
270
271
272 @Override
273 protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant,
274 Map<Object, Object> context )
275 {
276 List<Repository> src = source.getRepositories();
277 if ( !src.isEmpty() )
278 {
279 List<Repository> tgt = target.getRepositories();
280 Map<Object, Repository> merged = new LinkedHashMap<Object, Repository>( ( src.size() + tgt.size() ) * 2 );
281
282 List<Repository> dominant, recessive;
283 if ( sourceDominant )
284 {
285 dominant = src;
286 recessive = tgt;
287 }
288 else
289 {
290 dominant = tgt;
291 recessive = src;
292 }
293
294 for ( Repository element : dominant )
295 {
296 Object key = getRepositoryKey( element );
297 merged.put( key, element );
298 }
299
300 for ( Repository element : recessive )
301 {
302 Object key = getRepositoryKey( element );
303 if ( !merged.containsKey( key ) )
304 {
305 merged.put( key, element );
306 }
307 }
308
309 target.setRepositories( new ArrayList<Repository>( merged.values() ) );
310 }
311 }
312
313
314
315
316 @Override
317 protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boolean sourceDominant,
318 Map<Object, Object> context )
319 {
320 List<String> src = source.getFilters();
321 if ( !src.isEmpty() )
322 {
323 List<String> tgt = target.getFilters();
324 Set<String> excludes = new LinkedHashSet<String>( tgt );
325 List<String> merged = new ArrayList<String>( tgt.size() + src.size() );
326 merged.addAll( tgt );
327 for ( String s : src )
328 {
329 if ( !excludes.contains( s ) )
330 {
331 merged.add( s );
332 }
333 }
334 target.setFilters( merged );
335 }
336 }
337
338 @Override
339 protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant,
340 Map<Object, Object> context )
341 {
342 if ( sourceDominant || target.getResources().isEmpty() )
343 {
344 super.mergeBuildBase_Resources( target, source, sourceDominant, context );
345 }
346 }
347
348 @Override
349 protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant,
350 Map<Object, Object> context )
351 {
352 if ( sourceDominant || target.getTestResources().isEmpty() )
353 {
354 super.mergeBuildBase_TestResources( target, source, sourceDominant, context );
355 }
356 }
357
358 @Override
359 protected void mergeDistributionManagement_Repository( DistributionManagement target,
360 DistributionManagement source, boolean sourceDominant,
361 Map<Object, Object> context )
362 {
363 DeploymentRepository src = source.getRepository();
364 if ( src != null )
365 {
366 DeploymentRepository tgt = target.getRepository();
367 if ( sourceDominant || tgt == null )
368 {
369 tgt = new DeploymentRepository();
370 target.setRepository( tgt );
371 mergeDeploymentRepository( tgt, src, sourceDominant, context );
372 }
373 }
374 }
375
376 @Override
377 protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement target,
378 DistributionManagement source,
379 boolean sourceDominant,
380 Map<Object, Object> context )
381 {
382 DeploymentRepository src = source.getSnapshotRepository();
383 if ( src != null )
384 {
385 DeploymentRepository tgt = target.getSnapshotRepository();
386 if ( sourceDominant || tgt == null )
387 {
388 tgt = new DeploymentRepository();
389 target.setSnapshotRepository( tgt );
390 mergeDeploymentRepository( tgt, src, sourceDominant, context );
391 }
392 }
393 }
394
395 @Override
396 protected void mergeDistributionManagement_Site( DistributionManagement target, DistributionManagement source,
397 boolean sourceDominant, Map<Object, Object> context )
398 {
399 Site src = source.getSite();
400 if ( src != null )
401 {
402 Site tgt = target.getSite();
403 if ( sourceDominant || tgt == null )
404 {
405 tgt = new Site();
406 target.setSite( tgt );
407 mergeSite( tgt, src, sourceDominant, context );
408 }
409 }
410 }
411
412 @Override
413 protected void mergeSite_Url( Site target, Site source, boolean sourceDominant, Map<Object, Object> context )
414 {
415 String src = source.getUrl();
416 if ( src != null )
417 {
418 if ( sourceDominant )
419 {
420 target.setUrl( src );
421 target.setLocation( "url", source.getLocation( "url" ) );
422 }
423 else if ( target.getUrl() == null )
424 {
425 target.setUrl( appendPath( src, context ) );
426 target.setLocation( "url", source.getLocation( "url" ) );
427 }
428 }
429 }
430
431 @Override
432 protected void mergeScm_Url( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
433 {
434 String src = source.getUrl();
435 if ( src != null )
436 {
437 if ( sourceDominant )
438 {
439 target.setUrl( src );
440 target.setLocation( "url", source.getLocation( "url" ) );
441 }
442 else if ( target.getUrl() == null )
443 {
444 target.setUrl( appendPath( src, context ) );
445 target.setLocation( "url", source.getLocation( "url" ) );
446 }
447 }
448 }
449
450 @Override
451 protected void mergeScm_Connection( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
452 {
453 String src = source.getConnection();
454 if ( src != null )
455 {
456 if ( sourceDominant )
457 {
458 target.setConnection( src );
459 target.setLocation( "connection", source.getLocation( "connection" ) );
460 }
461 else if ( target.getConnection() == null )
462 {
463 target.setConnection( appendPath( src, context ) );
464 target.setLocation( "connection", source.getLocation( "connection" ) );
465 }
466 }
467 }
468
469 @Override
470 protected void mergeScm_DeveloperConnection( Scm target, Scm source, boolean sourceDominant,
471 Map<Object, Object> context )
472 {
473 String src = source.getDeveloperConnection();
474 if ( src != null )
475 {
476 if ( sourceDominant )
477 {
478 target.setDeveloperConnection( src );
479 target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) );
480 }
481 else if ( target.getDeveloperConnection() == null )
482 {
483 target.setDeveloperConnection( appendPath( src, context ) );
484 target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) );
485 }
486 }
487 }
488
489 @Override
490 protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant,
491 Map<Object, Object> context )
492 {
493 List<PluginExecution> src = source.getExecutions();
494 if ( !src.isEmpty() )
495 {
496 List<PluginExecution> tgt = target.getExecutions();
497 Map<Object, PluginExecution> merged =
498 new LinkedHashMap<Object, PluginExecution>( ( src.size() + tgt.size() ) * 2 );
499
500 for ( PluginExecution element : src )
501 {
502 if ( sourceDominant
503 || ( element.getInherited() != null ? element.isInherited() : source.isInherited() ) )
504 {
505 Object key = getPluginExecutionKey( element );
506 merged.put( key, element );
507 }
508 }
509
510 for ( PluginExecution element : tgt )
511 {
512 Object key = getPluginExecutionKey( element );
513 PluginExecution existing = merged.get( key );
514 if ( existing != null )
515 {
516 mergePluginExecution( element, existing, sourceDominant, context );
517 }
518 merged.put( key, element );
519 }
520
521 target.setExecutions( new ArrayList<PluginExecution>( merged.values() ) );
522 }
523 }
524
525 @Override
526 protected void mergePluginExecution_Goals( PluginExecution target, PluginExecution source, boolean sourceDominant,
527 Map<Object, Object> context )
528 {
529 List<String> src = source.getGoals();
530 if ( !src.isEmpty() )
531 {
532 List<String> tgt = target.getGoals();
533 Set<String> excludes = new LinkedHashSet<String>( tgt );
534 List<String> merged = new ArrayList<String>( tgt.size() + src.size() );
535 merged.addAll( tgt );
536 for ( String s : src )
537 {
538 if ( !excludes.contains( s ) )
539 {
540 merged.add( s );
541 }
542 }
543 target.setGoals( merged );
544 }
545 }
546
547 @Override
548 protected Object getDependencyKey( Dependency dependency )
549 {
550 return dependency.getManagementKey();
551 }
552
553 @Override
554 protected Object getPluginKey( Plugin object )
555 {
556 return object.getKey();
557 }
558
559 @Override
560 protected Object getPluginExecutionKey( PluginExecution object )
561 {
562 return object.getId();
563 }
564
565 @Override
566 protected Object getReportPluginKey( ReportPlugin object )
567 {
568 return object.getKey();
569 }
570
571 @Override
572 protected Object getReportSetKey( ReportSet object )
573 {
574 return object.getId();
575 }
576
577 @Override
578 protected Object getRepositoryBaseKey( RepositoryBase object )
579 {
580 return object.getId();
581 }
582
583 @Override
584 protected Object getExtensionKey( Extension object )
585 {
586 return object.getGroupId() + ':' + object.getArtifactId();
587 }
588
589 @Override
590 protected Object getExclusionKey( Exclusion object )
591 {
592 return object.getGroupId() + ':' + object.getArtifactId();
593 }
594
595 private String appendPath( String parentPath, Map<Object, Object> context )
596 {
597 Object artifactId = context.get( ARTIFACT_ID );
598 Object childPathAdjustment = context.get( CHILD_PATH_ADJUSTMENT );
599
600 if ( artifactId != null && childPathAdjustment != null )
601 {
602 return appendPath( parentPath, artifactId.toString(), childPathAdjustment.toString() );
603 }
604 else
605 {
606 return parentPath;
607 }
608 }
609
610 private String appendPath( String parentPath, String childPath, String pathAdjustment )
611 {
612 String path = parentPath;
613 path = concatPath( path, pathAdjustment );
614 path = concatPath( path, childPath );
615 return path;
616 }
617
618 private String concatPath( String base, String path )
619 {
620 String result = base;
621
622 if ( path != null && path.length() > 0 )
623 {
624 if ( ( result.endsWith( "/" ) && !path.startsWith( "/" ) )
625 || ( !result.endsWith( "/" ) && path.startsWith( "/" ) ) )
626 {
627 result += path;
628 }
629 else if ( result.endsWith( "/" ) && path.startsWith( "/" ) )
630 {
631 result += path.substring( 1 );
632 }
633 else
634 {
635 result += '/';
636 result += path;
637 }
638 if ( base.endsWith( "/" ) && !result.endsWith( "/" ) )
639 {
640 result += '/';
641 }
642 }
643
644 return result;
645 }
646
647 }