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