Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
EnforceMojo |
|
| 2.176470588235294;2.176 |
1 | package org.apache.maven.plugins.enforcer; | |
2 | ||
3 | /* | |
4 | * Licensed to the Apache Software Foundation (ASF) under one | |
5 | * or more contributor license agreements. See the NOTICE file | |
6 | * distributed with this work for additional information | |
7 | * regarding copyright ownership. The ASF licenses this file | |
8 | * to you under the Apache License, Version 2.0 (the | |
9 | * "License"); you may not use this file except in compliance | |
10 | * with the License. You may obtain a copy of the License at | |
11 | * | |
12 | * http://www.apache.org/licenses/LICENSE-2.0 | |
13 | * | |
14 | * Unless required by applicable law or agreed to in writing, | |
15 | * software distributed under the License is distributed on an | |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
17 | * KIND, either express or implied. See the License for the | |
18 | * specific language governing permissions and limitations | |
19 | * under the License. | |
20 | */ | |
21 | ||
22 | import java.util.ArrayList; | |
23 | import java.util.Hashtable; | |
24 | import java.util.List; | |
25 | ||
26 | import org.apache.maven.enforcer.rule.api.EnforcerRule; | |
27 | import org.apache.maven.enforcer.rule.api.EnforcerRuleException; | |
28 | import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; | |
29 | import org.apache.maven.execution.MavenSession; | |
30 | import org.apache.maven.plugin.AbstractMojo; | |
31 | import org.apache.maven.plugin.MojoExecutionException; | |
32 | import org.apache.maven.plugin.logging.Log; | |
33 | import org.apache.maven.project.MavenProject; | |
34 | import org.apache.maven.project.path.PathTranslator; | |
35 | import org.codehaus.plexus.PlexusConstants; | |
36 | import org.codehaus.plexus.PlexusContainer; | |
37 | import org.codehaus.plexus.context.Context; | |
38 | import org.codehaus.plexus.context.ContextException; | |
39 | import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; | |
40 | ||
41 | /** | |
42 | * This goal executes the defined enforcer-rules once per | |
43 | * module. | |
44 | * | |
45 | * @requiresDependencyResolution test | |
46 | * @goal enforce | |
47 | * @phase validate | |
48 | * @threadSafe | |
49 | * @author <a href="mailto:brianf@apache.org">Brian Fox</a> | |
50 | * @version $Id: EnforceMojo.java 1345522 2012-06-02 15:20:36Z rfscholte $ | |
51 | */ | |
52 | 0 | public class EnforceMojo |
53 | extends AbstractMojo | |
54 | implements Contextualizable | |
55 | { | |
56 | ||
57 | /** | |
58 | * Path Translator needed by the ExpressionEvaluator | |
59 | * | |
60 | * @component role="org.apache.maven.project.path.PathTranslator" | |
61 | */ | |
62 | protected PathTranslator translator; | |
63 | ||
64 | /** | |
65 | * The MavenSession | |
66 | * | |
67 | * @parameter expression="${session}" | |
68 | * @readonly | |
69 | */ | |
70 | protected MavenSession session; | |
71 | ||
72 | /** | |
73 | * POM | |
74 | * | |
75 | * @parameter expression="${project}" | |
76 | * @readonly | |
77 | * @required | |
78 | */ | |
79 | protected MavenProject project; | |
80 | ||
81 | /** | |
82 | * Flag to fail the build if a version check fails. | |
83 | * | |
84 | * @parameter expression="${enforcer.fail}" | |
85 | * default-value="true" | |
86 | */ | |
87 | 0 | protected boolean fail = true; |
88 | ||
89 | /** | |
90 | * Flag to easily skip all checks | |
91 | * | |
92 | * @parameter expression="${enforcer.skip}" | |
93 | * default-value="false" | |
94 | */ | |
95 | 0 | protected boolean skip = false; |
96 | ||
97 | /** | |
98 | * Fail on the first rule that doesn't pass | |
99 | * | |
100 | * @parameter expression="${enforcer.failFast}" | |
101 | * default-value="false" | |
102 | */ | |
103 | 0 | protected boolean failFast = false; |
104 | ||
105 | /** | |
106 | * Array of objects that implement the EnforcerRule | |
107 | * interface to execute. | |
108 | * | |
109 | * @parameter | |
110 | * @required | |
111 | */ | |
112 | private EnforcerRule[] rules; | |
113 | ||
114 | /** | |
115 | * Use this flag to disable rule result caching. This will cause | |
116 | * all rules to execute on each project even if the rule indicates it can | |
117 | * safely be cached. | |
118 | * @parameter expression="${enforcer.ignoreCache}" | |
119 | * default-value="false" | |
120 | */ | |
121 | 0 | protected boolean ignoreCache = false; |
122 | ||
123 | /** | |
124 | * This is a static variable used to persist the cached results across plugin invocations. | |
125 | */ | |
126 | 0 | protected static Hashtable<String, EnforcerRule> cache = new Hashtable<String, EnforcerRule>(); |
127 | ||
128 | ||
129 | // set by the contextualize method. Only way to get the | |
130 | // plugin's container in 2.0.x | |
131 | protected PlexusContainer container; | |
132 | ||
133 | public void contextualize ( Context context ) | |
134 | throws ContextException | |
135 | { | |
136 | 0 | container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY ); |
137 | 0 | } |
138 | ||
139 | /** | |
140 | * Entry point to the mojo | |
141 | */ | |
142 | public void execute () | |
143 | throws MojoExecutionException | |
144 | { | |
145 | 0 | Log log = this.getLog(); |
146 | ||
147 | 0 | EnforcerExpressionEvaluator evaluator = new EnforcerExpressionEvaluator( session, translator, project ); |
148 | ||
149 | // the entire execution can be easily skipped | |
150 | 0 | if ( !skip ) |
151 | { | |
152 | // list to store exceptions | |
153 | 0 | List<String> list = new ArrayList<String>(); |
154 | ||
155 | // make sure the rules exist | |
156 | 0 | if ( rules != null && rules.length > 0 ) |
157 | { | |
158 | 0 | String currentRule = "Unknown"; |
159 | ||
160 | // create my helper | |
161 | 0 | EnforcerRuleHelper helper = new DefaultEnforcementRuleHelper( session, evaluator, log, container ); |
162 | ||
163 | // if we are only warning, then disable | |
164 | // failFast | |
165 | 0 | if ( !fail ) |
166 | { | |
167 | 0 | failFast = false; |
168 | } | |
169 | ||
170 | // go through each rule | |
171 | 0 | for ( int i = 0; i < rules.length; i++ ) |
172 | { | |
173 | ||
174 | // prevent against empty rules | |
175 | 0 | EnforcerRule rule = rules[i]; |
176 | 0 | if ( rule != null ) |
177 | { | |
178 | // store the current rule for | |
179 | // logging purposes | |
180 | 0 | currentRule = rule.getClass().getName(); |
181 | 0 | log.debug( "Executing rule: " + currentRule ); |
182 | try | |
183 | { | |
184 | 0 | if ( ignoreCache || shouldExecute( rule ) ) |
185 | { | |
186 | // execute the rule | |
187 | //noinspection SynchronizationOnLocalVariableOrMethodParameter | |
188 | 0 | synchronized ( rule ) |
189 | { | |
190 | 0 | rule.execute( helper ); |
191 | 0 | } |
192 | } | |
193 | } | |
194 | 0 | catch ( EnforcerRuleException e ) |
195 | { | |
196 | // i can throw an exception | |
197 | // because failfast will be | |
198 | // false if fail is false. | |
199 | 0 | if ( failFast ) |
200 | { | |
201 | 0 | throw new MojoExecutionException( currentRule + " failed with message:\n" |
202 | + e.getMessage(), e ); | |
203 | } | |
204 | else | |
205 | { | |
206 | 0 | list.add( "Rule " + i + ": " + currentRule + " failed with message:\n" + e.getMessage() ); |
207 | 0 | log.debug( "Adding failure due to exception", e ); |
208 | } | |
209 | 0 | } |
210 | } | |
211 | } | |
212 | ||
213 | // if we found anything | |
214 | 0 | if ( !list.isEmpty() ) |
215 | { | |
216 | 0 | for ( String failure : list ) |
217 | { | |
218 | 0 | log.warn( failure ); |
219 | } | |
220 | 0 | if ( fail ) |
221 | { | |
222 | 0 | throw new MojoExecutionException( |
223 | "Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed." ); | |
224 | } | |
225 | } | |
226 | 0 | } |
227 | else | |
228 | { | |
229 | 0 | throw new MojoExecutionException( |
230 | "No rules are configured. Use the skip flag if you want to disable execution." ); | |
231 | } | |
232 | 0 | } |
233 | else | |
234 | { | |
235 | 0 | log.info( "Skipping Rule Enforcement." ); |
236 | } | |
237 | 0 | } |
238 | ||
239 | /** | |
240 | * This method determines if a rule should execute based | |
241 | * on the cache | |
242 | * | |
243 | * @param rule | |
244 | * @return | |
245 | */ | |
246 | protected boolean shouldExecute ( EnforcerRule rule ) | |
247 | { | |
248 | 0 | if ( rule.isCacheable() ) |
249 | { | |
250 | 0 | Log log = this.getLog(); |
251 | 0 | log.debug( "Rule " + rule.getClass().getName() + " is cacheable." ); |
252 | 0 | String key = rule.getClass().getName() + " " + rule.getCacheId(); |
253 | 0 | if ( EnforceMojo.cache.containsKey( key ) ) |
254 | { | |
255 | 0 | log.debug( "Key " + key + " was found in the cache" ); |
256 | 0 | if ( rule.isResultValid( (EnforcerRule) cache.get( key ) ) ) |
257 | { | |
258 | 0 | log.debug( "The cached results are still valid. Skipping the rule: "+rule.getClass().getName() ); |
259 | 0 | return false; |
260 | } | |
261 | } | |
262 | ||
263 | //add it to the cache of executed rules | |
264 | 0 | EnforceMojo.cache.put( key, rule ); |
265 | } | |
266 | 0 | return true; |
267 | } | |
268 | ||
269 | /** | |
270 | * @return the fail | |
271 | */ | |
272 | public boolean isFail () | |
273 | { | |
274 | 0 | return this.fail; |
275 | } | |
276 | ||
277 | /** | |
278 | * @param theFail the fail to set | |
279 | */ | |
280 | public void setFail ( boolean theFail ) | |
281 | { | |
282 | 0 | this.fail = theFail; |
283 | 0 | } |
284 | ||
285 | /** | |
286 | * @return the rules | |
287 | */ | |
288 | public EnforcerRule[] getRules () | |
289 | { | |
290 | 0 | return this.rules; |
291 | } | |
292 | ||
293 | /** | |
294 | * @param theRules the rules to set | |
295 | */ | |
296 | public void setRules ( EnforcerRule[] theRules ) | |
297 | { | |
298 | 0 | this.rules = theRules; |
299 | 0 | } |
300 | ||
301 | /** | |
302 | * @return the skip | |
303 | */ | |
304 | public boolean isSkip () | |
305 | { | |
306 | 0 | return this.skip; |
307 | } | |
308 | ||
309 | /** | |
310 | * @param theSkip the skip to set | |
311 | */ | |
312 | public void setSkip ( boolean theSkip ) | |
313 | { | |
314 | 0 | this.skip = theSkip; |
315 | 0 | } |
316 | ||
317 | /** | |
318 | * @return the failFast | |
319 | */ | |
320 | public boolean isFailFast () | |
321 | { | |
322 | 0 | return this.failFast; |
323 | } | |
324 | ||
325 | /** | |
326 | * @param theFailFast the failFast to set | |
327 | */ | |
328 | public void setFailFast ( boolean theFailFast ) | |
329 | { | |
330 | 0 | this.failFast = theFailFast; |
331 | 0 | } |
332 | ||
333 | /** | |
334 | * @return the project | |
335 | */ | |
336 | public MavenProject getProject () | |
337 | { | |
338 | 0 | return this.project; |
339 | } | |
340 | ||
341 | /** | |
342 | * @param theProject the project to set | |
343 | */ | |
344 | public void setProject ( MavenProject theProject ) | |
345 | { | |
346 | 0 | this.project = theProject; |
347 | 0 | } |
348 | ||
349 | /** | |
350 | * @return the session | |
351 | */ | |
352 | public MavenSession getSession () | |
353 | { | |
354 | 0 | return this.session; |
355 | } | |
356 | ||
357 | /** | |
358 | * @param theSession the session to set | |
359 | */ | |
360 | public void setSession ( MavenSession theSession ) | |
361 | { | |
362 | 0 | this.session = theSession; |
363 | 0 | } |
364 | ||
365 | /** | |
366 | * @return the translator | |
367 | */ | |
368 | public PathTranslator getTranslator () | |
369 | { | |
370 | 0 | return this.translator; |
371 | } | |
372 | ||
373 | /** | |
374 | * @param theTranslator the translator to set | |
375 | */ | |
376 | public void setTranslator ( PathTranslator theTranslator ) | |
377 | { | |
378 | 0 | this.translator = theTranslator; |
379 | 0 | } |
380 | } |