View Javadoc
1   
2   package it.serendigity.maven.plugin.lifecycle.helper;
3   
4   import java.util.ArrayList;
5   import java.util.Arrays;
6   import java.util.List;
7   import java.util.Objects;
8   
9   import org.apache.maven.execution.MavenSession;
10  import org.apache.maven.lifecycle.DefaultLifecycles;
11  import org.apache.maven.lifecycle.LifecycleExecutor;
12  import org.apache.maven.lifecycle.LifecycleNotFoundException;
13  import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
14  import org.apache.maven.lifecycle.MavenExecutionPlan;
15  import org.apache.maven.lifecycle.internal.GoalTask;
16  import org.apache.maven.lifecycle.internal.LifecycleTask;
17  import org.apache.maven.lifecycle.internal.LifecycleTaskSegmentCalculator;
18  import org.apache.maven.lifecycle.internal.TaskSegment;
19  import org.apache.maven.plugin.AbstractMojo;
20  import org.apache.maven.plugin.InvalidPluginDescriptorException;
21  import org.apache.maven.plugin.MojoExecution;
22  import org.apache.maven.plugin.MojoFailureException;
23  import org.apache.maven.plugin.MojoNotFoundException;
24  import org.apache.maven.plugin.PluginDescriptorParsingException;
25  import org.apache.maven.plugin.PluginNotFoundException;
26  import org.apache.maven.plugin.PluginResolutionException;
27  import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
28  import org.apache.maven.plugin.version.PluginVersionResolutionException;
29  import org.apache.maven.plugins.annotations.Component;
30  import org.apache.maven.plugins.annotations.Parameter;
31  import org.apache.maven.project.MavenProject;
32  import org.apache.maven.shared.utils.logging.MessageUtils;
33  
34  import it.serendigity.maven.plugin.lifecycle.helper.vo.MavenExecutionInfo;
35  import it.serendigity.maven.plugin.lifecycle.helper.vo.MavenExecutionPlanInfo;
36  
37  public abstract class AbstractLifecycleMojo extends AbstractMojo {
38  
39  	@Parameter(defaultValue = "${session}", readonly = true)
40  	private MavenSession session;
41  
42  	@Parameter(defaultValue = "${project}", readonly = true)
43  	private MavenProject project;
44  
45  	@Component
46  	private LifecycleExecutor lifecycleExecutor;
47  
48  	@Component
49  	private LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator;
50  
51  	/**
52  	 * The Maven default built-in lifecycles.
53  	 */
54  	@Component
55  	protected DefaultLifecycles defaultLifecycles;
56  
57  	/**
58  	 * Allows you to specify which tasks (lifecycle phases or plugin/goal) will be used to calculate the execution
59  	 * plan.
60  	 * If not specified the run tasks are the phases: post-clean, deploy, site-deploy.
61  	 * If you set {@link #paramForceTasksFromSession} to true this parameter is ignored!
62  	 */
63  	@Parameter(property = "lifecycle-helper.tasks", defaultValue = "post-clean,deploy,site-deploy")
64  	private String[] paramLifecycleTasks;
65  
66  	/** Allows you to filter the specified plugins (plugin-artifact-id). */
67  	@Parameter(property = "lifecycle-helper.filter.plugins")
68  	private String[] paramFilterPlugins;
69  
70  	/**
71  	 * If enabled the tasks are taken from maven session and the property {@link #paramLifecycleTasks} is ignored
72  	 * Helpful when you include the plugin in your pom in order to list the execution-plan of the current tasks build.
73  	 **/
74  	@Parameter(property = "lifecycle-helper.forceTasksFromSession", defaultValue = "false")
75  	private boolean paramForceTasksFromSession;
76  
77  	/**
78  	 * Skip the execution.
79  	 *
80  	 * @since 0.4.0
81  	 */
82  	@Parameter(property = "lifecycle-helper.skip", defaultValue = "false")
83  	private boolean paramSkip;
84  
85  	protected boolean isParamForceTasksFromSession() {
86  		return paramForceTasksFromSession;
87  	}
88  
89  	private List<String> pluginToElaborate;
90  	private String[] tasksToElaborate;
91  
92  	protected MavenExecutionPlanInfo calculateExecutionPlan( boolean calculateSummary ) throws MojoFailureException {
93  
94  		setPluginToElaborate( normalizeParamFilterPlugin() );
95  
96  		MavenExecutionPlanInfo planInfo = new MavenExecutionPlanInfo( calculateSummary );
97  
98  		try {
99  
100 			String[] tasks = calculateTasksToElaborate();
101 			setTasksToElaborate( tasks );
102 
103 			MavenExecutionPlan calculateExecutionPlan = lifecycleExecutor.calculateExecutionPlan( session, tasks );
104 			List<MojoExecution> mojoExecutions = calculateExecutionPlan.getMojoExecutions();
105 
106 			int order = 0;
107 
108 			for ( MojoExecution mojoExecution : mojoExecutions ) {
109 
110 				MavenExecutionInfo info = MavenExecutionInfo.from( order++, mojoExecution, defaultLifecycles );
111 				if ( validateMavenExecution( info ) ) {
112 					planInfo.addMavenExecutionInfo( info );
113 				}
114 			}
115 
116 			if ( planInfo.getMavenExecutionsInfo() == null || planInfo.getMavenExecutionsInfo().isEmpty() ) {
117 				getLog().info( "No execution plan item found for requested parameters." );
118 			}
119 
120 		}
121 		catch (Exception e) {
122 			throw new MojoFailureException( "Cannot calculate Maven execution plan, caused by: " + e.getMessage(), e );
123 		}
124 		return planInfo;
125 	}
126 
127 	protected String[] calculateTasksToElaborate() throws MojoFailureException {
128 		String[] result = null;
129 
130 		if ( isParamForceTasksFromSession() ) {
131 			List<String> tasksFromSession = retrieveTasksFromSession();
132 
133 			if ( !tasksFromSession.isEmpty() ) {
134 				result = tasksFromSession.toArray(new String[0]);
135 			}
136 		}
137 		else {
138 			result = paramLifecycleTasks;
139 		}
140 		return result;
141 	}
142 
143 	protected boolean validateMavenExecution( MavenExecutionInfo info ) {
144 		getLog().debug( "Validate maven execution ..." );
145 
146 		boolean result = validatePlugin( info, getPluginsToElaborate() );
147 
148 		if ( getLog().isDebugEnabled() ) {
149 
150 			getLog().debug( "Maven execution " + info + ". Validate: " + result );
151 		}
152 
153 		return result;
154 	}
155 
156 	/**
157 	 * Normalize filter plugin
158 	 *
159 	 * @return List of plugin to filter
160 	 */
161 	protected List<String> normalizeParamFilterPlugin() {
162 
163 		List<String> result = null;
164 
165 		for ( String f : getParamFilterPlugins() ) {
166 
167 			if ( result == null ) {
168 				result = new ArrayList<>();
169 			}
170 			if ( f != null ) {
171 				result.add( f.trim() );
172 			}
173 		}
174 
175 		return result;
176 	}
177 
178 	/**
179 	 * @param info a {@link MavenExecutionInfo }
180 	 * @param filterPlugin a list of plugin String (artifact Id)
181 	 * @return true if filterPlugin is null or contains the plugin
182 	 */
183 	protected static boolean validatePlugin( MavenExecutionInfo info, List<String> filterPlugin ) {
184 
185 		boolean result = true;
186 
187 		// Filter plugin
188 		if ( filterPlugin != null ) {
189 
190 			result = filterPlugin.contains( info.getPluginArtifactId() );
191 
192 		}
193 
194 		return result;
195 	}
196 
197 	protected void handleOutput( final String output ) {
198 		String header = headerParametersString();
199 
200 		String outputWithTitle = header + output;
201 		getLog().info( outputWithTitle );
202 
203 	}
204 
205 	/**
206 	 * Mojo parameters header
207 	 *
208 	 * @return String parameters
209 	 */
210 	protected String headerParametersString() {
211 		String header = MessageUtils.buffer().strong(
212 				"\nProject: " + project.getName() + " (" + project.getArtifactId() + ":" + project.getVersion() + ")" )
213 				+ ".";
214 
215 		header = header + "\nForce tasks from Session: " + isParamForceTasksFromSession();
216 
217 		if ( isParamForceTasksFromSession() ) {
218 			header = header + "\nExecution plan for Session tasks: " + Arrays.asList( getTasksToElaborate() );
219 		}
220 		else {
221 			header = header + "\nExecution plan for run tasks: " + Arrays.asList( paramLifecycleTasks );
222 		}
223 
224 		header = header + "\nFilter plugins: " + Objects.toString( getPluginsToElaborate(), "" );
225 
226 		return header;
227 	}
228 
229 	protected String[] getParamFilterPlugins() {
230 		return paramFilterPlugins;
231 	}
232 
233 	protected List<String> getPluginsToElaborate() {
234 		return pluginToElaborate;
235 	}
236 
237 	protected void setPluginToElaborate( List<String> pluginToElaborate ) {
238 		this.pluginToElaborate = pluginToElaborate;
239 	}
240 
241 	protected List<String> retrieveTasksFromSession() throws MojoFailureException {
242 
243 		List<String> sessionTasksResult = new ArrayList<>();
244 
245 		List<TaskSegment> taskSegments;
246 		try {
247 			taskSegments = lifecycleTaskSegmentCalculator.calculateTaskSegments( session );
248 
249 			if ( taskSegments != null ) {
250 
251 				for ( TaskSegment taskSegmentList : taskSegments ) {
252 
253 					for ( Object task : taskSegmentList.getTasks() ) {
254 
255 						if ( task instanceof LifecycleTask ) {
256 							sessionTasksResult.add( ( (LifecycleTask) task ).getLifecyclePhase() );
257 						}
258 						else if ( task instanceof GoalTask goalTask) {
259 							sessionTasksResult.add( ( goalTask ).toString() );
260 						}
261 						else {
262 							getLog().warn( "Task is not recognized. Task is ignored --> " + task + " " + task.getClass() );
263 						}
264 
265 					}
266 
267 				}
268 			}
269 		}
270 		catch (PluginNotFoundException | PluginResolutionException | PluginDescriptorParsingException | MojoNotFoundException | NoPluginFoundForPrefixException
271 				| InvalidPluginDescriptorException | PluginVersionResolutionException | LifecyclePhaseNotFoundException | LifecycleNotFoundException e) {
272 			throw new MojoFailureException( "Error retrieving task from session", e );
273 		}
274 
275 		return sessionTasksResult;
276 
277 	}
278 
279 	protected String[] getTasksToElaborate() {
280 		return tasksToElaborate;
281 	}
282 
283 	protected void setTasksToElaborate( String[] tasksToElaborate ) {
284 		this.tasksToElaborate = tasksToElaborate;
285 	}
286 
287 	/**
288 	 * Check if the execution should be skipped
289 	 *
290 	 * @return true to skip
291 	 */
292 	protected boolean isParamSkip() {
293 		return paramSkip;
294 	}
295 
296 }