001    package org.apache.maven.model.profile;
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.Collections;
024    import java.util.LinkedHashMap;
025    import java.util.List;
026    import java.util.Map;
027    
028    import org.apache.maven.model.Build;
029    import org.apache.maven.model.BuildBase;
030    import org.apache.maven.model.Model;
031    import org.apache.maven.model.ModelBase;
032    import org.apache.maven.model.Plugin;
033    import org.apache.maven.model.PluginContainer;
034    import org.apache.maven.model.PluginExecution;
035    import org.apache.maven.model.Profile;
036    import org.apache.maven.model.ReportPlugin;
037    import org.apache.maven.model.ReportSet;
038    import org.apache.maven.model.Reporting;
039    import org.apache.maven.model.building.ModelBuildingRequest;
040    import org.apache.maven.model.building.ModelProblemCollector;
041    import org.apache.maven.model.merge.MavenModelMerger;
042    import org.codehaus.plexus.component.annotations.Component;
043    
044    /**
045     * Handles profile injection into the model.
046     * 
047     * @author Benjamin Bentmann
048     */
049    @Component( role = ProfileInjector.class )
050    public class DefaultProfileInjector
051        implements ProfileInjector
052    {
053    
054        private ProfileModelMerger merger = new ProfileModelMerger();
055    
056        public void injectProfile( Model model, Profile profile, ModelBuildingRequest request,
057                                   ModelProblemCollector problems )
058        {
059            if ( profile != null )
060            {
061                merger.mergeModelBase( model, profile );
062    
063                if ( profile.getBuild() != null )
064                {
065                    if ( model.getBuild() == null )
066                    {
067                        model.setBuild( new Build() );
068                    }
069                    merger.mergeBuildBase( model.getBuild(), profile.getBuild() );
070                }
071            }
072        }
073    
074        private static class ProfileModelMerger
075            extends MavenModelMerger
076        {
077    
078            public void mergeModelBase( ModelBase target, ModelBase source )
079            {
080                mergeModelBase( target, source, true, Collections.emptyMap() );
081            }
082    
083            public void mergeBuildBase( BuildBase target, BuildBase source )
084            {
085                mergeBuildBase( target, source, true, Collections.emptyMap() );
086            }
087    
088            @Override
089            protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source,
090                                                         boolean sourceDominant, Map<Object, Object> context )
091            {
092                List<Plugin> src = source.getPlugins();
093                if ( !src.isEmpty() )
094                {
095                    List<Plugin> tgt = target.getPlugins();
096                    Map<Object, Plugin> master = new LinkedHashMap<Object, Plugin>( tgt.size() * 2 );
097    
098                    for ( Plugin element : tgt )
099                    {
100                        Object key = getPluginKey( element );
101                        master.put( key, element );
102                    }
103    
104                    Map<Object, List<Plugin>> predecessors = new LinkedHashMap<Object, List<Plugin>>();
105                    List<Plugin> pending = new ArrayList<Plugin>();
106                    for ( Plugin element : src )
107                    {
108                        Object key = getPluginKey( element );
109                        Plugin existing = master.get( key );
110                        if ( existing != null )
111                        {
112                            mergePlugin( existing, element, sourceDominant, context );
113    
114                            if ( !pending.isEmpty() )
115                            {
116                                predecessors.put( key, pending );
117                                pending = new ArrayList<Plugin>();
118                            }
119                        }
120                        else
121                        {
122                            pending.add( element );
123                        }
124                    }
125    
126                    List<Plugin> result = new ArrayList<Plugin>( src.size() + tgt.size() );
127                    for ( Map.Entry<Object, Plugin> entry : master.entrySet() )
128                    {
129                        List<Plugin> pre = predecessors.get( entry.getKey() );
130                        if ( pre != null )
131                        {
132                            result.addAll( pre );
133                        }
134                        result.add( entry.getValue() );
135                    }
136                    result.addAll( pending );
137    
138                    target.setPlugins( result );
139                }
140            }
141    
142            @Override
143            protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant,
144                                                   Map<Object, Object> context )
145            {
146                List<PluginExecution> src = source.getExecutions();
147                if ( !src.isEmpty() )
148                {
149                    List<PluginExecution> tgt = target.getExecutions();
150                    Map<Object, PluginExecution> merged =
151                        new LinkedHashMap<Object, PluginExecution>( ( src.size() + tgt.size() ) * 2 );
152    
153                    for ( PluginExecution element : tgt )
154                    {
155                        Object key = getPluginExecutionKey( element );
156                        merged.put( key, element );
157                    }
158    
159                    for ( PluginExecution element : src )
160                    {
161                        Object key = getPluginExecutionKey( element );
162                        PluginExecution existing = merged.get( key );
163                        if ( existing != null )
164                        {
165                            mergePluginExecution( existing, element, sourceDominant, context );
166                        }
167                        else
168                        {
169                            merged.put( key, element );
170                        }
171                    }
172    
173                    target.setExecutions( new ArrayList<PluginExecution>( merged.values() ) );
174                }
175            }
176    
177            @Override
178            protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant,
179                                                   Map<Object, Object> context )
180            {
181                List<ReportPlugin> src = source.getPlugins();
182                if ( !src.isEmpty() )
183                {
184                    List<ReportPlugin> tgt = target.getPlugins();
185                    Map<Object, ReportPlugin> merged =
186                        new LinkedHashMap<Object, ReportPlugin>( ( src.size() + tgt.size() ) * 2 );
187    
188                    for ( ReportPlugin element : tgt )
189                    {
190                        Object key = getReportPluginKey( element );
191                        merged.put( key, element );
192                    }
193    
194                    for ( ReportPlugin element : src )
195                    {
196                        Object key = getReportPluginKey( element );
197                        ReportPlugin existing = merged.get( key );
198                        if ( existing == null )
199                        {
200                            merged.put( key, element );
201                        }
202                        else
203                        {
204                            mergeReportPlugin( existing, element, sourceDominant, context );
205                        }
206                    }
207    
208                    target.setPlugins( new ArrayList<ReportPlugin>( merged.values() ) );
209                }
210            }
211    
212            @Override
213            protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
214                                                         Map<Object, Object> context )
215            {
216                List<ReportSet> src = source.getReportSets();
217                if ( !src.isEmpty() )
218                {
219                    List<ReportSet> tgt = target.getReportSets();
220                    Map<Object, ReportSet> merged = new LinkedHashMap<Object, ReportSet>( ( src.size() + tgt.size() ) * 2 );
221    
222                    for ( ReportSet element : tgt )
223                    {
224                        Object key = getReportSetKey( element );
225                        merged.put( key, element );
226                    }
227    
228                    for ( ReportSet element : src )
229                    {
230                        Object key = getReportSetKey( element );
231                        ReportSet existing = merged.get( key );
232                        if ( existing != null )
233                        {
234                            mergeReportSet( existing, element, sourceDominant, context );
235                        }
236                        else
237                        {
238                            merged.put( key, element );
239                        }
240                    }
241    
242                    target.setReportSets( new ArrayList<ReportSet>( merged.values() ) );
243                }
244            }
245    
246        }
247    
248    }