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