1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.lifecycle.internal;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.util.HashSet;
26 import java.util.LinkedHashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.NoSuchElementException;
30 import java.util.Set;
31
32 import org.apache.maven.api.xml.XmlNode;
33 import org.apache.maven.lifecycle.DefaultLifecycles;
34 import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
35 import org.apache.maven.lifecycle.Lifecycle;
36 import org.apache.maven.lifecycle.mapping.LifecycleMapping;
37 import org.apache.maven.lifecycle.mapping.LifecycleMojo;
38 import org.apache.maven.lifecycle.mapping.LifecyclePhase;
39 import org.apache.maven.model.InputLocation;
40 import org.apache.maven.model.InputSource;
41 import org.apache.maven.model.Plugin;
42 import org.apache.maven.model.PluginExecution;
43 import org.codehaus.plexus.PlexusContainer;
44 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
45 import org.codehaus.plexus.util.xml.Xpp3Dom;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import static java.util.Objects.requireNonNull;
50
51
52
53
54
55
56 @Singleton
57 @Named
58 public class DefaultLifecyclePluginAnalyzer implements LifeCyclePluginAnalyzer {
59 public static final String DEFAULTLIFECYCLEBINDINGS_MODELID = "org.apache.maven:maven-core:"
60 + DefaultLifecyclePluginAnalyzer.class.getPackage().getImplementationVersion()
61 + ":default-lifecycle-bindings";
62
63 private final Logger logger = LoggerFactory.getLogger(getClass());
64
65 private final PlexusContainer plexusContainer;
66
67 private final DefaultLifecycles defaultLifeCycles;
68
69 @Inject
70 public DefaultLifecyclePluginAnalyzer(
71 final PlexusContainer plexusContainer, final DefaultLifecycles defaultLifeCycles) {
72 this.plexusContainer = requireNonNull(plexusContainer);
73 this.defaultLifeCycles = requireNonNull(defaultLifeCycles);
74 }
75
76
77
78
79
80
81
82
83
84
85
86 @Override
87 public Set<Plugin> getPluginsBoundByDefaultToAllLifecycles(String packaging) {
88 if (logger.isDebugEnabled()) {
89 logger.debug("Looking up lifecycle mappings for packaging " + packaging + " from "
90 + Thread.currentThread().getContextClassLoader());
91 }
92
93 LifecycleMapping lifecycleMappingForPackaging = lookupLifecycleMapping(packaging);
94
95 if (lifecycleMappingForPackaging == null) {
96 return null;
97 }
98
99 Map<Plugin, Plugin> plugins = new LinkedHashMap<>();
100
101 for (Lifecycle lifecycle : defaultLifeCycles.getLifeCycles()) {
102 org.apache.maven.lifecycle.mapping.Lifecycle lifecycleConfiguration =
103 lifecycleMappingForPackaging.getLifecycles().get(lifecycle.getId());
104
105 Map<String, LifecyclePhase> phaseToGoalMapping = null;
106
107 if (lifecycleConfiguration != null) {
108 phaseToGoalMapping = lifecycleConfiguration.getLifecyclePhases();
109 } else if (lifecycle.getDefaultLifecyclePhases() != null) {
110 phaseToGoalMapping = lifecycle.getDefaultLifecyclePhases();
111 }
112
113 if (phaseToGoalMapping != null) {
114 for (Map.Entry<String, LifecyclePhase> goalsForLifecyclePhase : phaseToGoalMapping.entrySet()) {
115 String phase = goalsForLifecyclePhase.getKey();
116 LifecyclePhase goals = goalsForLifecyclePhase.getValue();
117 if (goals != null) {
118 parseLifecyclePhaseDefinitions(plugins, phase, goals);
119 }
120 }
121 }
122 }
123
124 return plugins.keySet();
125 }
126
127
128
129
130
131 private LifecycleMapping lookupLifecycleMapping(final String packaging) {
132 try {
133 return plexusContainer.lookup(LifecycleMapping.class, packaging);
134 } catch (ComponentLookupException e) {
135 if (e.getCause() instanceof NoSuchElementException) {
136 return null;
137 }
138 throw new RuntimeException(e);
139 }
140 }
141
142 private void parseLifecyclePhaseDefinitions(Map<Plugin, Plugin> plugins, String phase, LifecyclePhase goals) {
143 InputSource inputSource = new InputSource();
144 inputSource.setModelId(DEFAULTLIFECYCLEBINDINGS_MODELID);
145 InputLocation location = new InputLocation(-1, -1, inputSource);
146 location.setLocation(0, location);
147
148 List<LifecycleMojo> mojos = goals.getMojos();
149 if (mojos != null) {
150
151 for (int i = 0; i < mojos.size(); i++) {
152 LifecycleMojo mojo = mojos.get(i);
153
154 GoalSpec gs = parseGoalSpec(mojo.getGoal());
155
156 if (gs == null) {
157 logger.warn(
158 "Ignored invalid goal specification '{}' from lifecycle mapping for phase {}",
159 mojo.getGoal(),
160 phase);
161 continue;
162 }
163
164 Plugin plugin = new Plugin();
165 plugin.setGroupId(gs.groupId);
166 plugin.setArtifactId(gs.artifactId);
167 plugin.setVersion(gs.version);
168
169 plugin.setLocation("", location);
170 plugin.setLocation("groupId", location);
171 plugin.setLocation("artifactId", location);
172 plugin.setLocation("version", location);
173
174 Plugin existing = plugins.get(plugin);
175 if (existing != null) {
176 if (existing.getVersion() == null) {
177 existing.setVersion(plugin.getVersion());
178 existing.setLocation("version", location);
179 }
180 plugin = existing;
181 } else {
182 plugins.put(plugin, plugin);
183 }
184
185 PluginExecution execution = new PluginExecution();
186 execution.setId(getExecutionId(plugin, gs.goal));
187 execution.setPhase(phase);
188 execution.setPriority(i - mojos.size());
189 execution.getGoals().add(gs.goal);
190
191 execution.setLocation("", location);
192 execution.setLocation("id", location);
193 execution.setLocation("phase", location);
194 execution.setLocation("goals", location);
195
196 XmlNode lifecycleConfiguration = mojo.getConfiguration();
197 if (lifecycleConfiguration != null) {
198 execution.setConfiguration(new Xpp3Dom(lifecycleConfiguration));
199 }
200
201 if (mojo.getDependencies() != null) {
202 plugin.setDependencies(mojo.getDependencies());
203 }
204 plugin.getExecutions().add(execution);
205 }
206 }
207 }
208
209 private GoalSpec parseGoalSpec(String goalSpec) {
210 GoalSpec gs = new GoalSpec();
211
212 String[] p = goalSpec.trim().split(":");
213
214 if (p.length == 3) {
215
216 gs.groupId = p[0];
217 gs.artifactId = p[1];
218 gs.goal = p[2];
219 } else if (p.length == 4) {
220
221 gs.groupId = p[0];
222 gs.artifactId = p[1];
223 gs.version = p[2];
224 gs.goal = p[3];
225 } else {
226
227 gs = null;
228 }
229
230 return gs;
231 }
232
233 private String getExecutionId(Plugin plugin, String goal) {
234 Set<String> existingIds = new HashSet<>();
235 for (PluginExecution execution : plugin.getExecutions()) {
236 existingIds.add(execution.getId());
237 }
238
239 String base = "default-" + goal;
240 String id = base;
241
242 for (int index = 1; existingIds.contains(id); index++) {
243 id = base + '-' + index;
244 }
245
246 return id;
247 }
248
249 static class GoalSpec {
250
251 String groupId;
252
253 String artifactId;
254
255 String version;
256
257 String goal;
258 }
259 }