View Javadoc

1   package org.apache.maven.plugin.jar;
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-jar-plugin.<br/> Call <pre>  mvn jar:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
12   *
13   * @version generated on Thu Aug 18 16:58:09 CEST 2011
14   * @author org.apache.maven.tools.plugin.generator.PluginHelpGenerator (version 2.7)
15   * @goal help
16   * @requiresProject false
17   * @threadSafe
18   */
19  public class HelpMojo
20      extends AbstractMojo
21  {
22      /**
23       * If <code>true</code>, display all settable properties for each goal.
24       * 
25       * @parameter expression="${detail}" default-value="false"
26       */
27      private boolean detail;
28  
29      /**
30       * The name of the goal for which to show help. If unspecified, all goals will be displayed.
31       * 
32       * @parameter expression="${goal}"
33       */
34      private java.lang.String goal;
35  
36      /**
37       * The maximum length of a display line, should be positive.
38       * 
39       * @parameter expression="${lineLength}" default-value="80"
40       */
41      private int lineLength;
42  
43      /**
44       * The number of spaces per indentation level, should be positive.
45       * 
46       * @parameter expression="${indentSize}" default-value="2"
47       */
48      private int indentSize;
49  
50  
51      /** {@inheritDoc} */
52      public void execute()
53          throws MojoExecutionException
54      {
55          if ( lineLength <= 0 )
56          {
57              getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
58              lineLength = 80;
59          }
60          if ( indentSize <= 0 )
61          {
62              getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
63              indentSize = 2;
64          }
65  
66          StringBuffer sb = new StringBuffer();
67  
68          append( sb, "org.apache.maven.plugins:maven-jar-plugin:2.3.2", 0 );
69          append( sb, "", 0 );
70  
71          append( sb, "Maven JAR Plugin", 0 );
72          append( sb, "Builds a Java Archive (JAR) file from the compiled project classes and resources.", 1 );
73          append( sb, "", 0 );
74  
75          if ( goal == null || goal.length() <= 0 )
76          {
77              append( sb, "This plugin has 5 goals:", 0 );
78              append( sb, "", 0 );
79          }
80  
81          if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
82          {
83              append( sb, "jar:help", 0 );
84              append( sb, "Display help information on maven-jar-plugin.\nCall\n\u00a0\u00a0mvn\u00a0jar:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
85              append( sb, "", 0 );
86              if ( detail )
87              {
88                  append( sb, "Available parameters:", 1 );
89                  append( sb, "", 0 );
90  
91                  append( sb, "detail (Default: false)", 2 );
92                  append( sb, "If true, display all settable properties for each goal.", 3 );
93                  append( sb, "Expression: ${detail}", 3 );
94                  append( sb, "", 0 );
95  
96                  append( sb, "goal", 2 );
97                  append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
98                  append( sb, "Expression: ${goal}", 3 );
99                  append( sb, "", 0 );
100 
101                 append( sb, "indentSize (Default: 2)", 2 );
102                 append( sb, "The number of spaces per indentation level, should be positive.", 3 );
103                 append( sb, "Expression: ${indentSize}", 3 );
104                 append( sb, "", 0 );
105 
106                 append( sb, "lineLength (Default: 80)", 2 );
107                 append( sb, "The maximum length of a display line, should be positive.", 3 );
108                 append( sb, "Expression: ${lineLength}", 3 );
109                 append( sb, "", 0 );
110             }
111         }
112 
113         if ( goal == null || goal.length() <= 0 || "jar".equals( goal ) )
114         {
115             append( sb, "jar:jar", 0 );
116             append( sb, "Build a JAR from the current project.", 1 );
117             append( sb, "", 0 );
118             if ( detail )
119             {
120                 append( sb, "Available parameters:", 1 );
121                 append( sb, "", 0 );
122 
123                 append( sb, "archive", 2 );
124                 append( sb, "The archive configuration to use. See Maven Archiver Reference.", 3 );
125                 append( sb, "", 0 );
126 
127                 append( sb, "classesDirectory (Default: ${project.build.outputDirectory})", 2 );
128                 append( sb, "Directory containing the classes and resource files that should be packaged into the JAR.", 3 );
129                 append( sb, "Required: Yes", 3 );
130                 append( sb, "", 0 );
131 
132                 append( sb, "classifier", 2 );
133                 append( sb, "Classifier to add to the artifact generated. If given, the artifact will be an attachment instead.", 3 );
134                 append( sb, "", 0 );
135 
136                 append( sb, "excludes", 2 );
137                 append( sb, "List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents is being packaged into the JAR.", 3 );
138                 append( sb, "", 0 );
139 
140                 append( sb, "finalName (Default: ${project.build.finalName})", 2 );
141                 append( sb, "Name of the generated JAR.", 3 );
142                 append( sb, "Required: Yes", 3 );
143                 append( sb, "Expression: ${jar.finalName}", 3 );
144                 append( sb, "", 0 );
145 
146                 append( sb, "forceCreation (Default: false)", 2 );
147                 append( sb, "Whether creating the archive should be forced.", 3 );
148                 append( sb, "Expression: ${jar.forceCreation}", 3 );
149                 append( sb, "", 0 );
150 
151                 append( sb, "includes", 2 );
152                 append( sb, "List of files to include. Specified as fileset patterns which are relative to the input directory whose contents is being packaged into the JAR.", 3 );
153                 append( sb, "", 0 );
154 
155                 append( sb, "outputDirectory (Default: ${project.build.directory})", 2 );
156                 append( sb, "Directory containing the generated JAR.", 3 );
157                 append( sb, "Required: Yes", 3 );
158                 append( sb, "", 0 );
159 
160                 append( sb, "useDefaultManifestFile (Default: false)", 2 );
161                 append( sb, "Set this to true to enable the use of the defaultManifestFile.", 3 );
162                 append( sb, "Expression: ${jar.useDefaultManifestFile}", 3 );
163                 append( sb, "", 0 );
164             }
165         }
166 
167         if ( goal == null || goal.length() <= 0 || "sign".equals( goal ) )
168         {
169             append( sb, "jar:sign", 0 );
170             append( sb, "Deprecated. As of version 2.3, this goal is no longer supported in favor of the dedicated maven-jarsigner-plugin.", 1 );
171             if ( detail )
172             {
173                 append( sb, "", 0 );
174                 append( sb, "Signs a JAR using jarsigner.", 1 );
175             }
176             append( sb, "", 0 );
177             if ( detail )
178             {
179                 append( sb, "Available parameters:", 1 );
180                 append( sb, "", 0 );
181 
182                 append( sb, "alias", 2 );
183                 append( sb, "See options.", 3 );
184                 append( sb, "Required: Yes", 3 );
185                 append( sb, "Expression: ${alias}", 3 );
186                 append( sb, "", 0 );
187 
188                 append( sb, "classifier", 2 );
189                 append( sb, "Classifier to use for the generated artifact. If not specified, the generated artifact becomes the primary artifact.", 3 );
190                 append( sb, "Expression: ${classifier}", 3 );
191                 append( sb, "", 0 );
192 
193                 append( sb, "finalName", 2 );
194                 append( sb, "Name of the generated JAR (without classifier and extension).", 3 );
195                 append( sb, "Required: Yes", 3 );
196                 append( sb, "Expression: ${project.build.finalName}", 3 );
197                 append( sb, "", 0 );
198 
199                 append( sb, "jarPath (Default: ${project.build.directory}/${project.build.finalName}.${project.packaging})", 2 );
200                 append( sb, "Path of the jar to sign. When specified, the finalName is ignored.", 3 );
201                 append( sb, "", 0 );
202 
203                 append( sb, "keypass", 2 );
204                 append( sb, "See options.", 3 );
205                 append( sb, "Expression: ${keypass}", 3 );
206                 append( sb, "", 0 );
207 
208                 append( sb, "keystore", 2 );
209                 append( sb, "See options.", 3 );
210                 append( sb, "Expression: ${keystore}", 3 );
211                 append( sb, "", 0 );
212 
213                 append( sb, "sigfile", 2 );
214                 append( sb, "See options.", 3 );
215                 append( sb, "Expression: ${sigfile}", 3 );
216                 append( sb, "", 0 );
217 
218                 append( sb, "signedjar", 2 );
219                 append( sb, "See options.\n>Not specifying this argument will sign the jar in-place (your original jar is going to be overwritten).\n", 3 );
220                 append( sb, "Expression: ${signedjar}", 3 );
221                 append( sb, "", 0 );
222 
223                 append( sb, "skip (Default: false)", 2 );
224                 append( sb, "Set this to true to disable signing. Useful to speed up build process in development environment.", 3 );
225                 append( sb, "Expression: ${maven.jar.sign.skip}", 3 );
226                 append( sb, "", 0 );
227 
228                 append( sb, "storepass", 2 );
229                 append( sb, "See options.", 3 );
230                 append( sb, "Expression: ${storepass}", 3 );
231                 append( sb, "", 0 );
232 
233                 append( sb, "type", 2 );
234                 append( sb, "See options. The corresponding option in the command line is -storetype.", 3 );
235                 append( sb, "Expression: ${type}", 3 );
236                 append( sb, "", 0 );
237 
238                 append( sb, "verbose (Default: false)", 2 );
239                 append( sb, "Enable verbose. See options.", 3 );
240                 append( sb, "Expression: ${verbose}", 3 );
241                 append( sb, "", 0 );
242 
243                 append( sb, "verify (Default: false)", 2 );
244                 append( sb, "Automatically verify a jar after signing it.\n>See options.\n", 3 );
245                 append( sb, "Expression: ${verify}", 3 );
246                 append( sb, "", 0 );
247 
248                 append( sb, "workingDirectory (Default: ${basedir})", 2 );
249                 append( sb, "The working directory in which the jarsigner executable will be run.", 3 );
250                 append( sb, "Required: Yes", 3 );
251                 append( sb, "Expression: ${workingdir}", 3 );
252                 append( sb, "", 0 );
253             }
254         }
255 
256         if ( goal == null || goal.length() <= 0 || "sign-verify".equals( goal ) )
257         {
258             append( sb, "jar:sign-verify", 0 );
259             append( sb, "Deprecated. As of version 2.3, this goal is no longer supported in favor of the dedicated maven-jarsigner-plugin.", 1 );
260             if ( detail )
261             {
262                 append( sb, "", 0 );
263                 append( sb, "Checks the signature of a signed jar using jarsigner.", 1 );
264             }
265             append( sb, "", 0 );
266             if ( detail )
267             {
268                 append( sb, "Available parameters:", 1 );
269                 append( sb, "", 0 );
270 
271                 append( sb, "checkCerts (Default: false)", 2 );
272                 append( sb, "Check certificates. Requires setVerbose(). See options.", 3 );
273                 append( sb, "Expression: ${checkcerts}", 3 );
274                 append( sb, "", 0 );
275 
276                 append( sb, "errorWhenNotSigned (Default: true)", 2 );
277                 append( sb, "When true this will make the execute() operation fail, throwing an exception, when verifying a non signed jar. Primarily to keep backwards compatibility with existing code, and allow reusing the bean in unattended operations when set to false.", 3 );
278                 append( sb, "Expression: ${errorWhenNotSigned}", 3 );
279                 append( sb, "", 0 );
280 
281                 append( sb, "finalName", 2 );
282                 append( sb, "Name of the generated JAR (without classifier and extension).", 3 );
283                 append( sb, "Required: Yes", 3 );
284                 append( sb, "Expression: ${project.build.finalName}", 3 );
285                 append( sb, "", 0 );
286 
287                 append( sb, "jarPath", 2 );
288                 append( sb, "Path of the signed jar. When specified, the finalName is ignored.", 3 );
289                 append( sb, "Expression: ${jarpath}", 3 );
290                 append( sb, "", 0 );
291 
292                 append( sb, "verbose (Default: false)", 2 );
293                 append( sb, "Enable verbose See options.", 3 );
294                 append( sb, "Expression: ${verbose}", 3 );
295                 append( sb, "", 0 );
296 
297                 append( sb, "workingDirectory (Default: ${basedir})", 2 );
298                 append( sb, "The working directory in which the jarsigner executable will be run.", 3 );
299                 append( sb, "Required: Yes", 3 );
300                 append( sb, "Expression: ${workingdir}", 3 );
301                 append( sb, "", 0 );
302             }
303         }
304 
305         if ( goal == null || goal.length() <= 0 || "test-jar".equals( goal ) )
306         {
307             append( sb, "jar:test-jar", 0 );
308             append( sb, "Build a JAR of the test classes for the current project.", 1 );
309             append( sb, "", 0 );
310             if ( detail )
311             {
312                 append( sb, "Available parameters:", 1 );
313                 append( sb, "", 0 );
314 
315                 append( sb, "archive", 2 );
316                 append( sb, "The archive configuration to use. See Maven Archiver Reference.", 3 );
317                 append( sb, "", 0 );
318 
319                 append( sb, "excludes", 2 );
320                 append( sb, "List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents is being packaged into the JAR.", 3 );
321                 append( sb, "", 0 );
322 
323                 append( sb, "finalName (Default: ${project.build.finalName})", 2 );
324                 append( sb, "Name of the generated JAR.", 3 );
325                 append( sb, "Required: Yes", 3 );
326                 append( sb, "Expression: ${jar.finalName}", 3 );
327                 append( sb, "", 0 );
328 
329                 append( sb, "forceCreation (Default: false)", 2 );
330                 append( sb, "Whether creating the archive should be forced.", 3 );
331                 append( sb, "Expression: ${jar.forceCreation}", 3 );
332                 append( sb, "", 0 );
333 
334                 append( sb, "includes", 2 );
335                 append( sb, "List of files to include. Specified as fileset patterns which are relative to the input directory whose contents is being packaged into the JAR.", 3 );
336                 append( sb, "", 0 );
337 
338                 append( sb, "outputDirectory (Default: ${project.build.directory})", 2 );
339                 append( sb, "Directory containing the generated JAR.", 3 );
340                 append( sb, "Required: Yes", 3 );
341                 append( sb, "", 0 );
342 
343                 append( sb, "skip", 2 );
344                 append( sb, "Set this to true to bypass unit tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
345                 append( sb, "Expression: ${maven.test.skip}", 3 );
346                 append( sb, "", 0 );
347 
348                 append( sb, "testClassesDirectory (Default: ${project.build.testOutputDirectory})", 2 );
349                 append( sb, "Directory containing the test classes and resource files that should be packaged into the JAR.", 3 );
350                 append( sb, "Required: Yes", 3 );
351                 append( sb, "", 0 );
352 
353                 append( sb, "useDefaultManifestFile (Default: false)", 2 );
354                 append( sb, "Set this to true to enable the use of the defaultManifestFile.", 3 );
355                 append( sb, "Expression: ${jar.useDefaultManifestFile}", 3 );
356                 append( sb, "", 0 );
357             }
358         }
359 
360         if ( getLog().isInfoEnabled() )
361         {
362             getLog().info( sb.toString() );
363         }
364     }
365 
366     /**
367      * <p>Repeat a String <code>n</code> times to form a new string.</p>
368      *
369      * @param str String to repeat
370      * @param repeat number of times to repeat str
371      * @return String with repeated String
372      * @throws NegativeArraySizeException if <code>repeat < 0</code>
373      * @throws NullPointerException if str is <code>null</code>
374      */
375     private static String repeat( String str, int repeat )
376     {
377         StringBuffer buffer = new StringBuffer( repeat * str.length() );
378 
379         for ( int i = 0; i < repeat; i++ )
380         {
381             buffer.append( str );
382         }
383 
384         return buffer.toString();
385     }
386 
387     /** 
388      * Append a description to the buffer by respecting the indentSize and lineLength parameters.
389      * <b>Note</b>: The last character is always a new line.
390      * 
391      * @param sb The buffer to append the description, not <code>null</code>.
392      * @param description The description, not <code>null</code>.
393      * @param indent The base indentation level of each line, must not be negative.
394      */
395     private void append( StringBuffer sb, String description, int indent )
396     {
397         for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
398         {
399             sb.append( it.next().toString() ).append( '\n' );
400         }
401     }
402 
403     /** 
404      * Splits the specified text into lines of convenient display length.
405      * 
406      * @param text The text to split into lines, must not be <code>null</code>.
407      * @param indent The base indentation level of each line, must not be negative.
408      * @param indentSize The size of each indentation, must not be negative.
409      * @param lineLength The length of the line, must not be negative.
410      * @return The sequence of display lines, never <code>null</code>.
411      * @throws NegativeArraySizeException if <code>indent < 0</code>
412      */
413     private static List toLines( String text, int indent, int indentSize, int lineLength )
414     {
415         List lines = new ArrayList();
416 
417         String ind = repeat( "\t", indent );
418         String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
419         for ( int i = 0; i < plainLines.length; i++ )
420         {
421             toLines( lines, ind + plainLines[i], indentSize, lineLength );
422         }
423 
424         return lines;
425     }
426 
427     /** 
428      * Adds the specified line to the output sequence, performing line wrapping if necessary.
429      * 
430      * @param lines The sequence of display lines, must not be <code>null</code>.
431      * @param line The line to add, must not be <code>null</code>.
432      * @param indentSize The size of each indentation, must not be negative.
433      * @param lineLength The length of the line, must not be negative.
434      */
435     private static void toLines( List lines, String line, int indentSize, int lineLength )
436     {
437         int lineIndent = getIndentLevel( line );
438         StringBuffer buf = new StringBuffer( 256 );
439         String[] tokens = line.split( " +" );
440         for ( int i = 0; i < tokens.length; i++ )
441         {
442             String token = tokens[i];
443             if ( i > 0 )
444             {
445                 if ( buf.length() + token.length() >= lineLength )
446                 {
447                     lines.add( buf.toString() );
448                     buf.setLength( 0 );
449                     buf.append( repeat( " ", lineIndent * indentSize ) );
450                 }
451                 else
452                 {
453                     buf.append( ' ' );
454                 }
455             }
456             for ( int j = 0; j < token.length(); j++ )
457             {
458                 char c = token.charAt( j );
459                 if ( c == '\t' )
460                 {
461                     buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
462                 }
463                 else if ( c == '\u00A0' )
464                 {
465                     buf.append( ' ' );
466                 }
467                 else
468                 {
469                     buf.append( c );
470                 }
471             }
472         }
473         lines.add( buf.toString() );
474     }
475 
476     /** 
477      * Gets the indentation level of the specified line.
478      * 
479      * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
480      * @return The indentation level of the line.
481      */
482     private static int getIndentLevel( String line )
483     {
484         int level = 0;
485         for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
486         {
487             level++;
488         }
489         for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
490         {
491             if ( line.charAt( i ) == '\t' )
492             {
493                 level++;
494                 break;
495             }
496         }
497         return level;
498     }
499 }