Open vlsi opened 10 months ago
The workaround is to call org.codehaus.commons.compiler.CompilerFactoryFactory.getDefaultCompilerFactory(org.codehaus.janino.CompilerFactory.class.getClassLoader()))
It would CompilerFactoryFactory
initialize with a classloader that contains org.codehaus.commons.compiler.properties
(the one with janino.jar
). The factory is cached in a static field, so subsequent requests get a workable instance.
Hey Vladimir,
I replaced "org.codehaus.commons.compiler.properties" with Java's ServiceLoader
as you proposed. ServiceLoader
is available since Java 1.6, and Janino started with Java 1.2 -- that's why. But today, Janino requires at least Java 1.7, so it was no problem to switch to ServiceLoader
, which is actually 80% identical with Janino's old mechanism.
However, for exactly that reason I'm afraid that the change won't fix your issue - please test!
Ping
It looks like ServiceLoader
does not work with most OSGi implementations: https://github.com/jakartaee/websocket/issues/261
For now, I rely on CompilerFactoryFactory.getDefaultCompilerFactory(CompilerFactory.class.getClassLoader())
workaround.
In any case, it is probably worth adding the following bnd instructions so janino.jar does expose services via OSGi mediators (if mediator is available at all)
<Provide-Capability>osgi.serviceloader;osgi.serviceloader="org.codehaus.commons.compiler.ICompilerFactory"</Provide-Capability>
<Require-Capability>osgi.extender;filter:="(&(osgi.extender=osgi.serviceloader.registrar)(version>=1.0)(!(version>=2.0)))"</Require-Capability>
Hey Vladimir, Where do I put these BND bindings?
--- a/janino/pom.xml
+++ b/janino/pom.xml
@@ -65,6 +65,8 @@
<instructions>
<Export-Package>org.codehaus.janino, org.codehaus.janino.samples, org.codehaus.janino.tools, org.codehaus.janino.util, org.codehaus.janino.util.resource</Export-Package>
<Require-Bundle>org.codehaus.janino.commons-compiler</Require-Bundle>
+ <Provide-Capability>osgi.serviceloader;osgi.serviceloader="org.codehaus.commons.compiler.ICompilerFactory"</Provide-Capability>
+ <Require-Capability>osgi.extender;filter:="(&(osgi.extender=osgi.serviceloader.registrar)(version>=1.0)(!(version>=2.0)))"</Require-Capability>
</instructions>
</configuration>
</plugin>
It adds the relevant headers to the manifest, however, I can't test it. My current use case is Eclipse Equinox (I am maintaining a plugin for Eclise Memory Analyzer), and it turns out Equinox does not have serviceloader mediators.
Ok, I just merged your untested patch, hoping that it doesn't break anybody's code.
Is there really no way you can test it?
I think pax-exam can help with testing. I test pgjdbc as follows: https://github.com/pgjdbc/pgjdbc/tree/master/pgjdbc-osgi-test/src/test
I'm trying to run janino in OSGi environment (Eclipse plugin), and I am facing <<No implementation of org.codehaus.commons.compiler could be loaded. Typically, you'd have "janino.jar", or "commons-compiler-jdk.jar", or both on the classpath, and use the "ClassLoader.getSystemClassLoader" to load them>>
Here's the code that calls
getDefaultCompilerFactory
: https://github.com/apache/calcite/blob/816edd1fa1a1d6af7e72416d791eb01d8c66b6ea/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java#L151-L154Frankly speaking I have no idea why janino uses its own
properties
resource file to select the implementation, however, it looks like Java'sServiceLoader
would do exactly that in a more standard way.ServiceLoader
is supported for Java's Modules, and it is supported by OSGi, so I guess it should be less hassle for everybody if janino usedServiceLoader
.WDYT?
Here's the reproducer: https://github.com/vlsi/mat-calcite-plugin/pull/31