1 package org.apache.maven.plugin.plugin;
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
12
13
14
15
16
17
18
19 @SuppressWarnings( "all" )
20 public class HelpMojo
21 extends AbstractMojo
22 {
23
24
25
26
27
28 private boolean detail;
29
30
31
32
33
34
35 private java.lang.String goal;
36
37
38
39
40
41
42 private int lineLength;
43
44
45
46
47
48
49 private int indentSize;
50
51
52
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-plugin-plugin:3.0", 0 );
70 append( sb, "", 0 );
71
72 append( sb, "Maven Plugin Plugin", 0 );
73 append( sb, "The Plugin Plugin is used to create a Maven plugin descriptor for any Mojo\'s found in the source tree, to include in the JAR. It is also used to generate Xdoc files for the Mojos as well as for updating the plugin registry, the artifact metadata and a generic help goal.", 1 );
74 append( sb, "", 0 );
75
76 if ( goal == null || goal.length() <= 0 )
77 {
78 append( sb, "This plugin has 7 goals:", 0 );
79 append( sb, "", 0 );
80 }
81
82 if ( goal == null || goal.length() <= 0 || "addPluginArtifactMetadata".equals( goal ) )
83 {
84 append( sb, "plugin:addPluginArtifactMetadata", 0 );
85 append( sb, "Inject any plugin-specific artifact metadata to the project\'s artifact, for subsequent installation and deployment. It is used:\n1.\tto add the latest metadata (which is plugin-specific) for shipping alongside the plugin\'s artifact\n2.\tto define plugin mapping in the group\n", 1 );
86 append( sb, "", 0 );
87 if ( detail )
88 {
89 append( sb, "Available parameters:", 1 );
90 append( sb, "", 0 );
91
92 append( sb, "goalPrefix", 2 );
93 append( sb, "The prefix for the plugin goal.", 3 );
94 append( sb, "", 0 );
95
96 append( sb, "skip (Default: false)", 2 );
97 append( sb, "Set this to \'true\' to skip invoking any goals or reports of the plugin.", 3 );
98 append( sb, "Expression: ${maven.plugin.skip}", 3 );
99 append( sb, "", 0 );
100 }
101 }
102
103 if ( goal == null || goal.length() <= 0 || "descriptor".equals( goal ) )
104 {
105 append( sb, "plugin:descriptor", 0 );
106 append( sb, "Generate a plugin descriptor.\nNote: Since 3.0, phase is after the \'compilation\' of any scripts.", 1 );
107 append( sb, "", 0 );
108 if ( detail )
109 {
110 append( sb, "Available parameters:", 1 );
111 append( sb, "", 0 );
112
113 append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
114 append( sb, "The file encoding of the source files.", 3 );
115 append( sb, "Expression: ${encoding}", 3 );
116 append( sb, "", 0 );
117
118 append( sb, "extractors", 2 );
119 append( sb, "The role names of mojo extractors to use. If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors will be used. Example:\n\u00a0<!--\u00a0Use\u00a0all\u00a0mojo\u00a0extractors\u00a0-->\n\u00a0<extractors/>\n\n\u00a0<!--\u00a0Use\u00a0no\u00a0mojo\u00a0extractors\u00a0-->\n\u00a0<extractors>\n\u00a0\u00a0\u00a0\u00a0\u00a0<extractor/>\n\u00a0</extractors>\n\n\u00a0<!--\u00a0Use\u00a0only\u00a0bsh\u00a0mojo\u00a0extractor\u00a0-->\n\u00a0<extractors>\n\u00a0\u00a0\u00a0\u00a0\u00a0<extractor>bsh</extractor>\n\u00a0</extractors>\n", 3 );
120 append( sb, "", 0 );
121
122 append( sb, "goalPrefix", 2 );
123 append( sb, "The goal prefix that will appear before the \':\'.", 3 );
124 append( sb, "", 0 );
125
126 append( sb, "outputDirectory (Default: ${project.build.outputDirectory}/META-INF/maven)", 2 );
127 append( sb, "The directory where the generated plugin.xml file will be put.", 3 );
128 append( sb, "", 0 );
129
130 append( sb, "skip (Default: false)", 2 );
131 append( sb, "Set this to \'true\' to skip invoking any goals or reports of the plugin.", 3 );
132 append( sb, "Expression: ${maven.plugin.skip}", 3 );
133 append( sb, "", 0 );
134
135 append( sb, "skipDescriptor (Default: false)", 2 );
136 append( sb, "A flag to disable generation of the plugin.xml in favor of a hand authored plugin descriptor.", 3 );
137 append( sb, "", 0 );
138
139 append( sb, "skipErrorNoDescriptorsFound (Default: false)", 2 );
140 append( sb, "By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the descriptor generator mojo is bound to generate-resources phase. But for annotations, the compiled classes are needed, so skip error", 3 );
141 append( sb, "Expression: ${maven.plugin.skipErrorNoDescriptorsFound}", 3 );
142 append( sb, "", 0 );
143 }
144 }
145
146 if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
147 {
148 append( sb, "plugin:help", 0 );
149 append( sb, "Display help information on maven-plugin-plugin.\nCall\n\u00a0\u00a0mvn\u00a0plugin:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
150 append( sb, "", 0 );
151 if ( detail )
152 {
153 append( sb, "Available parameters:", 1 );
154 append( sb, "", 0 );
155
156 append( sb, "detail (Default: false)", 2 );
157 append( sb, "If true, display all settable properties for each goal.", 3 );
158 append( sb, "Expression: ${detail}", 3 );
159 append( sb, "", 0 );
160
161 append( sb, "goal", 2 );
162 append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
163 append( sb, "Expression: ${goal}", 3 );
164 append( sb, "", 0 );
165
166 append( sb, "indentSize (Default: 2)", 2 );
167 append( sb, "The number of spaces per indentation level, should be positive.", 3 );
168 append( sb, "Expression: ${indentSize}", 3 );
169 append( sb, "", 0 );
170
171 append( sb, "lineLength (Default: 80)", 2 );
172 append( sb, "The maximum length of a display line, should be positive.", 3 );
173 append( sb, "Expression: ${lineLength}", 3 );
174 append( sb, "", 0 );
175 }
176 }
177
178 if ( goal == null || goal.length() <= 0 || "helpmojo".equals( goal ) )
179 {
180 append( sb, "plugin:helpmojo", 0 );
181 append( sb, "Generates a HelpMojo class.", 1 );
182 append( sb, "", 0 );
183 if ( detail )
184 {
185 append( sb, "Available parameters:", 1 );
186 append( sb, "", 0 );
187
188 append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
189 append( sb, "The file encoding of the source files.", 3 );
190 append( sb, "Expression: ${encoding}", 3 );
191 append( sb, "", 0 );
192
193 append( sb, "extractors", 2 );
194 append( sb, "The role names of mojo extractors to use. If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors will be used. Example:\n\u00a0<!--\u00a0Use\u00a0all\u00a0mojo\u00a0extractors\u00a0-->\n\u00a0<extractors/>\n\n\u00a0<!--\u00a0Use\u00a0no\u00a0mojo\u00a0extractors\u00a0-->\n\u00a0<extractors>\n\u00a0\u00a0\u00a0\u00a0\u00a0<extractor/>\n\u00a0</extractors>\n\n\u00a0<!--\u00a0Use\u00a0only\u00a0bsh\u00a0mojo\u00a0extractor\u00a0-->\n\u00a0<extractors>\n\u00a0\u00a0\u00a0\u00a0\u00a0<extractor>bsh</extractor>\n\u00a0</extractors>\n", 3 );
195 append( sb, "", 0 );
196
197 append( sb, "goalPrefix", 2 );
198 append( sb, "The goal prefix that will appear before the \':\'.", 3 );
199 append( sb, "", 0 );
200
201 append( sb, "helpPackageName", 2 );
202 append( sb, "The name of the package for the generated HelpMojo. By default, the package will be calculated based on the packages of the other plugin goals.", 3 );
203 append( sb, "", 0 );
204
205 append( sb, "outputDirectory (Default: ${project.build.directory}/generated-sources/plugin)", 2 );
206 append( sb, "The directory where the generated HelpMojo file will be put.", 3 );
207 append( sb, "", 0 );
208
209 append( sb, "skip (Default: false)", 2 );
210 append( sb, "Set this to \'true\' to skip invoking any goals or reports of the plugin.", 3 );
211 append( sb, "Expression: ${maven.plugin.skip}", 3 );
212 append( sb, "", 0 );
213
214 append( sb, "skipErrorNoDescriptorsFound (Default: false)", 2 );
215 append( sb, "By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the descriptor generator mojo is bound to generate-resources phase. But for annotations, the compiled classes are needed, so skip error", 3 );
216 append( sb, "Expression: ${maven.plugin.skipErrorNoDescriptorsFound}", 3 );
217 append( sb, "", 0 );
218 }
219 }
220
221 if ( goal == null || goal.length() <= 0 || "report".equals( goal ) )
222 {
223 append( sb, "plugin:report", 0 );
224 append( sb, "Generates the Plugin\'s documentation report.", 1 );
225 append( sb, "", 0 );
226 if ( detail )
227 {
228 append( sb, "Available parameters:", 1 );
229 append( sb, "", 0 );
230
231 append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
232 append( sb, "The file encoding of the source files.", 3 );
233 append( sb, "Expression: ${encoding}", 3 );
234 append( sb, "", 0 );
235
236 append( sb, "goalPrefix", 2 );
237 append( sb, "The goal prefix that will appear before the \':\'. By default, this plugin applies a heuristic to derive a heuristic from the plugin\'s artifactId. It removes any occurrences of the regular expression -?maven-?, and then removes any occurrences of -?plugin-?.\nFor example, horsefeature-maven-plugin becomes horsefeature.\n\n(There is a special for maven-plugin-plugin; it is mapped to \'plugin\'.\n", 3 );
238 append( sb, "Expression: ${goalPrefix}", 3 );
239 append( sb, "", 0 );
240
241 append( sb, "outputDirectory (Default: ${project.build.directory}/generated-site/xdoc)", 2 );
242 append( sb, "Report output directory.", 3 );
243 append( sb, "", 0 );
244
245 append( sb, "requirements", 2 );
246 append( sb, "Specify some requirements to execute this plugin. Example:\n<requirements>\n\u00a0\u00a0<maven>2.0</maven>\n\u00a0\u00a0<jdk>1.4</jdk>\n\u00a0\u00a0<memory>256m</memory>\n\u00a0\u00a0<diskSpace>1m</diskSpace>\n\u00a0\u00a0<others>\n\u00a0\u00a0\u00a0\u00a0<property>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<name>SVN</name>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<value>1.4.6</value>\n\u00a0\u00a0\u00a0\u00a0</property>\n\u00a0\u00a0</others>\n</requirements>\n", 3 );
247 append( sb, "", 0 );
248
249 append( sb, "skip (Default: false)", 2 );
250 append( sb, "Set this to \'true\' to skip invoking any goals or reports of the plugin.", 3 );
251 append( sb, "Expression: ${maven.plugin.skip}", 3 );
252 append( sb, "", 0 );
253
254 append( sb, "skipReport (Default: false)", 2 );
255 append( sb, "Set this to \'true\' to skip generating the report.", 3 );
256 append( sb, "Expression: ${maven.plugin.report.skip}", 3 );
257 append( sb, "", 0 );
258 }
259 }
260
261 if ( goal == null || goal.length() <= 0 || "updateRegistry".equals( goal ) )
262 {
263 append( sb, "plugin:updateRegistry", 0 );
264 append( sb, "Update the user plugin registry (if it\'s in use) to reflect the version we\'re installing.", 1 );
265 append( sb, "", 0 );
266 if ( detail )
267 {
268 append( sb, "Available parameters:", 1 );
269 append( sb, "", 0 );
270
271 append( sb, "skip (Default: false)", 2 );
272 append( sb, "Set this to \'true\' to skip invoking any goals or reports of the plugin.", 3 );
273 append( sb, "Expression: ${maven.plugin.skip}", 3 );
274 append( sb, "", 0 );
275
276 append( sb, "skipUpdatePluginRegistry (Default: false)", 2 );
277 append( sb, "Set this to \'true\' to skip updating the plugin registry.", 3 );
278 append( sb, "Expression: ${maven.plugin.update.registry.skip}", 3 );
279 append( sb, "", 0 );
280 }
281 }
282
283 if ( goal == null || goal.length() <= 0 || "xdoc".equals( goal ) )
284 {
285 append( sb, "plugin:xdoc", 0 );
286 append( sb, "Generate Xdoc files for the project mojos or goals.", 1 );
287 append( sb, "", 0 );
288 if ( detail )
289 {
290 append( sb, "Available parameters:", 1 );
291 append( sb, "", 0 );
292
293 append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
294 append( sb, "The file encoding of the source files.", 3 );
295 append( sb, "Expression: ${encoding}", 3 );
296 append( sb, "", 0 );
297
298 append( sb, "extractors", 2 );
299 append( sb, "The role names of mojo extractors to use. If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors will be used. Example:\n\u00a0<!--\u00a0Use\u00a0all\u00a0mojo\u00a0extractors\u00a0-->\n\u00a0<extractors/>\n\n\u00a0<!--\u00a0Use\u00a0no\u00a0mojo\u00a0extractors\u00a0-->\n\u00a0<extractors>\n\u00a0\u00a0\u00a0\u00a0\u00a0<extractor/>\n\u00a0</extractors>\n\n\u00a0<!--\u00a0Use\u00a0only\u00a0bsh\u00a0mojo\u00a0extractor\u00a0-->\n\u00a0<extractors>\n\u00a0\u00a0\u00a0\u00a0\u00a0<extractor>bsh</extractor>\n\u00a0</extractors>\n", 3 );
300 append( sb, "", 0 );
301
302 append( sb, "goalPrefix", 2 );
303 append( sb, "The goal prefix that will appear before the \':\'.", 3 );
304 append( sb, "", 0 );
305
306 append( sb, "outputDirectory (Default: ${project.build.directory}/generated-site/xdoc)", 2 );
307 append( sb, "The directory where the generated Xdoc files will be put.", 3 );
308 append( sb, "", 0 );
309
310 append( sb, "skip (Default: false)", 2 );
311 append( sb, "Set this to \'true\' to skip invoking any goals or reports of the plugin.", 3 );
312 append( sb, "Expression: ${maven.plugin.skip}", 3 );
313 append( sb, "", 0 );
314
315 append( sb, "skipErrorNoDescriptorsFound (Default: false)", 2 );
316 append( sb, "By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the descriptor generator mojo is bound to generate-resources phase. But for annotations, the compiled classes are needed, so skip error", 3 );
317 append( sb, "Expression: ${maven.plugin.skipErrorNoDescriptorsFound}", 3 );
318 append( sb, "", 0 );
319 }
320 }
321
322 if ( getLog().isInfoEnabled() )
323 {
324 getLog().info( sb.toString() );
325 }
326 }
327
328
329
330
331
332
333
334
335
336
337 private static String repeat( String str, int repeat )
338 {
339 StringBuffer buffer = new StringBuffer( repeat * str.length() );
340
341 for ( int i = 0; i < repeat; i++ )
342 {
343 buffer.append( str );
344 }
345
346 return buffer.toString();
347 }
348
349
350
351
352
353
354
355
356
357 private void append( StringBuffer sb, String description, int indent )
358 {
359 for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
360 {
361 sb.append( it.next().toString() ).append( '\n' );
362 }
363 }
364
365
366
367
368
369
370
371
372
373
374
375 private static List toLines( String text, int indent, int indentSize, int lineLength )
376 {
377 List<String> lines = new ArrayList<String>();
378
379 String ind = repeat( "\t", indent );
380 String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
381 for ( int i = 0; i < plainLines.length; i++ )
382 {
383 toLines( lines, ind + plainLines[i], indentSize, lineLength );
384 }
385
386 return lines;
387 }
388
389
390
391
392
393
394
395
396
397 private static void toLines( List<String> lines, String line, int indentSize, int lineLength )
398 {
399 int lineIndent = getIndentLevel( line );
400 StringBuffer buf = new StringBuffer( 256 );
401 String[] tokens = line.split( " +" );
402 for ( int i = 0; i < tokens.length; i++ )
403 {
404 String token = tokens[i];
405 if ( i > 0 )
406 {
407 if ( buf.length() + token.length() >= lineLength )
408 {
409 lines.add( buf.toString() );
410 buf.setLength( 0 );
411 buf.append( repeat( " ", lineIndent * indentSize ) );
412 }
413 else
414 {
415 buf.append( ' ' );
416 }
417 }
418 for ( int j = 0; j < token.length(); j++ )
419 {
420 char c = token.charAt( j );
421 if ( c == '\t' )
422 {
423 buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
424 }
425 else if ( c == '\u00A0' )
426 {
427 buf.append( ' ' );
428 }
429 else
430 {
431 buf.append( c );
432 }
433 }
434 }
435 lines.add( buf.toString() );
436 }
437
438
439
440
441
442
443
444 private static int getIndentLevel( String line )
445 {
446 int level = 0;
447 for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
448 {
449 level++;
450 }
451 for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
452 {
453 if ( line.charAt( i ) == '\t' )
454 {
455 level++;
456 break;
457 }
458 }
459 return level;
460 }
461 }