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    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    protected 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}