View Javadoc

1   package org.apache.maven.project;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.model.Activation;
23  import org.apache.maven.model.ActivationFile;
24  import org.apache.maven.model.ActivationProperty;
25  import org.apache.maven.model.Build;
26  import org.apache.maven.model.BuildBase;
27  import org.apache.maven.model.Dependency;
28  import org.apache.maven.model.DependencyManagement;
29  import org.apache.maven.model.DeploymentRepository;
30  import org.apache.maven.model.DistributionManagement;
31  import org.apache.maven.model.Exclusion;
32  import org.apache.maven.model.Extension;
33  import org.apache.maven.model.Model;
34  import org.apache.maven.model.Parent;
35  import org.apache.maven.model.Plugin;
36  import org.apache.maven.model.PluginContainer;
37  import org.apache.maven.model.PluginExecution;
38  import org.apache.maven.model.PluginManagement;
39  import org.apache.maven.model.Profile;
40  import org.apache.maven.model.Relocation;
41  import org.apache.maven.model.ReportPlugin;
42  import org.apache.maven.model.ReportSet;
43  import org.apache.maven.model.Reporting;
44  import org.apache.maven.model.Repository;
45  import org.apache.maven.model.RepositoryBase;
46  import org.apache.maven.model.RepositoryPolicy;
47  import org.apache.maven.model.Resource;
48  import org.apache.maven.model.Site;
49  import org.apache.maven.project.inheritance.DefaultModelInheritanceAssembler;
50  import org.apache.maven.project.inheritance.ModelInheritanceAssembler;
51  import org.codehaus.plexus.util.xml.Xpp3Dom;
52  
53  import java.util.ArrayList;
54  import java.util.Iterator;
55  import java.util.LinkedHashMap;
56  import java.util.List;
57  import java.util.Map;
58  import java.util.Properties;
59  import java.util.TreeMap;
60  
61  public final class ModelUtils
62  {
63  
64      /**
65       * Given this plugin list:
66       *
67       * A1 -> B -> C -> A2 -> D
68       *
69       * Rearrange it to this:
70       *
71       * A(A1 + A2) -> B -> C -> D
72       *
73       * In cases of overlapping definitions, A1 is overridden by A2
74       *
75       */
76      public static void mergeDuplicatePluginDefinitions( PluginContainer pluginContainer )
77      {
78          if ( pluginContainer == null )
79          {
80              return;
81          }
82  
83          List originalPlugins = pluginContainer.getPlugins();
84  
85          if ( ( originalPlugins == null ) || originalPlugins.isEmpty() )
86          {
87              return;
88          }
89  
90          List normalized = new ArrayList( originalPlugins.size() );
91  
92          for ( Iterator it = originalPlugins.iterator(); it.hasNext(); )
93          {
94              Plugin currentPlugin = (Plugin) it.next();
95  
96              if ( normalized.contains( currentPlugin ) )
97              {
98                  int idx = normalized.indexOf( currentPlugin );
99                  Plugin firstPlugin = (Plugin) normalized.get( idx );
100 
101                 // MNG-3719: merge currentPlugin with firstPlugin as parent,
102                 // then use updated currentPlugin as new parent
103                 mergePluginDefinitions( currentPlugin, firstPlugin, false );
104                 normalized.set(idx, currentPlugin);
105             }
106             else
107             {
108                 normalized.add( currentPlugin );
109             }
110         }
111 
112         pluginContainer.setPlugins( normalized );
113     }
114 
115     /**
116      * This should be the resulting ordering of plugins after merging:
117      *
118      * Given:
119      *
120      *   parent: X -> A -> B -> D -> E
121      *   child: Y -> A -> C -> D -> F
122      *
123      * Result:
124      *
125      *   X -> Y -> A -> B -> C -> D -> E -> F
126      */
127     public static void mergePluginLists( PluginContainer child, PluginContainer parent,
128                                          boolean handleAsInheritance )
129     {
130         if ( ( child == null ) || ( parent == null ) )
131         {
132             // nothing to do.
133             return;
134         }
135 
136         List parentPlugins = parent.getPlugins();
137 
138         if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() )
139         {
140             parentPlugins = new ArrayList( parentPlugins );
141 
142             // If we're processing this merge as an inheritance, we have to build up a list of
143             // plugins that were considered for inheritance.
144             if ( handleAsInheritance )
145             {
146                 for ( Iterator it = parentPlugins.iterator(); it.hasNext(); )
147                 {
148                     Plugin plugin = (Plugin) it.next();
149 
150                     String inherited = plugin.getInherited();
151 
152                     if ( ( inherited != null ) && !Boolean.valueOf( inherited ).booleanValue() )
153                     {
154                         it.remove();
155                     }
156                 }
157             }
158 
159             List assembledPlugins = new ArrayList();
160 
161             Map childPlugins = child.getPluginsAsMap();
162 
163             for ( Iterator it = parentPlugins.iterator(); it.hasNext(); )
164             {
165                 Plugin parentPlugin = (Plugin) it.next();
166 
167                 String parentInherited = parentPlugin.getInherited();
168 
169                 // only merge plugin definition from the parent if at least one
170                 // of these is true:
171                 // 1. we're not processing the plugins in an inheritance-based merge
172                 // 2. the parent's <inherited/> flag is not set
173                 // 3. the parent's <inherited/> flag is set to true
174                 if ( !handleAsInheritance || ( parentInherited == null ) ||
175                     Boolean.valueOf( parentInherited ).booleanValue() )
176                 {
177                     Plugin childPlugin = (Plugin) childPlugins.get( parentPlugin.getKey() );
178 
179                     if ( ( childPlugin != null ) && !assembledPlugins.contains( childPlugin ) )
180                     {
181                         Plugin assembledPlugin = childPlugin;
182 
183                         mergePluginDefinitions( childPlugin, parentPlugin, handleAsInheritance );
184 
185                         // fix for MNG-2221 (assembly cache was not being populated for later reference):
186                         assembledPlugins.add( assembledPlugin );
187                     }
188 
189                     // if we're processing this as an inheritance-based merge, and
190                     // the parent's <inherited/> flag is not set, then we need to
191                     // clear the inherited flag in the merge result.
192                     if ( handleAsInheritance && ( parentInherited == null ) )
193                     {
194                         parentPlugin.unsetInheritanceApplied();
195                     }
196                 }
197 
198                 // very important to use the parentPlugins List, rather than parentContainer.getPlugins()
199                 // since this list is a local one, and may have been modified during processing.
200                 List results = ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins,
201                                                                         child.getPlugins() );
202 
203 
204                 child.setPlugins( results );
205 
206                 child.flushPluginMap();
207             }
208         }
209     }
210 
211     public static List orderAfterMerge( List merged, List highPrioritySource, List lowPrioritySource )
212     {
213         List results = new ArrayList();
214 
215         if ( !merged.isEmpty() )
216         {
217             results.addAll( merged );
218         }
219 
220         List missingFromResults = new ArrayList();
221 
222         List sources = new ArrayList();
223 
224         sources.add( highPrioritySource );
225         sources.add( lowPrioritySource );
226 
227         for ( Iterator sourceIterator = sources.iterator(); sourceIterator.hasNext(); )
228         {
229             List source = (List) sourceIterator.next();
230 
231             for ( Iterator it = source.iterator(); it.hasNext(); )
232             {
233                 Object item = it.next();
234 
235                 if ( results.contains( item ) )
236                 {
237                     if ( !missingFromResults.isEmpty() )
238                     {
239                         int idx = results.indexOf( item );
240 
241                         if ( idx < 0 )
242                         {
243                             idx = 0;
244                         }
245 
246                         results.addAll( idx, missingFromResults );
247 
248                         missingFromResults.clear();
249                     }
250                 }
251                 else
252                 {
253                     missingFromResults.add( item );
254                 }
255             }
256 
257             if ( !missingFromResults.isEmpty() )
258             {
259                 results.addAll( missingFromResults );
260 
261                 missingFromResults.clear();
262             }
263         }
264 
265         return results;
266     }
267 
268     /**
269      * Merge the list of reporting plugins from parent pom and child pom
270      * TODO it's pretty much a copy of {@link #mergePluginLists(PluginContainer, PluginContainer, boolean)}
271      * 
272      * @param child
273      * @param parent
274      * @param handleAsInheritance
275      */
276     public static void mergeReportPluginLists( Reporting child, Reporting parent, boolean handleAsInheritance )
277     {
278         if ( ( child == null ) || ( parent == null ) )
279         {
280             // nothing to do.
281             return;
282         }
283 
284         List parentPlugins = parent.getPlugins();
285 
286         if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() )
287         {
288             parentPlugins = new ArrayList( parentPlugins );
289 
290             // If we're processing this merge as an inheritance, we have to build up a list of
291             // plugins that were considered for inheritance.
292             if ( handleAsInheritance )
293             {
294                 for ( Iterator it = parentPlugins.iterator(); it.hasNext(); )
295                 {
296                     ReportPlugin plugin = (ReportPlugin) it.next();
297 
298                     String inherited = plugin.getInherited();
299 
300                     if ( ( inherited != null ) && !Boolean.valueOf( inherited ).booleanValue() )
301                     {
302                         it.remove();
303                     }
304                 }
305             }
306 
307             List assembledPlugins = new ArrayList();
308 
309             Map childPlugins = child.getReportPluginsAsMap();
310 
311             for ( Iterator it = parentPlugins.iterator(); it.hasNext(); )
312             {
313                 ReportPlugin parentPlugin = (ReportPlugin) it.next();
314 
315                 String parentInherited = parentPlugin.getInherited();
316 
317                 // only merge plugin definition from the parent if at least one
318                 // of these is true:
319                 // 1. we're not processing the plugins in an inheritance-based merge
320                 // 2. the parent's <inherited/> flag is not set
321                 // 3. the parent's <inherited/> flag is set to true
322                 if ( !handleAsInheritance || ( parentInherited == null ) ||
323                     Boolean.valueOf( parentInherited ).booleanValue() )
324                 {
325                     ReportPlugin childPlugin = (ReportPlugin) childPlugins.get( parentPlugin.getKey() );
326 
327                     if ( ( childPlugin != null ) && !assembledPlugins.contains( childPlugin ) )
328                     {
329                         ReportPlugin assembledPlugin = childPlugin;
330 
331                         mergeReportPluginDefinitions( childPlugin, parentPlugin, handleAsInheritance );
332 
333                         // fix for MNG-2221 (assembly cache was not being populated for later reference):
334                         assembledPlugins.add( assembledPlugin );
335                     }
336 
337                     // if we're processing this as an inheritance-based merge, and
338                     // the parent's <inherited/> flag is not set, then we need to
339                     // clear the inherited flag in the merge result.
340                     if ( handleAsInheritance && ( parentInherited == null ) )
341                     {
342                         parentPlugin.unsetInheritanceApplied();
343                     }
344                 }
345 
346                 // very important to use the parentPlugins List, rather than parentContainer.getPlugins()
347                 // since this list is a local one, and may have been modified during processing.
348                 List results = ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins,
349                                                                         child.getPlugins() );
350 
351                 child.setPlugins( results );
352 
353                 child.flushReportPluginMap();
354             }
355         }
356     }
357 
358     public static void mergePluginDefinitions( Plugin child, Plugin parent, boolean handleAsInheritance )
359     {
360         if ( ( child == null ) || ( parent == null ) )
361         {
362             // nothing to do.
363             return;
364         }
365 
366         if ( parent.isExtensions() )
367         {
368             child.setExtensions( true );
369         }
370 
371         if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) )
372         {
373             child.setVersion( parent.getVersion() );
374         }
375 
376         Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
377         Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
378 
379         childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
380 
381         child.setConfiguration( childConfiguration );
382 
383         child.setDependencies( mergeDependencyList( child.getDependencies(), parent.getDependencies() ) );
384 
385         // from here to the end of the method is dealing with merging of the <executions/> section.
386         String parentInherited = parent.getInherited();
387 
388         boolean parentIsInherited = ( parentInherited == null ) || Boolean.valueOf( parentInherited ).booleanValue();
389 
390         List parentExecutions = parent.getExecutions();
391 
392         if ( ( parentExecutions != null ) && !parentExecutions.isEmpty() )
393         {
394             List mergedExecutions = new ArrayList();
395 
396             Map assembledExecutions = new TreeMap();
397 
398             Map childExecutions = child.getExecutionsAsMap();
399 
400             for ( Iterator it = parentExecutions.iterator(); it.hasNext(); )
401             {
402                 PluginExecution parentExecution = (PluginExecution) it.next();
403 
404                 String inherited = parentExecution.getInherited();
405 
406                 boolean parentExecInherited = parentIsInherited && ( ( inherited == null ) || Boolean.valueOf( inherited ).booleanValue() );
407 
408                 if ( !handleAsInheritance || parentExecInherited )
409                 {
410                     PluginExecution assembled = parentExecution;
411 
412                     PluginExecution childExecution = (PluginExecution) childExecutions.get( parentExecution.getId() );
413 
414                     if ( childExecution != null )
415                     {
416                         mergePluginExecutionDefinitions( childExecution, parentExecution );
417 
418                         assembled = childExecution;
419                     }
420                     else if ( handleAsInheritance && ( parentInherited == null ) )
421                     {
422                         parentExecution.unsetInheritanceApplied();
423                     }
424 
425                     assembledExecutions.put( assembled.getId(), assembled );
426                     mergedExecutions.add(assembled);
427                 }
428             }
429 
430             for ( Iterator it = child.getExecutions().iterator(); it.hasNext(); )
431             {
432                 PluginExecution childExecution = (PluginExecution)it.next();
433 
434                 if ( !assembledExecutions.containsKey( childExecution.getId() ) )
435                 {
436                     mergedExecutions.add(childExecution);
437                 }
438             }
439 
440             child.setExecutions(mergedExecutions);
441 
442             child.flushExecutionMap();
443         }
444 
445     }
446 
447     public static void mergeReportPluginDefinitions( ReportPlugin child, ReportPlugin parent,
448                                                      boolean handleAsInheritance )
449     {
450         if ( ( child == null ) || ( parent == null ) )
451         {
452             // nothing to do.
453             return;
454         }
455 
456         if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) )
457         {
458             child.setVersion( parent.getVersion() );
459         }
460 
461         String parentInherited = parent.getInherited();
462 
463         boolean parentIsInherited = ( parentInherited == null ) || Boolean.valueOf( parentInherited ).booleanValue();
464 
465         // merge configuration just like with build plugins	
466         if ( parentIsInherited )
467         {
468             Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
469             Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
470 
471             childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
472 
473             child.setConfiguration( childConfiguration );
474         }
475 
476         // from here to the end of the method is dealing with merging of the <executions/> section.
477         List parentReportSets = parent.getReportSets();
478 
479         if ( ( parentReportSets != null ) && !parentReportSets.isEmpty() )
480         {
481             Map assembledReportSets = new TreeMap();
482 
483             Map childReportSets = child.getReportSetsAsMap();
484 
485             for ( Iterator it = parentReportSets.iterator(); it.hasNext(); )
486             {
487                 ReportSet parentReportSet = (ReportSet) it.next();
488 
489                 if ( !handleAsInheritance || parentIsInherited )
490                 {
491                     ReportSet assembledReportSet = parentReportSet;
492 
493                     ReportSet childReportSet = (ReportSet) childReportSets.get( parentReportSet.getId() );
494 
495                     if ( childReportSet != null )
496                     {
497                         mergeReportSetDefinitions( childReportSet, parentReportSet );
498 
499                         assembledReportSet = childReportSet;
500                     }
501                     else if ( handleAsInheritance && ( parentInherited == null ) )
502                     {
503                         parentReportSet.unsetInheritanceApplied();
504                     }
505 
506                     assembledReportSets.put( assembledReportSet.getId(), assembledReportSet );
507                 }
508             }
509 
510             for ( Iterator it = childReportSets.entrySet().iterator(); it.hasNext(); )
511             {
512                 Map.Entry entry = (Map.Entry) it.next();
513 
514                 String id = (String) entry.getKey();
515 
516                 if ( !assembledReportSets.containsKey( id ) )
517                 {
518                     assembledReportSets.put( id, entry.getValue() );
519                 }
520             }
521 
522             child.setReportSets( new ArrayList( assembledReportSets.values() ) );
523 
524             child.flushReportSetMap();
525         }
526 
527     }
528 
529     private static void mergePluginExecutionDefinitions( PluginExecution child, PluginExecution parent )
530     {
531         if ( child.getPhase() == null )
532         {
533             child.setPhase( parent.getPhase() );
534         }
535 
536         List parentGoals = parent.getGoals();
537         List childGoals = child.getGoals();
538 
539         List goals = new ArrayList();
540 
541         if ( ( childGoals != null ) && !childGoals.isEmpty() )
542         {
543             goals.addAll( childGoals );
544         }
545 
546         if ( parentGoals != null )
547         {
548             for ( Iterator goalIterator = parentGoals.iterator(); goalIterator.hasNext(); )
549             {
550                 String goal = (String) goalIterator.next();
551 
552                 if ( !goals.contains( goal ) )
553                 {
554                     goals.add( goal );
555                 }
556             }
557         }
558 
559         child.setGoals( goals );
560 
561         Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
562         Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
563 
564         childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
565 
566         child.setConfiguration( childConfiguration );
567     }
568 
569     private static void mergeReportSetDefinitions( ReportSet child, ReportSet parent )
570     {
571         List parentReports = parent.getReports();
572         List childReports = child.getReports();
573 
574         List reports = new ArrayList();
575 
576         if ( ( childReports != null ) && !childReports.isEmpty() )
577         {
578             reports.addAll( childReports );
579         }
580 
581         if ( parentReports != null )
582         {
583             for ( Iterator i = parentReports.iterator(); i.hasNext(); )
584             {
585                 String report = (String) i.next();
586 
587                 if ( !reports.contains( report ) )
588                 {
589                     reports.add( report );
590                 }
591             }
592         }
593 
594         child.setReports( reports );
595 
596         Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
597         Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
598 
599         childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
600 
601         child.setConfiguration( childConfiguration );
602     }
603 
604     public static Model cloneModel( Model model )
605     {
606         // TODO: would be nice for the modello:java code to generate this as a copy constructor
607         Model newModel = new Model();
608         ModelInheritanceAssembler assembler = new DefaultModelInheritanceAssembler();
609         newModel.setModelVersion( model.getModelVersion() );
610         newModel.setName( model.getName() );
611         newModel.setParent( cloneParent( model.getParent() ) );
612         newModel.setVersion( model.getVersion() );
613         newModel.setArtifactId( model.getArtifactId() );
614         newModel.setProperties( new Properties( model.getProperties() ) );
615         newModel.setGroupId( model.getGroupId() );
616         newModel.setPackaging( model.getPackaging() );
617         newModel.setModules( cloneModules( model.getModules() ) );
618 
619         newModel.setProfiles( cloneProfiles( model.getProfiles() ) );
620 
621         assembler.copyModel( newModel, model );
622 
623         return newModel;
624     }
625 
626     private static List cloneProfiles( List profiles )
627     {
628         if ( profiles == null )
629         {
630             return profiles;
631         }
632 
633         List newProfiles = new ArrayList( profiles.size() );
634 
635         for ( Iterator it = profiles.iterator(); it.hasNext(); )
636         {
637             Profile profile = (Profile) it.next();
638 
639             Profile newProfile = new Profile();
640 
641             newProfile.setId( profile.getId() );
642 
643             newProfile.setActivation( cloneProfileActivation( profile.getActivation() ) );
644 
645             newProfile.setBuild( cloneProfileBuild( profile.getBuild() ) );
646 
647             newProfile.setDependencies( cloneProfileDependencies( profile.getDependencies() ) );
648 
649             DependencyManagement dm = profile.getDependencyManagement();
650 
651             if ( dm != null )
652             {
653                 DependencyManagement newDM = new DependencyManagement();
654 
655                 newDM.setDependencies( cloneProfileDependencies( dm.getDependencies() ) );
656 
657                 newProfile.setDependencyManagement( newDM );
658             }
659 
660             newProfile.setDistributionManagement( cloneProfileDistributionManagement( profile
661                 .getDistributionManagement() ) );
662 
663             List modules = profile.getModules();
664 
665             if ( ( modules != null ) && !modules.isEmpty() )
666             {
667                 newProfile.setModules( new ArrayList( modules ) );
668             }
669 
670             newProfile.setPluginRepositories( cloneProfileRepositories( profile.getPluginRepositories() ) );
671 
672             Properties props = profile.getProperties();
673 
674             if ( props != null )
675             {
676                 Properties newProps = new Properties();
677                 newProps.putAll( props );
678 
679                 newProfile.setProperties( newProps );
680             }
681 
682             newProfile.setReporting( cloneProfileReporting( profile.getReporting() ) );
683 
684             newProfile.setReports( profile.getReports() );
685 
686             newProfile.setRepositories( cloneProfileRepositories( profile.getRepositories() ) );
687 
688             newProfile.setSource( profile.getSource() );
689 
690             newProfiles.add( newProfile );
691         }
692 
693         return newProfiles;
694     }
695 
696     private static Reporting cloneProfileReporting( Reporting reporting )
697     {
698         Reporting newR = null;
699 
700         if ( reporting != null )
701         {
702             newR = new Reporting();
703 
704             newR.setOutputDirectory( reporting.getOutputDirectory() );
705 
706             List plugins = reporting.getPlugins();
707 
708             if ( plugins != null )
709             {
710                 List newP = new ArrayList( plugins.size() );
711 
712                 for ( Iterator it = plugins.iterator(); it.hasNext(); )
713                 {
714                     ReportPlugin plugin = (ReportPlugin) it.next();
715 
716                     ReportPlugin newPlugin = new ReportPlugin();
717 
718                     newPlugin.setArtifactId( plugin.getArtifactId() );
719                     newPlugin.setGroupId( plugin.getGroupId() );
720                     newPlugin.setVersion( plugin.getVersion() );
721                     newPlugin.setInherited( plugin.getInherited() );
722                     newPlugin.setReportSets( cloneReportSets( plugin.getReportSets() ) );
723 
724                     // TODO: Implement deep-copy of configuration.
725                     newPlugin.setConfiguration( plugin.getConfiguration() );
726 
727                     newP.add( newPlugin );
728                 }
729 
730                 newR.setPlugins( newP );
731             }
732         }
733 
734         return newR;
735     }
736 
737     private static List cloneReportSets( List sets )
738     {
739         List newSets = null;
740 
741         if ( sets != null )
742         {
743             newSets = new ArrayList( sets.size() );
744 
745             for ( Iterator it = sets.iterator(); it.hasNext(); )
746             {
747                 ReportSet set = (ReportSet) it.next();
748 
749                 ReportSet newSet = new ReportSet();
750 
751                 // TODO: Deep-copy config.
752                 newSet.setConfiguration( set.getConfiguration() );
753 
754                 newSet.setId( set.getId() );
755                 newSet.setInherited( set.getInherited() );
756 
757                 newSet.setReports( new ArrayList( set.getReports() ) );
758 
759                 newSets.add( newSet );
760             }
761         }
762 
763         return newSets;
764     }
765 
766     private static List cloneProfileRepositories( List repos )
767     {
768         List newRepos = null;
769 
770         if ( repos != null )
771         {
772             newRepos = new ArrayList( repos.size() );
773 
774             for ( Iterator it = repos.iterator(); it.hasNext(); )
775             {
776                 Repository repo = (Repository) it.next();
777 
778                 Repository newRepo = new Repository();
779 
780                 newRepo.setId( repo.getId() );
781                 newRepo.setLayout( repo.getLayout() );
782                 newRepo.setName( repo.getName() );
783 
784                 RepositoryPolicy releasePolicy = repo.getReleases();
785 
786                 if ( releasePolicy != null )
787                 {
788                     RepositoryPolicy newPolicy = new RepositoryPolicy();
789                     newPolicy.setEnabled( releasePolicy.isEnabled() );
790                     newPolicy.setChecksumPolicy( releasePolicy.getChecksumPolicy() );
791                     newPolicy.setUpdatePolicy( releasePolicy.getUpdatePolicy() );
792 
793                     newRepo.setReleases( newPolicy );
794                 }
795 
796                 RepositoryPolicy snapPolicy = repo.getSnapshots();
797 
798                 if ( snapPolicy != null )
799                 {
800                     RepositoryPolicy newPolicy = new RepositoryPolicy();
801                     newPolicy.setEnabled( snapPolicy.isEnabled() );
802                     newPolicy.setChecksumPolicy( snapPolicy.getChecksumPolicy() );
803                     newPolicy.setUpdatePolicy( snapPolicy.getUpdatePolicy() );
804 
805                     newRepo.setSnapshots( newPolicy );
806                 }
807 
808                 newRepo.setUrl( repo.getUrl() );
809 
810                 newRepos.add( newRepo );
811             }
812         }
813 
814         return newRepos;
815     }
816 
817     private static DistributionManagement cloneProfileDistributionManagement( DistributionManagement dm )
818     {
819         DistributionManagement newDM = null;
820 
821         if ( dm != null )
822         {
823             newDM = new DistributionManagement();
824 
825             newDM.setDownloadUrl( dm.getDownloadUrl() );
826             newDM.setStatus( dm.getStatus() );
827 
828             Relocation relocation = dm.getRelocation();
829 
830             if ( relocation != null )
831             {
832                 Relocation newR = new Relocation();
833 
834                 newR.setArtifactId( relocation.getArtifactId() );
835                 newR.setGroupId( relocation.getGroupId() );
836                 newR.setMessage( relocation.getMessage() );
837                 newR.setVersion( relocation.getVersion() );
838 
839                 newDM.setRelocation( newR );
840             }
841 
842             DeploymentRepository repo = dm.getRepository();
843 
844             if ( repo != null )
845             {
846                 DeploymentRepository newRepo = new DeploymentRepository();
847 
848                 newRepo.setId( repo.getId() );
849                 newRepo.setLayout( repo.getLayout() );
850                 newRepo.setName( repo.getName() );
851                 newRepo.setUrl( repo.getUrl() );
852                 newRepo.setUniqueVersion( repo.isUniqueVersion() );
853 
854                 newDM.setRepository( newRepo );
855             }
856 
857             Site site = dm.getSite();
858 
859             if ( site != null )
860             {
861                 Site newSite = new Site();
862 
863                 newSite.setId( site.getId() );
864                 newSite.setName( site.getName() );
865                 newSite.setUrl( site.getUrl() );
866 
867                 newDM.setSite( newSite );
868             }
869 
870             DeploymentRepository sRepo = dm.getSnapshotRepository();
871 
872             if ( sRepo != null )
873             {
874                 DeploymentRepository newRepo = new DeploymentRepository();
875 
876                 newRepo.setId( sRepo.getId() );
877                 newRepo.setLayout( sRepo.getLayout() );
878                 newRepo.setName( sRepo.getName() );
879                 newRepo.setUrl( sRepo.getUrl() );
880                 newRepo.setUniqueVersion( sRepo.isUniqueVersion() );
881 
882                 newDM.setSnapshotRepository( newRepo );
883             }
884         }
885 
886         return newDM;
887     }
888 
889     private static List cloneProfileDependencies( List dependencies )
890     {
891         List newDependencies = null;
892 
893         if ( dependencies != null )
894         {
895             newDependencies = new ArrayList( dependencies.size() );
896 
897             for ( Iterator it = dependencies.iterator(); it.hasNext(); )
898             {
899                 Dependency dep = (Dependency) it.next();
900 
901                 Dependency newDep = new Dependency();
902 
903                 newDep.setArtifactId( dep.getArtifactId() );
904                 newDep.setClassifier( dep.getClassifier() );
905                 newDep.setExclusions( cloneDependencyExclusions( dep.getExclusions() ) );
906                 newDep.setGroupId( dep.getGroupId() );
907                 newDep.setScope( dep.getScope() );
908                 newDep.setSystemPath( dep.getSystemPath() );
909                 newDep.setType( dep.getType() );
910                 newDep.setVersion( dep.getVersion() );
911 
912                 newDependencies.add( newDep );
913             }
914         }
915 
916         return newDependencies;
917     }
918 
919     private static List cloneDependencyExclusions( List ex )
920     {
921         List newEx = null;
922 
923         if ( ex != null )
924         {
925             newEx = new ArrayList( ex.size() );
926 
927             for ( Iterator it = ex.iterator(); it.hasNext(); )
928             {
929                 Exclusion exclusion = (Exclusion) it.next();
930 
931                 Exclusion newExclusion = new Exclusion();
932 
933                 newExclusion.setArtifactId( exclusion.getArtifactId() );
934                 newExclusion.setGroupId( exclusion.getGroupId() );
935 
936                 newEx.add( newExclusion );
937             }
938         }
939 
940         return newEx;
941     }
942 
943     private static BuildBase cloneProfileBuild( BuildBase build )
944     {
945         BuildBase newBuild = null;
946         if ( build != null )
947         {
948             newBuild = new BuildBase();
949 
950             newBuild.setDefaultGoal( build.getDefaultGoal() );
951             newBuild.setDirectory( build.getDirectory() );
952             newBuild.setFinalName( build.getFinalName() );
953 
954             newBuild.setPluginManagement( cloneProfilePluginManagement( build.getPluginManagement() ) );
955             newBuild.setPlugins( cloneProfilePlugins( build.getPlugins() ) );
956             newBuild.setResources( cloneProfileResources( build.getResources() ) );
957             newBuild.setTestResources( cloneProfileResources( build.getTestResources() ) );
958         }
959 
960         return newBuild;
961     }
962 
963     private static List cloneProfileResources( List resources )
964     {
965         List newResources = null;
966 
967         if ( resources != null )
968         {
969             newResources = new ArrayList( resources.size() );
970 
971             for ( Iterator it = resources.iterator(); it.hasNext(); )
972             {
973                 Resource resource = (Resource) it.next();
974 
975                 Resource newResource = new Resource();
976 
977                 newResource.setDirectory( resource.getDirectory() );
978                 newResource.setExcludes( new ArrayList( resource.getExcludes() ) );
979                 newResource.setFiltering( resource.isFiltering() );
980                 newResource.setIncludes( new ArrayList( resource.getIncludes() ) );
981                 newResource.setTargetPath( resource.getTargetPath() );
982 
983                 newResources.add( newResource );
984             }
985         }
986 
987         return newResources;
988     }
989 
990     private static PluginManagement cloneProfilePluginManagement( PluginManagement pluginManagement )
991     {
992         PluginManagement newPM = null;
993 
994         if ( pluginManagement != null )
995         {
996             newPM = new PluginManagement();
997 
998             List plugins = pluginManagement.getPlugins();
999 
1000             newPM.setPlugins( cloneProfilePlugins( plugins ) );
1001         }
1002 
1003         return newPM;
1004     }
1005 
1006     private static List cloneProfilePlugins( List plugins )
1007     {
1008         List newPlugins = null;
1009 
1010         if ( plugins != null )
1011         {
1012             newPlugins = new ArrayList( plugins.size() );
1013 
1014             for ( Iterator it = plugins.iterator(); it.hasNext(); )
1015             {
1016                 Plugin plugin = (Plugin) it.next();
1017 
1018                 Plugin newPlugin = new Plugin();
1019 
1020                 newPlugin.setArtifactId( plugin.getArtifactId() );
1021                 newPlugin.setExtensions( plugin.isExtensions() );
1022                 newPlugin.setGroupId( plugin.getGroupId() );
1023                 newPlugin.setInherited( plugin.getInherited() );
1024                 newPlugin.setVersion( plugin.getVersion() );
1025 
1026                 // TODO: Deep-copy this!
1027                 newPlugin.setConfiguration( plugin.getConfiguration() );
1028 
1029                 newPlugin.setExecutions( cloneExecutions( plugin.getExecutions() ) );
1030 
1031                 newPlugins.add( newPlugin );
1032             }
1033         }
1034 
1035         return newPlugins;
1036     }
1037 
1038     private static List cloneExecutions( List executions )
1039     {
1040         List newExecs = null;
1041 
1042         if ( executions != null )
1043         {
1044             newExecs = new ArrayList( executions.size() );
1045 
1046             for ( Iterator it = executions.iterator(); it.hasNext(); )
1047             {
1048                 PluginExecution exec = (PluginExecution) it.next();
1049 
1050                 PluginExecution newExec = new PluginExecution();
1051 
1052                 // TODO: Deep-copy configs.
1053                 newExec.setConfiguration( exec.getConfiguration() );
1054 
1055                 newExec.setId( exec.getId() );
1056                 newExec.setInherited( exec.getInherited() );
1057                 newExec.setPhase( exec.getPhase() );
1058 
1059                 List goals = exec.getGoals();
1060 
1061                 if ( ( goals != null ) && !goals.isEmpty() )
1062                 {
1063                     newExec.setGoals( new ArrayList( goals ) );
1064                 }
1065 
1066                 newExecs.add( newExec );
1067             }
1068         }
1069 
1070         return newExecs;
1071     }
1072 
1073     private static Activation cloneProfileActivation( Activation activation )
1074     {
1075         Activation newActivation = null;
1076         if ( activation != null )
1077         {
1078             newActivation = new Activation();
1079 
1080             newActivation.setActiveByDefault( activation.isActiveByDefault() );
1081 
1082             ActivationFile af = activation.getFile();
1083 
1084             if ( af != null )
1085             {
1086                 ActivationFile afNew = new ActivationFile();
1087                 afNew.setExists( af.getExists() );
1088                 afNew.setMissing( af.getMissing() );
1089 
1090                 newActivation.setFile( afNew );
1091             }
1092 
1093             newActivation.setJdk( activation.getJdk() );
1094 
1095             ActivationProperty ap = activation.getProperty();
1096 
1097             if ( ap != null )
1098             {
1099                 ActivationProperty newAp = new ActivationProperty();
1100 
1101                 newAp.setName( ap.getName() );
1102                 newAp.setValue( ap.getValue() );
1103 
1104                 newActivation.setProperty( newAp );
1105             }
1106         }
1107 
1108         return newActivation;
1109     }
1110 
1111     private static List cloneModules( List modules )
1112     {
1113         if ( modules == null )
1114         {
1115             return modules;
1116         }
1117         return new ArrayList( modules );
1118     }
1119 
1120     private static Parent cloneParent( Parent parent )
1121     {
1122         if ( parent == null )
1123         {
1124             return parent;
1125         }
1126 
1127         Parent newParent = new Parent();
1128         newParent.setArtifactId( parent.getArtifactId() );
1129         newParent.setGroupId( parent.getGroupId() );
1130         newParent.setRelativePath( parent.getRelativePath() );
1131         newParent.setVersion( parent.getVersion() );
1132         return newParent;
1133     }
1134 
1135     public static List mergeRepositoryLists( List dominant, List recessive )
1136     {
1137         List repositories = new ArrayList();
1138 
1139         for ( Iterator it = dominant.iterator(); it.hasNext(); )
1140         {
1141             Repository repository = (Repository) it.next();
1142 
1143             repositories.add( repository );
1144         }
1145 
1146         for ( Iterator it = recessive.iterator(); it.hasNext(); )
1147         {
1148             Repository repository = (Repository) it.next();
1149 
1150             if ( !repositories.contains( repository ) )
1151             {
1152                 repositories.add( repository );
1153             }
1154         }
1155 
1156         return repositories;
1157     }
1158 
1159     public static void mergeExtensionLists( Build childBuild, Build parentBuild )
1160     {
1161         Map extMap = new LinkedHashMap();
1162 
1163         List ext = childBuild.getExtensions();
1164 
1165         if ( ext != null )
1166         {
1167             for ( Iterator it = ext.iterator(); it.hasNext(); )
1168             {
1169                 Extension extension = (Extension) it.next();
1170                 extMap.put( extension.getKey(), extension );
1171             }
1172         }
1173 
1174         ext = parentBuild.getExtensions();
1175 
1176         if ( ext != null )
1177         {
1178             for ( Iterator it = ext.iterator(); it.hasNext(); )
1179             {
1180                 Extension extension = (Extension) it.next();
1181                 if ( !extMap.containsKey( extension.getKey() ) )
1182                 {
1183                     extMap.put( extension.getKey(), extension );
1184                 }
1185             }
1186         }
1187 
1188         childBuild.setExtensions( new ArrayList( extMap.values() ) );
1189     }
1190 
1191     public static void mergeResourceLists( List childResources, List parentResources )
1192     {
1193         for ( Iterator i = parentResources.iterator(); i.hasNext(); )
1194         {
1195             Resource r = (Resource) i.next();
1196             if ( !childResources.contains( r ) )
1197             {
1198                 childResources.add( r );
1199             }
1200         }
1201     }
1202 
1203     public static void mergeFilterLists( List childFilters, List parentFilters )
1204     {
1205         for ( Iterator i = parentFilters.iterator(); i.hasNext(); )
1206         {
1207             String f = (String) i.next();
1208             if ( !childFilters.contains( f ) )
1209             {
1210                 childFilters.add( f );
1211             }
1212         }
1213     }
1214 
1215     public static List mergeDependencyList( List child, List parent )
1216     {
1217         Map depsMap = new LinkedHashMap();
1218 
1219         if ( child != null )
1220         {
1221             for ( Iterator it = child.iterator(); it.hasNext(); )
1222             {
1223                 Dependency dependency = (Dependency) it.next();
1224                 depsMap.put( dependency.getManagementKey(), dependency );
1225             }
1226         }
1227 
1228         if ( parent != null )
1229         {
1230             for ( Iterator it = parent.iterator(); it.hasNext(); )
1231             {
1232                 Dependency dependency = (Dependency) it.next();
1233                 if ( !depsMap.containsKey( dependency.getManagementKey() ) )
1234                 {
1235                     depsMap.put( dependency.getManagementKey(), dependency );
1236                 }
1237             }
1238         }
1239 
1240         return new ArrayList( depsMap.values() );
1241     }
1242 
1243 }