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 @SuppressWarnings( "deprecation" )
183 protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w, boolean helpDescriptor )
184 {
185 w.startElement( "mojo" );
186
187
188
189
190
191 w.startElement( "goal" );
192 w.writeText( mojoDescriptor.getGoal() );
193 w.endElement();
194
195
196
197
198
199 String description = mojoDescriptor.getDescription();
200
201 if ( StringUtils.isNotEmpty( description ) )
202 {
203 w.startElement( "description" );
204 if ( helpDescriptor )
205 {
206 w.writeText( GeneratorUtils.toText( mojoDescriptor.getDescription() ) );
207 }
208 else
209 {
210 w.writeText( mojoDescriptor.getDescription() );
211 }
212 w.endElement();
213 }
214
215
216
217
218
219 if ( StringUtils.isNotEmpty( mojoDescriptor.isDependencyResolutionRequired() ) )
220 {
221 GeneratorUtils.element( w, "requiresDependencyResolution",
222 mojoDescriptor.isDependencyResolutionRequired() );
223 }
224
225
226
227
228
229 GeneratorUtils.element( w, "requiresDirectInvocation",
230 String.valueOf( mojoDescriptor.isDirectInvocationOnly() ) );
231
232
233
234
235
236 GeneratorUtils.element( w, "requiresProject", String.valueOf( mojoDescriptor.isProjectRequired() ) );
237
238
239
240
241
242 GeneratorUtils.element( w, "requiresReports", String.valueOf( mojoDescriptor.isRequiresReports() ) );
243
244
245
246
247
248 GeneratorUtils.element( w, "aggregator", String.valueOf( mojoDescriptor.isAggregator() ) );
249
250
251
252
253
254 GeneratorUtils.element( w, "requiresOnline", String.valueOf( mojoDescriptor.isOnlineRequired() ) );
255
256
257
258
259
260 GeneratorUtils.element( w, "inheritedByDefault", String.valueOf( mojoDescriptor.isInheritedByDefault() ) );
261
262
263
264
265
266 if ( StringUtils.isNotEmpty( mojoDescriptor.getPhase() ) )
267 {
268 GeneratorUtils.element( w, "phase", mojoDescriptor.getPhase() );
269 }
270
271
272
273
274
275 if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) )
276 {
277 GeneratorUtils.element( w, "executePhase", mojoDescriptor.getExecutePhase() );
278 }
279
280 if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteGoal() ) )
281 {
282 GeneratorUtils.element( w, "executeGoal", mojoDescriptor.getExecuteGoal() );
283 }
284
285 if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteLifecycle() ) )
286 {
287 GeneratorUtils.element( w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle() );
288 }
289
290
291
292
293
294 w.startElement( "implementation" );
295 w.writeText( mojoDescriptor.getImplementation() );
296 w.endElement();
297
298
299
300
301
302 w.startElement( "language" );
303 w.writeText( mojoDescriptor.getLanguage() );
304 w.endElement();
305
306
307
308
309
310 if ( StringUtils.isNotEmpty( mojoDescriptor.getComponentConfigurator() ) )
311 {
312 w.startElement( "configurator" );
313 w.writeText( mojoDescriptor.getComponentConfigurator() );
314 w.endElement();
315 }
316
317
318
319
320
321 if ( StringUtils.isNotEmpty( mojoDescriptor.getComponentComposer() ) )
322 {
323 w.startElement( "composer" );
324 w.writeText( mojoDescriptor.getComponentComposer() );
325 w.endElement();
326 }
327
328
329
330
331
332 w.startElement( "instantiationStrategy" );
333 w.writeText( mojoDescriptor.getInstantiationStrategy() );
334 w.endElement();
335
336
337
338
339
340 w.startElement( "executionStrategy" );
341 w.writeText( mojoDescriptor.getExecutionStrategy() );
342 w.endElement();
343
344
345
346
347
348 if ( mojoDescriptor.getSince() != null )
349 {
350 w.startElement( "since" );
351
352 if ( StringUtils.isEmpty( mojoDescriptor.getSince() ) )
353 {
354 w.writeText( "No version given" );
355 }
356 else
357 {
358 w.writeText( mojoDescriptor.getSince() );
359 }
360
361 w.endElement();
362 }
363
364
365
366
367
368 if ( mojoDescriptor.getDeprecated() != null )
369 {
370 w.startElement( "deprecated" );
371
372 if ( StringUtils.isEmpty( mojoDescriptor.getDeprecated() ) )
373 {
374 w.writeText( "No reason given" );
375 }
376 else
377 {
378 w.writeText( mojoDescriptor.getDeprecated() );
379 }
380
381 w.endElement();
382 }
383
384
385
386
387
388 if ( mojoDescriptor instanceof ExtendedMojoDescriptor )
389 {
390 ExtendedMojoDescriptor extendedMojoDescriptor = (ExtendedMojoDescriptor) mojoDescriptor;
391 if ( extendedMojoDescriptor.getDependencyCollectionRequired() != null )
392 {
393 GeneratorUtils.element( w, "requiresDependencyCollection",
394 extendedMojoDescriptor.getDependencyCollectionRequired() );
395 }
396
397 GeneratorUtils.element( w, "threadSafe", String.valueOf( extendedMojoDescriptor.isThreadSafe() ) );
398 }
399
400
401
402
403
404 List<Parameter> parameters = mojoDescriptor.getParameters();
405
406 w.startElement( "parameters" );
407
408 Map<String, Requirement> requirements = new LinkedHashMap<>();
409
410 Set<Parameter> configuration = new LinkedHashSet<>();
411
412 if ( parameters != null )
413 {
414 if ( helpDescriptor )
415 {
416 PluginUtils.sortMojoParameters( parameters );
417 }
418
419 for ( Parameter parameter : parameters )
420 {
421 String expression = getExpression( parameter );
422
423 if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) )
424 {
425
426
427
428 String role = expression.substring( "${component.".length(), expression.length() - 1 );
429
430 String roleHint = null;
431
432 int posRoleHintSeparator = role.indexOf( '#' );
433 if ( posRoleHintSeparator > 0 )
434 {
435 roleHint = role.substring( posRoleHintSeparator + 1 );
436
437 role = role.substring( 0, posRoleHintSeparator );
438 }
439
440
441 requirements.put( parameter.getName(), new Requirement( role, roleHint ) );
442 }
443 else if ( parameter.getRequirement() != null )
444 {
445 requirements.put( parameter.getName(), parameter.getRequirement() );
446 }
447 else if ( !helpDescriptor || parameter.isEditable() )
448 {
449
450
451 w.startElement( "parameter" );
452
453 GeneratorUtils.element( w, "name", parameter.getName() );
454
455 if ( parameter.getAlias() != null )
456 {
457 GeneratorUtils.element( w, "alias", parameter.getAlias() );
458 }
459
460 GeneratorUtils.element( w, "type", parameter.getType() );
461
462 if ( parameter.getSince() != null )
463 {
464 w.startElement( "since" );
465
466 if ( StringUtils.isEmpty( parameter.getSince() ) )
467 {
468 w.writeText( "No version given" );
469 }
470 else
471 {
472 w.writeText( parameter.getSince() );
473 }
474
475 w.endElement();
476 }
477
478 if ( parameter.getDeprecated() != null )
479 {
480 if ( StringUtils.isEmpty( parameter.getDeprecated() ) )
481 {
482 GeneratorUtils.element( w, "deprecated", "No reason given" );
483 }
484 else
485 {
486 GeneratorUtils.element( w, "deprecated", parameter.getDeprecated() );
487 }
488 }
489
490 if ( parameter.getImplementation() != null )
491 {
492 GeneratorUtils.element( w, "implementation", parameter.getImplementation() );
493 }
494
495 GeneratorUtils.element( w, "required", Boolean.toString( parameter.isRequired() ) );
496
497 GeneratorUtils.element( w, "editable", Boolean.toString( parameter.isEditable() ) );
498
499 GeneratorUtils.element( w, "description", parameter.getDescription(), helpDescriptor );
500
501 if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) || StringUtils.isNotEmpty(
502 parameter.getExpression() ) )
503 {
504 configuration.add( parameter );
505 }
506
507 w.endElement();
508 }
509
510 }
511 }
512
513 w.endElement();
514
515
516
517
518
519 if ( !configuration.isEmpty() )
520 {
521 w.startElement( "configuration" );
522
523 for ( Parameter parameter : configuration )
524 {
525 if ( helpDescriptor && !parameter.isEditable() )
526 {
527
528 continue;
529 }
530
531 w.startElement( parameter.getName() );
532
533 String type = parameter.getType();
534 if ( StringUtils.isNotEmpty( type ) )
535 {
536 w.addAttribute( "implementation", type );
537 }
538
539 if ( parameter.getDefaultValue() != null )
540 {
541 w.addAttribute( "default-value", parameter.getDefaultValue() );
542 }
543
544 if ( StringUtils.isNotEmpty( parameter.getExpression() ) )
545 {
546 w.writeText( parameter.getExpression() );
547 }
548
549 w.endElement();
550 }
551
552 w.endElement();
553 }
554
555
556
557
558
559 if ( !requirements.isEmpty() && !helpDescriptor )
560 {
561 w.startElement( "requirements" );
562
563 for ( Map.Entry<String, Requirement> entry : requirements.entrySet() )
564 {
565 String key = entry.getKey();
566 Requirement requirement = entry.getValue();
567
568 w.startElement( "requirement" );
569
570 GeneratorUtils.element( w, "role", requirement.getRole() );
571
572 if ( StringUtils.isNotEmpty( requirement.getRoleHint() ) )
573 {
574 GeneratorUtils.element( w, "role-hint", requirement.getRoleHint() );
575 }
576
577 GeneratorUtils.element( w, "field-name", key );
578
579 w.endElement();
580 }
581
582 w.endElement();
583 }
584
585 w.endElement();
586 }
587
588
589
590
591
592
593
594 private String getExpression( Parameter parameter )
595 {
596 String expression = parameter.getExpression();
597 if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) )
598 {
599 expression = "${" + expression.trim() + "}";
600 parameter.setExpression( expression );
601 }
602 return expression;
603 }
604 }