W tej sekcji opisano zmiany wymagane do zmodyfikowania modułu dodatkowego z wersji 2.1 w celu zaadaptowania mechanizmów i interfejsów API z wersji 3.0.
Środowisko wykonawcze platformy Eclipse 3.0 zostało znacząco zmodyfikowane. Implementacja bazowa opiera się na specyfikacji środowiska OSGi. Środowisko wykonawcze platformy Eclipse 3.0 zawiera warstwę kompatybilności (w module dodatkowym org.eclipse.core.runtime.compatibility), w której przechowuje się interfejsy API z wersji 2.1. Programiści tworzący moduły dodatkowe zainteresowani możliwością uzyskania dodatkowej wydajności i funkcjonalności powinni wziąć pod uwagę zaadaptowanie interfejsów API z wersji 3.0 i wyeliminowanie zależności od warstwy kompatybilności. Kod kompatybilności pojawia się w trzech miejscach:
W kolejnych sekcjach wyjaśniono bardziej szczegółowo, które klasy i metody są obecne w celu zachowania kompatybilności, a także przedstawiono instrukcje umożliwiające aktualizację modułów dodatkowych.
Środowisko wykonawcze platformy Eclipse zostało poddane refaktoryzacji w celu podziału na dwie części - zarządzanie wymaganiami wstępnymi i ładowaniem klas oraz zarządzanie rozszerzeniami/punktami rozszerzeń. Podział ten umożliwia naturalną, elastyczną adaptacje specyfikacji środowiska OSGi w celu zarządzania ładowaniem klas i wymaganiami wstępnymi. To pozwala z kolei korzystać z zestawu nowych możliwości środowiska wykonawczego, od dynamicznego instalowania/aktualizowania/deinstalowania modułów dodatkowych do zabezpieczeń i poszerzonych możliwości konfiguracyjnych.
Choć w dalszym ciągu pozostaje w użyciu określenie moduł dodatkowy, w nowym środowisku wykonawczym moduł dodatkowy to w istocie pakunek uzupełniony o dodatkowe rozszerzenia i punkty rozszerzeń. Termin pakunek jest zdefiniowany w specyfikacji środowiska OSGi i oznacza kolekcję typów i zasobów oraz powiązanych informacji o międzypakunkowych wymaganiach wstępnych. Rejestr rozszerzeń stanowi nową formę rejestru modułów dodatkowych i wyszczególnia jedynie informacje dotyczące rozszerzeń i punktów rozszerzeń. Interfejs API rejestru rozszerzeń w dużym stopniu pokrywa się z interfejsem API odpowiadającego mu rejestru modułów dodatkowych (więcej informacji na ten temat można znaleźć w sekcji Rejestry).
W środowisku wykonawczym platformy Eclipse 2.x obiekt modułu dodatkowego ma kilka ról i zadań:
W środowisku wykonawczym platformy Eclipse 3.0 te role i zadania są realizowane w ramach oddzielnych obiektów.
Klasa Plugin implementuje również klasę BundleActivator. Wygodnie jest mieć do dyspozycji jeden centralny obiekt, który reprezentuje cykl życia i semantykę modułu dodatkowego. Należy zauważyć, że nie ma to na celu usankcjonowania praktyki pochopnego inicjowania struktur danych stosowanej dziś powszechnie w modułach dodatkowych. Podkreślamy nieustannie, że odwołanie do peryferyjnej klasy może spowodować aktywację modułu dodatkowego podczas weryfikowania klasy w innym obiekcie. Innymi słowy, sam fakt aktywowania modułu nie oznacza koniecznie, że jego funkcja jest potrzebna. Ponadto warto zauważyć, że istnieje możliwość zdefiniowania innej klasy BundleActivator lub całkowite zrezygnowanie z aktywatora pakunku.
Kroki wymagane do przeniesienia klasy Plugin z wersji 2.x do środowiska Eclipse 3.0 zależą od zadań realizowanych przez tę klasę. Jak zasygnalizowano powyżej, większa część czynności uruchomieniowych cyklu życia przypada do jednej z następujących kategorii:
W nowym środowisku wykonawczym oddziela się od siebie informacje i struktury potrzebne do wykonania modułu dodatkowego oraz informacje i struktury związane z rozszerzeniami i punktami rozszerzeń modułu. Te pierwsze są definiowane i zarządzane przez specyfikację środowiska OSGi. Te drugie są pojęciami charakterystycznymi dla środowiska Eclipse i są dodawane przez kod środowiska wykonawczego tej platformy. Z tego względu oryginalny rejestr modułów dodatkowych i obiekty pokrewne zostały podzielone na pakunki środowiska OSGi oraz rejestr rozszerzeń środowiska Eclipse.
Te elementy interfejsu IPluginRegistry, które wiążą się ze specyfikacją wykonania (np. IPluginDescriptor, ILibrary, IPrequisite), są nieaktualne, a pozostałe elementy związane z rozszerzeniami i punktami rozszerzeń zostały przeniesione do interfejsu IExtensionRegistry. Ponadto tak zwane obiekty modeli powiązane całościowo z rejestrem modułów dodatkowych są już nieaktualne. Typy te były prezentowane, a ich instancje tworzone, przez środowisko wykonawcze przede wszystkim w celu zapewnienia obsługi narzędzi takich jak PDE. Niestety, często zdarzało się, że poziom wymaganych informacji wykraczał poza możliwości lub priorytety środowiska wykonawczego (np. zapamiętywanie numerów wierszy elementów pliku plugin.xml), w związku z czym potencjalni beneficjenci tych informacji i tak musieli ostatecznie przechowywać własne struktury.
W nowym środowisku wykonawczym zrewidowano udostępnianie narzędzia. Teraz dostępne są tylko narzędzia niezbędne dla realizacji funkcji wykonawczych lub wyjątkowo trudne do uzyskania w alternatywny sposób. Jak wspomniano wyżej, obiekty modeli z rejestru modułów dodatkowych są już nieaktualne. Aktualność stracił również interfejs API analizy modułów dodatkowych. Nowy rejestr rozszerzeń umożliwia przechowywanie najistotniejszych informacji związanych z rozszerzeniami. Nowa struktura state (patrz org.eclipse.osgi.service.resolver.State i obiekty zaprzyjaźnione) reprezentuje istotne informacje związane z wykonaniem i umożliwia manipulowanie nimi.
W środowisku Eclipse 3.0 struktura fragmentu dla języka narodowego została zaktualizowana w celu nadania jej większej spójności. We wcześniejszych wersjach zakładano, że tłumaczenia dla plików takich jak plugin.properties znajdują się wewnątrz plików JAR dostarczanych przez fragmenty. Ponieważ oryginalne pliki znajdują się w katalogu głównym odpowiedniego modułu dodatkowego hosta, bardziej logicznym położeniem tłumaczonych plików byłby katalog główny fragmentów dla języka narodowego. Na przykład:
org.eclipse.ui.workbench.nl/ fragment.xml plugin_fr.properties plugin_pt_BR.properties ... nl1.jar
Warto zauważyć, że plik nl1.jar zawierałby wcześniej tłumaczenia dla pliku plugin.properties. Pliki te znajdują się obecnie w katalogu głównym fragmentu, a plik JAR zawiera tłumaczenia wszystkich tłumaczonych zasobów (tzn. plików ładowanych przez program ładujący klasy) w module dodatkowym hosta.
Oczywiście struktura fragmentu dla języka narodowego w środowisku Eclipse 2.1 jest nadal obsługiwana dla macierzystych modułów dodatkowych z wersji 2.1 uruchamianych na platformie Eclipse 3.0. Nie można jednak korzystać z fragmentu dla języka narodowego z wersji 2.1 w module dodatkowym z wersji 3.0. Należy zaktualizować fragment do nowej struktury.
Cały pakiet org.eclipse.core.boot jest już nieaktualny. Klasa BootLoader została scalona z klasą org.eclipse.core.runtime.Platform, ponieważ podział na część startową i wykonawczą stracił uzasadnienie. Należy zauważyć, że moduł dodatkowy org.eclipse.core.boot został podzielony, a jego kod przeniesiono albo do nowego środowiska wykonawczego, albo do warstwy kompatybilności.
Interfejs IPlatformConfiguration był zawsze typem definiowanym przez komponent instalacyjny/deinstalacyjny środowiska Eclipse na potrzeby tego środowiska. Dzięki reorganizacji środowiska wykonawczego możliwe stało się przeniesienie tego typu do jego pierwotnego kontekstu. Klasa ta pozostaje w dużej części niezmieniona - została natomiast przemianowana na org.eclipse.update.configurator.IPlatformConfiguration.
Interfejs IPlatformRunnable został przeniesiony do pakietu org.eclipse.core.runtime.IPlatformRunnable.
Metoda getDeclaringPlugin()
(w obu klasach) udostępnia łącze do
modułu dodatkowego deklarującego rozszerzenie lub punkt rozszerzenia
(odpowiednio dla wymienionych interfejsów). Nowy model rejestru rozdziela
aspekt wykonawczy modułu dodatkowego od aspektu rozszerzenia lub punktu
rozszerzenia i nie zawiera już interfejsu IPluginDescriptors.
Użytkownicy tego interfejsu API powinni wziąć pod uwagę nową metodę
getParentIdentifier() znajdującą się zarówno w interfejsie
IExtension, jak i w IExtensionPoint.
W oryginalnym środowisku wykonawczym rejestr modułów dodatkowych przechowywał całościowy obraz konfiguracji środowiska wykonawczego. W środowisku Eclipse 3.0 obraz ten dzieli się na środowisko OSGi i rejestr rozszerzeń. Z tego względu omawiane klasy straciły aktualność. Noty dotyczące dezaktualizacji zawierają szczegółowe instrukcje omawiające sposób aktualizowania kodu.
W nowym środowisku wykonawczym obiekty Plugin nie są już zarządzane przez środowisko wykonawcze, zatem nie można do nich uzyskać dostępu w sposób ogólny za pośrednictwem klasy Platform. Podobnie rejestr modułów dodatkowych nie istnieje i nie udostępnia deskryptorów modułów dodatkowych. Dostępne są jednak odpowiednie metody zastępcze, które opisano szczegółowo w dokumentacji Javadoc dotyczącej metod zdezaktualizowanych w tych klasach.
Wszystkie typy w tym pakiecie są już nieaktualne. Więcej informacji można znaleźć w omówieniu rejestrów.
Klienci metody IWorkspace.run(IWorkspaceRunnable,IProgressMonitor) powinni zrewidować użycie tej metody i rozważyć zastosowanie poszerzonej metody IWorkspace.run(IWorkspaceRunnable,ISchedulingRule,int,IProgressMonitor). Stara metoda IWorkspace.run blokuje cały obszar roboczy na czas wykonywania interfejsu IWorkspaceRunnable. Oznacza to, że operacja wykonywana przy użyciu tej metody nigdy nie może odbywać się współbieżnie z innymi operacjami, które modyfikują obszar roboczy. W środowisku Eclipse 3.0 wiele czasochłonnych operacji zostało przeniesionych do wątków tła, więc prawdopodobieństwo konfliktów między operacjami znacznie się zwiększyło. Jeśli modalna operacja pierwszoplanowa zostanie zablokowana przez długotrwałą operację tła, interfejs użytkownika pozostanie zablokowany aż do zakończenia operacji tła lub do momentu anulowania jednej z operacji.
Zalecane rozwiązanie polega na przełączeniu wszystkich odwołań do starej
metody IWorkspace.run na korzystanie z nowej metody z parametrem reguły
planowania. Reguła planowania powinna cechować się największym stopniem
precyzji i zawierać reguły dla wszystkich zmian przeprowadzanych przez daną
operację. Jeśli operacja podejmie próbę zmodyfikowania zasobów poza zasięgiem
reguły planowania, wystąpi wyjątek środowiska wykonawczego. Dokładne reguły
planowania wymagane przez daną operację obszaru roboczego nie są określone i
mogą zmieniać się w zależności od zainstalowanego dostawcy repozytorium w
danym projekcie. Aby uzyskać regułę planowania dla operacji powodującej
zmianę zasobu, należy skorzystać z fabryki IResourceRuleFactory
. W
razie potrzeby można skorzystać z klasy MultiRule w celu określenia
wielu reguł zasobów, a za pomocą metody MultiRule.combine można
wygodnie połączyć reguły z różnych operacji modyfikujących zasoby.
Jeśli nie jest wymagane stosowanie blokady, można użyć reguły planowania o wartości null. Umożliwi to modyfikowanie wszystkich zasobów w obrębie obszaru roboczego przez element uruchamialny, ale nie zapobiegnie współbieżnemu modyfikowaniu obszaru roboczego przez inne wątki. W przypadku prostych zmian w obszarze roboczym jest to często rozwiązanie najłatwiejsze i najdogodniejsze pod kątem współbieżności.
filteredSelection
na podstawie wyboru
selection
:
IStructuredSelection filteredSelection = selection;
List selectedResources = IDE.computeSelectedResources(currentSelection);
if (!selectedResources.isEmpty()) {
filteredSelection = new
StructuredSelection(selectedResources);
}
IStructuredSelection filteredSelection = selection;
List selectedResources = IDE.computeSelectedResources(currentSelection);
if (!selectedResources.isEmpty()) {
filteredSelection = new
StructuredSelection(selectedResources);
}
if (selection.isEmpty()) { IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (window != null) { IWorkbenchPart part = window.getPartService().getActivePart(); if (part instanceof IEditorPart) { IEditorInput input = ((IEditorPart) part).getEditorInput(); if (input instanceof IFileEditorInput) { selection = new StructuredSelection(((IFileEditorInput) input).getFile()); } } } }
IActionBars actionBars= getActionBars(); if (actionBars != null) { actionBars.setGlobalActionHandler(IDEActionFactory.ADD_TASK.getId(), getAction(textEditor, IDEActionFactory.ADD_TASK.getId())); actionBars.setGlobalActionHandler(IDEActionFactory.BOOKMARK.getId(), getAction(textEditor, IDEActionFactory.BOOKMARK.getId())); }
Pojawia się obecnie wyraźne pojęcie typu adnotacji. Patrz metoda Annotation.getType() oraz Annotation.setType(). Typ adnotacji może ulec zmianie w ciągu jej cyklu życia. Dodano nowy punkt rozszerzenia dla deklaracji typu adnotacji: org.eclipse.ui.editors.annotationTypes. Typ adnotacji ma nazwę i może zostać zadeklarowany jako podtyp innego zadeklarowanego typu adnotacji. Deklaracja typu adnotacji może również korzystać z atrybutów markerType oraz markerSeverity w celu wskazania, że znaczniki określonego typu i istotności powinny być reprezentowane w edytorach tekstów jako adnotacje określonego typu. Nie należy już korzystać z atrybutów markerType oraz markerSeverity w punkcie rozszerzenia org.eclipse.ui.editors.markerAnnotationSpecification. Specyfikacje adnotacji znaczników stają się tym samym niezależne od znaczników i nazwa może być w związku z tym myląca. Została jednak zachowana, aby zapewnić kompatybilność wsteczną.
Instancje podklas klasy AbstractMarkerAnnotationModel wykrywają i ustawiają odpowiednie typy adnotacji dla adnotacji tworzonych przez siebie na bazie znaczników. Aby programowo pobrać typ adnotacji dla danego znacznika albo pary atrybutów markerType i markerSeverity, należy użyć klasy org.eclipse.ui.texteditor.AnnotationTypeLookup.
Dostęp do hierarchii typów adnotacji zapewnia interfejs IAnnotationAccessExtension. Dla danego typu adnotacji istnieje możliwość uzyskania łańcucha typów nadrzędnych i sprawdzenie, czy wybrany typ jest podtypem innego typu adnotacji. Interfejs ten implementuje klasa DefaultMarkerAnnotationAccess.
Typ adnotacji to klucz umożliwiający znalezienie powiązanej specyfikacji adnotacji znacznika. Tak jak typy adnotacji mogą stanowić rozszerzenie innych typów adnotacji, istnieją również niejawne powiązania między specyfikacjami adnotacji znaczników. Specyfikacja adnotacji znacznika dla danego typu adnotacji jest zatem uzupełniana przez specyfikacje dla typów nadrzędnych tego typu adnotacji. Z tego względu specyfikacje adnotacji znaczników nie muszą być kompletne, tak jak było to wymagane do tej pory. Specyfikacje są pobierane za pomocą klasy AnnotationPreferences. Korzystając z klasy org.eclipse.ui.texteditor.AnnotationPreferenceLookup, można pobrać preferencje adnotacji dla danego typu adnotacji, która umożliwia transparentne uzupełnienie preferencji na postawie łańcucha typów nadrzędnych adnotacji.
Specyfikacja adnotacji znacznika została poszerzona o trzy dodatkowe atrybuty mające na celu umożliwienie definicji niestandardowych wystąpień danego typu adnotacji na linijce pionowej. Atrybuty te to icon, symbolicIcon oraz annotationImageProvider. Wartością atrybutu icon jest ścieżka do pliku zawierającego obraz ikony. Wartością atrybutu symbolicIcon może być error, warning, info, task lub bookmark. Atrybutu symbolicIcon używa się do wskazania, że adnotacja ma być przedstawiona z użyciem tych samych obrazów, które są wykorzystywane przez platformę do prezentowania (odpowiednio) błędów, ostrzeżeń, informacji i zakładek. Wartością atrybutu annotationImageProvider jest klasa implementująca interfejs org.eclipse.ui.texteditor.IAnnotationImageProvider, która umożliwia pełną prezentację adnotacji niestandardowych.
Linijka pionowa korzysta z powiązanych z nią interfejsów IAnnotationAccess/IAnnotationAccessExtension do wyświetlenia adnotacji. Linijka pionowa nie wywołuje już metody Annotation.paint. Ogólnie nie oczekuje się już, że adnotacje będą wyświetlały się same. Metody paint oraz getLayer są już nieaktualne, co ma ostatecznie na celu uniezależnienie adnotacji od interfejsu użytkownika. Klasa DefaultMarkerAnnotationAccess służy jako domyślna implementacja interfejsu IAnnotationAccess/IAnnotationAccessExtension. Klasa DefaultMarkerAnnotationAccess implementuje następującą strategię w celu wyświetlenia adnotacji: jeśli adnotacja implementuje interfejs IAnnotationPresentation, metoda IAnnotationPresentation.paint nie zostanie wywołana. W przeciwnym razie w preferencjach adnotacji zostanie wyszukany dostawca obrazu adnotacji. Dostawca jest dostępny tylko pod warunkiem, że został określony i że moduł dodatkowy definiujący obejmującą specyfikację adnotacji znacznika został już załadowany. Jeśli dostawca obrazu adnotacji jest dostępny, zostanie do niego przekazane wywołanie. Jeśli nie, zostanie wyszukany obiekt wskazywany przez atrybut icon. Rolę ostatniej deski ratunku pełni atrybut symbolicIcon. W przypadku wyświetlania adnotacji istotna jest warstwa prezentacji adnotacji. Klasa DefaultMarkerAnnotationAccess wyszukuje warstwę prezentacji za pomocą następującej strategii: jeśli preferencja adnotacji określa warstwę prezentacji, warstwa ta zostanie użyta. Jeśli warstwa nie jest dostępna, a adnotacja implementuje interfejs IAnnotationPresentation, zostanie użyta metoda IAnnotationPresentation.getLayer. W pozostałych przypadkach zwracana jest domyślna warstwa prezentacji (tzn. 0).
W module org.eclipse.ui.editors deklarowane są następujące typy adnotacji:
<extension point="org.eclipse.ui.editors.annotationTypes"> <type name="org.eclipse.ui.workbench.texteditor.error" markerType="org.eclipse.core.resources.problemmarker" markerSeverity="2"> </type> <type name="org.eclipse.ui.workbench.texteditor.warning" markerType="org.eclipse.core.resources.problemmarker" markerSeverity="1"> </type> <type name="org.eclipse.ui.workbench.texteditor.info" markerType="org.eclipse.core.resources.problemmarker" markerSeverity="0"> </type> <type name="org.eclipse.ui.workbench.texteditor.task" markerType="org.eclipse.core.resources.taskmarker"> </type> <type name="org.eclipse.ui.workbench.texteditor.bookmark" markerType="org.eclipse.core.resources.bookmark"> </type> </extension>
Zdefiniowane rozszerzenie markerAnnotationSpecification nie udostępnia już atrybutów "markerType" i "markerSeverity". Rozszerzenia te definiują atrybut "symbolicIcon" z odpowiednią wartością. Metody MarkerAnnotation.paint oraz MarkerAnnotation.getLayer nie są już zatem wywoływane - innymi słowy, przesłonięcie tych metod nie będzie miało żadnego skutku. Klienci, których to dotyczy, powinni zaimplementować interfejs IAnnotationPresentation.
Wprowadzenie trybów uruchamiania rozszerzalnego w wersji 3.0 spowodowało, że
dla danego typu konfiguracji startowej może występować więcej niż jeden delegat
uruchamiania. Wersje wcześniejsze niż 3.0 obsługiwały tylko jednego delegata
uruchamiania przypadającego na typ konfiguracji startowej. Metoda
ILaunchConfigurationType.getDelegate()
jest już nieaktualna. Zamiast niej
należy używać metody getDelegate(String mode)
do
pobrania delegata uruchamiania dla danego trybu uruchomieniowego.
Zdezaktualizowana metoda została zmodyfikowana, tak aby zwracała delegata
uruchamiania dla trybu run
.
Grupy kart i karty uruchamiania nie są już powiadamianie po zakończeniu
uruchamiania. Metoda launched(ILaunch)
w interfejsach
ILaunchConfigurationTab
oraz
ILaunchConfigurationTabGroup
została zdezaktualizowana i nie jest
już wywoływana. Poleganie na tej metodzie w zakresie funkcji uruchomieniowych
było zawsze problematyczne, ponieważ karty występują tylko w przypadku, gdy
uruchamianie odbywa się z poziomu okna dialogowego. Ponadto nie można już
wywoływać tej metody ze względu na wprowadzenie uruchamiania w tle, ponieważ
okno dialogowe uruchamiania jest zamykane przed zaistnieniem wynikowego obiektu
uruchamiania.
Do interfejsu ILaunchConfigurationTab
dodano dwie metody -
activated oraz deactivated. Te nowe metody cyklu życia są wywoływane w momencie
(odpowiednio) wejścia na kartę i wyjścia z niej. Istniejące implementacje
interfejsu ILaunchConfigurationTab
, które tworzą podklasę klasy
abstrakcyjnej udostępnianej przez moduł dodatkowy debugowania
(AbstractLaunchConfigurationTab
), są kompatybilne binarnie,
ponieważ wymienione metody są zaimplementowane w tej klasie.
We wcześniejszych wersjach do karty w momencie jej aktywowania przesyłany
był komunikat initializeFrom
oraz komunikat
performApply
w momencie jej dezaktywacji. W ten sposób środowisko
kart konfiguracji startowych udostępniało komunikację między kartami za
pośrednictwem konfiguracji startowych (przez zaktualizowanie konfiguracji
bieżącymi wartościami atrybutów przy wyjściu z karty oraz przy wejściu na
kartę). Jednak ponieważ wiele kart nie wymaga komunikacji między kartami, takie
podejście może być nieskuteczne. Ponadto nie było możliwości rozróżnienia
między kartą właśnie aktywowaną oraz kartą wyświetlającą wybraną konfigurację
startową po raz pierwszy. Nowo dodane metody pozwalają rozróżniać między
aktywacją i inicjowaniem oraz dezaktywacją i zapisaniem bieżących wartości.
Domyślna implementacja metody activated
udostępniana przez
kartę abstrakcyjną wywołuje element initializeFrom
. Domyślna
implementacja metody deactivated
wywołuje element
performApply
. Karty, które mają korzystać z nowego interfejsu API,
powinny odpowiednio przesłaniać te metody. Ogólnie w przypadku kart, które nie
wymagają komunikacji między kartami, zalecane podejście to ponowna
implementacja tych metod, aby nie wykonywały żadnych operacji.
We wcześniejszych wersjach przełączanie perspektywy określane było w ramach
konfiguracji startowej, za pośrednictwem atrybutów konfiguracji startowej
ATTR_TARGET_DEBUG_PERSPECTIVE
oraz
ATTR_TARGET_RUN_PERSPECTIVE
. Wraz z wprowadzeniem trybów
uruchamiania rozszerzalnego w wersji 3.0 takie podejście nie pozwala już na
skalowanie. Przełączanie perspektywy odbywa się teraz na bazie typu
konfiguracji startowej według trybów uruchamiania obsługiwanych przez dany typ
konfiguracji startowej. Do elementu DebugUITools
dodano interfejs
API służący do ustawiania i pobierania perspektywy powiązanej z typem
konfiguracji startowej dla określonego typu uruchamiania.
Dodano opcjonalny element launchMode
do punktu rozszerzenia
launchConfigurationTabGroup
, który pozwala na określenie domyślnej
perspektywy dla konfiguracji startowej i typu uruchamiania przez udostępnioną
grupę kart.
Z poziomu interfejsu użytkownika środowiska Eclipse użytkownicy mogą edytować perspektywy powiązane z typem konfiguracji startowej, otwierając okno dialogowe konfiguracji startowej i wybierając z drzewa węzeł typu konfiguracji (a nie pojedynczą konfigurację). Zostanie wyświetlona karta, która umożliwia ustawienie perspektywy odpowiadającej każdemu obsługiwanemu trybowi uruchamiania.
Do klasy VMRunnerConfiguration
dodano dwie metody, które
umożliwiają ustawianie i pobieranie zmiennych środowiskowych. Implementatorzy
interfejsu IVMRunner
powinni wywoływać metodę
VMRunnerConfiguration.getEnvironment()
i przekazywać środowisko do
wykonywanej maszyny JVM. Klienci korzystający z metody
DebugPlugin.exec(String[] cmdLine, File workingDirectory)
mogą to
zrobić, wywołując metodę DebugPlugin.exec(String[] cmdLine, File
workingDirectory, String[] envp)
. Wystarczy po prostu przekazać wynik z
metody getEnvironment()
.
We wcześniejszych wersjach klasa VMRunnerConfiguration
miała
jeden atrybut służący do opisu ścieżki startowej. Atrybut jest kolekcją
elementów String
, które mają być podane w argumencie
-Xbootclasspath
. Do klasy VMRunnerConfiguration dodano trzy nowe
atrybuty, aby zapewnić obsługę maszyn JVM z możliwością dołączania z przodu lub
z tyłu ścieżki startowej. Nowe metody/atrybuty to:
getPrependBootClassPath()
- zwraca kolekcję wpisów, które
mają zostać dołączone z przodu ścieżki startowej (argument
-Xbootclasspath/p
).
getMainBootClassPath()
- zwraca kolekcję wpisów, które mają
zostać umieszczone w ścieżce startowej (argument -Xbootclasspath
).
getAppendBootClassPath()
- zwraca kolekcję wpisów, które
mają zostać dołączone z tyłu ścieżki startowej (argument
-Xbootclasspath/a
).
Stary atrybut getBootClassPath()
jest nadal dostępny i stanowi
odpowiednik trzech nowych atrybutów z kompletną ścieżką. Elementy
VMRunner
, które obsługują nowe opcje ścieżki startowej, powinny
jednak korzystać z nowych atrybutów.
Narzędzie kopii roboczej modelu Java zostało zmodyfikowane w wersji 3.0 w celu udostępnienia znacznie poszerzonej funkcjonalności. W wersjach wcześniejszych niż 3.0 model Java pozwalał tworzyć pojedyncze kopie robocze jednostek kompilacji. Istniała możliwość wprowadzania zmian w kopiach roboczych i zatwierdzania ich w późniejszym terminie. Dostępna była obsługa ograniczonej analizy kopii roboczej w kontekście pozostałej części modelu Java. Nie istniała jednak możliwość uwzględnienia w tych analizach więcej niż jednej kopii roboczej naraz.
Zmiany w wersji 3.0 umożliwiają tworzenie i zarządzanie zestawami kopii roboczych jednostek kompilacji oraz wykonywanie analiz uwzględniających wszystkie kopie w zestawie. Przykładowo klient taki jak refaktoryzacja JDT może utworzyć kopie robocze jednej lub kilku jednostek kompilacji, które być może mają zostać zmodyfikowane, a następnie może rozwiązać odwołania typów między kopiami roboczymi. We wcześniejszych wersjach było to możliwe dopiero po zatwierdzeniu zmian wprowadzonych w kopiach roboczych jednostek kompilacji.
Interfejs API modelu Java zmienia się w dwóch aspektach w celu dodania ulepszonej obsługi:
(1) Funkcje znajdujące się wcześniej w interfejsie IWorkingCopy
i dziedziczone przez interfejs ICompilationUnit
zostały
skonsolidowane w ramach interfejsu ICompilationUnit
.
Interfejs IWorkingCopy
był używany tylko w tym miejscu, a jego
zakres był dużo ogólniejszy, niż wynikałoby to z faktycznych potrzeb.
Wprowadzona zmiana upraszcza interfejs API. Interfejs IWorkingCopy
jest już nieaktualny. Dezaktualizacji uległy także inne miejsca w interfejsie
API, w których interfejs IWorkingCopy
był wykorzystywany jako
parametr lub typ wyniku. Nowe metody API odwołują się do interfejsu
ICompilationUnit
zamiast interfejsu IWorkingCopy
.
(2) Interfejs IBufferFactory
został zastąpiony przez klasę
WorkingCopyOwner
. Ulepszona obsługa kopii roboczych wymaga
obiektu, który może być ich właścicielem. Chociaż interfejs
IBufferFactory
znajduje się we właściwym miejscu, nazwa nie oddaje
adekwatnie sposobu, w jaki działa nowy mechanizm kopii roboczych. Nazwa
WorkingCopyOwner
mówi dużo więcej. Dodatkowo klasa
WorkingCopyOwner
jest deklarowana jako klasa abstrakcyjna, a nie
interfejs, aby pojęcie właściciela kopii roboczej mogło ewoluować w
przyszłości. Z interfejsu IBufferFactory
została przeniesiona bez
zmian do klasy WorkingCopyOwner
jedyna znajdująca się w nim
metoda. Klasa WorkingCopyOwner
nie implementuje interfejsu
IBufferFactory
, aby było jasne, że interfejs IBufferFactory
należy już do
przeszłości. Interfejs IBufferFactory
jest nieaktualny.
Dezaktualizacji uległy także inne miejsca w interfejsie API, w których
interfejs IBufferFactory
pojawia się jako parametr lub typ wyniku.
Nowe metody API odwołują się do klasy WorkingCopyOwner
zamiast
interfejsu IBufferFactory
.
Te zmiany nie naruszają kompatybilności binarnej.
Podczas migracji wszystkie odwołania do typu IWorkingCopy
powinny zostać zastąpione odwołaniami do typu ICompilationUnit
.
Jedyna implementacja interfejsu IWorkingCopy
implementuje również
typ ICompilationUnit
, co oznacza, że obiekty typu
IWorkingCopy
mogą być bezpiecznie rzutowane na typ
ICompilationUnit
.
Klasa implementująca interfejs IBufferFactory
będzie wymagała
zastąpienia przez podklasę klasy WorkingCopyOwner
. Chociaż sama
klasa WorkingCopyOwner
nie implementuje interfejsu
IBufferFactory
, byłoby możliwe zadeklarowanie podklasy klasy
WorkingCopyOwner
, która implementuje interfejs
IBufferFactory
. Spowodowałoby to utworzenie pomostu między starymi
i nowymi elementami (interfejs IBufferFactory
deklaruje metodę
createBuffer(IOpenable)
, a klasa WorkingCopyOwner
deklaruje metodę createBuffer(ICompilationUnit)
; interfejs
ICompilationUnit
rozszerza interfejs IOpenable
).
Ponieważ zmiany związane z interfejsami IWorkingCopy
i
IBufferFactory
są ze sobą powiązane, zaleca się zajęcie nimi
jednocześnie. Poniżej przedstawiono szczegóły dezaktualizacji:
IWorkingCopy
(pakiet
org.eclipse.jdt.core
)
public void commit(boolean, IProgressMonitor)
uległa dezaktualizacji.
ICompilationUnit
:
public void commitWorkingCopy(boolean, IProgressMonitor)
wc.commit(b,monitor)
na
((ICompilationUnit) wc).commitWorkingCopy(b,monitor)
public void destroy()
uległa dezaktualizacji.
ICompilationUnit
:
public void discardWorkingCopy(boolean, IProgressMonitor)
wc.destroy()
na
((ICompilationUnit) wc).discardWorkingCopy()
public IJavaElement
findSharedWorkingCopy(IBufferFactory)
uległa dezaktualizacji.
ICompilationUnit
:
public ICompilationUnit findWorkingCopy(WorkingCopyOwner)
WorkingCopyOwner
zastępuje interfejs
IBufferFactory.
public IJavaElement getOriginal(IJavaElement)
uległa dezaktualizacji.
IJavaElement
:
public IJavaElement getPrimaryElement()
wc.getOriginal(elt)
na
elt.getPrimaryElement()
IWorkingCopy.getOriginal
metoda
IJavaElement.getPrimaryElement
nie zwraca wartości
null
, jeśli odbiornik nie jest kopią roboczą.public IJavaElement getOriginalElement()
uległa
dezaktualizacji.
ICompilationUnit
:
public ICompilationUnit getPrimary()
wc.getOriginalElement()
na
((ICompilationUnit) wc).getPrimary()
IWorkingCopy.getOriginalElement
metoda
IWorkingCopy.getPrimary
nie zwraca wartości null
,
jeśli odbiornik nie jest kopią roboczą.public IJavaElement[] findElements(IJavaElement)
uległa dezaktualizacji.
ICompilationUnit
.wc.findElements(elts)
na
((ICompilationUnit) wc).findElements(elts)
public IType findPrimaryType()
uległa
dezaktualizacji.
ICompilationUnit
.wc.findPrimaryType()
na
((ICompilationUnit) wc).findPrimaryType()
public IJavaElement getSharedWorkingCopy(IProgressMonitor,
IBufferFactory, IProblemRequestor)
uległa dezaktualizacji.
ICompilationUnit
:
public ICompilationUnit getWorkingCopy(WorkingCopyOwner,
IProblemRequestor, IProgressMonitor)
WorkingCopyOwner
zastępuje interfejs IBufferFactory.
public IJavaElement getWorkingCopy()
uległa
dezaktualizacji.
ICompilationUnit
:
public ICompilationUnit getWorkingCopy(IProgressMonitor)
wc.getWorkingCopy()
na
((ICompilationUnit) wc).getWorkingCopy(null)
public IJavaElement getWorkingCopy(IProgressMonitor,
IBufferFactory, IProblemRequestor)
uległa dezaktualizacji.
ICompilationUnit
:
public ICompilationUnit getWorkingCopy(WorkingCopyOwner,
IProblemRequestor, IProgressMonitor)
WorkingCopyOwner
zastępuje interfejs IBufferFactory.
public boolean isBasedOn(IResource)
uległa
dezaktualizacji.
ICompilationUnit
:
public boolean hasResourceChanged()
wc.isBasesOn(res)
na
((ICompilationUnit) wc).hasResourceChanged()
public boolean isWorkingCopy(IResource)
uległa
dezaktualizacji.
ICompilationUnit
.wc.isWorkingCopy()
na
((ICompilationUnit) wc).isWorkingCopy()
public IMarker[] reconcile()
uległa
dezaktualizacji.
ICompilationUnit
:
public void reconcile(boolean,IProgressMonitor)
wc.reconcile()
na
((ICompilationUnit) wc).reconcile(false, null)
null
;
metoda, która ją zastępuje, nie zwraca wyniku.public void reconcile(boolean, IProgressMonitor)
uległa dezaktualizacji.
ICompilationUnit
.wc.reconcile(b,monitor)
na
((ICompilationUnit) wc).reconcile(b.monitor)
public void restore()
uległa dezaktualizacji.
ICompilationUnit
.wc.restore()
na
((ICompilationUnit) wc).restore()
IType
(pakiet org.eclipse.jdt.core
)
public ITypeHierarchy
newSupertypeHierarchy(IWorkingCopy[], IProgressMonitor)
uległa
dezaktualizacji.
public ITypeHierarchy newSupertypeHierarchy(c,
IProgressMonitor)
IWorkingCopy[]
na
ICompilationUnit[]
.public ITypeHierarchy newTypeHierarchy(IWorkingCopy[],
IProgressMonitor)
uległa dezaktualizacji.
public ITypeHierarchy newTypeHierarchy(ICompilationUnit[],
IProgressMonitor)
IWorkingCopy[]
na
ICompilationUnit[]
.IClassFile
(pakiet
org.eclipse.jdt.core
)
public IJavaElement getWorkingCopy(IProgressMonitor,
IBufferFactory)
uległa dezaktualizacji.
public ICompilationUnit getWorkingCopy(WorkingCopyOwner,
IProgressMonitor)
WorkingCopyOwner
zastępuje interfejs IBufferFactory.
JavaCore
(pakiet org.eclipse.jdt.core
)
public IWorkingCopy[]
getSharedWorkingCopies(IBufferFactory)
uległa dezaktualizacji.
public ICompilationUnit[] getWorkingCopies(WorkingCopyOwner)
WorkingCopyOwner
zastępuje interfejs
IBufferFactory.
ICompilationUnit[]
na
IWorkingCopy[]
.SearchEngine
(pakiet org.eclipse.jdt.core
)
public SearchEngine(IWorkingCopy[])
uległa
dezaktualizacji.
public SearchEngine(ICompilationUnit[])
IWorkingCopy[]
na
ICompilationUnit[]
.Moduł dodatkowy org.eclipse.help, który był używany do przechowywania interfejsów API i punktów rozszerzeń służących do dostarczania zasobów rozszerzających system pomocy, a także do wyświetlania pomocy, zawiera teraz wyłącznie interfejsy API i punkty rozszerzeń służące do dostarczania i uzyskiwania dostępu do zasobów pomocy. Część domyślnej implementacji interfejsu użytkownika pomocy zawarta w tym module dodatkowym została przeniesiona do nowego modułu dodatkowego org.eclipse.help.base wraz z interfejsami API służącymi do rozszerzania implementacji. Interfejsy API i punkty rozszerzeń przeznaczone do dostarczania interfejsów użytkownika pomocy i wyświetlania pomocy zostały przeniesione do modułu org.eclipse.ui. Restrukturyzacja pozwala na zapewnienie aplikacjom większej elastyczności w odniesieniu do systemu pomocy. Nowa struktura pozwala aplikacjom bazującym na ogólnym środowisku roboczym udostępniać własne interfejsy lub implementacje pomocy, a także całkowicie pominąć system pomocy.
Ponieważ punkty rozszerzeń i pakiety interfejsów API, których dotyczy ta restrukturyzacja, są przeznaczone tylko do użytku przez sam system pomocy, nie zachodzi prawdopodobieństwo zakłócenia istniejących modułów dodatkowych. Zostały tutaj dołączone wyłącznie dla zachowania kompletności opisu:
W wersji 3.0 dodano nowy interfejs API umożliwiający implementowanie niestandardowych wyszukiwań. Oryginalny interfejs API jest już nieaktualny w wersji 3.0 i zaleca się migrację klientów do nowego interfejsu API w pakietach org.eclipse.search.ui oraz org.eclipse.search.ui.text.
Klienci będą musieli utworzyć implementacje interfejsów
ISearchQuery
, ISearchResult
oraz
ISearchResultPage
. Implementacja interfejsu
ISearchResultPage
musi zostać zatem wniesiona do nowego punktu
rozszerzenia org.eclipse.search.searchResultViewPages
.
Domyślne implementacje interfejsów ISearchResult
i
ISearchResultPage
są udostępniane w pakiecie
org.eclipse.search.ui.text
.
Przed wprowadzeniem wersji 3.0 wywołanie metody SWT DirectoryDialog.setMessage(String string) lub MessageBox.setMessage(String string) z wartością null dla łańcucha spowodowałoby wyświetlenie okna dialogowego z tytułem niezawierającym żadnego tekstu. Zachowanie to nie wynikało ze specyfikacji (przekazywanie wartości null nie było nigdy dozwolone) i rodziło problemy z metodą getMessage, która nie może zwracać wartości null. W wersji 3.0 przekazanie wartości null powoduje teraz zgłoszenie wyjątku IllegalArgumentException, a specyfikacje zostały odpowiednio zmodyfikowane, aby odzwierciedlić to zachowanie i uspójnić z metodą w nadklasie Dialog.setMessage. Jeśli wykorzystuje się metodę Dialog.setMessage, należy się upewnić, że przekazany łańcuch nigdy nie jest wartością null. Aby uzyskać okno dialogowe bez tytułu, należy po prostu przekazać pusty łańcuch.
Obsługa operacji współbieżnych wymaga bardziej zaawansowanych sposobów sygnalizowania postępu dla operacji modalnych. W ramach ulepszania zwracanych odpowiedzi i reakcji w klasie IProgressService zaimplementowano dodatkową obsługę postępu. Nadal działa istniejący do tej pory sposób sygnalizowania postępu za pomocą klasy ProgressMonitorDialog. Jednak aby zwiększyć walory użytkowe, zaleca się migrację do nowego interfejsu IProgressService.
Odpowiednie instrukcje na ten temat zawiera dokument Showing Modal Progress in Eclipse 3.0 (Sygnalizowanie postępu dla operacji modalnych w środowisku Eclipse 3.0).
Usunięto punkt rozszerzenia grup akcji debugowania (org.eclipse.debug.ui.debugActionGroups). W wersji Eclipse 3.0 w środowisku roboczym wprowadzono obsługę działań za pośrednictwem punktu rozszerzenia org.eclipse.platform.ui.activities. Obsługa ta obejmuje wszystkie funkcje udostępniane przez grupy akcji debugowania i jest łatwiejsza w użyciu (obsługuje wzorce zamiast wyczerpującego określania wszystkich akcji). Dostępny jest również programowy interfejs API do obsługi tych funkcji. Nieusunięcie odwołań do starego punktu rozszerzenia nie spowoduje żadnych błędów. Zostaną one po prostu zignorowane. Zaleca się, aby dostawcy produktów korzystali z obsługi działań oferowanej przez środowisko robocze w celu powiązania akcji debugera specyficznych dla języka z działaniami specyficznymi dla języka (np. akcje debugera C++ można powiązać z działaniem o nazwie "Opracowywanie kodu C++").
Interfejs IBreakpointManager definiuje teraz metody setEnabled(boolean) oraz isEnabled(). Kiedy menedżer punktów zatrzymania jest wyłączony, debugery będą ignorować wszystkie zarejestrowane punkty zatrzymania. Platforma debugowania udostępnia również nowy mechanizm nasłuchiwania, IBreakpointManagerListener, który pozwala klientom rejestrować się w ramach menedżera punktów zatrzymania w celu otrzymania powiadomienia o zmianie jego stanu. Widok Punkty zatrzymania wywołuje ten interfejs API z poziomu nowej akcji przełączania, która pozwala użytkownikom "pominąć wszystkie punkty zatrzymania". Działanie debugerów, które nie uwzględniają stanu menedżera punktów zatrzymania, będzie wyglądało na nieprawidłowe, kiedy użytkownik spróbuje skorzystać z tej funkcji.
Języki zbliżone do języka Java (takie jak JSP, SQLJ, JWS itd.) powinny oferować możliwość uczestnictwa w wyszukiwaniu Java. W szczególności implementatorzy takich języków powinni być w stanie:
Implementatorów tego typu określa się mianem uczestników wyszukiwania. Rozszerzają oni klasę SearchParticipant. Uczestnicy wyszukiwania są przekazywani do zapytań - patrz opis metody SearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor).
W przypadku indeksowania lub znajdowania dopasowań uczestnik wyszukiwania musi definiować podklasę klasy SearchDocument, która będzie w stanie pobrać treść dokumentu, przesłaniając metodę getByteContents() lub getCharContents(). Instancja tej podklasy jest zwracana przez metodę getDocument(String).
Uczestnik wyszukiwania, który chce indeksować wybrany dokument, skorzysta z metody SearchParticipant.scheduleDocumentIndexing(SearchDocument, IPath), aby zaplanować indeksowanie tego dokumentu w określonym indeksie. Kiedy dokument będzie już gotowy do indeksowania, struktura bazowa wywoła metodę SearchParticipant.indexDocument(SearchDocument, IPath). Uczestnik wyszukiwania uzyskuje następnie treść dokumentu, analizuje ją i dodaje wpisy indeksu przy użyciu metody SearchDocument.addIndexEntry(char[], char[]).
Po zakończeniu indeksowania można tworzyć zapytania bazujące na indeksach i znajdować wyniki przy użyciu metody SearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor). Powoduje to w pierwszej kolejności przekazanie do każdego uczestnika wyszukiwania żądania dotyczącego indeksów wymaganych do przeprowadzenia zapytania. Używana jest do tego metoda SearchParticipant.selectIndexes(SearchPattern, IJavaSearchScope). Dla każdej pozycji indeksu, która pasuje do zadanego wzorca, tworzony jest dokument wyszukiwania - w tym celu do uczestnika wyszukiwania kierowane jest odpowiednie zapytanie (patrz getDocument(String)). Wszystkie te dokumenty są przekazywane do uczestnika wyszukiwania w celu znalezienia wyników za pomocą metody locateMatches(SearchDocument[], SearchPattern, IJavaSearchScope, SearchRequestor, IProgressMonitor). Uczestnik wyszukiwania powiadamia element SearchRequestor o wynikach za pomocą metody acceptSearchMatch(SearchMatch) i przekazuje instancję podklasy klasy SearchMatch.
Uczestnik wyszukiwania może delegować część swojej pracy do domyślnego uczestnika wyszukiwania Java. Instancję tego uczestnika uzyskuje się przy użyciu metody SearchEngine.getDefaultSearchParticipant(). Na przykład uczestnik SQLJ poproszony o znalezienie dopasowań może utworzyć dokumenty .java na bazie swoich dokumentów .sqlj i delegować pracę do uczestnika domyślnego, przekazując mu te dokumenty .java.