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