On 5/9/2017 5:20 PM, Ralph Goers wrote:
Log4j already has a robust plugin approach for users to implement
their own Appenders, Filters, Layouts, and other Log4j components. We
are not going to modify that as it would severely impact our users
who have already implemented custom components and what we have works
very well. Although the FlumeAppender I mentioned previously is
provided by Log4j it, and all other Log4j components, are located via
an annotation processor provided by Log4j. The processor runs at
compile time and generates a file named
META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat.
All of these files are then located at runtime using
ClassLoader.getResources(). As we parse the configuration provided by
the user we instantiate the plugins using the class names provided in
those files and the static builder or static factory method provided
in the plugin class. From what I am reading in the javadoc we should
not have any trouble with this because META-INF is not a valid
package name so the resource file will not be hidden. Log4j uses
reflection to call the static builder or static method to create the
plugin.

With all this in mind, if users create modules will they be required
to declare the packages where they have created plugins as “open” to
log4j for this to work? I am assuming that Log4j will be able to
access this module without having to declare a dependency on it?

Basically you've got it.

- The Log4j module does not need to 'requires' any user module, nor invoke addReads to "read" any user module.

- Log4j code can continue to invoke Class::forName to obtain a Class object for a class in a user module. This is based purely on class loader visibility, no changes from the module system.

- Log4j code can continue to invoke Class::getMethod et al to obtain a Method object for a static builder/factory method. There are no access control rules when simply "inspecting" the Class object via getMethod, getMethods, getFields, etc.

- Log4j code can attempt to invoke Method::invoke on its preferred Method object, but for the attempt to succeed, the user module must open or export the class's package. If you mandate that a plugin class must be public with a public builder/factory method, then exporting the package will be enough; otherwise the package needs to be open.

- I recommend that you recommend that users should open the package to specifically Log4j, rather than opening the package to everyone (or opening the entire module). You said that your JARs will probably be automatic modules for some time, so you can use the Automatic-Module-name manifest entry to introduce a stable name that user modules can open to.

Alex

Reply via email to