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