tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Konstantin Kolinko <knst.koli...@gmail.com>
Subject Re: Difference in the behaviour of WebappClassLoaderBase.getResource for jar resources
Date Tue, 03 May 2016 14:56:39 GMT
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();
    }

    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
View raw message