1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.impl;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Map;
30 import java.util.Optional;
31 import java.util.Set;
32 import java.util.stream.Collectors;
33
34 import org.apache.maven.api.Packaging;
35 import org.apache.maven.api.Type;
36 import org.apache.maven.api.model.Dependency;
37 import org.apache.maven.api.model.InputLocation;
38 import org.apache.maven.api.model.InputSource;
39 import org.apache.maven.api.model.Plugin;
40 import org.apache.maven.api.model.PluginContainer;
41 import org.apache.maven.api.model.PluginExecution;
42 import org.apache.maven.api.services.Lookup;
43 import org.apache.maven.api.services.PackagingRegistry;
44 import org.apache.maven.api.services.TypeRegistry;
45 import org.apache.maven.api.spi.PackagingProvider;
46 import org.apache.maven.lifecycle.internal.DefaultLifecyclePluginAnalyzer;
47 import org.apache.maven.lifecycle.mapping.LifecycleMapping;
48 import org.apache.maven.lifecycle.mapping.LifecycleMojo;
49 import org.apache.maven.lifecycle.mapping.LifecyclePhase;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53
54
55
56 @Named
57 @Singleton
58 public class DefaultPackagingRegistry
59 extends ExtensibleEnumRegistries.DefaultExtensibleEnumRegistry<Packaging, PackagingProvider>
60 implements PackagingRegistry {
61
62 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPackagingRegistry.class);
63
64 private final Lookup lookup;
65
66 private final TypeRegistry typeRegistry;
67
68 @Inject
69 public DefaultPackagingRegistry(Lookup lookup, TypeRegistry typeRegistry, List<PackagingProvider> providers) {
70 super(providers);
71 this.lookup = lookup;
72 this.typeRegistry = typeRegistry;
73 }
74
75 @Override
76 public Optional<Packaging> lookup(String id) {
77 id = id.toLowerCase(Locale.ROOT);
78
79
80
81
82
83 LifecycleMapping lifecycleMapping =
84 lookup.lookupOptional(LifecycleMapping.class, id).orElse(null);
85 if (lifecycleMapping == null) {
86 return Optional.empty();
87 }
88 Type type = typeRegistry.lookup(id).orElse(null);
89 if (type == null) {
90 return Optional.empty();
91 }
92 return Optional.of(new DefaultPackaging(id, type, getPlugins(lifecycleMapping)));
93 }
94
95 private Map<String, PluginContainer> getPlugins(LifecycleMapping lifecycleMapping) {
96 Map<String, PluginContainer> lfs = new HashMap<>();
97 lifecycleMapping.getLifecycles().forEach((id, lifecycle) -> {
98 Map<String, Plugin> plugins = new HashMap<>();
99 lifecycle
100 .getLifecyclePhases()
101 .forEach((phase, lifecyclePhase) -> parseLifecyclePhaseDefinitions(plugins, phase, lifecyclePhase));
102 lfs.put(id, PluginContainer.newBuilder().plugins(plugins.values()).build());
103 });
104 return lfs;
105 }
106
107 static void parseLifecyclePhaseDefinitions(Map<String, Plugin> plugins, String phase, LifecyclePhase goals) {
108 InputSource inputSource =
109 new InputSource(DefaultLifecyclePluginAnalyzer.DEFAULTLIFECYCLEBINDINGS_MODELID, null);
110 InputLocation location = new InputLocation(-1, -1, inputSource, 0);
111
112 List<LifecycleMojo> mojos = goals.getMojos();
113 if (mojos != null) {
114 for (int i = 0; i < mojos.size(); i++) {
115 LifecycleMojo mojo = mojos.get(i);
116
117
118 String groupId, artifactId, version, goal;
119 String[] p = mojo.getGoal().trim().split(":");
120 if (p.length == 3) {
121
122 groupId = p[0];
123 artifactId = p[1];
124 version = null;
125 goal = p[2];
126 } else if (p.length == 4) {
127
128 groupId = p[0];
129 artifactId = p[1];
130 version = p[2];
131 goal = p[3];
132 } else {
133
134 LOGGER.warn(
135 "Ignored invalid goal specification '{}' from lifecycle mapping for phase {}",
136 mojo.getGoal(),
137 phase);
138 continue;
139 }
140
141 String key = groupId + ":" + artifactId;
142
143
144 List<PluginExecution> execs = new ArrayList<>();
145 List<Dependency> deps = new ArrayList<>();
146
147 Plugin existing = plugins.get(key);
148 if (existing != null) {
149 if (version == null) {
150 version = existing.getVersion();
151 }
152 execs.addAll(existing.getExecutions());
153 deps.addAll(existing.getDependencies());
154 }
155
156 PluginExecution execution = PluginExecution.newBuilder()
157 .id(getExecutionId(existing, goal))
158 .priority(i - mojos.size())
159 .phase(phase)
160 .goals(List.of(goal))
161 .configuration(mojo.getConfiguration())
162 .location("", location)
163 .location("id", location)
164 .location("phase", location)
165 .location("goals", location)
166 .build();
167 execs.add(execution);
168
169 if (mojo.getDependencies() != null) {
170 mojo.getDependencies().forEach(d -> deps.add(d.getDelegate()));
171 }
172
173 Plugin plugin = Plugin.newBuilder()
174 .groupId(groupId)
175 .artifactId(artifactId)
176 .version(version)
177 .location("", location)
178 .location("groupId", location)
179 .location("artifactId", location)
180 .location("version", location)
181 .executions(execs)
182 .dependencies(deps)
183 .build();
184
185 plugins.put(key, plugin);
186 }
187 }
188 }
189
190 private static String getExecutionId(Plugin plugin, String goal) {
191 Set<String> existingIds = plugin != null
192 ? plugin.getExecutions().stream().map(PluginExecution::getId).collect(Collectors.toSet())
193 : Set.of();
194 String base = "default-" + goal;
195 String id = base;
196 for (int index = 1; existingIds.contains(id); index++) {
197 id = base + '-' + index;
198 }
199 return id;
200 }
201
202 private record DefaultPackaging(String id, Type type, Map<String, PluginContainer> plugins) implements Packaging {}
203 }