3232import io .undertow .server .handlers .GracefulShutdownHandler ;
3333import org .apache .commons .logging .Log ;
3434import org .apache .commons .logging .LogFactory ;
35+ import org .jspecify .annotations .Nullable ;
3536import org .xnio .channels .BoundChannel ;
3637
3738import org .springframework .aot .hint .RuntimeHints ;
@@ -61,7 +62,7 @@ public class UndertowWebServer implements WebServer {
6162
6263 private static final Log logger = LogFactory .getLog (UndertowWebServer .class );
6364
64- private final AtomicReference <GracefulShutdownCallback > gracefulShutdownCallback = new AtomicReference <>();
65+ private final AtomicReference <@ Nullable GracefulShutdownCallback > gracefulShutdownCallback = new AtomicReference <>();
6566
6667 private final Object monitor = new Object ();
6768
@@ -71,13 +72,13 @@ public class UndertowWebServer implements WebServer {
7172
7273 private final boolean autoStart ;
7374
74- private Undertow undertow ;
75+ private @ Nullable Undertow undertow ;
7576
7677 private volatile boolean started = false ;
7778
78- private volatile GracefulShutdownHandler gracefulShutdown ;
79+ private volatile @ Nullable GracefulShutdownHandler gracefulShutdown ;
7980
80- private volatile List <Closeable > closeables ;
81+ private volatile @ Nullable List <Closeable > closeables ;
8182
8283 /**
8384 * Create a new {@link UndertowWebServer} instance.
@@ -142,6 +143,7 @@ private void destroySilently() {
142143 try {
143144 if (this .undertow != null ) {
144145 this .undertow .stop ();
146+ Assert .state (this .closeables != null , "'closeables' must not be null" );
145147 this .closeables .forEach (this ::closeSilently );
146148 }
147149 }
@@ -167,11 +169,12 @@ private Undertow createUndertowServer() {
167169 return this .builder .build ();
168170 }
169171
170- protected HttpHandler createHttpHandler () {
172+ protected @ Nullable HttpHandler createHttpHandler () {
171173 HttpHandler handler = null ;
172174 for (HttpHandlerFactory factory : this .httpHandlerFactories ) {
173175 handler = factory .getHandler (handler );
174176 if (handler instanceof Closeable closeable ) {
177+ Assert .state (this .closeables != null , "'closeables' must not be null" );
175178 this .closeables .add (closeable );
176179 }
177180 if (handler instanceof GracefulShutdownHandler shutdownHandler ) {
@@ -220,11 +223,14 @@ private List<Port> getActualPorts() {
220223 @ SuppressWarnings ("unchecked" )
221224 private List <BoundChannel > extractChannels () {
222225 Field channelsField = ReflectionUtils .findField (Undertow .class , "channels" );
226+ Assert .state (channelsField != null , "'channelsField' must not be null" );
223227 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 ;
225231 }
226232
227- private UndertowWebServer .Port getPortFromChannel (BoundChannel channel ) {
233+ private UndertowWebServer .@ Nullable Port getPortFromChannel (BoundChannel channel ) {
228234 SocketAddress socketAddress = channel .getLocalAddress ();
229235 if (socketAddress instanceof InetSocketAddress inetSocketAddress ) {
230236 Field sslField = ReflectionUtils .findField (channel .getClass (), "ssl" );
@@ -253,20 +259,37 @@ private List<UndertowWebServer.Port> getConfiguredPorts() {
253259 @ SuppressWarnings ("unchecked" )
254260 private List <Object > extractListeners () {
255261 Field listenersField = ReflectionUtils .findField (Undertow .class , "listeners" );
262+ Assert .state (listenersField != null , "'listenersField' must not be null" );
256263 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 ;
258267 }
259268
260269 private UndertowWebServer .Port getPortFromListener (Object listener ) {
261270 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 );
264273 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 );
267276 return new UndertowWebServer .Port (port , protocol );
268277 }
269278
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+
270293 @ Override
271294 public void stop () throws WebServerException {
272295 synchronized (this .monitor ) {
@@ -278,9 +301,12 @@ public void stop() throws WebServerException {
278301 notifyGracefulCallback (false );
279302 }
280303 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+ }
284310 }
285311 }
286312 catch (Exception ex ) {
@@ -304,7 +330,7 @@ public int getPort() {
304330 * @return the Undertow server or {@code null} if the server hasn't been started yet
305331 * @since 4.0.0
306332 */
307- public Undertow getUndertow () {
333+ public @ Nullable Undertow getUndertow () {
308334 return this .undertow ;
309335 }
310336
@@ -396,27 +422,30 @@ public String toString() {
396422 */
397423 private static final class CloseableHttpHandlerFactory implements HttpHandlerFactory {
398424
399- private final Closeable closeable ;
425+ private final @ Nullable Closeable closeable ;
400426
401- private CloseableHttpHandlerFactory (Closeable closeable ) {
427+ private CloseableHttpHandlerFactory (@ Nullable Closeable closeable ) {
402428 this .closeable = closeable ;
403429 }
404430
405431 @ 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 ) {
408435 return next ;
409436 }
410437 return new CloseableHttpHandler () {
411438
412439 @ Override
413440 public void handleRequest (HttpServerExchange exchange ) throws Exception {
414- next .handleRequest (exchange );
441+ if (next != null ) {
442+ next .handleRequest (exchange );
443+ }
415444 }
416445
417446 @ Override
418447 public void close () throws IOException {
419- CloseableHttpHandlerFactory . this . closeable .close ();
448+ closeable .close ();
420449 }
421450
422451 };
@@ -438,7 +467,7 @@ private interface CloseableHttpHandler extends HttpHandler, Closeable {
438467 static class UndertowWebServerRuntimeHints implements RuntimeHintsRegistrar {
439468
440469 @ Override
441- public void registerHints (RuntimeHints hints , ClassLoader classLoader ) {
470+ public void registerHints (RuntimeHints hints , @ Nullable ClassLoader classLoader ) {
442471 hints .reflection ()
443472 .registerTypeIfPresent (classLoader , "io.undertow.Undertow" ,
444473 (hint ) -> hint .withField ("listeners" ).withField ("channels" ));
0 commit comments