Obsługa dynamicznych modułów dodatkowych umożliwia wstawianie i usuwanie modułów dodatkowych przy uruchomionej instancji środowiska Eclipse. Są to komponenty, które można używać wielokrotnie, z możliwością usuwania ich z pamięci. Taki mechanizm pomaga zapanować nad dodawaniem i usuwaniem modułów dodatkowych.
Dynamiczny moduł dodatkowy nie musi pozostawać aktywny przez cały czas działania aplikacji. Z tego powodu konieczne jest zadbanie o to, żeby po usunięciu komponentu została wykonana procedura czyszcząca. Jeśli do środowiska roboczego są dodawane funkcje nasłuchiwania i są w nim rejestrowane elementy, pozostają one aktywne po wyłączeniu modułu dodatkowego. Moduł musi mieć na ten temat informacje.
Założenie, że odczytanie wszystkich implementacji punktu rozszerzenia podczas uruchamiania będzie wystarczające na cały czas działania aplikacji jest błędne. Konieczne jest dodanie funkcji nasłuchiwania lub całkowite wyeliminowanie stosowania pamięci podręcznej, co pozwoli na wykrywanie zmian rejestru. Ważny jest fakt, że elementy środowiska roboczego nie muszą być statyczne. Są w rzeczywistości elementami przejściowymi i mogą zostać usunięte w każdej chwili. Pisząc moduł dodatkowy dla konkretnego widoku należy pamiętać, aby program zawsze sprawdzał, czy widok ten jest dostępny.
Programując moduł dodatkowy należy upewnić się, że będzie on w stanie obsługiwać rozszerzenia, które mogą w każdej chwili stawać się dostępne lub niedostępne. Jeśli rozszerzenie staje się niedostępne, moduł powinien odpowiednio reagować na taką sytuację, wykonując procedurę czyszczącą wszelkie struktury wewnętrzne związane z danym rozszerzeniem i usuwając ewentualne artefakty interfejsu użytkownika sterowane przez dane rozszerzenie. Analogicznie uzyskanie dostępu do nowego rozszerzenia powinno powodować dodanie odpowiednich struktur wewnętrznych i utworzenie artefaktów interfejsu użytkownika. Zakładając, że aplikacja odczytuje dane z rejestru i zawiera rozszerzenie, należy utworzyć dla niej odpowiedni rekord i przypisać mu położenie. Po zakończeniu aplikacji wygenerowane zostanie powiadomienie o wymaganym przeprowadzeniu procedury czyszczącej. Dodatkowo funkcje nasłuchiwania będą powiadamiać o pojawieniu się nowych elementów i będą je tworzyć.
Interfejs org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker i powiązane z nim interfejsy udostępniają programistom modułów dodatkowych mechanizm śledzenia dodawanych i usuwanych rozszerzeń, a także zarządzania zasobami generowanymi w wyniku tych akcji.
W poniższym przykładzie założono, że moduł dodatkowy zawiera punkt rozszerzenia o nazwie "widgets" i korzysta z interfejsu IExtensionTracker. Wewnątrz modułu używane są klasy WidgetDescriptor, które opakowują rozszerzenia widgetów, i klasa WidgetRegistry, która służy do zarządzania nimi.
public class WidgetRegistry implements IExtensionChangeHandler { public WidgetRegistry() { IExtensionTracker tracker = PlatformUI.getWorkbench() .getExtensionTracker();
IExtensionPoint point = Platform.getExtensionRegistry() .getExtensionPoint("my.plugin.namespace", "widget");
IExtension[] extensions = point.getExtensions();
// początkowe zapełnienie
for (int i = 0; i < extensions.length; i++) { addExtension(tracker, extensions[i]);
} tracker
.registerHandler(this, tracker
.createExtensionPointFilter(point)); } public void addExtension(IExtensionTracker tracker, IExtension extension){ WidgetDescriptor descriptor = new WidgetDescriptor(extension); tracker.registerObject(extension, descriptor,
IExtensionTracker.REF_STRONG); addToInternalStructure(descriptor) } private void addToInternalStructure(WidgetDescriptor descriptor) { // logika związana z rejestrem } public void removeExtension(IExtension extension, Object[] objects) { for (int i = 0; i < objects.length; i++) { WidgetDescriptor descriptor = (WidgetDescriptor) objects[i];
removeFromInternalStructure(descriptor);
}
} private void removeFromInternalStructure(WidgetDescriptor descriptor) { // logika związana z rejestrem }
} public void dispose() { PlatformUI.getWorkbench() .getExtensionTracker().unregisterHandler(this)
} }
W tym przykładzie klasa PlatformUI udostępnia instancje klasie IExtensionTracker na różnych poziomach środowiska roboczego. Jeśli moduł korzysta z obiektów, które są dostępne tak długo, jak środowisko robocze, należy używać rejestratorów udostępnianych przez metodę IWorkbench.getExtensionTracker(). Jeśli obiekty są związane z konkretnymi oknami lub stronami środowiska roboczego, należy używać rejestratorów udostępnianych odpowiednio przez metodę IWorkbenchWindow.getExtensionTracker() lub IWorkbenchPage.getExtensionTracker(). Na przykład środowisko robocze śledzi deskryptory widoku na poziomie środowiska roboczego, ale rzeczywiste instancje widoków - na poziomie strony środowiska roboczego. Procedury obsługi mogą być rejestrowane w wybranych punktach rozszerzenia przez podanie instancji interfejsu IFilter w wywołaniu metody IExtensionTracker.registerHandler(). Procedura obsługi będzie wywoływana tylko w wyniku dodania lub usunięcia rozszerzeń zgodnych z interfejsem IFilter.
Ta metoda jest wywoływana, gdy rozszerzenie jest wprowadzane do środowiska wykonawczego. Procedura obsługi może wtedy dołączyć rozszerzenie do powiązanego z nią modelu. Wszelkie obiekty tworzone na podstawie interfejsu IExtension udostępnianego w tym interfejsie powinny być rejestrowane w rejestratorze za pomocą metody IExtensionTracker.registerObject(). Ta metoda jest wywoływana przy usuwaniu rozszerzenia ze środowiska wykonawczego. Wszelkie obiekty zarejestrowane wcześniej w rozszerzeniu są przekazywane jako argumenty. Procedura obsługi może wtedy wykonać procedurę czyszczącą i, w razie konieczności, usunąć obiekty. Dobrą praktyką jest wyrejestrowanie procedur obsługi, aby uniknąć wycieków pamięci w rejestrach.