View Javadoc
1   package org.apache.maven.model.profile;
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 javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.LinkedHashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.apache.maven.api.model.Build;
32  import org.apache.maven.api.model.BuildBase;
33  import org.apache.maven.api.model.Model;
34  import org.apache.maven.api.model.ModelBase;
35  import org.apache.maven.api.model.Plugin;
36  import org.apache.maven.api.model.PluginContainer;
37  import org.apache.maven.api.model.PluginExecution;
38  import org.apache.maven.api.model.ReportPlugin;
39  import org.apache.maven.api.model.ReportSet;
40  import org.apache.maven.api.model.Reporting;
41  import org.apache.maven.model.building.ModelBuildingRequest;
42  import org.apache.maven.model.building.ModelProblemCollector;
43  import org.apache.maven.model.merge.MavenModelMerger;
44  
45  /**
46   * Handles profile injection into the model.
47   *
48   * @author Benjamin Bentmann
49   */
50  @Named
51  @Singleton
52  @SuppressWarnings( { "checkstyle:methodname" } )
53  public class DefaultProfileInjector
54      implements ProfileInjector
55  {
56  
57      private ProfileModelMerger merger = new ProfileModelMerger();
58  
59      @Override
60      public void injectProfile( org.apache.maven.model.Model model,
61                                 org.apache.maven.model.Profile profile,
62                                 ModelBuildingRequest request,
63                                 ModelProblemCollector problems )
64      {
65          if ( profile != null )
66          {
67              Model.Builder builder = Model.newBuilder( model.getDelegate() );
68              merger.mergeModelBase( builder, model.getDelegate(), profile.getDelegate() );
69  
70              if ( profile.getBuild() != null )
71              {
72                  Build build = model.getBuild() != null ? model.getBuild().getDelegate() : Build.newInstance();
73                  Build.Builder bbuilder = Build.newBuilder( build );
74                  merger.mergeBuildBase( bbuilder, build, profile.getBuild().getDelegate() );
75                  builder.build( bbuilder.build() );
76              }
77  
78              model.update( builder.build() );
79          }
80      }
81  
82      /**
83       * ProfileModelMerger
84       */
85      protected static class ProfileModelMerger
86          extends MavenModelMerger
87      {
88  
89          public void mergeModelBase( ModelBase.Builder builder, ModelBase target, ModelBase source )
90          {
91              mergeModelBase( builder, target, source, true, Collections.emptyMap() );
92          }
93  
94          public void mergeBuildBase( BuildBase.Builder builder, BuildBase target, BuildBase source )
95          {
96              mergeBuildBase( builder, target, source, true, Collections.emptyMap() );
97          }
98  
99          @Override
100         protected void mergePluginContainer_Plugins( PluginContainer.Builder builder,
101                                                      PluginContainer target,  PluginContainer source,
102                                                      boolean sourceDominant,  Map<Object, Object> context )
103         {
104             List<Plugin> src = source.getPlugins();
105             if ( !src.isEmpty() )
106             {
107                 List<Plugin> tgt = target.getPlugins();
108                 Map<Object, Plugin> master = new LinkedHashMap<>( tgt.size() * 2 );
109 
110                 for ( Plugin element : tgt )
111                 {
112                     Object key = getPluginKey().apply( element );
113                     master.put( key, element );
114                 }
115 
116                 Map<Object, List<Plugin>> predecessors = new LinkedHashMap<>();
117                 List<Plugin> pending = new ArrayList<>();
118                 for ( Plugin element : src )
119                 {
120                     Object key = getPluginKey().apply( element );
121                     Plugin existing = master.get( key );
122                     if ( existing != null )
123                     {
124                         existing = mergePlugin( existing, element, sourceDominant, context );
125                         master.put( key, existing );
126                         if ( !pending.isEmpty() )
127                         {
128                             predecessors.put( key, pending );
129                             pending = new ArrayList<>();
130                         }
131                     }
132                     else
133                     {
134                         pending.add( element );
135                     }
136                 }
137 
138                 List<Plugin> result = new ArrayList<>( src.size() + tgt.size() );
139                 for ( Map.Entry<Object, Plugin> entry : master.entrySet() )
140                 {
141                     List<Plugin> pre = predecessors.get( entry.getKey() );
142                     if ( pre != null )
143                     {
144                         result.addAll( pre );
145                     }
146                     result.add( entry.getValue() );
147                 }
148                 result.addAll( pending );
149 
150                 builder.plugins( result );
151             }
152         }
153 
154         @Override
155         protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Plugin source,
156                                                boolean sourceDominant, Map<Object, Object> context )
157         {
158             List<PluginExecution> src = source.getExecutions();
159             if ( !src.isEmpty() )
160             {
161                 List<PluginExecution> tgt = target.getExecutions();
162                 Map<Object, PluginExecution> merged =
163                     new LinkedHashMap<>( ( src.size() + tgt.size() ) * 2 );
164 
165                 for ( PluginExecution element : tgt )
166                 {
167                     Object key = getPluginExecutionKey().apply( element );
168                     merged.put( key, element );
169                 }
170 
171                 for ( PluginExecution element : src )
172                 {
173                     Object key = getPluginExecutionKey().apply( element );
174                     PluginExecution existing = merged.get( key );
175                     if ( existing != null )
176                     {
177                         element = mergePluginExecution( existing, element, sourceDominant, context );
178                     }
179                     merged.put( key, element );
180                 }
181 
182                 builder.executions( merged.values() );
183             }
184         }
185 
186         @Override
187         protected void mergeReporting_Plugins( Reporting.Builder builder, Reporting target, Reporting source,
188                                                boolean sourceDominant, Map<Object, Object> context )
189         {
190             List<ReportPlugin> src = source.getPlugins();
191             if ( !src.isEmpty() )
192             {
193                 List<ReportPlugin> tgt = target.getPlugins();
194                 Map<Object, ReportPlugin> merged =
195                     new LinkedHashMap<>( ( src.size() + tgt.size() ) * 2 );
196 
197                 for ( ReportPlugin element : tgt )
198                 {
199                     Object key = getReportPluginKey().apply( element );
200                     merged.put( key, element );
201                 }
202 
203                 for ( ReportPlugin element : src )
204                 {
205                     Object key = getReportPluginKey().apply( element );
206                     ReportPlugin existing = merged.get( key );
207                     if ( existing != null )
208                     {
209                         element = mergeReportPlugin( existing, element, sourceDominant, context );
210                     }
211                     merged.put( key, element );
212                 }
213 
214                 builder.plugins( merged.values() );
215             }
216         }
217 
218         @Override
219         protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, ReportPlugin target,
220                                                      ReportPlugin source, boolean sourceDominant,
221                                                      Map<Object, Object> context )
222         {
223             List<ReportSet> src = source.getReportSets();
224             if ( !src.isEmpty() )
225             {
226                 List<ReportSet> tgt = target.getReportSets();
227                 Map<Object, ReportSet> merged = new LinkedHashMap<>( ( src.size() + tgt.size() ) * 2 );
228 
229                 for ( ReportSet element : tgt )
230                 {
231                     Object key = getReportSetKey().apply( element );
232                     merged.put( key, element );
233                 }
234 
235                 for ( ReportSet element : src )
236                 {
237                     Object key = getReportSetKey().apply( element );
238                     ReportSet existing = merged.get( key );
239                     if ( existing != null )
240                     {
241                         element = mergeReportSet( existing, element, sourceDominant, context );
242                     }
243                     merged.put( key, element );
244                 }
245 
246                 builder.reportSets( merged.values() );
247             }
248         }
249 
250     }
251 
252 }