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