[
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: [email protected]
For additional commands, e-mail: [email protected]