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