Using JavaCompiler in OSGi

I am refactoring a Java application to use OSGi. One of the features of the application is to compile Java on the fly using javax.tools.JavaCompiler . In the original application, this process worked, giving the compiler an existing class path.

 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); String[] options = {"-classpath", System.getProperty("java.class.path")}; DiagnosticListener<JavaFileObject> listener = new DiagnosticListener<JavaFileObject>() {...}; StandardJavaFileManager fileManager = compiler.getStandardFileManager(listener, null, null); Iterable<? extends JavaFileObject> fileObjects = fileManager.getFileObjects(sourceFile); CompilationTask task = compiler.getTask(null, fileManager, listener, Arrays.asList(options), null, fileObjects); task.call(); 

However, this will not work in the OSGi bundle, since the classpath no longer contains the necessary paths. In a refactored version of an OSGi application, the compiler needs access to classes that are in the same package as the above code, as well as classes from other packages. How do I know the compiler about these classes?

I thought of two possible solutions:

  • Provide the compiler with the class loader used by the package containing the above code, since it knows all the necessary classes. However, this does not seem like a viable solution from what I read here and here .
  • Create a class path using the physical locations of installed packages. I looked at org.osgi.framework.Bundle.getLocation() , but I'm not sure if this will be a reliable solution. The paths I return (at least when deployed to Eclipse) are relative, and I'm not sure if they will be safe to use in all platforms and situations.

Is option two above possible? Is there a better solution?

+6
source share
1 answer

I created a working GitHub example.

This is not option 1 or 2; it creates a custom JavaFileManager that scans all packages and retrieves their resources.

What to consider:

  • It uses the JSR 199 compiler API, but only works on the OpenJDK / Sun compiler, the Eclipse JDT compiler looks broken in this regard.
  • I tested only Equinox, I did not use any special code for the equinox, so it should work with other implementations.
  • It is not optimized, so it can be slow and / or hungry.
  • It registers a packet listener, so it will clear the class cache when a package that offers a specific package allows or does not allow
  • I think this is not very deterministic for shared packages.
  • It uses the BundleWiring API, which was introduced in OSGi 4.3, so it will not work with older OSGi OSGi implementations (e.g. Karaf 2.x).

I must mention Technology Excruciation , his example helped me a lot in this.

+3
source

Source: https://habr.com/ru/post/891226/


All Articles