View Javadoc

1   package org.apache.maven.plugin.pmd;
2   
3   import java.util.ArrayList;
4   import java.util.Iterator;
5   import java.util.List;
6   
7   import org.apache.maven.plugin.AbstractMojo;
8   import org.apache.maven.plugin.MojoExecutionException;
9   
10  /**
11   * Display help information on maven-pmd-plugin.<br/> Call <pre>  mvn pmd:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
12   *
13   * @version generated on Tue Nov 08 18:57:08 CET 2011
14   * @author org.apache.maven.tools.plugin.generator.PluginHelpGenerator (version 2.8)
15   * @goal help
16   * @requiresProject false
17   * @threadSafe
18   */
19  @SuppressWarnings( "all" )
20  public class HelpMojo
21      extends AbstractMojo
22  {
23      /**
24       * If <code>true</code>, display all settable properties for each goal.
25       * 
26       * @parameter expression="${detail}" default-value="false"
27       */
28      private boolean detail;
29  
30      /**
31       * The name of the goal for which to show help. If unspecified, all goals will be displayed.
32       * 
33       * @parameter expression="${goal}"
34       */
35      private java.lang.String goal;
36  
37      /**
38       * The maximum length of a display line, should be positive.
39       * 
40       * @parameter expression="${lineLength}" default-value="80"
41       */
42      private int lineLength;
43  
44      /**
45       * The number of spaces per indentation level, should be positive.
46       * 
47       * @parameter expression="${indentSize}" default-value="2"
48       */
49      private int indentSize;
50  
51  
52      /** {@inheritDoc} */
53      public void execute()
54          throws MojoExecutionException
55      {
56          if ( lineLength <= 0 )
57          {
58              getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
59              lineLength = 80;
60          }
61          if ( indentSize <= 0 )
62          {
63              getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
64              indentSize = 2;
65          }
66  
67          StringBuffer sb = new StringBuffer();
68  
69          append( sb, "org.apache.maven.plugins:maven-pmd-plugin:2.6", 0 );
70          append( sb, "", 0 );
71  
72          append( sb, "Maven PMD Plugin", 0 );
73          append( sb, "A Maven plugin for the PMD toolkit, that produces a report on both code rule violations and detected copy and paste fragments, as well as being able to fail the build based on these metrics.", 1 );
74          append( sb, "", 0 );
75  
76          if ( goal == null || goal.length() <= 0 )
77          {
78              append( sb, "This plugin has 5 goals:", 0 );
79              append( sb, "", 0 );
80          }
81  
82          if ( goal == null || goal.length() <= 0 || "check".equals( goal ) )
83          {
84              append( sb, "pmd:check", 0 );
85              append( sb, "Fail the build if there were any PMD violations in the source code.", 1 );
86              append( sb, "", 0 );
87              if ( detail )
88              {
89                  append( sb, "Available parameters:", 1 );
90                  append( sb, "", 0 );
91  
92                  append( sb, "aggregate (Default: false)", 2 );
93                  append( sb, "Whether to build an aggregated report at the root, or build individual reports.", 3 );
94                  append( sb, "Expression: ${aggregate}", 3 );
95                  append( sb, "", 0 );
96  
97                  append( sb, "failOnViolation (Default: true)", 2 );
98                  append( sb, "Whether to fail the build if the validation check fails.", 3 );
99                  append( sb, "Required: Yes", 3 );
100                 append( sb, "Expression: ${pmd.failOnViolation}", 3 );
101                 append( sb, "", 0 );
102 
103                 append( sb, "failurePriority (Default: 5)", 2 );
104                 append( sb, "What priority level to fail the build on. Failures at or above this level will stop the build. Anything below will be warnings and will be displayed in the build output if verbose=true. Note: Minimum Priority = 5 Maximum Priority = 0", 3 );
105                 append( sb, "Required: Yes", 3 );
106                 append( sb, "Expression: ${pmd.failurePriority}", 3 );
107                 append( sb, "", 0 );
108 
109                 append( sb, "skip (Default: false)", 2 );
110                 append( sb, "Skip the PMD checks. Most useful on the command line via \'-Dpmd.skip=true\'.", 3 );
111                 append( sb, "Expression: ${pmd.skip}", 3 );
112                 append( sb, "", 0 );
113 
114                 append( sb, "targetDirectory", 2 );
115                 append( sb, "The location of the XML report to check, as generated by the PMD report.", 3 );
116                 append( sb, "Required: Yes", 3 );
117                 append( sb, "Expression: ${project.build.directory}", 3 );
118                 append( sb, "", 0 );
119 
120                 append( sb, "verbose (Default: false)", 2 );
121                 append( sb, "Print details of check failures to build output.", 3 );
122                 append( sb, "Expression: ${pmd.verbose}", 3 );
123                 append( sb, "", 0 );
124             }
125         }
126 
127         if ( goal == null || goal.length() <= 0 || "cpd".equals( goal ) )
128         {
129             append( sb, "pmd:cpd", 0 );
130             append( sb, "Creates a report for PMD\'s CPD tool. See http://pmd.sourceforge.net/cpd.html for more detail.", 1 );
131             append( sb, "", 0 );
132             if ( detail )
133             {
134                 append( sb, "Available parameters:", 1 );
135                 append( sb, "", 0 );
136 
137                 append( sb, "aggregate (Default: false)", 2 );
138                 append( sb, "Whether to build an aggregated report at the root, or build individual reports.", 3 );
139                 append( sb, "Expression: ${aggregate}", 3 );
140                 append( sb, "", 0 );
141 
142                 append( sb, "excludeRoots", 2 );
143                 append( sb, "The project source directories that should be excluded.", 3 );
144                 append( sb, "", 0 );
145 
146                 append( sb, "excludes", 2 );
147                 append( sb, "A list of files to exclude from checking. Can contain Ant-style wildcards and double wildcards. Note that these exclusion patterns only operate on the path of a source file relative to its source root directory. In other words, files are excluded based on their package and/or class name. If you want to exclude entire source root directories, use the parameter excludeRoots instead.", 3 );
148                 append( sb, "", 0 );
149 
150                 append( sb, "format (Default: xml)", 2 );
151                 append( sb, "Set the output format type, in addition to the HTML report. Must be one of: \'none\', \'csv\', \'xml\', \'txt\' or the full class name of the PMD renderer to use. See the net.sourceforge.pmd.renderers package javadoc for available renderers. XML is required if the pmd:check goal is being used.", 3 );
152                 append( sb, "Expression: ${format}", 3 );
153                 append( sb, "", 0 );
154 
155                 append( sb, "ignoreIdentifiers (Default: false)", 2 );
156                 append( sb, "Similar to ignoreLiterals but for identifiers; i.e., variable names, methods names, and so forth.", 3 );
157                 append( sb, "Expression: ${cpd.ignoreIdentifiers}", 3 );
158                 append( sb, "", 0 );
159 
160                 append( sb, "ignoreLiterals (Default: false)", 2 );
161                 append( sb, "If true, CPD ignores literal value differences when evaluating a duplicate block. This means that foo=42; and foo=43; will be seen as equivalent. You may want to run PMD with this option off to start with and then switch it on to see what it turns up.", 3 );
162                 append( sb, "Expression: ${cpd.ignoreLiterals}", 3 );
163                 append( sb, "", 0 );
164 
165                 append( sb, "includes", 2 );
166                 append( sb, "A list of files to include from checking. Can contain Ant-style wildcards and double wildcards. Defaults to **\\/*.java.", 3 );
167                 append( sb, "", 0 );
168 
169                 append( sb, "includeTests (Default: false)", 2 );
170                 append( sb, "Run PMD on the tests.", 3 );
171                 append( sb, "", 0 );
172 
173                 append( sb, "linkXRef (Default: true)", 2 );
174                 append( sb, "Link the violation line numbers to the source xref. Links will be created automatically if the jxr plugin is being used.", 3 );
175                 append( sb, "Expression: ${linkXRef}", 3 );
176                 append( sb, "", 0 );
177 
178                 append( sb, "minimumTokens (Default: 100)", 2 );
179                 append( sb, "The minimum number of tokens that need to be duplicated before it causes a violation.", 3 );
180                 append( sb, "Expression: ${minimumTokens}", 3 );
181                 append( sb, "", 0 );
182 
183                 append( sb, "outputDirectory", 2 );
184                 append( sb, "The output directory for the final HTML report. Note that this parameter is only evaluated if the goal is run directly from the command line or during the default lifecycle. If the goal is run indirectly as part of a site generation, the output directory configured in the Maven Site Plugin is used instead.", 3 );
185                 append( sb, "Required: Yes", 3 );
186                 append( sb, "Expression: ${project.reporting.outputDirectory}", 3 );
187                 append( sb, "", 0 );
188 
189                 append( sb, "outputEncoding (Default: ${project.reporting.outputEncoding})", 2 );
190                 append( sb, "The file encoding when writing non-HTML reports.", 3 );
191                 append( sb, "Expression: ${outputEncoding}", 3 );
192                 append( sb, "", 0 );
193 
194                 append( sb, "skip (Default: false)", 2 );
195                 append( sb, "Skip the CPD report generation. Most useful on the command line via \'-Dcpd.skip=true\'.", 3 );
196                 append( sb, "Expression: ${cpd.skip}", 3 );
197                 append( sb, "", 0 );
198 
199                 append( sb, "sourceEncoding (Default: ${project.build.sourceEncoding})", 2 );
200                 append( sb, "The file encoding to use when reading the Java sources.", 3 );
201                 append( sb, "Expression: ${encoding}", 3 );
202                 append( sb, "", 0 );
203 
204                 append( sb, "targetDirectory", 2 );
205                 append( sb, "The output directory for the intermediate XML report.", 3 );
206                 append( sb, "Required: Yes", 3 );
207                 append( sb, "Expression: ${project.build.directory}", 3 );
208                 append( sb, "", 0 );
209 
210                 append( sb, "xrefLocation (Default: ${project.reporting.outputDirectory}/xref)", 2 );
211                 append( sb, "Location of the Xrefs to link to.", 3 );
212                 append( sb, "", 0 );
213 
214                 append( sb, "xrefTestLocation (Default: ${project.reporting.outputDirectory}/xref-test)", 2 );
215                 append( sb, "Location of the Test Xrefs to link to.", 3 );
216                 append( sb, "", 0 );
217             }
218         }
219 
220         if ( goal == null || goal.length() <= 0 || "cpd-check".equals( goal ) )
221         {
222             append( sb, "pmd:cpd-check", 0 );
223             append( sb, "Fail the build if there were any CPD violations in the source code.", 1 );
224             append( sb, "", 0 );
225             if ( detail )
226             {
227                 append( sb, "Available parameters:", 1 );
228                 append( sb, "", 0 );
229 
230                 append( sb, "aggregate (Default: false)", 2 );
231                 append( sb, "Whether to build an aggregated report at the root, or build individual reports.", 3 );
232                 append( sb, "Expression: ${aggregate}", 3 );
233                 append( sb, "", 0 );
234 
235                 append( sb, "failOnViolation (Default: true)", 2 );
236                 append( sb, "Whether to fail the build if the validation check fails.", 3 );
237                 append( sb, "Required: Yes", 3 );
238                 append( sb, "Expression: ${pmd.failOnViolation}", 3 );
239                 append( sb, "", 0 );
240 
241                 append( sb, "skip (Default: false)", 2 );
242                 append( sb, "Skip the CPD violation checks. Most useful on the command line via \'-Dcpd.skip=true\'.", 3 );
243                 append( sb, "Expression: ${cpd.skip}", 3 );
244                 append( sb, "", 0 );
245 
246                 append( sb, "targetDirectory", 2 );
247                 append( sb, "The location of the XML report to check, as generated by the PMD report.", 3 );
248                 append( sb, "Required: Yes", 3 );
249                 append( sb, "Expression: ${project.build.directory}", 3 );
250                 append( sb, "", 0 );
251 
252                 append( sb, "verbose (Default: false)", 2 );
253                 append( sb, "Print details of check failures to build output.", 3 );
254                 append( sb, "Expression: ${pmd.verbose}", 3 );
255                 append( sb, "", 0 );
256             }
257         }
258 
259         if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
260         {
261             append( sb, "pmd:help", 0 );
262             append( sb, "Display help information on maven-pmd-plugin.\nCall\n\u00a0\u00a0mvn\u00a0pmd:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
263             append( sb, "", 0 );
264             if ( detail )
265             {
266                 append( sb, "Available parameters:", 1 );
267                 append( sb, "", 0 );
268 
269                 append( sb, "detail (Default: false)", 2 );
270                 append( sb, "If true, display all settable properties for each goal.", 3 );
271                 append( sb, "Expression: ${detail}", 3 );
272                 append( sb, "", 0 );
273 
274                 append( sb, "goal", 2 );
275                 append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
276                 append( sb, "Expression: ${goal}", 3 );
277                 append( sb, "", 0 );
278 
279                 append( sb, "indentSize (Default: 2)", 2 );
280                 append( sb, "The number of spaces per indentation level, should be positive.", 3 );
281                 append( sb, "Expression: ${indentSize}", 3 );
282                 append( sb, "", 0 );
283 
284                 append( sb, "lineLength (Default: 80)", 2 );
285                 append( sb, "The maximum length of a display line, should be positive.", 3 );
286                 append( sb, "Expression: ${lineLength}", 3 );
287                 append( sb, "", 0 );
288             }
289         }
290 
291         if ( goal == null || goal.length() <= 0 || "pmd".equals( goal ) )
292         {
293             append( sb, "pmd:pmd", 0 );
294             append( sb, "Creates a PMD report.", 1 );
295             append( sb, "", 0 );
296             if ( detail )
297             {
298                 append( sb, "Available parameters:", 1 );
299                 append( sb, "", 0 );
300 
301                 append( sb, "aggregate (Default: false)", 2 );
302                 append( sb, "Whether to build an aggregated report at the root, or build individual reports.", 3 );
303                 append( sb, "Expression: ${aggregate}", 3 );
304                 append( sb, "", 0 );
305 
306                 append( sb, "excludeRoots", 2 );
307                 append( sb, "The project source directories that should be excluded.", 3 );
308                 append( sb, "", 0 );
309 
310                 append( sb, "excludes", 2 );
311                 append( sb, "A list of files to exclude from checking. Can contain Ant-style wildcards and double wildcards. Note that these exclusion patterns only operate on the path of a source file relative to its source root directory. In other words, files are excluded based on their package and/or class name. If you want to exclude entire source root directories, use the parameter excludeRoots instead.", 3 );
312                 append( sb, "", 0 );
313 
314                 append( sb, "format (Default: xml)", 2 );
315                 append( sb, "Set the output format type, in addition to the HTML report. Must be one of: \'none\', \'csv\', \'xml\', \'txt\' or the full class name of the PMD renderer to use. See the net.sourceforge.pmd.renderers package javadoc for available renderers. XML is required if the pmd:check goal is being used.", 3 );
316                 append( sb, "Expression: ${format}", 3 );
317                 append( sb, "", 0 );
318 
319                 append( sb, "includes", 2 );
320                 append( sb, "A list of files to include from checking. Can contain Ant-style wildcards and double wildcards. Defaults to **\\/*.java.", 3 );
321                 append( sb, "", 0 );
322 
323                 append( sb, "includeTests (Default: false)", 2 );
324                 append( sb, "Run PMD on the tests.", 3 );
325                 append( sb, "", 0 );
326 
327                 append( sb, "linkXRef (Default: true)", 2 );
328                 append( sb, "Link the violation line numbers to the source xref. Links will be created automatically if the jxr plugin is being used.", 3 );
329                 append( sb, "Expression: ${linkXRef}", 3 );
330                 append( sb, "", 0 );
331 
332                 append( sb, "minimumPriority (Default: 5)", 2 );
333                 append( sb, "The rule priority threshold; rules with lower priority than this will not be evaluated.", 3 );
334                 append( sb, "Expression: ${minimumPriority}", 3 );
335                 append( sb, "", 0 );
336 
337                 append( sb, "outputDirectory", 2 );
338                 append( sb, "The output directory for the final HTML report. Note that this parameter is only evaluated if the goal is run directly from the command line or during the default lifecycle. If the goal is run indirectly as part of a site generation, the output directory configured in the Maven Site Plugin is used instead.", 3 );
339                 append( sb, "Required: Yes", 3 );
340                 append( sb, "Expression: ${project.reporting.outputDirectory}", 3 );
341                 append( sb, "", 0 );
342 
343                 append( sb, "outputEncoding (Default: ${project.reporting.outputEncoding})", 2 );
344                 append( sb, "The file encoding when writing non-HTML reports.", 3 );
345                 append( sb, "Expression: ${outputEncoding}", 3 );
346                 append( sb, "", 0 );
347 
348                 append( sb, "rulesets", 2 );
349                 append( sb, "The PMD rulesets to use. See the Stock Rulesets for a list of some included. Since version 2.5, the ruleset \'rulesets/maven.xml\' is also available. Defaults to the basic, imports and unusedcode rulesets.", 3 );
350                 append( sb, "", 0 );
351 
352                 append( sb, "skip (Default: false)", 2 );
353                 append( sb, "Skip the PMD report generation. Most useful on the command line via \'-Dpmd.skip=true\'.", 3 );
354                 append( sb, "Expression: ${pmd.skip}", 3 );
355                 append( sb, "", 0 );
356 
357                 append( sb, "sourceEncoding (Default: ${project.build.sourceEncoding})", 2 );
358                 append( sb, "The file encoding to use when reading the Java sources.", 3 );
359                 append( sb, "Expression: ${encoding}", 3 );
360                 append( sb, "", 0 );
361 
362                 append( sb, "targetDirectory", 2 );
363                 append( sb, "The output directory for the intermediate XML report.", 3 );
364                 append( sb, "Required: Yes", 3 );
365                 append( sb, "Expression: ${project.build.directory}", 3 );
366                 append( sb, "", 0 );
367 
368                 append( sb, "targetJdk", 2 );
369                 append( sb, "The target JDK to analyze based on. Should match the target used in the compiler plugin. Valid values are currently 1.3, 1.4, 1.5 and 1.6.\nNote: support for 1.6 was added in version 2.3 of this plugin.\n", 3 );
370                 append( sb, "Expression: ${targetJdk}", 3 );
371                 append( sb, "", 0 );
372 
373                 append( sb, "xrefLocation (Default: ${project.reporting.outputDirectory}/xref)", 2 );
374                 append( sb, "Location of the Xrefs to link to.", 3 );
375                 append( sb, "", 0 );
376 
377                 append( sb, "xrefTestLocation (Default: ${project.reporting.outputDirectory}/xref-test)", 2 );
378                 append( sb, "Location of the Test Xrefs to link to.", 3 );
379                 append( sb, "", 0 );
380             }
381         }
382 
383         if ( getLog().isInfoEnabled() )
384         {
385             getLog().info( sb.toString() );
386         }
387     }
388 
389     /**
390      * <p>Repeat a String <code>n</code> times to form a new string.</p>
391      *
392      * @param str String to repeat
393      * @param repeat number of times to repeat str
394      * @return String with repeated String
395      * @throws NegativeArraySizeException if <code>repeat < 0</code>
396      * @throws NullPointerException if str is <code>null</code>
397      */
398     private static String repeat( String str, int repeat )
399     {
400         StringBuffer buffer = new StringBuffer( repeat * str.length() );
401 
402         for ( int i = 0; i < repeat; i++ )
403         {
404             buffer.append( str );
405         }
406 
407         return buffer.toString();
408     }
409 
410     /** 
411      * Append a description to the buffer by respecting the indentSize and lineLength parameters.
412      * <b>Note</b>: The last character is always a new line.
413      * 
414      * @param sb The buffer to append the description, not <code>null</code>.
415      * @param description The description, not <code>null</code>.
416      * @param indent The base indentation level of each line, must not be negative.
417      */
418     private void append( StringBuffer sb, String description, int indent )
419     {
420         for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
421         {
422             sb.append( it.next().toString() ).append( '\n' );
423         }
424     }
425 
426     /** 
427      * Splits the specified text into lines of convenient display length.
428      * 
429      * @param text The text to split into lines, must not be <code>null</code>.
430      * @param indent The base indentation level of each line, must not be negative.
431      * @param indentSize The size of each indentation, must not be negative.
432      * @param lineLength The length of the line, must not be negative.
433      * @return The sequence of display lines, never <code>null</code>.
434      * @throws NegativeArraySizeException if <code>indent < 0</code>
435      */
436     private static List toLines( String text, int indent, int indentSize, int lineLength )
437     {
438         List<String> lines = new ArrayList<String>();
439 
440         String ind = repeat( "\t", indent );
441         String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
442         for ( int i = 0; i < plainLines.length; i++ )
443         {
444             toLines( lines, ind + plainLines[i], indentSize, lineLength );
445         }
446 
447         return lines;
448     }
449 
450     /** 
451      * Adds the specified line to the output sequence, performing line wrapping if necessary.
452      * 
453      * @param lines The sequence of display lines, must not be <code>null</code>.
454      * @param line The line to add, must not be <code>null</code>.
455      * @param indentSize The size of each indentation, must not be negative.
456      * @param lineLength The length of the line, must not be negative.
457      */
458     private static void toLines( List<String> lines, String line, int indentSize, int lineLength )
459     {
460         int lineIndent = getIndentLevel( line );
461         StringBuffer buf = new StringBuffer( 256 );
462         String[] tokens = line.split( " +" );
463         for ( int i = 0; i < tokens.length; i++ )
464         {
465             String token = tokens[i];
466             if ( i > 0 )
467             {
468                 if ( buf.length() + token.length() >= lineLength )
469                 {
470                     lines.add( buf.toString() );
471                     buf.setLength( 0 );
472                     buf.append( repeat( " ", lineIndent * indentSize ) );
473                 }
474                 else
475                 {
476                     buf.append( ' ' );
477                 }
478             }
479             for ( int j = 0; j < token.length(); j++ )
480             {
481                 char c = token.charAt( j );
482                 if ( c == '\t' )
483                 {
484                     buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
485                 }
486                 else if ( c == '\u00A0' )
487                 {
488                     buf.append( ' ' );
489                 }
490                 else
491                 {
492                     buf.append( c );
493                 }
494             }
495         }
496         lines.add( buf.toString() );
497     }
498 
499     /** 
500      * Gets the indentation level of the specified line.
501      * 
502      * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
503      * @return The indentation level of the line.
504      */
505     private static int getIndentLevel( String line )
506     {
507         int level = 0;
508         for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
509         {
510             level++;
511         }
512         for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
513         {
514             if ( line.charAt( i ) == '\t' )
515             {
516                 level++;
517                 break;
518             }
519         }
520         return level;
521     }
522 }