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