This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit dbfe9dea370f5f4280c38fd8b3be9254cab04197
Author: opencode <[email protected]>
AuthorDate: Tue Oct 20 13:55:02 2026 +0200

    Return null from ResourceLinkFactory when the global naming context is 
unavailable
    
    ResourceLinkFactory.getObjectInstance() threw a null pointer exception
    when a resource link had been registered while the static global naming
    context had not yet been set, which can happen with embedded start-up
    ordering because registerGlobalResourceAccess() accepts a null global
    context.
    
    Replace the NPE with the standard "cannot resolve" behaviour: log a
    warning naming the global resource and return null, which results in the
    usual namingContext.failResolvingReference NamingException at the lookup
    site. Add a regression test that reproduces the original NPE with the
    global context set to null.
---
 .../apache/naming/factory/LocalStrings.properties  |  1 +
 .../apache/naming/factory/ResourceLinkFactory.java | 13 +++++-
 .../naming/factory/TestResourceLinkFactory.java    | 54 ++++++++++++++++++++++
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/naming/factory/LocalStrings.properties 
b/java/org/apache/naming/factory/LocalStrings.properties
index a9c5074c0e..b46da5b2b8 100644
--- a/java/org/apache/naming/factory/LocalStrings.properties
+++ b/java/org/apache/naming/factory/LocalStrings.properties
@@ -38,6 +38,7 @@ lookupFactory.typeMismatch=The JNDI reference [{0}] was 
expected to be of type [
 resourceFactory.factoryCreationError=Could not create resource factory instance
 
 resourceLinkFactory.invalidGlobalContext=Caller provided invalid global context
+resourceLinkFactory.noGlobalContext=The global naming context is not 
available. The local resource link that refers to global resource [{0}] can not 
be resolved
 resourceLinkFactory.nullName=The local resource link [{0}] that refers to 
global resource [{1}] does not specify the required name or global attribute
 resourceLinkFactory.nullType=The local resource link [{0}] that refers to 
global resource [{1}] does not specify the required attribute type
 resourceLinkFactory.unknownType=The local resource link [{0}] that refers to 
global resource [{1}] specified the unknown type [{2}]
diff --git a/java/org/apache/naming/factory/ResourceLinkFactory.java 
b/java/org/apache/naming/factory/ResourceLinkFactory.java
index 40f8ad4e57..4a959fcc27 100644
--- a/java/org/apache/naming/factory/ResourceLinkFactory.java
+++ b/java/org/apache/naming/factory/ResourceLinkFactory.java
@@ -26,6 +26,8 @@ import javax.naming.NamingException;
 import javax.naming.RefAddr;
 import javax.naming.spi.ObjectFactory;
 
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
 import org.apache.naming.ResourceLinkRef;
 import org.apache.naming.StringManager;
 
@@ -48,6 +50,8 @@ public class ResourceLinkFactory implements ObjectFactory {
      */
     protected static final StringManager sm = 
StringManager.getManager(ResourceLinkFactory.class);
 
+    private static final Log log = 
LogFactory.getLog(ResourceLinkFactory.class);
+
     /**
      * Global naming context.
      */
@@ -148,7 +152,7 @@ public class ResourceLinkFactory implements ObjectFactory {
      * @param nameCtx     unused
      * @param environment unused
      *
-     * @return the object instance
+     * @return the object instance or {@code null} if the reference cannot be 
resolved
      *
      * @throws IllegalArgumentException if the type of the reference is 
missing or does not match the type of the
      *                                  global resource
@@ -174,6 +178,13 @@ public class ResourceLinkFactory implements ObjectFactory {
             if (!validateGlobalResourceAccess(globalName)) {
                 return null;
             }
+            // The global context may be missing if the web application was
+            // registered before the server created its naming context, which
+            // can happen with embedded start-up ordering
+            if (globalContext == null) {
+                log.warn(sm.getString("resourceLinkFactory.noGlobalContext", 
globalName));
+                return null;
+            }
             Object result = globalContext.lookup(globalName);
             if (result == null) {
                 return null;
diff --git a/test/org/apache/naming/factory/TestResourceLinkFactory.java 
b/test/org/apache/naming/factory/TestResourceLinkFactory.java
new file mode 100644
index 0000000000..8ef35d7ca7
--- /dev/null
+++ b/test/org/apache/naming/factory/TestResourceLinkFactory.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.naming.factory;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.naming.ResourceLinkRef;
+
+public class TestResourceLinkFactory {
+
+    /*
+     * Regression test for the case where a resource link has been registered
+     * before the global context has been set, e.g. when an embedded Tomcat
+     * initialises the container before the naming context for the server is
+     * created. Prior to the fix, this resulted in a null pointer exception.
+     */
+    @Test
+    public void testGetResourceLinkWithoutGlobalContext() throws Exception {
+        // Arrange: no global context is available and the link is registered
+        ResourceLinkFactory.setGlobalContext(null);
+        ResourceLinkFactory.registerGlobalResourceAccess(null, "link", 
"global");
+        ResourceLinkRef ref = new ResourceLinkRef("type", "global", null, 
null);
+        ResourceLinkFactory factory = new ResourceLinkFactory();
+        // Act
+        Object result = factory.getObjectInstance(ref, null, null, null);
+        // Assert
+        // Since the global context is not available, the link can not be
+        // resolved
+        Assert.assertNull(result);
+    }
+
+    @After
+    public void tearDown() {
+        // Remove the registration made by the test so that other tests in the
+        // same JVM are not affected by it
+        ResourceLinkFactory.deregisterGlobalResourceAccess(null, "link");
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to