You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2015/12/05 00:40:41 UTC

[Bug 58692] New: Odd classpath URLs cause Tomcat to abort loading webapps

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.abdine@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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 58692] Odd classpath URLs cause Tomcat to abort loading webapps

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=58692

Mark Thomas <ma...@apache.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |FIXED
             Status|NEW                         |RESOLVED

--- Comment #3 from Mark Thomas <ma...@apache.org> ---
Thanks for the report and the test case. It made investigating this really
simple.

The fix and test case have been applied to 9.0.x and 8.0.x. Just the fix was
applied to 7.0.x due to the refactoring of StandardJarScanner that took place
between 7.0.x and 8.0.x.

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

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


[Bug 58692] Odd classpath URLs cause Tomcat to abort loading webapps

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=58692

--- Comment #2 from Derek Abdine <de...@gmail.com> ---
Just a slight correction: I mentioned in the description

   "There is no way to prevent this issue with a JarScanFilter"

Just to clarify, there is no way to prevent this with the built in
StandardJarScanFilter. As the workaround states, you can subclass and create
your own to do this.

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

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


[Bug 58692] Odd classpath URLs cause Tomcat to abort loading webapps

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=58692

--- Comment #1 from Derek Abdine <de...@gmail.com> ---
Here's the stack trace from the attached test case / unit test:
java.lang.IllegalArgumentException: URI scheme is not "file"
    at java.io.File.<init>(File.java:421)
    at
org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:317)
    at
org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:244)
    at
org.apache.tomcat.util.scan.TestStandardJarScanner.test(TestStandardJarScanner.java:83)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

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

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