1 package org.apache.maven.plugins.enforcer;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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.EnforcerLevel;
27 import org.apache.maven.enforcer.rule.api.EnforcerRule;
28 import org.apache.maven.enforcer.rule.api.EnforcerRule2;
29 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
30 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
31 import org.apache.maven.execution.MavenSession;
32 import org.apache.maven.plugin.AbstractMojo;
33 import org.apache.maven.plugin.MojoExecution;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugin.logging.Log;
36 import org.apache.maven.plugins.annotations.LifecyclePhase;
37 import org.apache.maven.plugins.annotations.Mojo;
38 import org.apache.maven.plugins.annotations.Parameter;
39 import org.apache.maven.plugins.annotations.ResolutionScope;
40 import org.apache.maven.project.MavenProject;
41 import org.codehaus.plexus.PlexusConstants;
42 import org.codehaus.plexus.PlexusContainer;
43 import org.codehaus.plexus.context.Context;
44 import org.codehaus.plexus.context.ContextException;
45 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
46
47
48
49
50
51
52
53 @Mojo( name = "enforce", defaultPhase = LifecyclePhase.VALIDATE, requiresDependencyCollection = ResolutionScope.TEST, threadSafe = true )
54
55 public class EnforceMojo
56 extends AbstractMojo
57 implements Contextualizable
58 {
59
60
61
62 protected static Hashtable<String, EnforcerRule> cache = new Hashtable<String, EnforcerRule>();
63
64
65
66
67 @Parameter( defaultValue = "${mojoExecution}", readonly = true, required = true )
68 protected MojoExecution mojoExecution;
69
70
71
72
73 @Parameter( defaultValue = "${session}", readonly = true, required = true )
74 protected MavenSession session;
75
76
77
78
79 @Parameter( defaultValue = "${project}", readonly = true, required = true )
80 protected MavenProject project;
81
82
83
84
85 @Parameter( property = "enforcer.skip", defaultValue = "false" )
86 protected boolean skip = false;
87
88
89
90
91 @Parameter( property = "enforcer.fail", defaultValue = "true" )
92 private boolean fail = true;
93
94
95
96
97 @Parameter( property = "enforcer.failFast", defaultValue = "false" )
98 private boolean failFast = false;
99
100
101
102
103 @Parameter( required = false )
104 private EnforcerRule[] rules;
105
106
107
108
109 @Parameter( required = false, property = "rules" )
110 private String[] commandLineRules;
111
112
113
114
115
116 @Parameter( property = "enforcer.ignoreCache", defaultValue = "false" )
117 protected boolean ignoreCache = false;
118
119
120
121 protected PlexusContainer container;
122
123 @Override
124 public void contextualize( Context context )
125 throws ContextException
126 {
127 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
128 }
129
130 private boolean havingRules()
131 {
132 return rules != null && rules.length > 0;
133 }
134
135
136
137
138
139
140 @Override
141 public void execute()
142 throws MojoExecutionException
143 {
144 Log log = this.getLog();
145
146 EnforcerExpressionEvaluator evaluator =
147 new EnforcerExpressionEvaluator( session, mojoExecution );
148 if ( commandLineRules != null && commandLineRules.length > 0 )
149 {
150 this.rules = createRulesFromCommandLineOptions();
151 }
152
153 if ( isSkip() )
154 {
155 log.info( "Skipping Rule Enforcement." );
156 return;
157 }
158
159 if ( !havingRules() )
160 {
161
162 throw new MojoExecutionException( "No rules are configured. Use the skip flag if you want to disable execution." );
163
164 }
165
166
167 List<String> list = new ArrayList<String>();
168
169 String currentRule = "Unknown";
170
171
172 EnforcerRuleHelper helper = new DefaultEnforcementRuleHelper( session, evaluator, log, container );
173
174
175
176 if ( !fail )
177 {
178 failFast = false;
179 }
180
181 boolean hasErrors = false;
182
183
184 for ( int i = 0; i < rules.length; i++ )
185 {
186
187
188 EnforcerRule rule = rules[i];
189 final EnforcerLevel level = getLevel( rule );
190 if ( rule != null )
191 {
192
193
194 currentRule = rule.getClass().getName();
195 log.debug( "Executing rule: " + currentRule );
196 try
197 {
198 if ( ignoreCache || shouldExecute( rule ) )
199 {
200
201
202
203 synchronized ( rule )
204 {
205 rule.execute( helper );
206 }
207 }
208 }
209 catch ( EnforcerRuleException e )
210 {
211
212
213
214 if ( failFast && level == EnforcerLevel.ERROR )
215 {
216 throw new MojoExecutionException( currentRule + " failed with message:"
217 + System.lineSeparator() + e.getMessage(), e );
218 }
219 else
220 {
221
222
223 final String exceptionMessage = e.getMessage();
224 if ( exceptionMessage != null )
225 {
226 log.debug( "Adding " + level + " message due to exception", e );
227 }
228 else
229 {
230 log.warn( "Rule " + i + ": " + currentRule + " failed without a message", e );
231 }
232
233
234 if ( level == EnforcerLevel.ERROR )
235 {
236 hasErrors = true;
237 list.add( "Rule " + i + ": " + currentRule + " failed with message:"
238 + System.lineSeparator() + exceptionMessage );
239 }
240 else
241 {
242 list.add( "Rule " + i + ": " + currentRule + " warned with message:"
243 + System.lineSeparator() + exceptionMessage );
244 }
245 }
246 }
247 }
248 }
249
250
251
252 if ( !list.isEmpty() )
253 {
254 for ( String failure : list )
255 {
256 log.warn( failure );
257 }
258 if ( fail && hasErrors )
259 {
260 throw new MojoExecutionException( "Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed." );
261 }
262 }
263
264 }
265
266 private EnforcerRule[] createRulesFromCommandLineOptions() throws MojoExecutionException
267 {
268 EnforcerRule[] rules = new EnforcerRule[commandLineRules.length];
269 for ( int i = 0; i < commandLineRules.length; i++ )
270 {
271 String rule = commandLineRules[i];
272 if ( !rule.contains( "." ) )
273 {
274 rule = getClass().getPackage().getName()
275 + "." + Character.toUpperCase( rule.charAt( 0 ) ) + rule.substring( 1 );
276 }
277
278 try
279 {
280 rules[i] = ( EnforcerRule ) Class.forName( rule ).newInstance();
281 }
282 catch ( Exception e )
283 {
284 throw new MojoExecutionException( "Failed to create enforcer rules from command line argument", e );
285 }
286 }
287 return rules;
288 }
289
290
291
292
293
294
295
296 protected boolean shouldExecute( EnforcerRule rule )
297 {
298 if ( rule.isCacheable() )
299 {
300 Log log = this.getLog();
301 log.debug( "Rule " + rule.getClass().getName() + " is cacheable." );
302 String key = rule.getClass().getName() + " " + rule.getCacheId();
303 if ( EnforceMojo.cache.containsKey( key ) )
304 {
305 log.debug( "Key " + key + " was found in the cache" );
306 if ( rule.isResultValid( cache.get( key ) ) )
307 {
308 log.debug( "The cached results are still valid. Skipping the rule: " + rule.getClass().getName() );
309 return false;
310 }
311 }
312
313
314 EnforceMojo.cache.put( key, rule );
315 }
316 return true;
317 }
318
319
320
321
322 public boolean isFail()
323 {
324 return this.fail;
325 }
326
327
328
329
330 public void setFail( boolean theFail )
331 {
332 this.fail = theFail;
333 }
334
335
336
337
338 public EnforcerRule[] getRules()
339 {
340 return this.rules;
341 }
342
343
344
345
346 public void setRules( EnforcerRule[] theRules )
347 {
348 this.rules = theRules;
349 }
350
351
352
353
354 public void setFailFast( boolean theFailFast )
355 {
356 this.failFast = theFailFast;
357 }
358
359 public boolean isFailFast()
360 {
361 return failFast;
362 }
363
364 protected String createRuleMessage( int i, String currentRule, EnforcerRuleException e )
365 {
366 return "Rule " + i + ": " + currentRule + " failed with message:" + System.lineSeparator() + e.getMessage();
367 }
368
369
370
371
372
373
374
375 private EnforcerLevel getLevel( EnforcerRule rule )
376 {
377 if ( rule instanceof EnforcerRule2 )
378 {
379 return ( (EnforcerRule2) rule ).getLevel();
380 }
381 else
382 {
383 return EnforcerLevel.ERROR;
384 }
385 }
386
387
388
389
390 public boolean isSkip()
391 {
392 return this.skip;
393 }
394
395
396
397
398 public void setSkip( boolean theSkip )
399 {
400 this.skip = theSkip;
401 }
402
403
404
405
406 public MavenProject getProject()
407 {
408 return this.project;
409 }
410
411
412
413
414 public void setProject( MavenProject theProject )
415 {
416 this.project = theProject;
417 }
418
419
420
421
422 public MavenSession getSession()
423 {
424 return this.session;
425 }
426
427
428
429
430 public void setSession( MavenSession theSession )
431 {
432 this.session = theSession;
433 }
434
435 }