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