View Javadoc

1   package org.apache.maven.plugin.gpg;
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-gpg-plugin.<br/> Call <pre>  mvn gpg:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
12   *
13   * @version generated on Mon Aug 22 11:12:48 IST 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-gpg-plugin:1.4", 0 );
70          append( sb, "", 0 );
71  
72          append( sb, "Maven GPG Plugin", 0 );
73          append( sb, "Signs the project artifacts with GnuPG.", 1 );
74          append( sb, "", 0 );
75  
76          if ( goal == null || goal.length() <= 0 )
77          {
78              append( sb, "This plugin has 3 goals:", 0 );
79              append( sb, "", 0 );
80          }
81  
82          if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
83          {
84              append( sb, "gpg:help", 0 );
85              append( sb, "Display help information on maven-gpg-plugin.\nCall\n\u00a0\u00a0mvn\u00a0gpg:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
86              append( sb, "", 0 );
87              if ( detail )
88              {
89                  append( sb, "Available parameters:", 1 );
90                  append( sb, "", 0 );
91  
92                  append( sb, "detail (Default: false)", 2 );
93                  append( sb, "If true, display all settable properties for each goal.", 3 );
94                  append( sb, "Expression: ${detail}", 3 );
95                  append( sb, "", 0 );
96  
97                  append( sb, "goal", 2 );
98                  append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
99                  append( sb, "Expression: ${goal}", 3 );
100                 append( sb, "", 0 );
101 
102                 append( sb, "indentSize (Default: 2)", 2 );
103                 append( sb, "The number of spaces per indentation level, should be positive.", 3 );
104                 append( sb, "Expression: ${indentSize}", 3 );
105                 append( sb, "", 0 );
106 
107                 append( sb, "lineLength (Default: 80)", 2 );
108                 append( sb, "The maximum length of a display line, should be positive.", 3 );
109                 append( sb, "Expression: ${lineLength}", 3 );
110                 append( sb, "", 0 );
111             }
112         }
113 
114         if ( goal == null || goal.length() <= 0 || "sign".equals( goal ) )
115         {
116             append( sb, "gpg:sign", 0 );
117             append( sb, "Sign project artifact, the POM, and attached artifacts with GnuPG for deployment.", 1 );
118             append( sb, "", 0 );
119             if ( detail )
120             {
121                 append( sb, "Available parameters:", 1 );
122                 append( sb, "", 0 );
123 
124                 append( sb, "ascDirectory (Default: ${project.build.directory}/gpg)", 2 );
125                 append( sb, "The directory where to store signature files.", 3 );
126                 append( sb, "", 0 );
127 
128                 append( sb, "defaultKeyring (Default: true)", 2 );
129                 append( sb, "Whether to add the default keyrings from gpg\'s home directory to the list of used keyrings.", 3 );
130                 append( sb, "Expression: ${gpg.defaultKeyring}", 3 );
131                 append( sb, "", 0 );
132 
133                 append( sb, "excludes", 2 );
134                 append( sb, "A list of files to exclude from being signed. Can contain Ant-style wildcards and double wildcards. The default excludes are **/*.md5 **/*.sha1 **/*.asc.", 3 );
135                 append( sb, "", 0 );
136 
137                 append( sb, "executable", 2 );
138                 append( sb, "The path to the GnuPG executable to use for artifact signing. Defaults to either \'gpg\' or \'gpg.exe\' depending on the operating system.", 3 );
139                 append( sb, "Expression: ${gpg.executable}", 3 );
140                 append( sb, "", 0 );
141 
142                 append( sb, "homedir", 2 );
143                 append( sb, "The directory from which gpg will load keyrings. If not specified, gpg will use the value configured for its installation, e.g. ~/.gnupg or %APPDATA%/gnupg.", 3 );
144                 append( sb, "Expression: ${gpg.homedir}", 3 );
145                 append( sb, "", 0 );
146 
147                 append( sb, "keyname", 2 );
148                 append( sb, "The \'name\' of the key to sign with. Passed to gpg as --local-user.", 3 );
149                 append( sb, "Expression: ${gpg.keyname}", 3 );
150                 append( sb, "", 0 );
151 
152                 append( sb, "passphrase", 2 );
153                 append( sb, "The passphrase to use when signing.", 3 );
154                 append( sb, "Expression: ${gpg.passphrase}", 3 );
155                 append( sb, "", 0 );
156 
157                 append( sb, "publicKeyring", 2 );
158                 append( sb, "The path to a public keyring to add to the list of keyrings. By default, only the pubring.gpg from gpg\'s home directory is considered. Use this option (and defaultKeyring if required) to use a different public key. Note: Relative paths are resolved against gpg\'s home directory, not the project base directory.", 3 );
159                 append( sb, "Expression: ${gpg.publicKeyring}", 3 );
160                 append( sb, "", 0 );
161 
162                 append( sb, "secretKeyring", 2 );
163                 append( sb, "The path to a secret keyring to add to the list of keyrings. By default, only the secring.gpg from gpg\'s home directory is considered. Use this option (in combination with publicKeyring and defaultKeyring if required) to use a different secret key. Note: Relative paths are resolved against gpg\'s home directory, not the project base directory.", 3 );
164                 append( sb, "Expression: ${gpg.secretKeyring}", 3 );
165                 append( sb, "", 0 );
166 
167                 append( sb, "skip (Default: false)", 2 );
168                 append( sb, "Skip doing the gpg signing.", 3 );
169                 append( sb, "Expression: ${gpg.skip}", 3 );
170                 append( sb, "", 0 );
171 
172                 append( sb, "useAgent (Default: false)", 2 );
173                 append( sb, "Passes --use-agent or --no-use-agent to gpg. If using an agent, the passphrase is optional as the agent will provide it. For gpg2, specify true as --no-use-agent was removed in gpg2 and doesn\'t ask for a passphrase anymore.", 3 );
174                 append( sb, "Expression: ${gpg.useagent}", 3 );
175                 append( sb, "", 0 );
176             }
177         }
178 
179         if ( goal == null || goal.length() <= 0 || "sign-and-deploy-file".equals( goal ) )
180         {
181             append( sb, "gpg:sign-and-deploy-file", 0 );
182             append( sb, "Signs artifacts and installs the artifact in the remote repository.", 1 );
183             append( sb, "", 0 );
184             if ( detail )
185             {
186                 append( sb, "Available parameters:", 1 );
187                 append( sb, "", 0 );
188 
189                 append( sb, "artifactId", 2 );
190                 append( sb, "ArtifactId of the artifact to be deployed. Retrieved from POM file if specified.", 3 );
191                 append( sb, "Expression: ${artifactId}", 3 );
192                 append( sb, "", 0 );
193 
194                 append( sb, "ascDirectory", 2 );
195                 append( sb, "The directory where to store signature files.", 3 );
196                 append( sb, "Expression: ${gpg.ascDirectory}", 3 );
197                 append( sb, "", 0 );
198 
199                 append( sb, "classifier", 2 );
200                 append( sb, "Add classifier to the artifact", 3 );
201                 append( sb, "Expression: ${classifier}", 3 );
202                 append( sb, "", 0 );
203 
204                 append( sb, "classifiers", 2 );
205                 append( sb, "A comma separated list of classifiers for each of the extra side artifacts to deploy. If there is a mis-match in the number of entries in files or types, then an error will be raised.", 3 );
206                 append( sb, "Expression: ${classifiers}", 3 );
207                 append( sb, "", 0 );
208 
209                 append( sb, "defaultKeyring (Default: true)", 2 );
210                 append( sb, "Whether to add the default keyrings from gpg\'s home directory to the list of used keyrings.", 3 );
211                 append( sb, "Expression: ${gpg.defaultKeyring}", 3 );
212                 append( sb, "", 0 );
213 
214                 append( sb, "description", 2 );
215                 append( sb, "Description passed to a generated POM file (in case of generatePom=true).", 3 );
216                 append( sb, "Expression: ${generatePom.description}", 3 );
217                 append( sb, "", 0 );
218 
219                 append( sb, "executable", 2 );
220                 append( sb, "The path to the GnuPG executable to use for artifact signing. Defaults to either \'gpg\' or \'gpg.exe\' depending on the operating system.", 3 );
221                 append( sb, "Expression: ${gpg.executable}", 3 );
222                 append( sb, "", 0 );
223 
224                 append( sb, "file", 2 );
225                 append( sb, "File to be deployed.", 3 );
226                 append( sb, "Required: Yes", 3 );
227                 append( sb, "Expression: ${file}", 3 );
228                 append( sb, "", 0 );
229 
230                 append( sb, "files", 2 );
231                 append( sb, "A comma separated list of files for each of the extra side artifacts to deploy. If there is a mis-match in the number of entries in types or classifiers, then an error will be raised.", 3 );
232                 append( sb, "Expression: ${files}", 3 );
233                 append( sb, "", 0 );
234 
235                 append( sb, "generatePom (Default: true)", 2 );
236                 append( sb, "Upload a POM for this artifact. Will generate a default POM if none is supplied with the pomFile argument.", 3 );
237                 append( sb, "Expression: ${generatePom}", 3 );
238                 append( sb, "", 0 );
239 
240                 append( sb, "groupId", 2 );
241                 append( sb, "GroupId of the artifact to be deployed. Retrieved from POM file if specified.", 3 );
242                 append( sb, "Expression: ${groupId}", 3 );
243                 append( sb, "", 0 );
244 
245                 append( sb, "homedir", 2 );
246                 append( sb, "The directory from which gpg will load keyrings. If not specified, gpg will use the value configured for its installation, e.g. ~/.gnupg or %APPDATA%/gnupg.", 3 );
247                 append( sb, "Expression: ${gpg.homedir}", 3 );
248                 append( sb, "", 0 );
249 
250                 append( sb, "javadoc", 2 );
251                 append( sb, "The bundled API docs for the artifact.", 3 );
252                 append( sb, "Expression: ${javadoc}", 3 );
253                 append( sb, "", 0 );
254 
255                 append( sb, "keyname", 2 );
256                 append( sb, "The \'name\' of the key to sign with. Passed to gpg as --local-user.", 3 );
257                 append( sb, "Expression: ${gpg.keyname}", 3 );
258                 append( sb, "", 0 );
259 
260                 append( sb, "packaging", 2 );
261                 append( sb, "Type of the artifact to be deployed. Retrieved from POM file if specified. Defaults to file extension if not specified via command line or POM.", 3 );
262                 append( sb, "Expression: ${packaging}", 3 );
263                 append( sb, "", 0 );
264 
265                 append( sb, "passphrase", 2 );
266                 append( sb, "The passphrase to use when signing.", 3 );
267                 append( sb, "Expression: ${gpg.passphrase}", 3 );
268                 append( sb, "", 0 );
269 
270                 append( sb, "pomFile", 2 );
271                 append( sb, "Location of an existing POM file to be deployed alongside the main artifact, given by the ${file} parameter.", 3 );
272                 append( sb, "Expression: ${pomFile}", 3 );
273                 append( sb, "", 0 );
274 
275                 append( sb, "publicKeyring", 2 );
276                 append( sb, "The path to a public keyring to add to the list of keyrings. By default, only the pubring.gpg from gpg\'s home directory is considered. Use this option (and defaultKeyring if required) to use a different public key. Note: Relative paths are resolved against gpg\'s home directory, not the project base directory.", 3 );
277                 append( sb, "Expression: ${gpg.publicKeyring}", 3 );
278                 append( sb, "", 0 );
279 
280                 append( sb, "repositoryId (Default: remote-repository)", 2 );
281                 append( sb, "Server Id to map on the <id> under <server> section of settings.xml. In most cases, this parameter will be required for authentication.", 3 );
282                 append( sb, "Required: Yes", 3 );
283                 append( sb, "Expression: ${repositoryId}", 3 );
284                 append( sb, "", 0 );
285 
286                 append( sb, "repositoryLayout (Default: default)", 2 );
287                 append( sb, "The type of remote repository layout to deploy to. Try legacy for a Maven 1.x-style repository layout.", 3 );
288                 append( sb, "Expression: ${repositoryLayout}", 3 );
289                 append( sb, "", 0 );
290 
291                 append( sb, "retryFailedDeploymentCount (Default: 1)", 2 );
292                 append( sb, "Parameter used to control how many times a failed deployment will be retried before giving up and failing. If a value outside the range 1-10 is specified it will be pulled to the nearest value within the range 1-10.", 3 );
293                 append( sb, "Expression: ${retryFailedDeploymentCount}", 3 );
294                 append( sb, "", 0 );
295 
296                 append( sb, "secretKeyring", 2 );
297                 append( sb, "The path to a secret keyring to add to the list of keyrings. By default, only the secring.gpg from gpg\'s home directory is considered. Use this option (in combination with publicKeyring and defaultKeyring if required) to use a different secret key. Note: Relative paths are resolved against gpg\'s home directory, not the project base directory.", 3 );
298                 append( sb, "Expression: ${gpg.secretKeyring}", 3 );
299                 append( sb, "", 0 );
300 
301                 append( sb, "sources", 2 );
302                 append( sb, "The bundled sources for the artifact.", 3 );
303                 append( sb, "Expression: ${sources}", 3 );
304                 append( sb, "", 0 );
305 
306                 append( sb, "types", 2 );
307                 append( sb, "A comma separated list of types for each of the extra side artifacts to deploy. If there is a mis-match in the number of entries in files or classifiers, then an error will be raised.", 3 );
308                 append( sb, "Expression: ${types}", 3 );
309                 append( sb, "", 0 );
310 
311                 append( sb, "uniqueVersion (Default: true)", 2 );
312                 append( sb, "Whether to deploy snapshots with a unique version or not.", 3 );
313                 append( sb, "Expression: ${uniqueVersion}", 3 );
314                 append( sb, "", 0 );
315 
316                 append( sb, "updateReleaseInfo (Default: false)", 2 );
317                 append( sb, "Parameter used to update the metadata to make the artifact as release.", 3 );
318                 append( sb, "Expression: ${updateReleaseInfo}", 3 );
319                 append( sb, "", 0 );
320 
321                 append( sb, "url", 2 );
322                 append( sb, "URL where the artifact will be deployed.\nie ( file:///C:/m2-repo or scp://host.com/path/to/repo )", 3 );
323                 append( sb, "Required: Yes", 3 );
324                 append( sb, "Expression: ${url}", 3 );
325                 append( sb, "", 0 );
326 
327                 append( sb, "useAgent (Default: false)", 2 );
328                 append( sb, "Passes --use-agent or --no-use-agent to gpg. If using an agent, the passphrase is optional as the agent will provide it. For gpg2, specify true as --no-use-agent was removed in gpg2 and doesn\'t ask for a passphrase anymore.", 3 );
329                 append( sb, "Expression: ${gpg.useagent}", 3 );
330                 append( sb, "", 0 );
331 
332                 append( sb, "version", 2 );
333                 append( sb, "Version of the artifact to be deployed. Retrieved from POM file if specified.", 3 );
334                 append( sb, "Expression: ${version}", 3 );
335                 append( sb, "", 0 );
336             }
337         }
338 
339         if ( getLog().isInfoEnabled() )
340         {
341             getLog().info( sb.toString() );
342         }
343     }
344 
345     /**
346      * <p>Repeat a String <code>n</code> times to form a new string.</p>
347      *
348      * @param str String to repeat
349      * @param repeat number of times to repeat str
350      * @return String with repeated String
351      * @throws NegativeArraySizeException if <code>repeat < 0</code>
352      * @throws NullPointerException if str is <code>null</code>
353      */
354     private static String repeat( String str, int repeat )
355     {
356         StringBuffer buffer = new StringBuffer( repeat * str.length() );
357 
358         for ( int i = 0; i < repeat; i++ )
359         {
360             buffer.append( str );
361         }
362 
363         return buffer.toString();
364     }
365 
366     /** 
367      * Append a description to the buffer by respecting the indentSize and lineLength parameters.
368      * <b>Note</b>: The last character is always a new line.
369      * 
370      * @param sb The buffer to append the description, not <code>null</code>.
371      * @param description The description, not <code>null</code>.
372      * @param indent The base indentation level of each line, must not be negative.
373      */
374     private void append( StringBuffer sb, String description, int indent )
375     {
376         for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
377         {
378             sb.append( it.next().toString() ).append( '\n' );
379         }
380     }
381 
382     /** 
383      * Splits the specified text into lines of convenient display length.
384      * 
385      * @param text The text to split into lines, must not be <code>null</code>.
386      * @param indent The base indentation level of each line, must not be negative.
387      * @param indentSize The size of each indentation, must not be negative.
388      * @param lineLength The length of the line, must not be negative.
389      * @return The sequence of display lines, never <code>null</code>.
390      * @throws NegativeArraySizeException if <code>indent < 0</code>
391      */
392     private static List toLines( String text, int indent, int indentSize, int lineLength )
393     {
394         List<String> lines = new ArrayList<String>();
395 
396         String ind = repeat( "\t", indent );
397         String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
398         for ( int i = 0; i < plainLines.length; i++ )
399         {
400             toLines( lines, ind + plainLines[i], indentSize, lineLength );
401         }
402 
403         return lines;
404     }
405 
406     /** 
407      * Adds the specified line to the output sequence, performing line wrapping if necessary.
408      * 
409      * @param lines The sequence of display lines, must not be <code>null</code>.
410      * @param line The line to add, must not be <code>null</code>.
411      * @param indentSize The size of each indentation, must not be negative.
412      * @param lineLength The length of the line, must not be negative.
413      */
414     private static void toLines( List<String> lines, String line, int indentSize, int lineLength )
415     {
416         int lineIndent = getIndentLevel( line );
417         StringBuffer buf = new StringBuffer( 256 );
418         String[] tokens = line.split( " +" );
419         for ( int i = 0; i < tokens.length; i++ )
420         {
421             String token = tokens[i];
422             if ( i > 0 )
423             {
424                 if ( buf.length() + token.length() >= lineLength )
425                 {
426                     lines.add( buf.toString() );
427                     buf.setLength( 0 );
428                     buf.append( repeat( " ", lineIndent * indentSize ) );
429                 }
430                 else
431                 {
432                     buf.append( ' ' );
433                 }
434             }
435             for ( int j = 0; j < token.length(); j++ )
436             {
437                 char c = token.charAt( j );
438                 if ( c == '\t' )
439                 {
440                     buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
441                 }
442                 else if ( c == '\u00A0' )
443                 {
444                     buf.append( ' ' );
445                 }
446                 else
447                 {
448                     buf.append( c );
449                 }
450             }
451         }
452         lines.add( buf.toString() );
453     }
454 
455     /** 
456      * Gets the indentation level of the specified line.
457      * 
458      * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
459      * @return The indentation level of the line.
460      */
461     private static int getIndentLevel( String line )
462     {
463         int level = 0;
464         for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
465         {
466             level++;
467         }
468         for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
469         {
470             if ( line.charAt( i ) == '\t' )
471             {
472                 level++;
473                 break;
474             }
475         }
476         return level;
477     }
478 }