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 Sat May 28 12:01:24 IST 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-gpg-plugin:1.3", 0 );
69          append( sb, "", 0 );
70  
71          append( sb, "Maven GPG Plugin", 0 );
72          append( sb, "Signs the project artifacts with GnuPG.", 1 );
73          append( sb, "", 0 );
74  
75          if ( goal == null || goal.length() <= 0 )
76          {
77              append( sb, "This plugin has 3 goals:", 0 );
78              append( sb, "", 0 );
79          }
80  
81          if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
82          {
83              append( sb, "gpg:help", 0 );
84              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 );
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 || "sign".equals( goal ) )
114         {
115             append( sb, "gpg:sign", 0 );
116             append( sb, "Sign project artifact, the POM, and attached artifacts with GnuPG for deployment.", 1 );
117             append( sb, "", 0 );
118             if ( detail )
119             {
120                 append( sb, "Available parameters:", 1 );
121                 append( sb, "", 0 );
122 
123                 append( sb, "ascDirectory (Default: ${project.build.directory}/gpg)", 2 );
124                 append( sb, "The directory where to store signature files.", 3 );
125                 append( sb, "", 0 );
126 
127                 append( sb, "defaultKeyring (Default: true)", 2 );
128                 append( sb, "Whether to add the default keyrings from gpg\'s home directory to the list of used keyrings.", 3 );
129                 append( sb, "Expression: ${gpg.defaultKeyring}", 3 );
130                 append( sb, "", 0 );
131 
132                 append( sb, "excludes", 2 );
133                 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 );
134                 append( sb, "", 0 );
135 
136                 append( sb, "executable", 2 );
137                 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 );
138                 append( sb, "Expression: ${gpg.executable}", 3 );
139                 append( sb, "", 0 );
140 
141                 append( sb, "homedir", 2 );
142                 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 );
143                 append( sb, "Expression: ${gpg.homedir}", 3 );
144                 append( sb, "", 0 );
145 
146                 append( sb, "keyname", 2 );
147                 append( sb, "The \'name\' of the key to sign with. Passed to gpg as --local-user.", 3 );
148                 append( sb, "Expression: ${gpg.keyname}", 3 );
149                 append( sb, "", 0 );
150 
151                 append( sb, "passphrase", 2 );
152                 append( sb, "The passphrase to use when signing.", 3 );
153                 append( sb, "Expression: ${gpg.passphrase}", 3 );
154                 append( sb, "", 0 );
155 
156                 append( sb, "publicKeyring", 2 );
157                 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 );
158                 append( sb, "Expression: ${gpg.publicKeyring}", 3 );
159                 append( sb, "", 0 );
160 
161                 append( sb, "secretKeyring", 2 );
162                 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 );
163                 append( sb, "Expression: ${gpg.secretKeyring}", 3 );
164                 append( sb, "", 0 );
165 
166                 append( sb, "skip (Default: false)", 2 );
167                 append( sb, "Skip doing the gpg signing.", 3 );
168                 append( sb, "Expression: ${gpg.skip}", 3 );
169                 append( sb, "", 0 );
170 
171                 append( sb, "useAgent (Default: false)", 2 );
172                 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 );
173                 append( sb, "Expression: ${gpg.useagent}", 3 );
174                 append( sb, "", 0 );
175             }
176         }
177 
178         if ( goal == null || goal.length() <= 0 || "sign-and-deploy-file".equals( goal ) )
179         {
180             append( sb, "gpg:sign-and-deploy-file", 0 );
181             append( sb, "Signs artifacts and installs the artifact in the remote repository.", 1 );
182             append( sb, "", 0 );
183             if ( detail )
184             {
185                 append( sb, "Available parameters:", 1 );
186                 append( sb, "", 0 );
187 
188                 append( sb, "artifactId", 2 );
189                 append( sb, "ArtifactId of the artifact to be deployed. Retrieved from POM file if specified.", 3 );
190                 append( sb, "Expression: ${artifactId}", 3 );
191                 append( sb, "", 0 );
192 
193                 append( sb, "ascDirectory", 2 );
194                 append( sb, "The directory where to store signature files.", 3 );
195                 append( sb, "Expression: ${gpg.ascDirectory}", 3 );
196                 append( sb, "", 0 );
197 
198                 append( sb, "classifier", 2 );
199                 append( sb, "Add classifier to the artifact", 3 );
200                 append( sb, "Expression: ${classifier}", 3 );
201                 append( sb, "", 0 );
202 
203                 append( sb, "defaultKeyring (Default: true)", 2 );
204                 append( sb, "Whether to add the default keyrings from gpg\'s home directory to the list of used keyrings.", 3 );
205                 append( sb, "Expression: ${gpg.defaultKeyring}", 3 );
206                 append( sb, "", 0 );
207 
208                 append( sb, "description", 2 );
209                 append( sb, "Description passed to a generated POM file (in case of generatePom=true).", 3 );
210                 append( sb, "Expression: ${generatePom.description}", 3 );
211                 append( sb, "", 0 );
212 
213                 append( sb, "executable", 2 );
214                 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 );
215                 append( sb, "Expression: ${gpg.executable}", 3 );
216                 append( sb, "", 0 );
217 
218                 append( sb, "file", 2 );
219                 append( sb, "File to be deployed.", 3 );
220                 append( sb, "Required: Yes", 3 );
221                 append( sb, "Expression: ${file}", 3 );
222                 append( sb, "", 0 );
223 
224                 append( sb, "generatePom (Default: true)", 2 );
225                 append( sb, "Upload a POM for this artifact. Will generate a default POM if none is supplied with the pomFile argument.", 3 );
226                 append( sb, "Expression: ${generatePom}", 3 );
227                 append( sb, "", 0 );
228 
229                 append( sb, "groupId", 2 );
230                 append( sb, "GroupId of the artifact to be deployed. Retrieved from POM file if specified.", 3 );
231                 append( sb, "Expression: ${groupId}", 3 );
232                 append( sb, "", 0 );
233 
234                 append( sb, "homedir", 2 );
235                 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 );
236                 append( sb, "Expression: ${gpg.homedir}", 3 );
237                 append( sb, "", 0 );
238 
239                 append( sb, "javadoc", 2 );
240                 append( sb, "The bundled API docs for the artifact.", 3 );
241                 append( sb, "Expression: ${javadoc}", 3 );
242                 append( sb, "", 0 );
243 
244                 append( sb, "keyname", 2 );
245                 append( sb, "The \'name\' of the key to sign with. Passed to gpg as --local-user.", 3 );
246                 append( sb, "Expression: ${gpg.keyname}", 3 );
247                 append( sb, "", 0 );
248 
249                 append( sb, "packaging", 2 );
250                 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 );
251                 append( sb, "Expression: ${packaging}", 3 );
252                 append( sb, "", 0 );
253 
254                 append( sb, "passphrase", 2 );
255                 append( sb, "The passphrase to use when signing.", 3 );
256                 append( sb, "Expression: ${gpg.passphrase}", 3 );
257                 append( sb, "", 0 );
258 
259                 append( sb, "pomFile", 2 );
260                 append( sb, "Location of an existing POM file to be deployed alongside the main artifact, given by the ${file} parameter.", 3 );
261                 append( sb, "Expression: ${pomFile}", 3 );
262                 append( sb, "", 0 );
263 
264                 append( sb, "publicKeyring", 2 );
265                 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 );
266                 append( sb, "Expression: ${gpg.publicKeyring}", 3 );
267                 append( sb, "", 0 );
268 
269                 append( sb, "repositoryId (Default: remote-repository)", 2 );
270                 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 );
271                 append( sb, "Required: Yes", 3 );
272                 append( sb, "Expression: ${repositoryId}", 3 );
273                 append( sb, "", 0 );
274 
275                 append( sb, "repositoryLayout (Default: default)", 2 );
276                 append( sb, "The type of remote repository layout to deploy to. Try legacy for a Maven 1.x-style repository layout.", 3 );
277                 append( sb, "Expression: ${repositoryLayout}", 3 );
278                 append( sb, "", 0 );
279 
280                 append( sb, "retryFailedDeploymentCount (Default: 1)", 2 );
281                 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 );
282                 append( sb, "Expression: ${retryFailedDeploymentCount}", 3 );
283                 append( sb, "", 0 );
284 
285                 append( sb, "secretKeyring", 2 );
286                 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 );
287                 append( sb, "Expression: ${gpg.secretKeyring}", 3 );
288                 append( sb, "", 0 );
289 
290                 append( sb, "sources", 2 );
291                 append( sb, "The bundled sources for the artifact.", 3 );
292                 append( sb, "Expression: ${sources}", 3 );
293                 append( sb, "", 0 );
294 
295                 append( sb, "uniqueVersion (Default: true)", 2 );
296                 append( sb, "Whether to deploy snapshots with a unique version or not.", 3 );
297                 append( sb, "Expression: ${uniqueVersion}", 3 );
298                 append( sb, "", 0 );
299 
300                 append( sb, "updateReleaseInfo (Default: false)", 2 );
301                 append( sb, "Parameter used to update the metadata to make the artifact as release.", 3 );
302                 append( sb, "Expression: ${updateReleaseInfo}", 3 );
303                 append( sb, "", 0 );
304 
305                 append( sb, "url", 2 );
306                 append( sb, "URL where the artifact will be deployed.\nie ( file:///C:/m2-repo or scp://host.com/path/to/repo )", 3 );
307                 append( sb, "Required: Yes", 3 );
308                 append( sb, "Expression: ${url}", 3 );
309                 append( sb, "", 0 );
310 
311                 append( sb, "useAgent (Default: false)", 2 );
312                 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 );
313                 append( sb, "Expression: ${gpg.useagent}", 3 );
314                 append( sb, "", 0 );
315 
316                 append( sb, "version", 2 );
317                 append( sb, "Version of the artifact to be deployed. Retrieved from POM file if specified.", 3 );
318                 append( sb, "Expression: ${version}", 3 );
319                 append( sb, "", 0 );
320             }
321         }
322 
323         if ( getLog().isInfoEnabled() )
324         {
325             getLog().info( sb.toString() );
326         }
327     }
328 
329     /**
330      * <p>Repeat a String <code>n</code> times to form a new string.</p>
331      *
332      * @param str String to repeat
333      * @param repeat number of times to repeat str
334      * @return String with repeated String
335      * @throws NegativeArraySizeException if <code>repeat < 0</code>
336      * @throws NullPointerException if str is <code>null</code>
337      */
338     private static String repeat( String str, int repeat )
339     {
340         StringBuffer buffer = new StringBuffer( repeat * str.length() );
341 
342         for ( int i = 0; i < repeat; i++ )
343         {
344             buffer.append( str );
345         }
346 
347         return buffer.toString();
348     }
349 
350     /** 
351      * Append a description to the buffer by respecting the indentSize and lineLength parameters.
352      * <b>Note</b>: The last character is always a new line.
353      * 
354      * @param sb The buffer to append the description, not <code>null</code>.
355      * @param description The description, not <code>null</code>.
356      * @param indent The base indentation level of each line, must not be negative.
357      */
358     private void append( StringBuffer sb, String description, int indent )
359     {
360         for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
361         {
362             sb.append( it.next().toString() ).append( '\n' );
363         }
364     }
365 
366     /** 
367      * Splits the specified text into lines of convenient display length.
368      * 
369      * @param text The text to split into lines, must not be <code>null</code>.
370      * @param indent The base indentation level of each line, must not be negative.
371      * @param indentSize The size of each indentation, must not be negative.
372      * @param lineLength The length of the line, must not be negative.
373      * @return The sequence of display lines, never <code>null</code>.
374      * @throws NegativeArraySizeException if <code>indent < 0</code>
375      */
376     private static List toLines( String text, int indent, int indentSize, int lineLength )
377     {
378         List lines = new ArrayList();
379 
380         String ind = repeat( "\t", indent );
381         String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
382         for ( int i = 0; i < plainLines.length; i++ )
383         {
384             toLines( lines, ind + plainLines[i], indentSize, lineLength );
385         }
386 
387         return lines;
388     }
389 
390     /** 
391      * Adds the specified line to the output sequence, performing line wrapping if necessary.
392      * 
393      * @param lines The sequence of display lines, must not be <code>null</code>.
394      * @param line The line to add, must not be <code>null</code>.
395      * @param indentSize The size of each indentation, must not be negative.
396      * @param lineLength The length of the line, must not be negative.
397      */
398     private static void toLines( List lines, String line, int indentSize, int lineLength )
399     {
400         int lineIndent = getIndentLevel( line );
401         StringBuffer buf = new StringBuffer( 256 );
402         String[] tokens = line.split( " +" );
403         for ( int i = 0; i < tokens.length; i++ )
404         {
405             String token = tokens[i];
406             if ( i > 0 )
407             {
408                 if ( buf.length() + token.length() >= lineLength )
409                 {
410                     lines.add( buf.toString() );
411                     buf.setLength( 0 );
412                     buf.append( repeat( " ", lineIndent * indentSize ) );
413                 }
414                 else
415                 {
416                     buf.append( ' ' );
417                 }
418             }
419             for ( int j = 0; j < token.length(); j++ )
420             {
421                 char c = token.charAt( j );
422                 if ( c == '\t' )
423                 {
424                     buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
425                 }
426                 else if ( c == '\u00A0' )
427                 {
428                     buf.append( ' ' );
429                 }
430                 else
431                 {
432                     buf.append( c );
433                 }
434             }
435         }
436         lines.add( buf.toString() );
437     }
438 
439     /** 
440      * Gets the indentation level of the specified line.
441      * 
442      * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
443      * @return The indentation level of the line.
444      */
445     private static int getIndentLevel( String line )
446     {
447         int level = 0;
448         for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
449         {
450             level++;
451         }
452         for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
453         {
454             if ( line.charAt( i ) == '\t' )
455             {
456                 level++;
457                 break;
458             }
459         }
460         return level;
461     }
462 }