001    package org.apache.maven.project;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.ArrayList;
023    import java.util.Iterator;
024    import java.util.LinkedHashMap;
025    import java.util.List;
026    import java.util.Map;
027    import java.util.TreeMap;
028    
029    import org.apache.maven.model.Dependency;
030    import org.apache.maven.model.Plugin;
031    import org.apache.maven.model.PluginContainer;
032    import org.apache.maven.model.PluginExecution;
033    import org.apache.maven.model.Repository;
034    import org.codehaus.plexus.util.xml.Xpp3Dom;
035    
036    /** @deprecated */
037    @Deprecated
038    public final class ModelUtils
039    {
040    
041        /**
042         * This should be the resulting ordering of plugins after merging:
043         * <p/>
044         * Given:
045         * <p/>
046         * parent: X -> A -> B -> D -> E
047         * child: Y -> A -> C -> D -> F
048         * <p/>
049         * Result:
050         * <p/>
051         * X -> Y -> A -> B -> C -> D -> E -> F
052         */
053        public static void mergePluginLists( PluginContainer childContainer, PluginContainer parentContainer,
054                                             boolean handleAsInheritance )
055        {
056            if ( ( childContainer == null ) || ( parentContainer == null ) )
057            {
058                // nothing to do.
059                return;
060            }
061    
062            List<Plugin> parentPlugins = parentContainer.getPlugins();
063    
064            if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() )
065            {
066                parentPlugins = new ArrayList<Plugin>( parentPlugins );
067    
068                // If we're processing this merge as an inheritance, we have to build up a list of
069                // plugins that were considered for inheritance.
070                if ( handleAsInheritance )
071                {
072                    for ( Iterator<Plugin> it = parentPlugins.iterator(); it.hasNext(); )
073                    {
074                        Plugin plugin = it.next();
075    
076                        String inherited = plugin.getInherited();
077    
078                        if ( ( inherited != null ) && !Boolean.valueOf( inherited ) )
079                        {
080                            it.remove();
081                        }
082                    }
083                }
084    
085                List<Plugin> assembledPlugins = new ArrayList<Plugin>();
086    
087                Map<String, Plugin> childPlugins = childContainer.getPluginsAsMap();
088    
089                for ( Plugin parentPlugin : parentPlugins )
090                {
091                    String parentInherited = parentPlugin.getInherited();
092    
093                    // only merge plugin definition from the parent if at least one
094                    // of these is true:
095                    // 1. we're not processing the plugins in an inheritance-based merge
096                    // 2. the parent's <inherited/> flag is not set
097                    // 3. the parent's <inherited/> flag is set to true
098                    if ( !handleAsInheritance || ( parentInherited == null )
099                        || Boolean.valueOf( parentInherited ) )
100                    {
101                        Plugin childPlugin = (Plugin) childPlugins.get( parentPlugin.getKey() );
102    
103                        if ( ( childPlugin != null ) && !assembledPlugins.contains( childPlugin ) )
104                        {
105                            Plugin assembledPlugin = childPlugin;
106    
107                            mergePluginDefinitions( childPlugin, parentPlugin, handleAsInheritance );
108    
109                            // fix for MNG-2221 (assembly cache was not being populated for later reference):
110                            assembledPlugins.add( assembledPlugin );
111                        }
112    
113                        // if we're processing this as an inheritance-based merge, and
114                        // the parent's <inherited/> flag is not set, then we need to
115                        // clear the inherited flag in the merge result.
116                        if ( handleAsInheritance && ( parentInherited == null ) )
117                        {
118                            parentPlugin.unsetInheritanceApplied();
119                        }
120                    }
121    
122                    // very important to use the parentPlugins List, rather than parentContainer.getPlugins()
123                    // since this list is a local one, and may have been modified during processing.
124                    List<Plugin> results =
125                        ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins, childContainer.getPlugins() );
126    
127                    childContainer.setPlugins( results );
128    
129                    childContainer.flushPluginMap();
130                }
131            }
132        }
133    
134        public static List<Plugin> orderAfterMerge( List<Plugin> merged, List<Plugin> highPrioritySource,
135                                                    List<Plugin> lowPrioritySource )
136        {
137            List<Plugin> results = new ArrayList<Plugin>();
138    
139            if ( !merged.isEmpty() )
140            {
141                results.addAll( merged );
142            }
143    
144            List<Plugin> missingFromResults = new ArrayList<Plugin>();
145    
146            List<List<Plugin>> sources = new ArrayList<List<Plugin>>();
147    
148            sources.add( highPrioritySource );
149            sources.add( lowPrioritySource );
150    
151            for ( List<Plugin> source : sources )
152            {
153                for ( Plugin item : source )
154                {
155                    if ( results.contains( item ) )
156                    {
157                        if ( !missingFromResults.isEmpty() )
158                        {
159                            int idx = results.indexOf( item );
160    
161                            if ( idx < 0 )
162                            {
163                                idx = 0;
164                            }
165    
166                            results.addAll( idx, missingFromResults );
167    
168                            missingFromResults.clear();
169                        }
170                    }
171                    else
172                    {
173                        missingFromResults.add( item );
174                    }
175                }
176    
177                if ( !missingFromResults.isEmpty() )
178                {
179                    results.addAll( missingFromResults );
180    
181                    missingFromResults.clear();
182                }
183            }
184    
185            return results;
186        }
187    
188    
189        public static void mergePluginDefinitions( Plugin child, Plugin parent, boolean handleAsInheritance )
190        {
191            if ( ( child == null ) || ( parent == null ) )
192            {
193                // nothing to do.
194                return;
195            }
196    
197            if ( parent.isExtensions() )
198            {
199                child.setExtensions( true );
200            }
201    
202            if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) )
203            {
204                child.setVersion( parent.getVersion() );
205            }
206    
207            Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
208            Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
209    
210            childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
211    
212            child.setConfiguration( childConfiguration );
213    
214            child.setDependencies( mergeDependencyList( child.getDependencies(), parent.getDependencies() ) );
215    
216            // from here to the end of the method is dealing with merging of the <executions/> section.
217            String parentInherited = parent.getInherited();
218    
219            boolean parentIsInherited = ( parentInherited == null ) || Boolean.valueOf( parentInherited );
220    
221            List<PluginExecution> parentExecutions = parent.getExecutions();
222    
223            if ( ( parentExecutions != null ) && !parentExecutions.isEmpty() )
224            {
225                List<PluginExecution> mergedExecutions = new ArrayList<PluginExecution>();
226    
227                Map<String, PluginExecution> assembledExecutions = new TreeMap<String, PluginExecution>();
228    
229                Map<String, PluginExecution> childExecutions = child.getExecutionsAsMap();
230    
231                for ( PluginExecution parentExecution : parentExecutions )
232                {
233                    String inherited = parentExecution.getInherited();
234    
235                    boolean parentExecInherited =
236                        parentIsInherited && ( ( inherited == null ) || Boolean.valueOf( inherited ) );
237    
238                    if ( !handleAsInheritance || parentExecInherited )
239                    {
240                        PluginExecution assembled = parentExecution;
241    
242                        PluginExecution childExecution = childExecutions.get( parentExecution.getId() );
243    
244                        if ( childExecution != null )
245                        {
246                            mergePluginExecutionDefinitions( childExecution, parentExecution );
247    
248                            assembled = childExecution;
249                        }
250                        else if ( handleAsInheritance && ( parentInherited == null ) )
251                        {
252                            parentExecution.unsetInheritanceApplied();
253                        }
254    
255                        assembledExecutions.put( assembled.getId(), assembled );
256                        mergedExecutions.add( assembled );
257                    }
258                }
259    
260                for ( PluginExecution childExecution : child.getExecutions() )
261                {
262                    if ( !assembledExecutions.containsKey( childExecution.getId() ) )
263                    {
264                        mergedExecutions.add( childExecution );
265                    }
266                }
267    
268                child.setExecutions( mergedExecutions );
269    
270                child.flushExecutionMap();
271            }
272    
273        }
274    
275        private static void mergePluginExecutionDefinitions( PluginExecution child, PluginExecution parent )
276        {
277            if ( child.getPhase() == null )
278            {
279                child.setPhase( parent.getPhase() );
280            }
281    
282            List<String> parentGoals = parent.getGoals();
283            List<String> childGoals = child.getGoals();
284    
285            List<String> goals = new ArrayList<String>();
286    
287            if ( ( childGoals != null ) && !childGoals.isEmpty() )
288            {
289                goals.addAll( childGoals );
290            }
291    
292            if ( parentGoals != null )
293            {
294                for (  String goal : parentGoals )
295                {
296                    if ( !goals.contains( goal ) )
297                    {
298                        goals.add( goal );
299                    }
300                }
301            }
302    
303            child.setGoals( goals );
304    
305            Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
306            Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
307    
308            childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
309    
310            child.setConfiguration( childConfiguration );
311        }
312    
313        public static List<Repository> mergeRepositoryLists( List<Repository> dominant, List<Repository> recessive )
314        {
315            List<Repository> repositories = new ArrayList<Repository>();
316    
317            for ( Repository repository : dominant )
318            {
319                repositories.add( repository );
320            }
321    
322            for ( Repository repository : recessive )
323            {
324                if ( !repositories.contains( repository ) )
325                {
326                    repositories.add( repository );
327                }
328            }
329    
330            return repositories;
331        }
332    
333        public static void mergeFilterLists( List<String> childFilters, List<String> parentFilters )
334        {
335            for ( String f : parentFilters )
336            {
337                if ( !childFilters.contains( f ) )
338                {
339                    childFilters.add( f );
340                }
341            }
342        }
343    
344        private static List<Dependency> mergeDependencyList( List<Dependency> child, List<Dependency> parent )
345        {
346            Map<String, Dependency> depsMap = new LinkedHashMap<String, Dependency>();
347    
348            if ( parent != null )
349            {
350                for ( Dependency dependency : parent )
351                {
352                    depsMap.put( dependency.getManagementKey(), dependency );
353                }
354            }
355    
356            if ( child != null )
357            {
358                for ( Dependency dependency : child )
359                {
360                    depsMap.put( dependency.getManagementKey(), dependency );
361                }
362            }
363    
364            return new ArrayList<Dependency>( depsMap.values() );
365        }
366    
367    }