2016-05-03 17:56 GMT+03:00 Konstantin Kolinko <knst.koli...@gmail.com>: > > 2016-05-03 17:07 GMT+03:00 Violeta Georgieva <miles...@gmail.com>: > > Hi, > > > > 2016-04-27 14:27 GMT+03:00 Konstantin Kolinko <knst.koli...@gmail.com>: > >> > >> 2016-04-27 14:00 GMT+03:00 Violeta Georgieva <miles...@gmail.com>: > >> > Hi, > >> > > >> > I have a question about difference in the behaviour of > >> > org.apache.catalina.loader.WebappClassLoaderBase.getResource(String). > >> > I'm investigating the issue reported here [1]. > >> > > >> > In Tomcat 8+ when WebappClassLoaderBase.getResource is invoked with a > > path > >> > that represents a jar resource and starts with a slash > >> > (classpath:/schema/shibboleth-2.0-services.xsd) this resource will be > >> > served. > >> > In > >> > > > org.apache.catalina.webresources.AbstractArchiveResourceSet.getResource(String) > >> > it is clearly stated that when the path starts with a slash then this > >> > leading slash will be removed. > >> > > >> > In Tomcat 7 WebappClassLoaderBase.getResource, such resource will not be > >> > found. If I remove the leading slash everything is OK. > >> > > >> > Is that difference intentional or I can apply a change for removing the > >> > leading slash in Tomcat 7 WebappClassLoaderBase? > >> > > >> > Thanks a lot, > >> > Violeta > >> > > >> > [1] http://marc.info/?t=146170035100001&r=1&w=2 > >> > >> > >> 1.) webresources API is a one thing. It should perform consistently > >> across all webresource implementation. > >> > >> (IIRC in Tomcat 7 JNDI resources API was too forgiving of leading > >> slashes, leading to some inconsistencies such as duplicate entries in > >> resource cache. I think that that has already been fixed in TC7 by > >> doing normalization before looking up into file system & caching. A > >> discussion was ~2 years ago) > >> > >> 2.) webresources API is also used by Servet API calls. Here we have > >> org.apache.catalina.core.ApplicationContext GET_RESOURCE_REQUIRE_SLASH > >> > >> > > http://tomcat.apache.org/tomcat-7.0-doc/config/systemprops.html#Specification > >> > > http://tomcat.apache.org/tomcat-8.0-doc/config/systemprops.html#Specification > >> > >> 3.) WebappClassLoader.getResource() shall be consistent with Java API > >> of java.lang.ClassLoader.getResource() > >> > >> > > http://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html#getResource-java.lang.String- > >> > >> It just says: > >> [q] > >> The name of a resource is a '/'-separated path name that identifies > >> the resource. > >> [/q] > >> > >> Unfortunately, this is unclear about leading slashes. (Maybe some > >> experimenting with classloaders provided by JRE, or reading the Java > >> Lang Spec clarifies this.) This likely was also discussed 2-3 years > >> ago. > >> > >> 4. Beware of similar-named method Class.getResource() > >> > >> > > http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getResource%28java.lang.String%29 > >> > >> This method differentiates names starting with '/' or without it as > >> absolute vs relative resource names. > >> > >> [q] > >> If the name begins with a '/' ('\u002f'), then the absolute name of > >> the resource is the portion of the name following the '/'. > >> [/q] > >> > >> I think that the above fragment hints that the resource name in > >> ClassLoader,getResource() should not start with '/'. > >> > >> > >> I think that changing WebappClassLoader.getResource() to accept > >> resource names starting with '/' might be wrong. > >> > > > > Thanks for the input. I'll take it into account. > > > > However the problem is not a generic one but related to resources placed > > into jar files. > > With the current implementation: > > > > org.apache.catalina.loader.WebappClassLoaderBase.findResourceInternal(String, > > String, boolean) > > > > row 3309 synchronized (jarFiles) { > > row 3310 > > row 3311 try { > > row 3312 if (!openJARs()) { > > row 3313 return null; > > row 3314 } > > row 3315 for (i = 0; (entry == null) && (i < > > jarFilesLength); i++) { > > row 3316 > > row 3317 jarEntry = jarFiles[i].getJarEntry(path); > > ......... > > > > The entry will never be found if it starts with "/" because of the > > implementation of java.util.jar.JarFile.getJarEntry(String) > > > Simple test: > > [[[ > public class Sample { > public static void main(String[] args) { > > ClassLoader cld = System.class.getClassLoader(); > > if (cld == null) { > System.out.println("Using System classloader"); > cld = ClassLoader.getSystemClassLoader(); > }
And here is the difference between ClassLoader and URLClassLoader If you construct URLClassLoader with rt.jar then both statements below will return the needed resource. > testGetResource(cld, "java/lang/System.class"); > testGetResource(cld, "/java/lang/System.class"); > } > > private static void testGetResource(ClassLoader cld, String resourceName) { > System.out.println("getResource(" + resourceName + "): " + > cld.getResource(resourceName)); > } > } > ]]] > > Running the class with JDK 8u92 produces the following: (I replaced > JDK path in the message) > > [[[ > Using System classloader > getResource(java/lang/System.class): jar:file:/<JDK HOME > (jdk1.8.0_92)>/jre/lib/rt.jar! > /java/lang/System.class > getResource(/java/lang/System.class): null > ]]] > > Thus the expected behaviour is that calling ClassLoader,getResource() > with a path that starts with "/" results in non finding the resource > (the method returning "null"). > > Best regards, > Konstantin Kolinko > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail: dev-h...@tomcat.apache.org >