Bug 56016

Summary: DigesterFactory.idFor(...) assumes that javax.servlet.jsp.resources.** are available from the same class loader that defines javax.servlet.ServletContext
Product: Tomcat 6 Reporter: Dmitri Bourlatchkov <dmitri.bourlatchkov>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: unspecified   
Target Milestone: default   
Hardware: All   
OS: All   
Attachments: Patch for DigesterFactory.ifFor(...) method to relax assumptions related to class loading

Description Dmitri Bourlatchkov 2014-01-15 23:51:30 UTC
Created attachment 31214 [details]
Patch for DigesterFactory.ifFor(...) method to relax assumptions related to class loading

The idFor(String url) method in org.apache.tomcat.util.descriptor.DigesterFactory appears to try loading resources from the javax.servlet.jsp.resources package using the defining class loader of javax.servlet.ServletContext.

This is perfectly fine for standalone Tomcat, of course. However, in our application we run embedded Tomcat in an isolated class loader, which includes all of Tomcat's jar files _except_ servlet-api.jar. servlet-api.jar is part of the class loader that is a  parent of the class loader for the embedded Tomcat.

Tomcat 7.0.47 worked well in this setup. However in 7.0.50 we hit exceptions like the following:

java.lang.ExceptionInInitializerError
    at org.apache.catalina.startup.TldConfig.createTldDigester(TldConfig.java:94)
    at org.apache.catalina.startup.TldConfig.init(TldConfig.java:576)
    at org.apache.catalina.startup.TldConfig.lifecycleEvent(TldConfig.java:559)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:402)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:133)
    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:156)
    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:145)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:875)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:634)
    [...]
Caused by: java.lang.NullPointerException
    at org.apache.tomcat.util.descriptor.DigesterFactory.idFor(DigesterFactory.java:107)
    at org.apache.tomcat.util.descriptor.DigesterFactory.<clinit>(DigesterFactory.java:59)
    ... 25 more 

The reason why the resource is not found is apparently that the class loader of ServletContext does not 'see' resources from jsp-api.jar.

We can work around that by placing jsp-api.jar into the same class loader that has servlet-api.jar, however this workaround is not ideal from our design perspective.

From the source of the idFor(...) method one could guess that the fallback attempt to find the requested resource in the javax.servlet.jsp.resources package is meant to look in jsp-api.jar. For that reason, would it be appropriate to perform the fallback lookup in the defining class loader of javax.servlet.jsp.JspContext? A patch file for the proposed fix is attached. If it is accepted please credit Juan Carlos Estibariz with it.
Comment 1 Dmitri Bourlatchkov 2014-01-16 00:01:46 UTC
The affected url parameter for the idFor(...) method in this case is "web-jsptaglibrary_1_1.dtd"
Comment 2 Mark Thomas 2014-01-16 19:49:45 UTC
Thsi doe snot affect 8.0.x where all the referenced resources have been moved to the servlet-api.jar

This has been fixed in 7.0.x for 7.0.51 onwards.

This has been proposed for 6.0.x.
Comment 3 Mark Thomas 2014-01-17 15:46:14 UTC
This has been fixed in 6.0.x for 6.0.38 onwards.