tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Violeta Georgieva <miles...@gmail.com>
Subject Re: Difference in the behaviour of WebappClassLoaderBase.getResource for jar resources
Date Tue, 03 May 2016 15:20:20 GMT
2016-05-03 17:56 GMT+03:00 Konstantin Kolinko <knst.kolinko@gmail.com>:
>
> 2016-05-03 17:07 GMT+03:00 Violeta Georgieva <milesg78@gmail.com>:
> > Hi,
> >
> > 2016-04-27 14:27 GMT+03:00 Konstantin Kolinko <knst.kolinko@gmail.com>:
> >>
> >> 2016-04-27 14:00 GMT+03:00 Violeta Georgieva <milesg78@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-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message