1 package org.apache.maven.plugin.resources.remote;
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.LinkedList;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.StringTokenizer;
29 import java.util.TreeMap;
30
31 import org.apache.maven.model.Build;
32 import org.apache.maven.model.Dependency;
33 import org.apache.maven.model.DependencyManagement;
34 import org.apache.maven.model.DeploymentRepository;
35 import org.apache.maven.model.DistributionManagement;
36 import org.apache.maven.model.Extension;
37 import org.apache.maven.model.Model;
38 import org.apache.maven.model.PluginManagement;
39 import org.apache.maven.model.ReportPlugin;
40 import org.apache.maven.model.ReportSet;
41 import org.apache.maven.model.Reporting;
42 import org.apache.maven.model.Resource;
43 import org.apache.maven.model.Scm;
44 import org.apache.maven.model.Site;
45 import org.codehaus.plexus.util.StringUtils;
46 import org.codehaus.plexus.util.xml.Xpp3Dom;
47
48
49
50
51 public class ModelInheritanceAssembler
52 {
53
54 public void assembleBuildInheritance( Build childBuild, Build parentBuild, boolean handleAsInheritance )
55 {
56
57
58
59 if ( childBuild.getSourceDirectory() == null )
60 {
61 childBuild.setSourceDirectory( parentBuild.getSourceDirectory() );
62 }
63
64 if ( childBuild.getScriptSourceDirectory() == null )
65 {
66 childBuild.setScriptSourceDirectory( parentBuild.getScriptSourceDirectory() );
67 }
68
69 if ( childBuild.getTestSourceDirectory() == null )
70 {
71 childBuild.setTestSourceDirectory( parentBuild.getTestSourceDirectory() );
72 }
73
74 if ( childBuild.getOutputDirectory() == null )
75 {
76 childBuild.setOutputDirectory( parentBuild.getOutputDirectory() );
77 }
78
79 if ( childBuild.getTestOutputDirectory() == null )
80 {
81 childBuild.setTestOutputDirectory( parentBuild.getTestOutputDirectory() );
82 }
83
84
85 mergeExtensionLists( childBuild, parentBuild );
86
87 if ( childBuild.getDirectory() == null )
88 {
89 childBuild.setDirectory( parentBuild.getDirectory() );
90 }
91
92 if ( childBuild.getDefaultGoal() == null )
93 {
94 childBuild.setDefaultGoal( parentBuild.getDefaultGoal() );
95 }
96
97 if ( childBuild.getFinalName() == null )
98 {
99 childBuild.setFinalName( parentBuild.getFinalName() );
100 }
101
102 ModelUtils.mergeFilterLists( childBuild.getFilters(), parentBuild.getFilters() );
103
104 List<Resource> resources = childBuild.getResources();
105 if ( ( resources == null ) || resources.isEmpty() )
106 {
107 childBuild.setResources( parentBuild.getResources() );
108 }
109
110 resources = childBuild.getTestResources();
111 if ( ( resources == null ) || resources.isEmpty() )
112 {
113 childBuild.setTestResources( parentBuild.getTestResources() );
114 }
115
116
117 ModelUtils.mergePluginLists( childBuild, parentBuild, handleAsInheritance );
118
119
120 PluginManagement dominantPM = childBuild.getPluginManagement();
121 PluginManagement recessivePM = parentBuild.getPluginManagement();
122
123 if ( ( dominantPM == null ) && ( recessivePM != null ) )
124 {
125
126 childBuild.setPluginManagement( recessivePM );
127 }
128 else
129 {
130 ModelUtils.mergePluginLists( childBuild.getPluginManagement(), parentBuild.getPluginManagement(), false );
131 }
132 }
133
134 private void assembleScmInheritance( Model child, Model parent, String childPathAdjustment, boolean appendPaths )
135 {
136 if ( parent.getScm() != null )
137 {
138 Scm parentScm = parent.getScm();
139
140 Scm childScm = child.getScm();
141
142 if ( childScm == null )
143 {
144 childScm = new Scm();
145
146 child.setScm( childScm );
147 }
148
149 if ( StringUtils.isEmpty( childScm.getConnection() ) && !StringUtils.isEmpty( parentScm.getConnection() ) )
150 {
151 childScm.setConnection(
152 appendPath( parentScm.getConnection(), child.getArtifactId(), childPathAdjustment, appendPaths ) );
153 }
154
155 if ( StringUtils.isEmpty( childScm.getDeveloperConnection() )
156 && !StringUtils.isEmpty( parentScm.getDeveloperConnection() ) )
157 {
158 childScm
159 .setDeveloperConnection( appendPath( parentScm.getDeveloperConnection(), child.getArtifactId(),
160 childPathAdjustment, appendPaths ) );
161 }
162
163 if ( StringUtils.isEmpty( childScm.getUrl() ) && !StringUtils.isEmpty( parentScm.getUrl() ) )
164 {
165 childScm.setUrl(
166 appendPath( parentScm.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) );
167 }
168 }
169 }
170
171 public void copyModel( Model dest, Model source )
172 {
173 assembleModelInheritance( dest, source, null, false );
174 }
175
176 public void assembleModelInheritance( Model child, Model parent, String childPathAdjustment )
177 {
178 assembleModelInheritance( child, parent, childPathAdjustment, true );
179 }
180
181 public void assembleModelInheritance( Model child, Model parent )
182 {
183 assembleModelInheritance( child, parent, null, true );
184 }
185
186 private void assembleModelInheritance( Model child, Model parent, String childPathAdjustment, boolean appendPaths )
187 {
188
189 if ( parent == null )
190 {
191 return;
192 }
193
194
195 if ( child.getGroupId() == null )
196 {
197 child.setGroupId( parent.getGroupId() );
198 }
199
200
201 if ( child.getVersion() == null )
202 {
203
204
205
206 if ( child.getParent() != null )
207 {
208 child.setVersion( child.getParent().getVersion() );
209 }
210 }
211
212
213 if ( child.getInceptionYear() == null )
214 {
215 child.setInceptionYear( parent.getInceptionYear() );
216 }
217
218
219 if ( child.getUrl() == null )
220 {
221 if ( parent.getUrl() != null )
222 {
223 child.setUrl( appendPath( parent.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) );
224 }
225 else
226 {
227 child.setUrl( parent.getUrl() );
228 }
229 }
230
231 assembleDistributionInheritance( child, parent, childPathAdjustment, appendPaths );
232
233
234 if ( child.getIssueManagement() == null )
235 {
236 child.setIssueManagement( parent.getIssueManagement() );
237 }
238
239
240 if ( child.getDescription() == null )
241 {
242 child.setDescription( parent.getDescription() );
243 }
244
245
246 if ( child.getOrganization() == null )
247 {
248 child.setOrganization( parent.getOrganization() );
249 }
250
251
252 assembleScmInheritance( child, parent, childPathAdjustment, appendPaths );
253
254
255 if ( child.getCiManagement() == null )
256 {
257 child.setCiManagement( parent.getCiManagement() );
258 }
259
260
261 if ( child.getDevelopers().size() == 0 )
262 {
263 child.setDevelopers( parent.getDevelopers() );
264 }
265
266
267 if ( child.getLicenses().size() == 0 )
268 {
269 child.setLicenses( parent.getLicenses() );
270 }
271
272
273 if ( child.getContributors().size() == 0 )
274 {
275 child.setContributors( parent.getContributors() );
276 }
277
278
279 if ( child.getMailingLists().size() == 0 )
280 {
281 child.setMailingLists( parent.getMailingLists() );
282 }
283
284
285 assembleBuildInheritance( child, parent );
286
287 assembleDependencyInheritance( child, parent );
288
289 child.setRepositories( ModelUtils.mergeRepositoryLists( child.getRepositories(), parent.getRepositories() ) );
290
291
292
293 assembleReportingInheritance( child, parent );
294
295 assembleDependencyManagementInheritance( child, parent );
296
297 Properties props = new Properties();
298 props.putAll( parent.getProperties() );
299 props.putAll( child.getProperties() );
300
301 child.setProperties( props );
302 }
303
304
305 private void assembleDependencyManagementInheritance( Model child, Model parent )
306 {
307 DependencyManagement parentDepMgmt = parent.getDependencyManagement();
308
309 DependencyManagement childDepMgmt = child.getDependencyManagement();
310
311 if ( parentDepMgmt != null )
312 {
313 if ( childDepMgmt == null )
314 {
315 child.setDependencyManagement( parentDepMgmt );
316 }
317 else
318 {
319 List<Dependency> childDeps = childDepMgmt.getDependencies();
320
321 Map<String, Dependency> mappedChildDeps = new TreeMap<>();
322 for ( Dependency dep : childDeps )
323 {
324 mappedChildDeps.put( dep.getManagementKey(), dep );
325 }
326
327 for ( Dependency dep : parentDepMgmt.getDependencies() )
328 {
329 if ( !mappedChildDeps.containsKey( dep.getManagementKey() ) )
330 {
331 childDepMgmt.addDependency( dep );
332 }
333 }
334 }
335 }
336 }
337
338 private void assembleReportingInheritance( Model child, Model parent )
339 {
340
341 Reporting childReporting = child.getReporting();
342 Reporting parentReporting = parent.getReporting();
343
344 if ( parentReporting != null )
345 {
346 if ( childReporting == null )
347 {
348 childReporting = new Reporting();
349 child.setReporting( childReporting );
350 }
351
352 childReporting.setExcludeDefaults( parentReporting.isExcludeDefaults() );
353
354 if ( StringUtils.isEmpty( childReporting.getOutputDirectory() ) )
355 {
356 childReporting.setOutputDirectory( parentReporting.getOutputDirectory() );
357 }
358
359 mergeReportPluginLists( childReporting, parentReporting, true );
360 }
361 }
362
363 private static void mergeReportPluginLists( Reporting child, Reporting parent, boolean handleAsInheritance )
364 {
365 if ( ( child == null ) || ( parent == null ) )
366 {
367
368 return;
369 }
370
371 List<ReportPlugin> parentPlugins = parent.getPlugins();
372
373 if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() )
374 {
375 Map<String, ReportPlugin> assembledPlugins = new TreeMap<>();
376
377 Map<String, ReportPlugin> childPlugins = child.getReportPluginsAsMap();
378
379 for ( ReportPlugin parentPlugin : parentPlugins )
380 {
381 String parentInherited = parentPlugin.getInherited();
382
383 if ( !handleAsInheritance || ( parentInherited == null ) || Boolean.parseBoolean( parentInherited ) )
384 {
385
386 ReportPlugin assembledPlugin = parentPlugin;
387
388 ReportPlugin childPlugin = childPlugins.get( parentPlugin.getKey() );
389
390 if ( childPlugin != null )
391 {
392 assembledPlugin = childPlugin;
393
394 mergeReportPluginDefinitions( childPlugin, parentPlugin, handleAsInheritance );
395 }
396
397 if ( handleAsInheritance && ( parentInherited == null ) )
398 {
399 assembledPlugin.unsetInheritanceApplied();
400 }
401
402 assembledPlugins.put( assembledPlugin.getKey(), assembledPlugin );
403 }
404 }
405
406 for ( ReportPlugin childPlugin : childPlugins.values() )
407 {
408 if ( !assembledPlugins.containsKey( childPlugin.getKey() ) )
409 {
410 assembledPlugins.put( childPlugin.getKey(), childPlugin );
411 }
412 }
413
414 child.setPlugins( new ArrayList<>( assembledPlugins.values() ) );
415
416 child.flushReportPluginMap();
417 }
418 }
419
420 private static void mergeReportSetDefinitions( ReportSet child, ReportSet parent )
421 {
422 List<String> parentReports = parent.getReports();
423 List<String> childReports = child.getReports();
424
425 List<String> reports = new ArrayList<>();
426
427 if ( ( childReports != null ) && !childReports.isEmpty() )
428 {
429 reports.addAll( childReports );
430 }
431
432 if ( parentReports != null )
433 {
434 for ( String report : parentReports )
435 {
436 if ( !reports.contains( report ) )
437 {
438 reports.add( report );
439 }
440 }
441 }
442
443 child.setReports( reports );
444
445 Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
446 Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
447
448 childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
449
450 child.setConfiguration( childConfiguration );
451 }
452
453
454 public static void mergeReportPluginDefinitions( ReportPlugin child, ReportPlugin parent,
455 boolean handleAsInheritance )
456 {
457 if ( ( child == null ) || ( parent == null ) )
458 {
459
460 return;
461 }
462
463 if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) )
464 {
465 child.setVersion( parent.getVersion() );
466 }
467
468
469 String parentInherited = parent.getInherited();
470
471 boolean parentIsInherited = ( parentInherited == null ) || Boolean.parseBoolean( parentInherited );
472
473 List<ReportSet> parentReportSets = parent.getReportSets();
474
475 if ( ( parentReportSets != null ) && !parentReportSets.isEmpty() )
476 {
477 Map<String, ReportSet> assembledReportSets = new TreeMap<>();
478
479 Map<String, ReportSet> childReportSets = child.getReportSetsAsMap();
480
481 for ( Object parentReportSet1 : parentReportSets )
482 {
483 ReportSet parentReportSet = (ReportSet) parentReportSet1;
484
485 if ( !handleAsInheritance || parentIsInherited )
486 {
487 ReportSet assembledReportSet = parentReportSet;
488
489 ReportSet childReportSet = childReportSets.get( parentReportSet.getId() );
490
491 if ( childReportSet != null )
492 {
493 mergeReportSetDefinitions( childReportSet, parentReportSet );
494
495 assembledReportSet = childReportSet;
496 }
497 else if ( handleAsInheritance && ( parentInherited == null ) )
498 {
499 parentReportSet.unsetInheritanceApplied();
500 }
501
502 assembledReportSets.put( assembledReportSet.getId(), assembledReportSet );
503 }
504 }
505
506 for ( Map.Entry<String, ReportSet> entry : childReportSets.entrySet() )
507 {
508 String id = entry.getKey();
509
510 if ( !assembledReportSets.containsKey( id ) )
511 {
512 assembledReportSets.put( id, entry.getValue() );
513 }
514 }
515
516 child.setReportSets( new ArrayList<>( assembledReportSets.values() ) );
517
518 child.flushReportSetMap();
519 }
520
521 }
522
523
524 private void assembleDependencyInheritance( Model child, Model parent )
525 {
526 Map<String, Dependency> depsMap = new LinkedHashMap<>();
527
528 List<Dependency> deps = parent.getDependencies();
529
530 if ( deps != null )
531 {
532 for ( Dependency dependency : deps )
533 {
534 depsMap.put( dependency.getManagementKey(), dependency );
535 }
536 }
537
538 deps = child.getDependencies();
539
540 if ( deps != null )
541 {
542 for ( Dependency dependency : deps )
543 {
544 depsMap.put( dependency.getManagementKey(), dependency );
545 }
546 }
547
548 child.setDependencies( new ArrayList<>( depsMap.values() ) );
549 }
550
551 private void assembleBuildInheritance( Model child, Model parent )
552 {
553 Build childBuild = child.getBuild();
554 Build parentBuild = parent.getBuild();
555
556 if ( parentBuild != null )
557 {
558 if ( childBuild == null )
559 {
560 childBuild = new Build();
561 child.setBuild( childBuild );
562 }
563
564 assembleBuildInheritance( childBuild, parentBuild, true );
565 }
566 }
567
568 private void assembleDistributionInheritance( Model child, Model parent, String childPathAdjustment,
569 boolean appendPaths )
570 {
571 if ( parent.getDistributionManagement() != null )
572 {
573 DistributionManagement parentDistMgmt = parent.getDistributionManagement();
574
575 DistributionManagement childDistMgmt = child.getDistributionManagement();
576
577 if ( childDistMgmt == null )
578 {
579 childDistMgmt = new DistributionManagement();
580
581 child.setDistributionManagement( childDistMgmt );
582 }
583
584 if ( childDistMgmt.getSite() == null )
585 {
586 if ( parentDistMgmt.getSite() != null )
587 {
588 Site site = new Site();
589
590 childDistMgmt.setSite( site );
591
592 site.setId( parentDistMgmt.getSite().getId() );
593
594 site.setName( parentDistMgmt.getSite().getName() );
595
596 site.setUrl( parentDistMgmt.getSite().getUrl() );
597
598 if ( site.getUrl() != null )
599 {
600 site.setUrl(
601 appendPath( site.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) );
602 }
603 }
604 }
605
606 if ( childDistMgmt.getRepository() == null )
607 {
608 if ( parentDistMgmt.getRepository() != null )
609 {
610 DeploymentRepository repository = copyDistributionRepository( parentDistMgmt.getRepository() );
611 childDistMgmt.setRepository( repository );
612 }
613 }
614
615 if ( childDistMgmt.getSnapshotRepository() == null )
616 {
617 if ( parentDistMgmt.getSnapshotRepository() != null )
618 {
619 DeploymentRepository repository =
620 copyDistributionRepository( parentDistMgmt.getSnapshotRepository() );
621 childDistMgmt.setSnapshotRepository( repository );
622 }
623 }
624
625 if ( StringUtils.isEmpty( childDistMgmt.getDownloadUrl() ) )
626 {
627 childDistMgmt.setDownloadUrl( parentDistMgmt.getDownloadUrl() );
628 }
629
630
631
632 }
633 }
634
635 private static DeploymentRepository copyDistributionRepository( DeploymentRepository parentRepository )
636 {
637 DeploymentRepository repository = new DeploymentRepository();
638
639 repository.setId( parentRepository.getId() );
640
641 repository.setName( parentRepository.getName() );
642
643 repository.setUrl( parentRepository.getUrl() );
644
645 repository.setLayout( parentRepository.getLayout() );
646
647 repository.setUniqueVersion( parentRepository.isUniqueVersion() );
648
649 return repository;
650 }
651
652
653 protected String appendPath( String parentPath, String childPath, String pathAdjustment, boolean appendPaths )
654 {
655 String uncleanPath = parentPath;
656
657 if ( appendPaths )
658 {
659 if ( pathAdjustment != null )
660 {
661 uncleanPath += "/" + pathAdjustment;
662 }
663
664 if ( childPath != null )
665 {
666 uncleanPath += "/" + childPath;
667 }
668 }
669
670 String cleanedPath = "";
671
672 int protocolIdx = uncleanPath.indexOf( "://" );
673
674 if ( protocolIdx > -1 )
675 {
676 cleanedPath = uncleanPath.substring( 0, protocolIdx + 3 );
677 uncleanPath = uncleanPath.substring( protocolIdx + 3 );
678 }
679
680 if ( uncleanPath.startsWith( "/" ) )
681 {
682 cleanedPath += "/";
683 }
684
685 return cleanedPath + resolvePath( uncleanPath );
686 }
687
688
689 private static String resolvePath( String uncleanPath )
690 {
691 LinkedList<String> pathElements = new LinkedList<>();
692
693 StringTokenizer tokenizer = new StringTokenizer( uncleanPath, "/" );
694
695 while ( tokenizer.hasMoreTokens() )
696 {
697 String token = tokenizer.nextToken();
698
699 switch ( token )
700 {
701 case "":
702
703 break;
704 case "..":
705 if ( pathElements.isEmpty() )
706 {
707
708
709
710 }
711 else
712 {
713 pathElements.removeLast();
714 }
715 break;
716 default:
717 pathElements.addLast( token );
718 break;
719 }
720 }
721
722 StringBuilder cleanedPath = new StringBuilder();
723
724 while ( !pathElements.isEmpty() )
725 {
726 cleanedPath.append( pathElements.removeFirst() );
727 if ( !pathElements.isEmpty() )
728 {
729 cleanedPath.append( '/' );
730 }
731 }
732
733 return cleanedPath.toString();
734 }
735
736 private static void mergeExtensionLists( Build childBuild, Build parentBuild )
737 {
738 for ( Extension e : parentBuild.getExtensions() )
739 {
740 if ( !childBuild.getExtensions().contains( e ) )
741 {
742 childBuild.addExtension( e );
743 }
744 }
745 }
746 }