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