32
32
import io .undertow .server .handlers .GracefulShutdownHandler ;
33
33
import org .apache .commons .logging .Log ;
34
34
import org .apache .commons .logging .LogFactory ;
35
+ import org .jspecify .annotations .Nullable ;
35
36
import org .xnio .channels .BoundChannel ;
36
37
37
38
import org .springframework .aot .hint .RuntimeHints ;
@@ -61,7 +62,7 @@ public class UndertowWebServer implements WebServer {
61
62
62
63
private static final Log logger = LogFactory .getLog (UndertowWebServer .class );
63
64
64
- private final AtomicReference <GracefulShutdownCallback > gracefulShutdownCallback = new AtomicReference <>();
65
+ private final AtomicReference <@ Nullable GracefulShutdownCallback > gracefulShutdownCallback = new AtomicReference <>();
65
66
66
67
private final Object monitor = new Object ();
67
68
@@ -71,13 +72,13 @@ public class UndertowWebServer implements WebServer {
71
72
72
73
private final boolean autoStart ;
73
74
74
- private Undertow undertow ;
75
+ private @ Nullable Undertow undertow ;
75
76
76
77
private volatile boolean started = false ;
77
78
78
- private volatile GracefulShutdownHandler gracefulShutdown ;
79
+ private volatile @ Nullable GracefulShutdownHandler gracefulShutdown ;
79
80
80
- private volatile List <Closeable > closeables ;
81
+ private volatile @ Nullable List <Closeable > closeables ;
81
82
82
83
/**
83
84
* Create a new {@link UndertowWebServer} instance.
@@ -142,6 +143,7 @@ private void destroySilently() {
142
143
try {
143
144
if (this .undertow != null ) {
144
145
this .undertow .stop ();
146
+ Assert .state (this .closeables != null , "'closeables' must not be null" );
145
147
this .closeables .forEach (this ::closeSilently );
146
148
}
147
149
}
@@ -167,11 +169,12 @@ private Undertow createUndertowServer() {
167
169
return this .builder .build ();
168
170
}
169
171
170
- protected HttpHandler createHttpHandler () {
172
+ protected @ Nullable HttpHandler createHttpHandler () {
171
173
HttpHandler handler = null ;
172
174
for (HttpHandlerFactory factory : this .httpHandlerFactories ) {
173
175
handler = factory .getHandler (handler );
174
176
if (handler instanceof Closeable closeable ) {
177
+ Assert .state (this .closeables != null , "'closeables' must not be null" );
175
178
this .closeables .add (closeable );
176
179
}
177
180
if (handler instanceof GracefulShutdownHandler shutdownHandler ) {
@@ -220,11 +223,14 @@ private List<Port> getActualPorts() {
220
223
@ SuppressWarnings ("unchecked" )
221
224
private List <BoundChannel > extractChannels () {
222
225
Field channelsField = ReflectionUtils .findField (Undertow .class , "channels" );
226
+ Assert .state (channelsField != null , "'channelsField' must not be null" );
223
227
ReflectionUtils .makeAccessible (channelsField );
224
- return (List <BoundChannel >) ReflectionUtils .getField (channelsField , this .undertow );
228
+ List <BoundChannel > channels = (List <BoundChannel >) ReflectionUtils .getField (channelsField , this .undertow );
229
+ Assert .state (channels != null , "'channels' must not be null" );
230
+ return channels ;
225
231
}
226
232
227
- private UndertowWebServer .Port getPortFromChannel (BoundChannel channel ) {
233
+ private UndertowWebServer .@ Nullable Port getPortFromChannel (BoundChannel channel ) {
228
234
SocketAddress socketAddress = channel .getLocalAddress ();
229
235
if (socketAddress instanceof InetSocketAddress inetSocketAddress ) {
230
236
Field sslField = ReflectionUtils .findField (channel .getClass (), "ssl" );
@@ -253,20 +259,37 @@ private List<UndertowWebServer.Port> getConfiguredPorts() {
253
259
@ SuppressWarnings ("unchecked" )
254
260
private List <Object > extractListeners () {
255
261
Field listenersField = ReflectionUtils .findField (Undertow .class , "listeners" );
262
+ Assert .state (listenersField != null , "'listenersField' must not be null" );
256
263
ReflectionUtils .makeAccessible (listenersField );
257
- return (List <Object >) ReflectionUtils .getField (listenersField , this .undertow );
264
+ List <Object > listeners = (List <Object >) ReflectionUtils .getField (listenersField , this .undertow );
265
+ Assert .state (listeners != null , "'listeners' must not be null" );
266
+ return listeners ;
258
267
}
259
268
260
269
private UndertowWebServer .Port getPortFromListener (Object listener ) {
261
270
Field typeField = ReflectionUtils .findField (listener .getClass (), "type" );
262
- ReflectionUtils . makeAccessible (typeField );
263
- String protocol = ReflectionUtils . getField ( typeField , listener ). toString ( );
271
+ Assert . state (typeField != null , "'typeField' must not be null" );
272
+ String protocol = getProtocol ( listener , typeField );
264
273
Field portField = ReflectionUtils .findField (listener .getClass (), "port" );
265
- ReflectionUtils . makeAccessible (portField );
266
- int port = ( Integer ) ReflectionUtils . getField ( portField , listener );
274
+ Assert . state (portField != null , "'portField' must not be null" );
275
+ int port = getPort ( listener , portField );
267
276
return new UndertowWebServer .Port (port , protocol );
268
277
}
269
278
279
+ private static Integer getPort (Object listener , Field portField ) {
280
+ ReflectionUtils .makeAccessible (portField );
281
+ Integer value = (Integer ) ReflectionUtils .getField (portField , listener );
282
+ Assert .state (value != null , "'value' must not be null" );
283
+ return value ;
284
+ }
285
+
286
+ private String getProtocol (Object listener , Field typeField ) {
287
+ ReflectionUtils .makeAccessible (typeField );
288
+ Object value = ReflectionUtils .getField (typeField , listener );
289
+ Assert .state (value != null , "'value' must not be null" );
290
+ return value .toString ();
291
+ }
292
+
270
293
@ Override
271
294
public void stop () throws WebServerException {
272
295
synchronized (this .monitor ) {
@@ -278,9 +301,12 @@ public void stop() throws WebServerException {
278
301
notifyGracefulCallback (false );
279
302
}
280
303
try {
281
- this .undertow .stop ();
282
- for (Closeable closeable : this .closeables ) {
283
- closeable .close ();
304
+ if (this .undertow != null ) {
305
+ this .undertow .stop ();
306
+ Assert .state (this .closeables != null , "'closeables' must not be null" );
307
+ for (Closeable closeable : this .closeables ) {
308
+ closeable .close ();
309
+ }
284
310
}
285
311
}
286
312
catch (Exception ex ) {
@@ -304,7 +330,7 @@ public int getPort() {
304
330
* @return the Undertow server or {@code null} if the server hasn't been started yet
305
331
* @since 4.0.0
306
332
*/
307
- public Undertow getUndertow () {
333
+ public @ Nullable Undertow getUndertow () {
308
334
return this .undertow ;
309
335
}
310
336
@@ -396,27 +422,30 @@ public String toString() {
396
422
*/
397
423
private static final class CloseableHttpHandlerFactory implements HttpHandlerFactory {
398
424
399
- private final Closeable closeable ;
425
+ private final @ Nullable Closeable closeable ;
400
426
401
- private CloseableHttpHandlerFactory (Closeable closeable ) {
427
+ private CloseableHttpHandlerFactory (@ Nullable Closeable closeable ) {
402
428
this .closeable = closeable ;
403
429
}
404
430
405
431
@ Override
406
- public HttpHandler getHandler (HttpHandler next ) {
407
- if (this .closeable == null ) {
432
+ public @ Nullable HttpHandler getHandler (@ Nullable HttpHandler next ) {
433
+ Closeable closeable = this .closeable ;
434
+ if (closeable == null ) {
408
435
return next ;
409
436
}
410
437
return new CloseableHttpHandler () {
411
438
412
439
@ Override
413
440
public void handleRequest (HttpServerExchange exchange ) throws Exception {
414
- next .handleRequest (exchange );
441
+ if (next != null ) {
442
+ next .handleRequest (exchange );
443
+ }
415
444
}
416
445
417
446
@ Override
418
447
public void close () throws IOException {
419
- CloseableHttpHandlerFactory . this . closeable .close ();
448
+ closeable .close ();
420
449
}
421
450
422
451
};
@@ -438,7 +467,7 @@ private interface CloseableHttpHandler extends HttpHandler, Closeable {
438
467
static class UndertowWebServerRuntimeHints implements RuntimeHintsRegistrar {
439
468
440
469
@ Override
441
- public void registerHints (RuntimeHints hints , ClassLoader classLoader ) {
470
+ public void registerHints (RuntimeHints hints , @ Nullable ClassLoader classLoader ) {
442
471
hints .reflection ()
443
472
.registerTypeIfPresent (classLoader , "io.undertow.Undertow" ,
444
473
(hint ) -> hint .withField ("listeners" ).withField ("channels" ));
0 commit comments