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