Dawid Weiss created LOG4J2-1484:
-----------------------------------

             Summary: 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 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.







--
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