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 Mar 21 20:23:35 CET 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.2", 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, "keyname", 2 );
240                 append( sb, "The \'name\' of the key to sign with. Passed to gpg as --local-user.", 3 );
241                 append( sb, "Expression: ${gpg.keyname}", 3 );
242                 append( sb, "", 0 );
243 
244                 append( sb, "packaging", 2 );
245                 append( sb, "Type of the artifact to be deployed. Retrieved from POM file if specified.", 3 );
246                 append( sb, "Expression: ${packaging}", 3 );
247                 append( sb, "", 0 );
248 
249                 append( sb, "passphrase", 2 );
250                 append( sb, "The passphrase to use when signing.", 3 );
251                 append( sb, "Expression: ${gpg.passphrase}", 3 );
252                 append( sb, "", 0 );
253 
254                 append( sb, "pomFile", 2 );
255                 append( sb, "Location of an existing POM file to be deployed alongside the main artifact, given by the ${file} parameter.", 3 );
256                 append( sb, "Expression: ${pomFile}", 3 );
257                 append( sb, "", 0 );
258 
259                 append( sb, "publicKeyring", 2 );
260                 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 );
261                 append( sb, "Expression: ${gpg.publicKeyring}", 3 );
262                 append( sb, "", 0 );
263 
264                 append( sb, "repositoryId (Default: remote-repository)", 2 );
265                 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 );
266                 append( sb, "Required: Yes", 3 );
267                 append( sb, "Expression: ${repositoryId}", 3 );
268                 append( sb, "", 0 );
269 
270                 append( sb, "repositoryLayout (Default: default)", 2 );
271                 append( sb, "The type of remote repository layout to deploy to. Try legacy for a Maven 1.x-style repository layout.", 3 );
272                 append( sb, "Expression: ${repositoryLayout}", 3 );
273                 append( sb, "", 0 );
274 
275                 append( sb, "secretKeyring", 2 );
276                 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 );
277                 append( sb, "Expression: ${gpg.secretKeyring}", 3 );
278                 append( sb, "", 0 );
279 
280                 append( sb, "uniqueVersion (Default: true)", 2 );
281                 append( sb, "Whether to deploy snapshots with a unique version or not.", 3 );
282                 append( sb, "Expression: ${uniqueVersion}", 3 );
283                 append( sb, "", 0 );
284 
285                 append( sb, "url", 2 );
286                 append( sb, "URL where the artifact will be deployed.\nie ( file:///C:/m2-repo or scp://host.com/path/to/repo )", 3 );
287                 append( sb, "Required: Yes", 3 );
288                 append( sb, "Expression: ${url}", 3 );
289                 append( sb, "", 0 );
290 
291                 append( sb, "useAgent (Default: false)", 2 );
292                 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 );
293                 append( sb, "Expression: ${gpg.useagent}", 3 );
294                 append( sb, "", 0 );
295 
296                 append( sb, "version", 2 );
297                 append( sb, "Version of the artifact to be deployed. Retrieved from POM file if specified.", 3 );
298                 append( sb, "Expression: ${version}", 3 );
299                 append( sb, "", 0 );
300             }
301         }
302 
303         if ( getLog().isInfoEnabled() )
304         {
305             getLog().info( sb.toString() );
306         }
307     }
308 
309     /**
310      * <p>Repeat a String <code>n</code> times to form a new string.</p>
311      *
312      * @param str String to repeat
313      * @param repeat number of times to repeat str
314      * @return String with repeated String
315      * @throws NegativeArraySizeException if <code>repeat < 0</code>
316      * @throws NullPointerException if str is <code>null</code>
317      */
318     private static String repeat( String str, int repeat )
319     {
320         StringBuffer buffer = new StringBuffer( repeat * str.length() );
321 
322         for ( int i = 0; i < repeat; i++ )
323         {
324             buffer.append( str );
325         }
326 
327         return buffer.toString();
328     }
329 
330     /** 
331      * Append a description to the buffer by respecting the indentSize and lineLength parameters.
332      * <b>Note</b>: The last character is always a new line.
333      * 
334      * @param sb The buffer to append the description, not <code>null</code>.
335      * @param description The description, not <code>null</code>.
336      * @param indent The base indentation level of each line, must not be negative.
337      */
338     private void append( StringBuffer sb, String description, int indent )
339     {
340         for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
341         {
342             sb.append( it.next().toString() ).append( '\n' );
343         }
344     }
345 
346     /** 
347      * Splits the specified text into lines of convenient display length.
348      * 
349      * @param text The text to split into lines, must not be <code>null</code>.
350      * @param indent The base indentation level of each line, must not be negative.
351      * @param indentSize The size of each indentation, must not be negative.
352      * @param lineLength The length of the line, must not be negative.
353      * @return The sequence of display lines, never <code>null</code>.
354      * @throws NegativeArraySizeException if <code>indent < 0</code>
355      */
356     private static List toLines( String text, int indent, int indentSize, int lineLength )
357     {
358         List lines = new ArrayList();
359 
360         String ind = repeat( "\t", indent );
361         String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
362         for ( int i = 0; i < plainLines.length; i++ )
363         {
364             toLines( lines, ind + plainLines[i], indentSize, lineLength );
365         }
366 
367         return lines;
368     }
369 
370     /** 
371      * Adds the specified line to the output sequence, performing line wrapping if necessary.
372      * 
373      * @param lines The sequence of display lines, must not be <code>null</code>.
374      * @param line The line to add, must not be <code>null</code>.
375      * @param indentSize The size of each indentation, must not be negative.
376      * @param lineLength The length of the line, must not be negative.
377      */
378     private static void toLines( List lines, String line, int indentSize, int lineLength )
379     {
380         int lineIndent = getIndentLevel( line );
381         StringBuffer buf = new StringBuffer( 256 );
382         String[] tokens = line.split( " +" );
383         for ( int i = 0; i < tokens.length; i++ )
384         {
385             String token = tokens[i];
386             if ( i > 0 )
387             {
388                 if ( buf.length() + token.length() >= lineLength )
389                 {
390                     lines.add( buf.toString() );
391                     buf.setLength( 0 );
392                     buf.append( repeat( " ", lineIndent * indentSize ) );
393                 }
394                 else
395                 {
396                     buf.append( ' ' );
397                 }
398             }
399             for ( int j = 0; j < token.length(); j++ )
400             {
401                 char c = token.charAt( j );
402                 if ( c == '\t' )
403                 {
404                     buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
405                 }
406                 else if ( c == '\u00A0' )
407                 {
408                     buf.append( ' ' );
409                 }
410                 else
411                 {
412                     buf.append( c );
413                 }
414             }
415         }
416         lines.add( buf.toString() );
417     }
418 
419     /** 
420      * Gets the indentation level of the specified line.
421      * 
422      * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
423      * @return The indentation level of the line.
424      */
425     private static int getIndentLevel( String line )
426     {
427         int level = 0;
428         for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
429         {
430             level++;
431         }
432         for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
433         {
434             if ( line.charAt( i ) == '\t' )
435             {
436                 level++;
437                 break;
438             }
439         }
440         return level;
441     }
442 }