View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.model.profile;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.LinkedHashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.maven.api.model.Build;
31  import org.apache.maven.api.model.BuildBase;
32  import org.apache.maven.api.model.Model;
33  import org.apache.maven.api.model.ModelBase;
34  import org.apache.maven.api.model.Plugin;
35  import org.apache.maven.api.model.PluginContainer;
36  import org.apache.maven.api.model.PluginExecution;
37  import org.apache.maven.api.model.ReportPlugin;
38  import org.apache.maven.api.model.ReportSet;
39  import org.apache.maven.api.model.Reporting;
40  import org.apache.maven.model.building.ModelBuildingRequest;
41  import org.apache.maven.model.building.ModelProblemCollector;
42  import org.apache.maven.model.merge.MavenModelMerger;
43  
44  /**
45   * Handles profile injection into the model.
46   *
47   * @author Benjamin Bentmann
48   */
49  @Named
50  @Singleton
51  @SuppressWarnings({"checkstyle:methodname"})
52  public class DefaultProfileInjector implements ProfileInjector {
53  
54      private ProfileModelMerger merger = new ProfileModelMerger();
55  
56      @Override
57      public void injectProfile(
58              org.apache.maven.model.Model model,
59              org.apache.maven.model.Profile profile,
60              ModelBuildingRequest request,
61              ModelProblemCollector problems) {
62          if (profile != null) {
63              Model.Builder builder = Model.newBuilder(model.getDelegate());
64              merger.mergeModelBase(builder, model.getDelegate(), profile.getDelegate());
65  
66              if (profile.getBuild() != null) {
67                  Build build = model.getBuild() != null ? model.getBuild().getDelegate() : Build.newInstance();
68                  Build.Builder bbuilder = Build.newBuilder(build);
69                  merger.mergeBuildBase(bbuilder, build, profile.getBuild().getDelegate());
70                  builder.build(bbuilder.build());
71              }
72  
73              model.update(builder.build());
74          }
75      }
76  
77      /**
78       * ProfileModelMerger
79       */
80      protected static class ProfileModelMerger extends MavenModelMerger {
81  
82          public void mergeModelBase(ModelBase.Builder builder, ModelBase target, ModelBase source) {
83              mergeModelBase(builder, target, source, true, Collections.emptyMap());
84          }
85  
86          public void mergeBuildBase(BuildBase.Builder builder, BuildBase target, BuildBase source) {
87              mergeBuildBase(builder, target, source, true, Collections.emptyMap());
88          }
89  
90          @Override
91          protected void mergePluginContainer_Plugins(
92                  PluginContainer.Builder builder,
93                  PluginContainer target,
94                  PluginContainer source,
95                  boolean sourceDominant,
96                  Map<Object, Object> context) {
97              List<Plugin> src = source.getPlugins();
98              if (!src.isEmpty()) {
99                  List<Plugin> tgt = target.getPlugins();
100                 Map<Object, Plugin> master = new LinkedHashMap<>(tgt.size() * 2);
101 
102                 for (Plugin element : tgt) {
103                     Object key = getPluginKey().apply(element);
104                     master.put(key, element);
105                 }
106 
107                 Map<Object, List<Plugin>> predecessors = new LinkedHashMap<>();
108                 List<Plugin> pending = new ArrayList<>();
109                 for (Plugin element : src) {
110                     Object key = getPluginKey().apply(element);
111                     Plugin existing = master.get(key);
112                     if (existing != null) {
113                         existing = mergePlugin(existing, element, sourceDominant, context);
114                         master.put(key, existing);
115                         if (!pending.isEmpty()) {
116                             predecessors.put(key, pending);
117                             pending = new ArrayList<>();
118                         }
119                     } else {
120                         pending.add(element);
121                     }
122                 }
123 
124                 List<Plugin> result = new ArrayList<>(src.size() + tgt.size());
125                 for (Map.Entry<Object, Plugin> entry : master.entrySet()) {
126                     List<Plugin> pre = predecessors.get(entry.getKey());
127                     if (pre != null) {
128                         result.addAll(pre);
129                     }
130                     result.add(entry.getValue());
131                 }
132                 result.addAll(pending);
133 
134                 builder.plugins(result);
135             }
136         }
137 
138         @Override
139         protected void mergePlugin_Executions(
140                 Plugin.Builder builder,
141                 Plugin target,
142                 Plugin source,
143                 boolean sourceDominant,
144                 Map<Object, Object> context) {
145             List<PluginExecution> src = source.getExecutions();
146             if (!src.isEmpty()) {
147                 List<PluginExecution> tgt = target.getExecutions();
148                 Map<Object, PluginExecution> merged = new LinkedHashMap<>((src.size() + tgt.size()) * 2);
149 
150                 for (PluginExecution element : tgt) {
151                     Object key = getPluginExecutionKey().apply(element);
152                     merged.put(key, element);
153                 }
154 
155                 for (PluginExecution element : src) {
156                     Object key = getPluginExecutionKey().apply(element);
157                     PluginExecution existing = merged.get(key);
158                     if (existing != null) {
159                         element = mergePluginExecution(existing, element, sourceDominant, context);
160                     }
161                     merged.put(key, element);
162                 }
163 
164                 builder.executions(merged.values());
165             }
166         }
167 
168         @Override
169         protected void mergeReporting_Plugins(
170                 Reporting.Builder builder,
171                 Reporting target,
172                 Reporting source,
173                 boolean sourceDominant,
174                 Map<Object, Object> context) {
175             List<ReportPlugin> src = source.getPlugins();
176             if (!src.isEmpty()) {
177                 List<ReportPlugin> tgt = target.getPlugins();
178                 Map<Object, ReportPlugin> merged = new LinkedHashMap<>((src.size() + tgt.size()) * 2);
179 
180                 for (ReportPlugin element : tgt) {
181                     Object key = getReportPluginKey().apply(element);
182                     merged.put(key, element);
183                 }
184 
185                 for (ReportPlugin element : src) {
186                     Object key = getReportPluginKey().apply(element);
187                     ReportPlugin existing = merged.get(key);
188                     if (existing != null) {
189                         element = mergeReportPlugin(existing, element, sourceDominant, context);
190                     }
191                     merged.put(key, element);
192                 }
193 
194                 builder.plugins(merged.values());
195             }
196         }
197 
198         @Override
199         protected void mergeReportPlugin_ReportSets(
200                 ReportPlugin.Builder builder,
201                 ReportPlugin target,
202                 ReportPlugin source,
203                 boolean sourceDominant,
204                 Map<Object, Object> context) {
205             List<ReportSet> src = source.getReportSets();
206             if (!src.isEmpty()) {
207                 List<ReportSet> tgt = target.getReportSets();
208                 Map<Object, ReportSet> merged = new LinkedHashMap<>((src.size() + tgt.size()) * 2);
209 
210                 for (ReportSet element : tgt) {
211                     Object key = getReportSetKey().apply(element);
212                     merged.put(key, element);
213                 }
214 
215                 for (ReportSet element : src) {
216                     Object key = getReportSetKey().apply(element);
217                     ReportSet existing = merged.get(key);
218                     if (existing != null) {
219                         element = mergeReportSet(existing, element, sourceDominant, context);
220                     }
221                     merged.put(key, element);
222                 }
223 
224                 builder.reportSets(merged.values());
225             }
226         }
227     }
228 }