45
45
@ ImportRuntimeHints (SbomEndpointRuntimeHints .class )
46
46
public class SbomEndpoint {
47
47
48
- private static final List <String > DEFAULT_APPLICATION_SBOM_LOCATIONS = List .of ("classpath:META-INF/sbom/bom.json" ,
49
- "classpath:META-INF/sbom/application.cdx.json" );
50
-
51
48
static final String APPLICATION_SBOM_ID = "application" ;
52
49
50
+ private static final List <AutodetectedSbom > AUTODETECTED_SBOMS = List .of (
51
+ new AutodetectedSbom (APPLICATION_SBOM_ID , "classpath:META-INF/sbom/bom.json" , true ),
52
+ new AutodetectedSbom (APPLICATION_SBOM_ID , "classpath:META-INF/sbom/application.cdx.json" , true ),
53
+ new AutodetectedSbom ("native-image" , "classpath:META-INF/native-image/sbom.json" , false ));
54
+
53
55
private final SbomProperties properties ;
54
56
55
57
private final ResourceLoader resourceLoader ;
@@ -59,14 +61,26 @@ public class SbomEndpoint {
59
61
public SbomEndpoint (SbomProperties properties , ResourceLoader resourceLoader ) {
60
62
this .properties = properties ;
61
63
this .resourceLoader = resourceLoader ;
62
- this .sboms = Collections .unmodifiableMap (getSboms ());
64
+ this .sboms = loadSboms ();
65
+ }
66
+
67
+ private Map <String , Resource > loadSboms () {
68
+ Map <String , Resource > sboms = new HashMap <>();
69
+ addConfiguredApplicationSbom (sboms );
70
+ addAdditionalSboms (sboms );
71
+ addAutodetectedSboms (sboms );
72
+ return Collections .unmodifiableMap (sboms );
63
73
}
64
74
65
- private Map <String , Resource > getSboms () {
66
- Map <String , Resource > result = new HashMap <>();
67
- addKnownSboms (result );
68
- addAdditionalSboms (result );
69
- return result ;
75
+ private void addConfiguredApplicationSbom (Map <String , Resource > sboms ) {
76
+ String location = this .properties .getApplication ().getLocation ();
77
+ if (!StringUtils .hasLength (location )) {
78
+ return ;
79
+ }
80
+ Resource resource = loadResource (location );
81
+ if (resource != null ) {
82
+ sboms .put (APPLICATION_SBOM_ID , resource );
83
+ }
70
84
}
71
85
72
86
private void addAdditionalSboms (Map <String , Resource > result ) {
@@ -80,34 +94,16 @@ private void addAdditionalSboms(Map<String, Resource> result) {
80
94
});
81
95
}
82
96
83
- private void addKnownSboms (Map <String , Resource > result ) {
84
- Resource applicationSbom = getApplicationSbom ();
85
- if (applicationSbom != null ) {
86
- result .put (APPLICATION_SBOM_ID , applicationSbom );
87
- }
88
- }
89
-
90
- @ ReadOperation
91
- Sboms sboms () {
92
- return new Sboms (new TreeSet <>(this .sboms .keySet ()));
93
- }
94
-
95
- @ ReadOperation
96
- Resource sbom (@ Selector String id ) {
97
- return this .sboms .get (id );
98
- }
99
-
100
- private Resource getApplicationSbom () {
101
- if (StringUtils .hasLength (this .properties .getApplication ().getLocation ())) {
102
- return loadResource (this .properties .getApplication ().getLocation ());
103
- }
104
- for (String location : DEFAULT_APPLICATION_SBOM_LOCATIONS ) {
105
- Resource resource = this .resourceLoader .getResource (location );
97
+ private void addAutodetectedSboms (Map <String , Resource > sboms ) {
98
+ for (AutodetectedSbom sbom : AUTODETECTED_SBOMS ) {
99
+ if (sboms .containsKey (sbom .id ())) {
100
+ continue ;
101
+ }
102
+ Resource resource = this .resourceLoader .getResource (sbom .resource ());
106
103
if (resource .exists ()) {
107
- return resource ;
104
+ sboms . put ( sbom . id (), resource ) ;
108
105
}
109
106
}
110
- return null ;
111
107
}
112
108
113
109
private Resource loadResource (String location ) {
@@ -125,6 +121,16 @@ private Resource loadResource(String location) {
125
121
throw new IllegalStateException ("Resource '%s' doesn't exist and it's not marked optional" .formatted (location ));
126
122
}
127
123
124
+ @ ReadOperation
125
+ Sboms sboms () {
126
+ return new Sboms (new TreeSet <>(this .sboms .keySet ()));
127
+ }
128
+
129
+ @ ReadOperation
130
+ Resource sbom (@ Selector String id ) {
131
+ return this .sboms .get (id );
132
+ }
133
+
128
134
record Sboms (Collection <String > ids ) implements OperationResponseBody {
129
135
}
130
136
@@ -146,18 +152,26 @@ private static String stripOptionalPrefix(String location) {
146
152
}
147
153
}
148
154
149
- static class SbomEndpointRuntimeHints implements RuntimeHintsRegistrar {
150
-
151
- @ Override
152
- public void registerHints (RuntimeHints hints , ClassLoader classLoader ) {
153
- for (String defaultLocation : DEFAULT_APPLICATION_SBOM_LOCATIONS ) {
154
- hints .resources ().registerPattern (stripClasspathPrefix (defaultLocation ));
155
+ private record AutodetectedSbom (String id , String resource , boolean needsHints ) {
156
+ void registerHintsIfNeeded (RuntimeHints hints ) {
157
+ if (this .needsHints ) {
158
+ hints .resources ().registerPattern (stripClasspathPrefix (this .resource ));
155
159
}
156
160
}
157
161
158
162
private String stripClasspathPrefix (String location ) {
159
163
return location .substring ("classpath:" .length ());
160
164
}
165
+ }
166
+
167
+ static class SbomEndpointRuntimeHints implements RuntimeHintsRegistrar {
168
+
169
+ @ Override
170
+ public void registerHints (RuntimeHints hints , ClassLoader classLoader ) {
171
+ for (AutodetectedSbom sbom : AUTODETECTED_SBOMS ) {
172
+ sbom .registerHintsIfNeeded (hints );
173
+ }
174
+ }
161
175
162
176
}
163
177
0 commit comments