16
16
17
17
package org .springframework .boot .build .bom ;
18
18
19
+ import java .io .BufferedReader ;
20
+ import java .io .IOException ;
21
+ import java .io .InputStreamReader ;
22
+ import java .net .URI ;
19
23
import java .util .Collections ;
24
+ import java .util .HashMap ;
20
25
import java .util .List ;
21
26
import java .util .Locale ;
27
+ import java .util .Map ;
28
+ import java .util .regex .Matcher ;
29
+ import java .util .regex .Pattern ;
22
30
23
31
import org .apache .maven .artifact .versioning .VersionRange ;
32
+ import org .gradle .api .GradleException ;
24
33
25
34
import org .springframework .boot .build .bom .bomr .version .DependencyVersion ;
26
35
@@ -34,37 +43,41 @@ public class Library {
34
43
35
44
private final String name ;
36
45
37
- private final DependencyVersion version ;
46
+ private final LibraryVersion version ;
38
47
39
48
private final List <Group > groups ;
40
49
41
50
private final String versionProperty ;
42
51
43
52
private final List <ProhibitedVersion > prohibitedVersions ;
44
53
54
+ private final DependencyVersions dependencyVersions ;
55
+
45
56
/**
46
57
* Create a new {@code Library} with the given {@code name}, {@code version}, and
47
58
* {@code groups}.
48
59
* @param name name of the library
49
60
* @param version version of the library
50
61
* @param groups groups in the library
51
62
* @param prohibitedVersions version of the library that are prohibited
63
+ * @param dependencyVersions the library's dependency versions
52
64
*/
53
- public Library (String name , DependencyVersion version , List <Group > groups ,
54
- List < ProhibitedVersion > prohibitedVersions ) {
65
+ public Library (String name , LibraryVersion version , List <Group > groups , List < ProhibitedVersion > prohibitedVersions ,
66
+ DependencyVersions dependencyVersions ) {
55
67
this .name = name ;
56
68
this .version = version ;
57
69
this .groups = groups ;
58
70
this .versionProperty = "Spring Boot" .equals (name ) ? null
59
71
: name .toLowerCase (Locale .ENGLISH ).replace (' ' , '-' ) + ".version" ;
60
72
this .prohibitedVersions = prohibitedVersions ;
73
+ this .dependencyVersions = dependencyVersions ;
61
74
}
62
75
63
76
public String getName () {
64
77
return this .name ;
65
78
}
66
79
67
- public DependencyVersion getVersion () {
80
+ public LibraryVersion getVersion () {
68
81
return this .version ;
69
82
}
70
83
@@ -80,6 +93,10 @@ public List<ProhibitedVersion> getProhibitedVersions() {
80
93
return this .prohibitedVersions ;
81
94
}
82
95
96
+ public DependencyVersions getDependencyVersions () {
97
+ return this .dependencyVersions ;
98
+ }
99
+
83
100
/**
84
101
* A version or range of versions that are prohibited from being used in a bom.
85
102
*/
@@ -104,6 +121,27 @@ public String getReason() {
104
121
105
122
}
106
123
124
+ public static class LibraryVersion {
125
+
126
+ private final DependencyVersion version ;
127
+
128
+ private final VersionAlignment versionAlignment ;
129
+
130
+ public LibraryVersion (DependencyVersion version , VersionAlignment versionAlignment ) {
131
+ this .version = version ;
132
+ this .versionAlignment = versionAlignment ;
133
+ }
134
+
135
+ public DependencyVersion getVersion () {
136
+ return this .version ;
137
+ }
138
+
139
+ public VersionAlignment getVersionAlignment () {
140
+ return this .versionAlignment ;
141
+ }
142
+
143
+ }
144
+
107
145
/**
108
146
* A collection of modules, Maven plugins, and Maven boms with the same group ID.
109
147
*/
@@ -194,4 +232,128 @@ public String getArtifactId() {
194
232
195
233
}
196
234
235
+ public interface DependencyVersions {
236
+
237
+ String getVersion (String groupId , String artifactId );
238
+
239
+ default boolean available () {
240
+ return true ;
241
+ }
242
+
243
+ }
244
+
245
+ public static class DependencyLockDependencyVersions implements DependencyVersions {
246
+
247
+ private final Map <String , Map <String , String >> dependencyVersions = new HashMap <>();
248
+
249
+ private final String sourceTemplate ;
250
+
251
+ private final String libraryVersion ;
252
+
253
+ public DependencyLockDependencyVersions (String sourceTemplate , String libraryVersion ) {
254
+ this .sourceTemplate = sourceTemplate ;
255
+ this .libraryVersion = libraryVersion ;
256
+ }
257
+
258
+ @ Override
259
+ public boolean available () {
260
+ return !this .libraryVersion .contains ("-SNAPSHOT" );
261
+ }
262
+
263
+ @ Override
264
+ public String getVersion (String groupId , String artifactId ) {
265
+ if (this .dependencyVersions .isEmpty ()) {
266
+ loadVersions ();
267
+ }
268
+ return this .dependencyVersions .computeIfAbsent (groupId , (key ) -> Collections .emptyMap ()).get (artifactId );
269
+ }
270
+
271
+ private void loadVersions () {
272
+ String source = this .sourceTemplate .replace ("<libraryVersion>" , this .libraryVersion );
273
+ try {
274
+ try (BufferedReader reader = new BufferedReader (
275
+ new InputStreamReader (URI .create (source ).toURL ().openStream ()))) {
276
+ String line ;
277
+ while ((line = reader .readLine ()) != null ) {
278
+ if (!line .startsWith ("#" )) {
279
+ String [] components = line .split (":" );
280
+ Map <String , String > groupDependencies = this .dependencyVersions
281
+ .computeIfAbsent (components [0 ], (key ) -> new HashMap <>());
282
+ groupDependencies .put (components [1 ], components [2 ]);
283
+ }
284
+ }
285
+ }
286
+ }
287
+ catch (IOException ex ) {
288
+ throw new GradleException ("Failed to load versions from dependency lock file '" + source + "'" , ex );
289
+ }
290
+ }
291
+
292
+ }
293
+
294
+ public static class DependencyConstraintsDependencyVersions implements DependencyVersions {
295
+
296
+ private static final Pattern CONSTRAINT_PATTERN = Pattern .compile ("api \" (.+):(.+):(.+)\" " );
297
+
298
+ private final Map <String , Map <String , String >> dependencyVersions = new HashMap <>();
299
+
300
+ private final String sourceTemplate ;
301
+
302
+ private final String libraryVersion ;
303
+
304
+ public DependencyConstraintsDependencyVersions (String sourceTemplate , String libraryVersion ) {
305
+ this .sourceTemplate = sourceTemplate ;
306
+ this .libraryVersion = libraryVersion ;
307
+ }
308
+
309
+ @ Override
310
+ public String getVersion (String groupId , String artifactId ) {
311
+ if (this .dependencyVersions .isEmpty ()) {
312
+ loadVersions ();
313
+ }
314
+ return this .dependencyVersions .computeIfAbsent (groupId , (key ) -> Collections .emptyMap ()).get (artifactId );
315
+ }
316
+
317
+ private void loadVersions () {
318
+ String version = this .libraryVersion ;
319
+ if (version .endsWith ("-SNAPSHOT" )) {
320
+ version = version .substring (0 , version .lastIndexOf ('.' )) + ".x" ;
321
+ }
322
+ String source = this .sourceTemplate .replace ("<libraryVersion>" , version );
323
+ try {
324
+ try (BufferedReader reader = new BufferedReader (
325
+ new InputStreamReader (URI .create (source ).toURL ().openStream ()))) {
326
+ String line ;
327
+ while ((line = reader .readLine ()) != null ) {
328
+ Matcher matcher = CONSTRAINT_PATTERN .matcher (line .trim ());
329
+ if (matcher .matches ()) {
330
+ Map <String , String > groupDependencies = this .dependencyVersions
331
+ .computeIfAbsent (matcher .group (1 ), (key ) -> new HashMap <>());
332
+ groupDependencies .put (matcher .group (2 ), matcher .group (3 ));
333
+ }
334
+ }
335
+ }
336
+ }
337
+ catch (IOException ex ) {
338
+ throw new GradleException (
339
+ "Failed to load versions from dependency constraints declared in '" + source + "'" , ex );
340
+ }
341
+ }
342
+
343
+ }
344
+
345
+ public static class VersionAlignment {
346
+
347
+ private final String libraryName ;
348
+
349
+ public VersionAlignment (String libraryName ) {
350
+ this .libraryName = libraryName ;
351
+ }
352
+
353
+ public String getLibraryName () {
354
+ return this .libraryName ;
355
+ }
356
+
357
+ }
358
+
197
359
}
0 commit comments