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

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new ee79bd778e Fix BZ 55470 - Add class path logging to help debug CNFE
ee79bd778e is described below

commit ee79bd778e82bc3e4e4b17c955160ad0f428a7b7
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Nov 6 10:07:15 2024 +0000

    Fix BZ 55470 - Add class path logging to help debug CNFE
    
    https://bz.apache.org/bugzilla/show_bug.cgi?id=55470
    Based on a patch by Ralf Hauser
---
 .../catalina/loader/WebappClassLoaderBase.java     |   4 +
 .../apache/tomcat/util/buf/LocalStrings.properties |   5 +
 java/org/apache/tomcat/util/buf/ToStringUtil.java  | 101 +++++++++++++++++++++
 java/org/apache/tomcat/util/digester/Digester.java |   7 ++
 4 files changed, 117 insertions(+)

diff --git a/java/org/apache/catalina/loader/WebappClassLoaderBase.java 
b/java/org/apache/catalina/loader/WebappClassLoaderBase.java
index 51548b71b7..d224e473f8 100644
--- a/java/org/apache/catalina/loader/WebappClassLoaderBase.java
+++ b/java/org/apache/catalina/loader/WebappClassLoaderBase.java
@@ -67,6 +67,7 @@ import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.InstrumentableClassLoader;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.IntrospectionUtils;
+import org.apache.tomcat.util.buf.ToStringUtil;
 import org.apache.tomcat.util.collections.ConcurrentLruCache;
 import org.apache.tomcat.util.compat.JreCompat;
 import org.apache.tomcat.util.res.StringManager;
@@ -1160,6 +1161,9 @@ public abstract class WebappClassLoaderBase extends 
URLClassLoader
             }
         }
 
+        if (log.isDebugEnabled()) {
+            log.debug(ToStringUtil.classPathForCNFE(this));
+        }
         throw new ClassNotFoundException(name);
     }
 
diff --git a/java/org/apache/tomcat/util/buf/LocalStrings.properties 
b/java/org/apache/tomcat/util/buf/LocalStrings.properties
index 63e2eb38a2..ce64e0df22 100644
--- a/java/org/apache/tomcat/util/buf/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/buf/LocalStrings.properties
@@ -33,6 +33,11 @@ hexUtils.fromHex.oddDigits=The input must consist of an even 
number of hex digit
 stringCache.byteTime=ByteCache generation time: {0}ms
 stringCache.charTime=CharCache generation time: {0}ms
 
+toStringUtil.classpath.classloader=ClassLoader [{0}] loading classes from:
+toStringUtil.classpath.header=Logging class path for each class loader in 
hierarchy to aid debugging of ClassNotFoundException
+toStringUtil.classpath.platform=JRE provided classes
+toStringUtil.classpath.unknown=Unknown - not an instance of URLClassLoader
+
 uDecoder.eof=End of file (EOF)
 uDecoder.isHexDigit=The hexadecimal encoding is invalid
 uDecoder.noSlash=The encoded slash character is not allowed
diff --git a/java/org/apache/tomcat/util/buf/ToStringUtil.java 
b/java/org/apache/tomcat/util/buf/ToStringUtil.java
new file mode 100644
index 0000000000..1d562d6f6d
--- /dev/null
+++ b/java/org/apache/tomcat/util/buf/ToStringUtil.java
@@ -0,0 +1,101 @@
+/*
+ * 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.tomcat.util.buf;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * Utility class used to provide String representations of objects. It is 
typically used in debug logging.
+ */
+public class ToStringUtil {
+
+    private static final StringManager sm = 
StringManager.getManager(ToStringUtil.class);
+
+    private static final String INDENT = "    ";
+
+
+    private ToStringUtil() {
+        // Utility class. Hide default constructor.
+    }
+
+
+    /**
+     * Generate a String representation of the class path for the given class 
loader and any parent class loaders to aid
+     * debugging of {@link ClassNotFoundException}.
+     *
+     * @param classLoader The class loader to analyse
+     *
+     * @return A String representation of the class path. The format is 
undefined and may change in future point
+     *             releases. The output includes new lines.
+     */
+    public static String classPathForCNFE(ClassLoader classLoader) {
+        // The result is expected to be fairly large
+        StringBuilder result = new StringBuilder(4096);
+        result.append(sm.getString("toStringUtil.classpath.header"));
+        result.append("\n");
+        while (classLoader != null) {
+            classPathForCNFE(classLoader, result);
+            classLoader = classLoader.getParent();
+        }
+        return result.toString();
+    }
+
+
+    private static void classPathForCNFE(ClassLoader classLoader, 
StringBuilder result) {
+        result.append(INDENT);
+        result.append(sm.getString("toStringUtil.classpath.classloader", 
classLoader));
+        result.append("\n");
+        if (classLoader instanceof URLClassLoader) {
+            URL[] urls = ((URLClassLoader) classLoader).getURLs();
+            for (URL url : urls) {
+                result.append(INDENT);
+                result.append(INDENT);
+                result.append(url);
+                result.append("\n");
+            }
+        } else if (classLoader == ClassLoader.getSystemClassLoader()) {
+            // From Java 9 the internal class loaders no longer extend
+            // URLCLassLoader
+            String cp = System.getProperty("java.class.path");
+            if (cp != null && cp.length() > 0) {
+                String[] paths = cp.split(File.pathSeparator);
+                for (String path : paths) {
+                    result.append(INDENT);
+                    result.append(INDENT);
+                    result.append(path);
+                    result.append("\n");
+                }
+            }
+        } else if (classLoader == ClassLoader.getPlatformClassLoader()) {
+            // From Java 9 the internal class loaders no longer extend
+            // URLCLassLoader
+            result.append(INDENT);
+            result.append(INDENT);
+            result.append(sm.getString("toStringUtil.classpath.platform"));
+            result.append("\n");
+        } else {
+            result.append(INDENT);
+            result.append(INDENT);
+            result.append(sm.getString("toStringUtil.classpath.unknown"));
+            result.append("\n");
+        }
+    }
+}
diff --git a/java/org/apache/tomcat/util/digester/Digester.java 
b/java/org/apache/tomcat/util/digester/Digester.java
index e7615ac7f0..ca64050436 100644
--- a/java/org/apache/tomcat/util/digester/Digester.java
+++ b/java/org/apache/tomcat/util/digester/Digester.java
@@ -44,6 +44,7 @@ import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.IntrospectionUtils;
 import org.apache.tomcat.util.IntrospectionUtils.PropertySource;
 import org.apache.tomcat.util.buf.B2CConverter;
+import org.apache.tomcat.util.buf.ToStringUtil;
 import org.apache.tomcat.util.res.StringManager;
 import org.xml.sax.Attributes;
 import org.xml.sax.EntityResolver;
@@ -1262,6 +1263,12 @@ public class Digester extends DefaultHandler2 {
                         log.trace("  Fire begin() for " + rule);
                     }
                     rule.begin(namespaceURI, name, list);
+                } catch (ClassNotFoundException cnfe) {
+                    log.error(sm.getString("digester.error.begin"), cnfe);
+                    if (log.isDebugEnabled()) {
+                        
log.debug(ToStringUtil.classPathForCNFE(getClassLoader()));
+                    }
+                    throw createSAXException(cnfe);
                 } catch (Exception e) {
                     log.error(sm.getString("digester.error.begin"), e);
                     throw createSAXException(e);


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to