Getting Hooked on Equinox - JAXenter
Equinox erweitern und modifizieren

Getting Hooked on Equinox

Martin Lippert und Heiko Seeberger

Viele verwenden Equinox als fertige OSGi Runtime, auf deren Basis vorhandene Anwendungen erweitert oder neu implementiert werden. Dazu kann Equinox in der Regel out-of-the-box verwendet werden. Was passiert aber, wenn diese Box nicht das leistet, was benötigt wird? Equinox bietet einen eleganten und wertvollen Mechanismus, um in solchen Situationen die Runtime selbst zu erweitern und zu modifizieren.

Equinox ist nicht nur ein Lieferant einer OSGi-Implementierung und erlaubt es damit, Anwendungen auf Basis von OSGi zu entwickeln. Die Equinox Runtime selbst ist mit dem Blick auf Erweiterbarkeit realisiert und bietet einen sehr mächtigen Mechanismus, um die OSGi Runtime zu erweitern oder zu modifizieren [1]. Zunächst soll ein Blick auf den Aufbau geworfen werden.

Aufbau der Equinox-OSGi-Implementierung

Bevor der Erweiterungsmechanismus von Equinox im Detail vorgestellt wird, soll der konzeptionelle Aufbau von Equinox betrachtet werden.
Equinox realisiert einerseits die drei OSGi Framework Layer: Der Module Layer ist dafür zuständig, das OSGi-Modul-Konzept in Form von Bundles umzusetzen sowie die Abhängigkeiten zwischen Bundles zu verwalten und aufzulösen. Dazu gehört auch das umfangreiche Delegationsmodell, mit dem die im Bundle-Manifest definierten Sichtbarkeiten von Packages zwischen Bundles realisiert werden. Der Life Cycle Layer kontrolliert den Lebenszyklus von Bundles und gestattet es, Bundles zur Laufzeit zu installieren, zu deinstallieren oder zu aktualisieren. Zusätzlich dazu realisiert dieser Layer auch einen Event-Mechanismus, über den OSGi das System über Zustandsänderungen benachrichtigt. Der dritte Layer ist der Service Layer. Dieser implementiert das OSGi-Servicekonzept, mit dem Bundles innerhalb einer Java Virtual Machine serviceorientiert zusammenarbeiten können.

Abb. 1: Konzeptioneller Aufbau der Equinox-OSGi-Implementierung [2]

Die Anbindung dieser Layer an eine konkret zugrunde liegende Plattform wird durch das Framework Adaptor API hergestellt. Der FrameworkAdaptor definiert das Format der Bundles, realisiert den Zugriff auf Ressourcen der Bundles über den Classloading-Mechanismus und verwaltet die Speicherung der persistenten Daten der OSGi Runtime.
Natürlich bringt Equinox eine Standardimplementierung des FrameworkAdaptors mit. Dieser BaseAdaptor erlaubt es, durch so genannte Framework Extensions alle drei Bereiche (Bundle-Formate, Classloading und Persistent Storage) zu erweitern. Dazu bietet dieser BaseAdaptor einen umfangreichen Hook-Mechanismus, der es sehr einfach erlaubt, an vordefinierten Stellen die Standardfunktionalität zu erweitern.

Hookable Adaptor

Vor Eclipse 3.2 war es nötig, für jegliche Anpassungen oder Erweiterungen einen eigenen FrameworkAdaptor zu implementieren, entweder komplett oder durch Erweiterung der gegebenen Standardimplementierung. Existierten mehrere, voneinander unabhängige Erweiterungen (also mehrere FrameworkAdaptors), konnte allerdings nur einer davon von Equinox verwendet werden (System Property osgi.adaptor), weil es konzeptionell nur einen FrameworkAdaptor zur Laufzeit geben kann.
Seit Eclipse 3.2 sieht der Standard-FrameworkAdaptor, der oben erwähnte BaseAdaptor, explizit Erweiterungsmöglichkeiten in Form von so genannten Hooks vor, weshalb er auch als Hookable Adaptor bezeichnet wird. Im Gegensatz zu selbst definierten FrameworkAdaptors kann es zur Laufzeit nun beliebig viele dieser Hooks geben. Sie werden alle vom BaseAdaptor entsprechend berücksichtigt. Es können also mehrere Erweiterungen (in Form von Hooks) gleichzeitig zum Einsatz kommen. Vom Equinox-Team wird ausdrücklich empfohlen, diesen Hook-Mechanismus zu verwenden und keinen eigenen FrameworkAdaptor mehr zu implementieren. Falls dies aufgrund von besonderen Anforderungen nicht möglich ist, sollte ein entsprechender Bug gemeldet werden.

Hook Interfaces

Welche verschiedenen Möglichkeiten bietet Equinox nun, um die Standardfunktionalität zu erweitern?

  • Der AdaptorHook klinkt sich direkt in verschiedene Methoden des FrameworkAdaptors bzw. des BaseAdaptors ein. So kann z.B. beim Starten und Stoppen der OSGi Runtime eingegriffen oder die Behandlung von Laufzeitfehlern erweitert werden.
  • Mit dem BundleFileFactoryHook ist es möglich, spezielle Formate für Bundles zu verwenden, die über den Equinox-Standard (JARs und Verzeichnisse) hinausgehen.
  • Der BundleFileWrapperFactoryHook ermöglicht es, den Zugriff auf die Ressourcen eines Bundles zu wrappen, z.B. um Security zu implementieren, oder den Inhalt von einzelnen Ressourcen beim Laden gezielt zu manipulieren.
  • Mit dem BundleWatcher kann der Lifecycle von Bundles verfolgt werden, wobei für jeden Statusübergang Start- und End-Events propagiert werden. Die Funktionalität ist jedoch ähnlich wie bei den OSGi BundleListenern.
  • Der ClassLoadingHook dient dazu, das Classloading-Verhalten zu modifizieren. So kann zum Beispiel der Bytecode modifiziert werden, bevor eine Klasse in der Virtual Machine definiert wird.
  • Der StorageHook wird für das Speichern und Laden von installierten Bundles verwendet.

Da es sich bei den Hooks um Erweiterungen der Standardfunktionalität der OSGi Runtime handelt, die zum Großteil im System Bundle org.eclipse.osgi implementiert ist, kommen so genannte Framework Extensions zum Einsatz. Eine Framework Extension ist ein Fragment Bundle zum System Bundle, d.h. der Fragment Host ist system.bundle bzw. org.eclipse.osgi. Damit Fragment Extensions von Equinox verwendet werden, müssen sie über die System Property osgi.framework.extensions bekannt gegeben werden, als JAR vorliegen und im Dateisystem im gleichen Verzeichnis wie das System Bundle liegen.

Geschrieben von
Martin Lippert und Heiko Seeberger
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.