https://bz.apache.org/bugzilla/show_bug.cgi?id=58692
            Bug ID: 58692
           Summary: Odd classpath URLs cause Tomcat to abort loading
                    webapps
           Product: Tomcat 8
           Version: trunk
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Util
          Assignee: dev@tomcat.apache.org
          Reporter: derek.abd...@gmail.com

Created attachment 33326
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=33326&action=edit
Test class for StandardJarScanner

An application was created with Tomcat 8 and Apache Felix both embedded on the
same JVM. Apache felix happens to add a URL to the application classloader's
classpath via it's extension manager, which is used to support bundle
fragment/extension features of the OSGi spec:

https://github.com/apache/felix/blob/ac5ec40ee40ec92dc8124e22afa855ab2c4a850f/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java#L106

When Tomcat is started on the same JVM and a context is created, Tomcat will
attempt to perform a jar scan on the classloader's classpath. It will call
getURLs to enumerate all classpath URLs and peek inside for pluggability
purposes:

https://github.com/apache/tomcat/blob/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java#L221

For each URL enumerated from the classloader Tomcat attempts to transform it
into a ClassPathEntry. For the special URL that Apache Felix adds,
ClassPathEntry's getName method will return the empty string, as there is no
file part in the URL itself:

https://github.com/apache/tomcat/blob/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java#L353

There is no way to prevent this issue with a JarScanFilter, since the check
method called here will use the empty string file name, which can't be matched
using the glob matching algorithm:

https://github.com/apache/tomcat/blob/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java#L237

Eventually this falls through to the process() method through this call:
https://github.com/apache/tomcat/blob/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java#L244

Since the URL "http://felix.extensions:9/"; has a compatible scheme (http) but
no file part (it doesn't match the jar extension) we fall through to the else
condition in the process method, which will attempt to call new File(new
URL("http://felix.extensions:9";)) and fail, because the File(URL) constructor
requires that the URL start with "file:/":

https://github.com/apache/tomcat/blob/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java#L317

This has the effect of bailing out the entire webapp loading.

Steps to reproduce:
I've created a test case which demonstrates the bug. I added this test case to
TestStandardJarScanner to validate against 9.0 TRUNK, though the original bug
was found on tomcat 8x.

For convenience i've attached a copy of the test class with this test case
embedded in it.

    /**
     * Tomcat should ignore URLs which do not have a file part and do not use
the file scheme.
     */
    @Test
    public void skipsInvalidClasspathURLNoFilePartNoFileScheme() {
        StandardJarScanner scanner = new StandardJarScanner();
        LoggingCallback callback = new LoggingCallback();
        TesterServletContext context = new TesterServletContext() {
            @Override
            public ClassLoader getClassLoader() {
                URLClassLoader urlClassLoader;
                try
                {
                    urlClassLoader = new URLClassLoader(new URL[] { new
URL("http://felix.extensions:9/";) });
                }
                catch (MalformedURLException e)
                {
                    throw new RuntimeException(e);
                }
                return urlClassLoader;
            }
        };
        scanner.scan(JarScanType.PLUGGABILITY, context, callback);
    }

WORKAROUNDS:
1. Disable classpath scanning in context.xml. This is a bit cumbersome for war
files which contain their own context.xml as it requires a rebuild of all those
downstream modules.
2. Add a LifecycleListener to hook into context creation events before they are
initialized and set the jar filter to ignore empty string file names (due to
the missing file name part of the class path entry).

-- 
You are receiving this mail because:
You are the assignee for the bug.

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

Reply via email to