[ 
https://issues.apache.org/jira/browse/LOG4J2-1484?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Dawid Weiss updated LOG4J2-1484:
--------------------------------
    Description: 
The configuration permits "by-package" plugin lookup mechanism, for example:
{code}
<Configuration packages="foo.bar,foo.baz">
{code}

I've encountered a problem where my application was picking up the plugins just 
fine before JAR postprocessing, but wouldn't find them afterwards, so I spent a 
few hours looking for the problem.

Turns out the problem (in my case) was twofold. The first issue is inside 
log4j2's plugin lookup mechanism, the other was a consequence of the first one.

1. ResolverUtil.findInPackage uses undocumented side effects of 
ClassLoader.getResource

Namely, this part:
{code}
    public void findInPackage(final Test test, String packageName) {
        packageName = packageName.replace('.', '/');
        final ClassLoader loader = getClassLoader();
        Enumeration<URL> urls;

        try {
            urls = loader.getResources(packageName);
        } catch (final IOException ioe) {
            LOGGER.warn("Could not read package: " + packageName, ioe);
            return;
        }
{code}

ClassLoader's getResources method is only specified to work for actual 
resources, not for folders (or directories). That it works for packages now (at 
least in URLClassLoader) is merely a side-effect (and implementation detail) as 
class loaders are not obliged to enumerate packages (or resources within) and 
in fact they don't permit it from Java 9 on.

I believe there is no sensible "fix" for this behavior; one could try to lookup 
{{META-INF/MANIFEST.MF}} to locate JAR files but this is also not guaranteed to 
exist, so it'd be hacking a hack...

The best fix would be to require explicit names of the plugins/ resources that 
must be located and loaded, then the code would use the typical 
{{Class.forName(ClassLoader)}} idiom and delegate the actual lookup to Java.

2. The way to demonstrate that the above is a real problem is to create a 
perfectly legitimate JAR file that contains no ZIP dictionary entries for 
"directories" (inside the ZIP archive), only entries for the zipped classes. 
This is a valid JAR file, works with the JVM/ JDK just fine (because classes 
are looked up as exactly-named resources), but the above package-lookup 
mechanism won't work because the ZIP file contains no entries for "directories" 
to which packages are converted by the code.





  was:
The configuration permits "by-package" plugin lookup mechanism, for example:
{code}
<Configuration packages="foo.bar,foo.baz">
{code}

I've encountered a problem where my application was picking up the plugins just 
fine before JAR postprocessing, but wouldn't find them afterwards, so I spent a 
few hours looking for the problem.

Turns out the problem (in my case) was twofold. The first issue is inside 
log4j2's plugin lookup mechanism, the other was a consequence of the first one.

1. ResolverUtil.findInPackage uses undocumented side effects of 
ClassLoader.getResource

Namely, this part:
{code}
    public void findInPackage(final Test test, String packageName) {
        packageName = packageName.replace('.', '/');
        final ClassLoader loader = getClassLoader();
        Enumeration<URL> urls;

        try {
            urls = loader.getResources(packageName);
        } catch (final IOException ioe) {
            LOGGER.warn("Could not read package: " + packageName, ioe);
            return;
        }
{code}

ClassLoader's getResources method is only specified to work for actual 
resources, not for folders (or directories). That it works for packages now (at 
least in URLClassLoader) is merely a side-effect (and implementation detail) as 
class loaders are not obliged to enumerate packages (or resources within) and 
in fact they don't permit it from Java 9 on.

I believe there is no sensible "fix" for this behavior; one could try to lookup 
{{META-INF/MANIFEST.MF}} to locate JAR files but this is also not guaranteed to 
exist, so it'd be hacking a hack...

The best fix would be to require explicit names of the plugins/ resources that 
must be located and loaded, then the code would use the typical 
{{Class.forName(ClassLoader)}} idiom and delegate the actual lookup to Java.

2. The way to demonstrate that the above is a real problem is to create a 
perfectly legitimate JAR file that contains no entries (inside the ZIP archive 
directory). This is a valid JAR file, works with the JVM/ JDK just fine 
(because classes are looked up as exactly-named resources), but the above 
package-lookup mechanism won't work because the ZIP file contains no entries 
for "directories" to which packages are converted by the code.






> Plugin lookup via packages attribute is broken (because of the lookup method 
> used)
> ----------------------------------------------------------------------------------
>
>                 Key: LOG4J2-1484
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-1484
>             Project: Log4j 2
>          Issue Type: Bug
>    Affects Versions: 2.6.2
>            Reporter: Dawid Weiss
>
> The configuration permits "by-package" plugin lookup mechanism, for example:
> {code}
> <Configuration packages="foo.bar,foo.baz">
> {code}
> I've encountered a problem where my application was picking up the plugins 
> just fine before JAR postprocessing, but wouldn't find them afterwards, so I 
> spent a few hours looking for the problem.
> Turns out the problem (in my case) was twofold. The first issue is inside 
> log4j2's plugin lookup mechanism, the other was a consequence of the first 
> one.
> 1. ResolverUtil.findInPackage uses undocumented side effects of 
> ClassLoader.getResource
> Namely, this part:
> {code}
>     public void findInPackage(final Test test, String packageName) {
>         packageName = packageName.replace('.', '/');
>         final ClassLoader loader = getClassLoader();
>         Enumeration<URL> urls;
>         try {
>             urls = loader.getResources(packageName);
>         } catch (final IOException ioe) {
>             LOGGER.warn("Could not read package: " + packageName, ioe);
>             return;
>         }
> {code}
> ClassLoader's getResources method is only specified to work for actual 
> resources, not for folders (or directories). That it works for packages now 
> (at least in URLClassLoader) is merely a side-effect (and implementation 
> detail) as class loaders are not obliged to enumerate packages (or resources 
> within) and in fact they don't permit it from Java 9 on.
> I believe there is no sensible "fix" for this behavior; one could try to 
> lookup {{META-INF/MANIFEST.MF}} to locate JAR files but this is also not 
> guaranteed to exist, so it'd be hacking a hack...
> The best fix would be to require explicit names of the plugins/ resources 
> that must be located and loaded, then the code would use the typical 
> {{Class.forName(ClassLoader)}} idiom and delegate the actual lookup to Java.
> 2. The way to demonstrate that the above is a real problem is to create a 
> perfectly legitimate JAR file that contains no ZIP dictionary entries for 
> "directories" (inside the ZIP archive), only entries for the zipped classes. 
> This is a valid JAR file, works with the JVM/ JDK just fine (because classes 
> are looked up as exactly-named resources), but the above package-lookup 
> mechanism won't work because the ZIP file contains no entries for 
> "directories" to which packages are converted by the code.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to