1 package org.apache.maven.tools.plugin.generator;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.OutputStreamWriter;
26 import java.io.Writer;
27 import java.util.LinkedHashMap;
28 import java.util.LinkedHashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException;
33 import org.apache.maven.plugin.descriptor.MojoDescriptor;
34 import org.apache.maven.plugin.descriptor.Parameter;
35 import org.apache.maven.plugin.descriptor.PluginDescriptor;
36 import org.apache.maven.plugin.descriptor.Requirement;
37 import org.apache.maven.plugin.logging.Log;
38 import org.apache.maven.project.MavenProject;
39 import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
40 import org.apache.maven.tools.plugin.PluginToolsRequest;
41 import org.apache.maven.tools.plugin.util.PluginUtils;
42 import org.codehaus.plexus.util.IOUtil;
43 import org.codehaus.plexus.util.StringUtils;
44 import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
45 import org.codehaus.plexus.util.xml.XMLWriter;
46
47
48
49
50
51
52 public class PluginDescriptorGenerator
53 implements Generator
54 {
55
56 private final Log log;
57
58 public PluginDescriptorGenerator( Log log )
59 {
60 this.log = log;
61 }
62
63
64
65
66 public void execute( File destinationDirectory, PluginToolsRequest request )
67 throws GeneratorException
68 {
69
70 PluginHelpGenerator.rewriteHelpMojo( request, log );
71
72 try
73 {
74
75 File f = new File( destinationDirectory, "plugin.xml" );
76 writeDescriptor( f, request, false );
77
78
79 MavenProject mavenProject = request.getProject();
80
81 f = new File( mavenProject.getBuild().getOutputDirectory(),
82 PluginHelpGenerator.getPluginHelpPath( mavenProject ) );
83
84 writeDescriptor( f, request, true );
85 }
86 catch ( IOException e )
87 {
88 throw new GeneratorException( e.getMessage(), e );
89 }
90 catch ( DuplicateMojoDescriptorException e )
91 {
92 throw new GeneratorException( e.getMessage(), e );
93 }
94 }
95
96 private String getVersion()
97 {
98 Package p = this.getClass().getPackage();
99 String version = ( p == null ) ? null : p.getSpecificationVersion();
100 return ( version == null ) ? "SNAPSHOT" : version;
101 }
102
103 public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor )
104 throws IOException, DuplicateMojoDescriptorException
105 {
106 PluginDescriptor pluginDescriptor = request.getPluginDescriptor();
107
108 if ( destinationFile.exists() )
109 {
110 destinationFile.delete();
111 }
112 else
113 {
114 if ( !destinationFile.getParentFile().exists() )
115 {
116 destinationFile.getParentFile().mkdirs();
117 }
118 }
119
120 String encoding = "UTF-8";
121
122 Writer writer = null;
123 try
124 {
125 writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), encoding );
126
127 XMLWriter w = new PrettyPrintXMLWriter( writer, encoding, null );
128
129 w.writeMarkup( "\n<!-- Generated by maven-plugin-tools " + getVersion() + " -->\n\n" );
130
131 w.startElement( "plugin" );
132
133 GeneratorUtils.element( w, "name", pluginDescriptor.getName() );
134
135 GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor );
136
137 GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() );
138
139 GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() );
140
141 GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() );
142
143 GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() );
144
145 if ( !helpDescriptor )
146 {
147 GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) );
148
149 GeneratorUtils.element( w, "inheritedByDefault",
150 String.valueOf( pluginDescriptor.isInheritedByDefault() ) );
151 }
152
153 w.startElement( "mojos" );
154
155 if ( pluginDescriptor.getMojos() != null )
156 {
157 @SuppressWarnings( "unchecked" ) List<MojoDescriptor> descriptors = pluginDescriptor.getMojos();
158
159 PluginUtils.sortMojos( descriptors );
160
161 for ( MojoDescriptor descriptor : descriptors )
162 {
163 processMojoDescriptor( descriptor, w, helpDescriptor );
164 }
165 }
166
167 w.endElement();
168
169 if ( !helpDescriptor )
170 {
171 GeneratorUtils.writeDependencies( w, pluginDescriptor );
172 }
173
174 w.endElement();
175
176 writer.flush();
177
178 }
179 finally
180 {
181 IOUtil.close( writer );
182 }
183 }
184
185 protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w )
186 {
187 processMojoDescriptor( mojoDescriptor, w, false );
188 }
189
190
191
192
193
194
195 protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w, boolean helpDescriptor )
196 {
197 w.startElement( "mojo" );
198
199
200
201
202
203 w.startElement( "goal" );
204 w.writeText( mojoDescriptor.getGoal() );
205 w.endElement();
206
207
208
209
210
211 String description = mojoDescriptor.getDescription();
212
213 if ( StringUtils.isNotEmpty( description ) )
214 {
215 w.startElement( "description" );
216 if ( helpDescriptor )
217 {
218 w.writeText( GeneratorUtils.toText( mojoDescriptor.getDescription() ) );
219 }
220 else
221 {
222 w.writeText( mojoDescriptor.getDescription() );
223 }
224 w.endElement();
225 }
226
227
228
229
230
231 if ( StringUtils.isNotEmpty( mojoDescriptor.isDependencyResolutionRequired() ) )
232 {
233 GeneratorUtils.element( w, "requiresDependencyResolution",
234 mojoDescriptor.isDependencyResolutionRequired() );
235 }
236
237
238
239
240
241 GeneratorUtils.element( w, "requiresDirectInvocation",
242 String.valueOf( mojoDescriptor.isDirectInvocationOnly() ) );
243
244
245
246
247
248 GeneratorUtils.element( w, "requiresProject", String.valueOf( mojoDescriptor.isProjectRequired() ) );
249
250
251
252
253
254 GeneratorUtils.element( w, "requiresReports", String.valueOf( mojoDescriptor.isRequiresReports() ) );
255
256
257
258
259
260 GeneratorUtils.element( w, "aggregator", String.valueOf( mojoDescriptor.isAggregator() ) );
261
262
263
264
265
266 GeneratorUtils.element( w, "requiresOnline", String.valueOf( mojoDescriptor.isOnlineRequired() ) );
267
268
269
270
271
272 GeneratorUtils.element( w, "inheritedByDefault", String.valueOf( mojoDescriptor.isInheritedByDefault() ) );
273
274
275
276
277
278 if ( StringUtils.isNotEmpty( mojoDescriptor.getPhase() ) )
279 {
280 GeneratorUtils.element( w, "phase", mojoDescriptor.getPhase() );
281 }
282
283
284
285
286
287 if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) )
288 {
289 GeneratorUtils.element( w, "executePhase", mojoDescriptor.getExecutePhase() );
290 }
291
292 if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteGoal() ) )
293 {
294 GeneratorUtils.element( w, "executeGoal", mojoDescriptor.getExecuteGoal() );
295 }
296
297 if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteLifecycle() ) )
298 {
299 GeneratorUtils.element( w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle() );
300 }
301
302
303
304
305
306 w.startElement( "implementation" );
307 w.writeText( mojoDescriptor.getImplementation() );
308 w.endElement();
309
310
311
312
313
314 w.startElement( "language" );
315 w.writeText( mojoDescriptor.getLanguage() );
316 w.endElement();
317
318
319
320
321
322 if ( StringUtils.isNotEmpty( mojoDescriptor.getComponentConfigurator() ) )
323 {
324 w.startElement( "configurator" );
325 w.writeText( mojoDescriptor.getComponentConfigurator() );
326 w.endElement();
327 }
328
329
330
331
332
333 if ( StringUtils.isNotEmpty( mojoDescriptor.getComponentComposer() ) )
334 {
335 w.startElement( "composer" );
336 w.writeText( mojoDescriptor.getComponentComposer() );
337 w.endElement();
338 }
339
340
341
342
343
344 w.startElement( "instantiationStrategy" );
345 w.writeText( mojoDescriptor.getInstantiationStrategy() );
346 w.endElement();
347
348
349
350
351
352 w.startElement( "executionStrategy" );
353 w.writeText( mojoDescriptor.getExecutionStrategy() );
354 w.endElement();
355
356
357
358
359
360 if ( mojoDescriptor.getSince() != null )
361 {
362 w.startElement( "since" );
363
364 if ( StringUtils.isEmpty( mojoDescriptor.getSince() ) )
365 {
366 w.writeText( "No version given" );
367 }
368 else
369 {
370 w.writeText( mojoDescriptor.getSince() );
371 }
372
373 w.endElement();
374 }
375
376
377
378
379
380 if ( mojoDescriptor.getDeprecated() != null )
381 {
382 w.startElement( "deprecated" );
383
384 if ( StringUtils.isEmpty( mojoDescriptor.getDeprecated() ) )
385 {
386 w.writeText( "No reason given" );
387 }
388 else
389 {
390 w.writeText( mojoDescriptor.getDeprecated() );
391 }
392
393 w.endElement();
394 }
395
396
397
398
399
400 if ( mojoDescriptor instanceof ExtendedMojoDescriptor )
401 {
402 ExtendedMojoDescriptor extendedMojoDescriptor = (ExtendedMojoDescriptor) mojoDescriptor;
403 if ( extendedMojoDescriptor.getDependencyCollectionRequired() != null )
404 {
405 GeneratorUtils.element( w, "requiresDependencyCollection",
406 extendedMojoDescriptor.getDependencyCollectionRequired() );
407 }
408
409 GeneratorUtils.element( w, "threadSafe", String.valueOf( extendedMojoDescriptor.isThreadSafe() ) );
410 }
411
412
413
414
415
416 @SuppressWarnings( "unchecked" ) List<Parameter> parameters = mojoDescriptor.getParameters();
417
418 w.startElement( "parameters" );
419
420 Map<String, Requirement> requirements = new LinkedHashMap<>();
421
422 Set<Parameter> configuration = new LinkedHashSet<>();
423
424 if ( parameters != null )
425 {
426 if ( helpDescriptor )
427 {
428 PluginUtils.sortMojoParameters( parameters );
429 }
430
431 for ( Parameter parameter : parameters )
432 {
433 String expression = getExpression( parameter );
434
435 if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) )
436 {
437
438
439
440 String role = expression.substring( "${component.".length(), expression.length() - 1 );
441
442 String roleHint = null;
443
444 int posRoleHintSeparator = role.indexOf( '#' );
445 if ( posRoleHintSeparator > 0 )
446 {
447 roleHint = role.substring( posRoleHintSeparator + 1 );
448
449 role = role.substring( 0, posRoleHintSeparator );
450 }
451
452
453 requirements.put( parameter.getName(), new Requirement( role, roleHint ) );
454 }
455 else if ( parameter.getRequirement() != null )
456 {
457 requirements.put( parameter.getName(), parameter.getRequirement() );
458 }
459 else if ( !helpDescriptor || parameter.isEditable() )
460 {
461
462
463 w.startElement( "parameter" );
464
465 GeneratorUtils.element( w, "name", parameter.getName() );
466
467 if ( parameter.getAlias() != null )
468 {
469 GeneratorUtils.element( w, "alias", parameter.getAlias() );
470 }
471
472 GeneratorUtils.element( w, "type", parameter.getType() );
473
474 if ( parameter.getSince() != null )
475 {
476 w.startElement( "since" );
477
478 if ( StringUtils.isEmpty( parameter.getSince() ) )
479 {
480 w.writeText( "No version given" );
481 }
482 else
483 {
484 w.writeText( parameter.getSince() );
485 }
486
487 w.endElement();
488 }
489
490 if ( parameter.getDeprecated() != null )
491 {
492 if ( StringUtils.isEmpty( parameter.getDeprecated() ) )
493 {
494 GeneratorUtils.element( w, "deprecated", "No reason given" );
495 }
496 else
497 {
498 GeneratorUtils.element( w, "deprecated", parameter.getDeprecated() );
499 }
500 }
501
502 if ( parameter.getImplementation() != null )
503 {
504 GeneratorUtils.element( w, "implementation", parameter.getImplementation() );
505 }
506
507 GeneratorUtils.element( w, "required", Boolean.toString( parameter.isRequired() ) );
508
509 GeneratorUtils.element( w, "editable", Boolean.toString( parameter.isEditable() ) );
510
511 GeneratorUtils.element( w, "description", parameter.getDescription(), helpDescriptor );
512
513 if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) || StringUtils.isNotEmpty(
514 parameter.getExpression() ) )
515 {
516 configuration.add( parameter );
517 }
518
519 w.endElement();
520 }
521
522 }
523 }
524
525 w.endElement();
526
527
528
529
530
531 if ( !configuration.isEmpty() )
532 {
533 w.startElement( "configuration" );
534
535 for ( Parameter parameter : configuration )
536 {
537 if ( helpDescriptor && !parameter.isEditable() )
538 {
539
540 continue;
541 }
542
543 w.startElement( parameter.getName() );
544
545 String type = parameter.getType();
546 if ( StringUtils.isNotEmpty( type ) )
547 {
548 w.addAttribute( "implementation", type );
549 }
550
551 if ( parameter.getDefaultValue() != null )
552 {
553 w.addAttribute( "default-value", parameter.getDefaultValue() );
554 }
555
556 if ( StringUtils.isNotEmpty( parameter.getExpression() ) )
557 {
558 w.writeText( parameter.getExpression() );
559 }
560
561 w.endElement();
562 }
563
564 w.endElement();
565 }
566
567
568
569
570
571 if ( !requirements.isEmpty() && !helpDescriptor )
572 {
573 w.startElement( "requirements" );
574
575 for ( Map.Entry<String, Requirement> entry : requirements.entrySet() )
576 {
577 String key = entry.getKey();
578 Requirement requirement = entry.getValue();
579
580 w.startElement( "requirement" );
581
582 GeneratorUtils.element( w, "role", requirement.getRole() );
583
584 if ( StringUtils.isNotEmpty( requirement.getRoleHint() ) )
585 {
586 GeneratorUtils.element( w, "role-hint", requirement.getRoleHint() );
587 }
588
589 GeneratorUtils.element( w, "field-name", key );
590
591 w.endElement();
592 }
593
594 w.endElement();
595 }
596
597 w.endElement();
598 }
599
600
601
602
603
604
605
606 private String getExpression( Parameter parameter )
607 {
608 String expression = parameter.getExpression();
609 if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) )
610 {
611 expression = "${" + expression.trim() + "}";
612 parameter.setExpression( expression );
613 }
614 return expression;
615 }
616 }