2011-06-23 16 views
6

Jestem w trakcie refaktoryzacji aplikacji Java do korzystania z OSGi. Jedną z funkcji aplikacji jest kompilacja Java w locie za pomocą javax.tools.JavaCompiler. W oryginalnym wniosku proces ten działał, dostarczając kompilatorowi istniejącą ścieżkę klas, tak jak.Używanie JavaCompiler w pakiecie OSGi

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

Nie działa to jednak w pakiecie OSGi, ponieważ ścieżka klasy nie zawiera już wymaganych ścieżek. W refakturowanej wersji OSGi, kompilator potrzebuje dostępu do klas, które znajdują się w tym samym pakiecie co powyższy kod, a także klas z innych pakietów. Jak uczynić kompilator świadomym tych klas?

myślałem o dwóch możliwych rozwiązań:

  1. Daj kompilator classloader używany przez pakiet zawierający powyższy kod, ponieważ jest świadomy wszystkich niezbędnych zajęć. Jednak nie wydaje się to realnym rozwiązaniem z tego, co przeczytałem: here i here.
  2. Utwórz ścieżkę klas, korzystając z fizycznych lokalizacji zainstalowanych pakietów. Spojrzałem na org.osgi.framework.Bundle.getLocation(), ale nie jestem pewien, czy byłoby to niezawodne rozwiązanie. Ścieżki, które otrzymuję (przynajmniej podczas wdrażania w środowisku Eclipse) są względne i nie jestem pewien, czy byłyby bezpieczne w użyciu na wszystkich platformach i w różnych sytuacjach.

Czy opcja druga wydaje się możliwa? Czy istnieje lepsze rozwiązanie?

+0

Jeszcze jedna uwaga: widziałem podejście [tutaj] (http://blog.linkedin.com/2008/06/12/osgi-at-linkedin-java-compilation-in-osgi/), które pojawia się do pracy, ale zależy to od wewnętrznych klas JDT. Z tego, co przeczytałem, nie jest to dobra praktyka. –

+0

Ktoś ma jakieś pomysły ...? –

Odpowiedz

3

Utworzono działający przykład na GitHub.

Nie jest to opcja 1 lub 2, tworzy niestandardowy JavaFileManager, który przegląda wszystkie pakunki i pobiera ich zasoby.

warte uwzględnia:

  • Wykorzystuje API JSR 199 kompilatora, ale działa tylko na kompilator OpenJDK/Sun, kompilator Eclipse JDT wydaje złamane w tym zakresie.
  • Testowałem tylko na Equinoxie, nie użyłem żadnego specjalnego kodu równonocy, więc powinno działać na innych implementacjach.
  • Nie jest zoptymalizowany, więc może być wolny i/lub głodny pamięci.
  • Czyni zarejestrować detektor wiązki więc będzie wylewać swoje klasy cache kiedy pakiet, który oferuje pewien pakiet rozwiązuje lub unresolves
  • To nie jest bardzo deterministyczny dla pakietów dzielonych, myślę.
  • Wykorzystuje API BundleWiring, który został wprowadzony w OSGi 4.3, więc to nie będzie działać na starszych implementacje OSGi OSGi (Karaf 2.x na przykład)

powinienem wspomnieć Technology Excruciation, jego przykład pomógł bardzo sobą.

Powiązane problemy