1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.model.inheritance;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.LinkedHashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Properties;
30
31 import org.apache.maven.model.InputLocation;
32 import org.apache.maven.model.Model;
33 import org.apache.maven.model.ModelBase;
34 import org.apache.maven.model.Plugin;
35 import org.apache.maven.model.PluginContainer;
36 import org.apache.maven.model.ReportPlugin;
37 import org.apache.maven.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 import org.codehaus.plexus.util.StringUtils;
42
43
44
45
46
47
48 @SuppressWarnings({"checkstyle:methodname"})
49 @Named
50 @Singleton
51 @Deprecated(since = "4.0.0")
52 public class DefaultInheritanceAssembler implements InheritanceAssembler {
53
54 private InheritanceModelMerger merger = new InheritanceModelMerger();
55
56 private static final String CHILD_DIRECTORY = "child-directory";
57
58 private static final String CHILD_DIRECTORY_PROPERTY = "project.directory";
59
60 @Override
61 public void assembleModelInheritance(
62 Model child, Model parent, ModelBuildingRequest request, ModelProblemCollector problems) {
63 Map<Object, Object> hints = new HashMap<>();
64 String childPath = child.getProperties().getProperty(CHILD_DIRECTORY_PROPERTY, child.getArtifactId());
65 hints.put(CHILD_DIRECTORY, childPath);
66 hints.put(MavenModelMerger.CHILD_PATH_ADJUSTMENT, getChildPathAdjustment(child, parent, childPath));
67 merger.merge(child, parent, false, hints);
68 }
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 private String getChildPathAdjustment(Model child, Model parent, String childDirectory) {
90 String adjustment = "";
91
92 if (parent != null) {
93 String childName = child.getArtifactId();
94
95
96
97
98
99
100
101
102 if (child.getProjectDirectory() != null) {
103 childName = child.getProjectDirectory().getName();
104 }
105
106 for (String module : parent.getModules()) {
107 module = module.replace('\\', '/');
108
109 if (module.regionMatches(true, module.length() - 4, ".xml", 0, 4)) {
110 module = module.substring(0, module.lastIndexOf('/') + 1);
111 }
112
113 String moduleName = module;
114 if (moduleName.endsWith("/")) {
115 moduleName = moduleName.substring(0, moduleName.length() - 1);
116 }
117
118 int lastSlash = moduleName.lastIndexOf('/');
119
120 moduleName = moduleName.substring(lastSlash + 1);
121
122 if ((moduleName.equals(childName) || (moduleName.equals(childDirectory))) && lastSlash >= 0) {
123 adjustment = module.substring(0, lastSlash);
124 break;
125 }
126 }
127 }
128
129 return adjustment;
130 }
131
132
133
134
135 protected static class InheritanceModelMerger extends MavenModelMerger {
136
137 @Override
138 protected String extrapolateChildUrl(String parentUrl, boolean appendPath, Map<Object, Object> context) {
139 Object childDirectory = context.get(CHILD_DIRECTORY);
140 Object childPathAdjustment = context.get(CHILD_PATH_ADJUSTMENT);
141
142 if (StringUtils.isBlank(parentUrl)
143 || childDirectory == null
144 || childPathAdjustment == null
145 || !appendPath) {
146 return parentUrl;
147 }
148
149
150 return appendPath(parentUrl, childDirectory.toString(), childPathAdjustment.toString());
151 }
152
153 private String appendPath(String parentUrl, String childPath, String pathAdjustment) {
154 StringBuilder url = new StringBuilder(parentUrl.length()
155 + pathAdjustment.length()
156 + childPath.length()
157 + ((pathAdjustment.length() == 0) ? 1 : 2));
158
159 url.append(parentUrl);
160 concatPath(url, pathAdjustment);
161 concatPath(url, childPath);
162
163 return url.toString();
164 }
165
166 private void concatPath(StringBuilder url, String path) {
167 if (path.length() > 0) {
168 boolean initialUrlEndsWithSlash = url.charAt(url.length() - 1) == '/';
169 boolean pathStartsWithSlash = path.charAt(0) == '/';
170
171 if (pathStartsWithSlash) {
172 if (initialUrlEndsWithSlash) {
173
174 url.setLength(url.length() - 1);
175 }
176 } else if (!initialUrlEndsWithSlash) {
177
178 url.append('/');
179 }
180
181 url.append(path);
182
183
184 if (initialUrlEndsWithSlash && !path.endsWith("/")) {
185 url.append('/');
186 }
187 }
188 }
189
190 @Override
191 protected void mergeModelBase_Properties(
192 ModelBase target, ModelBase source, boolean sourceDominant, Map<Object, Object> context) {
193 Properties merged = new Properties();
194 if (sourceDominant) {
195 merged.putAll(target.getProperties());
196 putAll(merged, source.getProperties(), CHILD_DIRECTORY_PROPERTY);
197 } else {
198 putAll(merged, source.getProperties(), CHILD_DIRECTORY_PROPERTY);
199 merged.putAll(target.getProperties());
200 }
201 target.setProperties(merged);
202 target.setLocation(
203 "properties",
204 InputLocation.merge(
205 target.getLocation("properties"), source.getLocation("properties"), sourceDominant));
206 }
207
208 private void putAll(Map<Object, Object> s, Map<Object, Object> t, Object excludeKey) {
209 for (Map.Entry<Object, Object> e : t.entrySet()) {
210 if (!e.getKey().equals(excludeKey)) {
211 s.put(e.getKey(), e.getValue());
212 }
213 }
214 }
215
216 @Override
217 protected void mergePluginContainer_Plugins(
218 PluginContainer target, PluginContainer source, boolean sourceDominant, Map<Object, Object> context) {
219 List<Plugin> src = source.getPlugins();
220 if (!src.isEmpty()) {
221 List<Plugin> tgt = target.getPlugins();
222 Map<Object, Plugin> master = new LinkedHashMap<>(src.size() * 2);
223
224 for (Plugin element : src) {
225 if (element.isInherited() || !element.getExecutions().isEmpty()) {
226
227 Plugin plugin = new Plugin();
228 plugin.setLocation("", element.getLocation(""));
229 plugin.setGroupId(null);
230 mergePlugin(plugin, element, sourceDominant, context);
231
232 Object key = getPluginKey(element);
233
234 master.put(key, plugin);
235 }
236 }
237
238 Map<Object, List<Plugin>> predecessors = new LinkedHashMap<>();
239 List<Plugin> pending = new ArrayList<>();
240 for (Plugin element : tgt) {
241 Object key = getPluginKey(element);
242 Plugin existing = master.get(key);
243 if (existing != null) {
244 mergePlugin(element, existing, sourceDominant, context);
245
246 master.put(key, element);
247
248 if (!pending.isEmpty()) {
249 predecessors.put(key, pending);
250 pending = new ArrayList<>();
251 }
252 } else {
253 pending.add(element);
254 }
255 }
256
257 List<Plugin> result = new ArrayList<>(src.size() + tgt.size());
258 for (Map.Entry<Object, Plugin> entry : master.entrySet()) {
259 List<Plugin> pre = predecessors.get(entry.getKey());
260 if (pre != null) {
261 result.addAll(pre);
262 }
263 result.add(entry.getValue());
264 }
265 result.addAll(pending);
266
267 target.setPlugins(result);
268 }
269 }
270
271 @Override
272 protected void mergePlugin(Plugin target, Plugin source, boolean sourceDominant, Map<Object, Object> context) {
273 if (source.isInherited()) {
274 mergeConfigurationContainer(target, source, sourceDominant, context);
275 }
276 mergePlugin_GroupId(target, source, sourceDominant, context);
277 mergePlugin_ArtifactId(target, source, sourceDominant, context);
278 mergePlugin_Version(target, source, sourceDominant, context);
279 mergePlugin_Extensions(target, source, sourceDominant, context);
280 mergePlugin_Dependencies(target, source, sourceDominant, context);
281 mergePlugin_Executions(target, source, sourceDominant, context);
282 }
283
284 @Override
285 protected void mergeReporting_Plugins(
286 Reporting target, Reporting source, boolean sourceDominant, Map<Object, Object> context) {
287 List<ReportPlugin> src = source.getPlugins();
288 if (!src.isEmpty()) {
289 List<ReportPlugin> tgt = target.getPlugins();
290 Map<Object, ReportPlugin> merged = new LinkedHashMap<>((src.size() + tgt.size()) * 2);
291
292 for (ReportPlugin element : src) {
293 Object key = getReportPluginKey(element);
294 if (element.isInherited()) {
295
296 ReportPlugin plugin = new ReportPlugin();
297 plugin.setLocation("", element.getLocation(""));
298 plugin.setGroupId(null);
299 mergeReportPlugin(plugin, element, sourceDominant, context);
300
301 merged.put(key, plugin);
302 }
303 }
304
305 for (ReportPlugin element : tgt) {
306 Object key = getReportPluginKey(element);
307 ReportPlugin existing = merged.get(key);
308 if (existing != null) {
309 mergeReportPlugin(element, existing, sourceDominant, context);
310 }
311 merged.put(key, element);
312 }
313
314 target.setPlugins(new ArrayList<>(merged.values()));
315 }
316 }
317 }
318 }