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