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(); } 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