1
1
/*
2
- * Copyright 2012-2021 the original author or authors.
2
+ * Copyright 2012-2022 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
package org .springframework .boot .build .mavenplugin ;
18
18
19
19
import java .io .File ;
20
+ import java .io .FileInputStream ;
21
+ import java .io .FileWriter ;
20
22
import java .io .IOException ;
23
+ import java .io .InputStream ;
24
+ import java .io .Writer ;
21
25
import java .nio .charset .StandardCharsets ;
22
26
import java .nio .file .Files ;
23
27
import java .nio .file .Path ;
24
28
import java .nio .file .StandardCopyOption ;
25
29
import java .util .Arrays ;
30
+ import java .util .Properties ;
31
+ import java .util .function .BiConsumer ;
32
+
33
+ import javax .xml .parsers .DocumentBuilder ;
34
+ import javax .xml .parsers .DocumentBuilderFactory ;
35
+ import javax .xml .parsers .ParserConfigurationException ;
36
+ import javax .xml .xpath .XPath ;
37
+ import javax .xml .xpath .XPathConstants ;
38
+ import javax .xml .xpath .XPathExpressionException ;
39
+ import javax .xml .xpath .XPathFactory ;
26
40
27
41
import io .spring .javaformat .formatter .FileEdit ;
28
42
import io .spring .javaformat .formatter .FileFormatter ;
29
43
import org .gradle .api .DefaultTask ;
44
+ import org .gradle .api .GradleException ;
30
45
import org .gradle .api .Plugin ;
31
46
import org .gradle .api .Project ;
32
47
import org .gradle .api .Task ;
41
56
import org .gradle .api .attributes .Usage ;
42
57
import org .gradle .api .file .CopySpec ;
43
58
import org .gradle .api .file .DirectoryProperty ;
59
+ import org .gradle .api .file .FileCollection ;
60
+ import org .gradle .api .file .RegularFileProperty ;
44
61
import org .gradle .api .model .ObjectFactory ;
45
62
import org .gradle .api .plugins .JavaLibraryPlugin ;
46
63
import org .gradle .api .plugins .JavaPlugin ;
50
67
import org .gradle .api .publish .maven .plugins .MavenPublishPlugin ;
51
68
import org .gradle .api .tasks .Classpath ;
52
69
import org .gradle .api .tasks .Copy ;
70
+ import org .gradle .api .tasks .InputFiles ;
53
71
import org .gradle .api .tasks .JavaExec ;
54
72
import org .gradle .api .tasks .OutputDirectory ;
73
+ import org .gradle .api .tasks .OutputFile ;
74
+ import org .gradle .api .tasks .PathSensitive ;
55
75
import org .gradle .api .tasks .PathSensitivity ;
56
76
import org .gradle .api .tasks .SourceSet ;
57
77
import org .gradle .api .tasks .SourceSetContainer ;
60
80
import org .gradle .api .tasks .bundling .Jar ;
61
81
import org .gradle .api .tasks .javadoc .Javadoc ;
62
82
import org .gradle .external .javadoc .StandardJavadocDocletOptions ;
83
+ import org .w3c .dom .Document ;
84
+ import org .w3c .dom .Node ;
85
+ import org .xml .sax .SAXException ;
63
86
64
87
import org .springframework .boot .build .DeployedPlugin ;
65
88
import org .springframework .boot .build .MavenRepositoryPlugin ;
66
89
import org .springframework .boot .build .test .IntegrationTestPlugin ;
90
+ import org .springframework .core .CollectionFactory ;
91
+ import org .springframework .util .Assert ;
67
92
68
93
/**
69
94
* Plugin for building Spring Boot's Maven Plugin.
@@ -88,6 +113,7 @@ public void apply(Project project) {
88
113
generateHelpMojoTask );
89
114
addDocumentPluginGoalsTask (project , generatePluginDescriptorTask );
90
115
addPrepareMavenBinariesTask (project );
116
+ addExtractVersionPropertiesTask (project );
91
117
}
92
118
93
119
private void configurePomPackaging (Project project ) {
@@ -240,6 +266,14 @@ private String replaceVersionPlaceholder(Project project, String input) {
240
266
return input .replace ("{{version}}" , project .getVersion ().toString ());
241
267
}
242
268
269
+ private void addExtractVersionPropertiesTask (Project project ) {
270
+ ExtractVersionProperties extractVersionProperties = project .getTasks ().create ("extractVersionProperties" ,
271
+ ExtractVersionProperties .class );
272
+ extractVersionProperties .setEffectiveBoms (project .getConfigurations ().create ("versionProperties" ));
273
+ extractVersionProperties .getDestination ().set (project .getLayout ().getBuildDirectory ().dir ("generated-resources" )
274
+ .map ((dir ) -> dir .file ("extracted-versions.properties" )));
275
+ }
276
+
243
277
public static class FormatHelpMojoSourceTask extends DefaultTask {
244
278
245
279
private Task generator ;
@@ -361,4 +395,109 @@ public void createRepository() {
361
395
362
396
}
363
397
398
+ public static class ExtractVersionProperties extends DefaultTask {
399
+
400
+ private final RegularFileProperty destination ;
401
+
402
+ private FileCollection effectiveBoms ;
403
+
404
+ public ExtractVersionProperties () {
405
+ this .destination = getProject ().getObjects ().fileProperty ();
406
+ }
407
+
408
+ @ InputFiles
409
+ @ PathSensitive (PathSensitivity .RELATIVE )
410
+ public FileCollection getEffectiveBoms () {
411
+ return this .effectiveBoms ;
412
+ }
413
+
414
+ public void setEffectiveBoms (FileCollection effectiveBoms ) {
415
+ this .effectiveBoms = effectiveBoms ;
416
+ }
417
+
418
+ @ OutputFile
419
+ public RegularFileProperty getDestination () {
420
+ return this .destination ;
421
+ }
422
+
423
+ @ TaskAction
424
+ public void extractVersionProperties () {
425
+ EffectiveBom effectiveBom = new EffectiveBom (this .effectiveBoms .getSingleFile ());
426
+ Properties versions = extractVersionProperties (effectiveBom );
427
+ writeProperties (versions );
428
+ }
429
+
430
+ private void writeProperties (Properties versions ) {
431
+ File outputFile = this .destination .getAsFile ().get ();
432
+ outputFile .getParentFile ().mkdirs ();
433
+ try (Writer writer = new FileWriter (outputFile )) {
434
+ versions .store (writer , null );
435
+ }
436
+ catch (IOException ex ) {
437
+ throw new GradleException ("Failed to write extracted version properties" , ex );
438
+ }
439
+ }
440
+
441
+ private Properties extractVersionProperties (EffectiveBom effectiveBom ) {
442
+ Properties versions = CollectionFactory .createSortedProperties (true );
443
+ versions .setProperty ("project.version" , effectiveBom .version ());
444
+ effectiveBom .property ("log4j2.version" , versions ::setProperty );
445
+ effectiveBom .property ("maven-jar-plugin.version" , versions ::setProperty );
446
+ effectiveBom .property ("maven-war-plugin.version" , versions ::setProperty );
447
+ effectiveBom .property ("build-helper-maven-plugin.version" , versions ::setProperty );
448
+ effectiveBom .property ("spring-framework.version" , versions ::setProperty );
449
+ effectiveBom .property ("jakarta-servlet.version" , versions ::setProperty );
450
+ effectiveBom .property ("kotlin.version" , versions ::setProperty );
451
+ return versions ;
452
+ }
453
+
454
+ }
455
+
456
+ private static final class EffectiveBom {
457
+
458
+ private final Document document ;
459
+
460
+ private final XPath xpath ;
461
+
462
+ private EffectiveBom (File bomFile ) {
463
+ this .document = loadDocument (bomFile );
464
+ this .xpath = XPathFactory .newInstance ().newXPath ();
465
+ }
466
+
467
+ private Document loadDocument (File bomFile ) {
468
+ try {
469
+ try (InputStream inputStream = new FileInputStream (bomFile )) {
470
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory .newInstance ();
471
+ DocumentBuilder builder = builderFactory .newDocumentBuilder ();
472
+ return builder .parse (inputStream );
473
+ }
474
+ }
475
+ catch (ParserConfigurationException | SAXException | IOException ex ) {
476
+ throw new IllegalStateException (ex );
477
+ }
478
+ }
479
+
480
+ private String version () {
481
+ return get ("version" );
482
+ }
483
+
484
+ private void property (String name , BiConsumer <String , String > handler ) {
485
+ handler .accept (name , get ("properties/" + name ));
486
+ }
487
+
488
+ private String get (String expression ) {
489
+ try {
490
+ Node node = (Node ) this .xpath .compile ("/project/" + expression ).evaluate (this .document ,
491
+ XPathConstants .NODE );
492
+ String text = (node != null ) ? node .getTextContent () : null ;
493
+ Assert .hasLength (text , () -> "No result for expression " + expression );
494
+ return text ;
495
+ }
496
+ catch (XPathExpressionException ex ) {
497
+ throw new IllegalStateException (ex );
498
+ }
499
+ }
500
+
501
+ }
502
+
364
503
}
0 commit comments