Использование JavaCompiler в OSGi Bundle - PullRequest
6 голосов
/ 23 июня 2011

Я в процессе рефакторинга приложения Java для использования OSGi. Одной из особенностей приложения является компиляция Java на лету с использованием javax.tools.JavaCompiler. В исходном приложении этот процесс работал, передавая компилятору существующий путь к классу, вот так.

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();

Однако, это не будет работать в пакете OSGi, так как путь к классу больше не содержит необходимые пути. В переработанной версии приложения для OSGi компилятору требуется доступ к классам, которые находятся в том же пакете, что и приведенный выше код, а также к классам из других пакетов. Как заставить компилятор знать об этих классах?

Я подумал о двух возможных решениях:

  1. Дайте компилятору загрузчик классов, используемый пакетом, содержащим приведенный выше код, поскольку он знает обо всех необходимых классах. Однако это не похоже на жизнеспособное решение из того, что я прочитал здесь и здесь .
  2. Создайте путь к классам, используя физические местоположения установленных пакетов. Я посмотрел на org.osgi.framework.Bundle.getLocation(), но я не уверен, что это будет надежным решением. Пути, которые я получаю (по крайней мере, при развертывании в Eclipse), относительны, и я не уверен, будет ли их безопасно использовать на всех платформах и в любых ситуациях.

Возможен ли второй вариант? Есть ли лучшее решение?

1 Ответ

3 голосов
/ 18 июля 2012

Я создал рабочий пример на GitHub .

Это не вариант 1 или 2, он создает пользовательский JavaFileManager, который просматривает все пакеты и извлекает их ресурсы.

Что нужно учитывать:

  • Он использует API компилятора JSR 199, но работает только на компиляторе OpenJDK / Sun, компилятор Eclipse JDT в этом отношении выглядит неработоспособным.
  • Я тестировал только на Equinox, я не использовал какой-либо код, специфичный для равноденствия, поэтому он должен работать на других реализациях.
  • Он не оптимизирован, поэтому может быть медленным и / или потреблять память.
  • Он регистрирует прослушиватель пакета, поэтому он сбрасывает кэш своего класса, когда пакет, который предлагает определенный пакет, разрешает или не разрешает
  • Я думаю, это не очень детерминировано для сплит-пакетов.
  • Он использует API BundleWiring, который был представлен в OSGi 4.3, поэтому он не будет работать на более старых реализациях OSGi OSGi (например, Karaf 2.x)

Я должен упомянуть Технология Excruciation , его пример мне очень помог.

...