W wersji 3.2 środowiska Eclipse wprowadzono zmiany powodujące niezgodność z wersją 3.1, które mają wpływ na wtyczki. Poniżej opisano obszary, w których nastąpiły zmiany, a także podano instrukcje umożliwiające migrację wtyczek z wersji 3.1 do wersji 3.2. Z podanych informacji należy korzystać jedynie w sytuacji, gdy przy uruchamianiu wtyczki z wersji 3.1 w środowisku w wersji 3.2 występują problemy.
Zakres: Klienty interfejsu API IWorkspace
, w przypadku których zakłada się, że zasoby są przechowywane w lokalnym systemie plików.
Opis: Przed wprowadzeniem wersji 3.2 środowiska Eclipse wszystkim istniejącym interfejsom IResource
odpowiadały pliki lub katalogi w systemie plików, które były dostępne za pośrednictwem klasy java.io.File
. W środowisku Eclipse 3.2 dodano możliwość tworzenia zasobów, których treść jest przechowywana w dowolnym systemie plików. Zasoby korzystające z tej opcji nie mogą już być odzwierciedlane bezpośrednio jako klasa java.io.File.
Wymagane działanie: Dotychczasowa metoda IResource.getLocation() zwraca ścieżkę do zasobu w lokalnym systemie plików. W przypadku zasobów, które nie są przechowywane w lokalnym systemie plików, zwracana jest wartość zerowa. W większości elementów wywołujących metodę getLocation() rozwiązanie to było stosowane w celu uzyskania instancji klasy java.io.File, której nie można już stosować w odniesieniu do zasobów przechowywanych poza lokalnym systemem plików.
Nowa wtyczka org.eclipse.core.filesystem pozwala uzyskać dostęp do ogólnego interfejsu API systemu plików, z którego można korzystać zamiast klasy java.io.File. Instancja interfejsu org.eclipse.core.filesystem.IFileStore pozwala korzystać z większości metod dostępnych za pośrednictwem klasy java.io.File. Poniższy fragment kodu pozwala uzyskać instancję interfejsu IFileStore w odniesieniu do danego zasobu:
IResource resource = ...;//zasób IFileStore store = EFS.getStore(resource.getLocationURI());
W poniższej tabeli przedstawiono metody interfejsu IFileStore odpowiadające operacjom wykonywanym zazwyczaj za pomocą klasy java.io.File.
java.io.File | IFileStore |
---|---|
delete | delete |
getName | getName |
getParent | getParent |
list | childNames |
mkdir | mkdir(EFS.SHALLOW, null) |
mkdirs | mkdir(EFS.NONE, null) |
renameTo | move |
new FileInputStream(file) | openInputStream |
new FileOutputStream(file) | openOutputStream |
W przypadku interfejsu API IFileStore większość informacji o pliku jest przechowywana w strukturze pod nazwą IFileInfo, którą uzyskuje się poprzez wywołanie metody IFileStore.fetchInfo(). Rozwiązanie to pozwala lepiej zoptymalizować kod niż klasa java.io.File, ponieważ wiele atrybutów związanych z plikiem można w wielu przypadkach uzyskać za pomocą jednego wywołania do systemu plików. Informacje zawarte w interfejsie IFileInfo stają się nieaktualne w przypadku zmiany pliku, którego dotyczą. W związku z tym instancje należy przechowywać wyłącznie wtedy, gdy są potrzebne. Poniżej przedstawiono metody klasy java.io.File, które mają swoje odpowiedniki w interfejsie IFileInfo:
java.io.File | IFileInfo |
---|---|
canWrite | isReadOnly |
exists | exists |
getName | getName |
isDirectory | isDirectory |
isFile | !isDirectory() |
isHidden | isHidden |
lastModified | getLastModified |
length | getLength |
setLastModified | setLastModified |
setReadOnly | setAttribute(EFS.ATTRIBUTE_READ_ONLY, true) |
Konkretnym przykładem może być kod, za pomocą którego wcześniej wywoływano metodę java.io.File.exists(), a obecnie można wywołać metodę IFileStore.fetchInfo().exists(). Zmodyfikowanie interfejsu IFileInfo powoduje konieczność ponownego zapisania rezultatów za pomocą metody IFileStore.putInfo. Poniższy fragment kodu służy do zmiany atrybutu "tylko do odczytu" pliku.
IFileStore store = ...;//składnica plików IFileInfo info = store.fetchInfo(); boolean readOnly = info.getAttribute(EFS.ATTRIBUTE_READ_ONLY); info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, !readOnly); store.putInfo(info, EFS.SET_ATTRIBUTES, null);
Podobnie jak w przypadku metody getLocation(), opis projektu nie musi znajdować się w lokalnym systemie plików. Metoda IProjectDescription.getLocationURI() pozwala uzyskać informację o położeniu zasobu w dowolnym systemie plików.
W przypadku niektórych klientów konieczne jest lokalne odwzorowanie pliku. Dzieje się tak na przykład w sytuacji, w której uruchamiane jest rodzime narzędzie odwołujące się do danego pliku lub wykorzystywane są biblioteki nierozpoznające środowiska Eclipse, umożliwiające wyłącznie obsługę zasobów znajdujących się w systemie plików (np. java.util.zip.ZipFile). W takich przypadkach interfejs IFileStore zwraca na żądanie lokalną kopię treści zasobu przechowywaną w buforze.
IFileStore store = ...;//składnica plików //Sprawdzenie, czy plik można odwzorować bezpośrednio jako plik lokalny java.io.File local = store.toLocalFile(EFS.NONE, null); //Jeśli nie, żądanie udostępnienia lokalnej kopii pliku if (local == null) local = store.toLocalFile(EFS.CACHE, null);
Kopia pliku uzyskana z bufora nie pozostaje zsynchronizowana z wersją znajdującą się w systemie plików, z którego pochodzi. Zmodyfikowanie kopii przechowywanej w buforze nie powoduje zmodyfikowania pliku bazowego.
Kod klientów, które nie obsługują zasobów znajdujących się poza lokalnym systemem plików, można modyfikować w taki sposób, aby ich działanie w przypadku błędów było bardziej kontrolowane. Klienty mogą sprawdzać, czy dany zasób znajduje się w lokalnym systemie plików, a następnie ignorować je bądź powiadamiać użytkownika o napotkaniu nieobsługiwanego zasobu. Aby stwierdzić, czy zasób znajduje się w lokalnym systemie plików, należy poznać schemat systemu plików tego zasobu. Schemat ten można uzyskać z zasobu w następujący sposób:
IResource resource = ...;//zasób URI uri = resource.getLocationURI(); if (uri != null && EFS.SCHEME_LOCAL.equals(uri.getScheme())) { //Plik znajduje się w lokalnym systemie plików } else { //Plik nie znajduje się w lokalnym systemie plików }
Jeśli dostępna jest instancja interfejsu IFileStore, schemat można uzyskać w następujący sposób:
IFileStore store = ...;//składnica plików store.getFileSystem().getScheme();
Zakres: Klienty wywołujące metodę MultiPageEditorSite.progressStart()
lub MultiPageEditorSite.progressEnd()
.
Opis: Podczas opracowywania wersji 3.0 środowiska Eclipse dodano powyższe metody, które mają na celu zapewnienie obsługi informacji o postępie. Przed wprowadzeniem wersji 3.0 sposób obsługi informacji o postępie uległ zmianie, w związku z czym ówczesna metoda przestała być potrzebna. W wyniku błędu programistów powyższe metody publiczne pozostały jednak w wersji 3.0. Nie spełniały one jednak żadnej funkcji w którejkolwiek wersji środowiska Eclipse, w związku z czym zostały usunięte.
Wymagane działanie: Klienty wywołujące metodę MultiPageEditorSite.progressStart()
lub MultiPageEditorSite.progressEnd()
należy przełączyć na korzystanie z interfejsu IWorkbenchSiteProgressService
.
Zakres: Klienty korzystające z niestandardowych plików config.ini, których aplikacje są przenoszone do wersji 3.2.
Opis: Przed wprowadzeniem wersji 3.2 atrybut osgi.bundles w pliku config.ini miał standardowo wartość org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start
. W związku z refaktoryzacją środowiska wykonawczego wartość tę należy zaktualizować, aby można było pomyślnie uruchomić aplikację.
Wymagane działanie: Należy zmienić wartość atrybutu osgi.bundles na następującą: org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start.
Zakres: Klienty, na których wdrożono aplikacje RCP i określono wartość atrybutu osgi.bundles.
Opis: Przed wprowadzeniem wersji 3.2 atrybut osgi.bundles w głównym pliku jnlp miał standardowo wartość org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start
. W związku z refaktoryzacją środowiska wykonawczego wartość tę należy zaktualizować. W przeciwnym razie mogą być zgłaszane błędy NullPointerException
, które uniemożliwiają uruchomienie aplikacji.
Wymagane działanie: Należy zmienić wartość atrybutu osgi.bundles na następującą: org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start.
Zakres: Klienty wywołujące metodę Bundle.start()
.
Opis: W środowisku Eclipse opóźnione uruchamianie pakunku określa się za pomocą nagłówka Eclipse-LazyStart
(lub nieaktualnego nagłówka Eclipse-AutoStart
). W wersji Eclipse 3.1 skorzystanie z metody org.osgi.framework.Bundle.start()
nie powodowało oznaczenia pakunków uruchamianych z opóźnieniem jako uruchamianych trwale. W związku z tym pakunki uruchamiane z opóźnieniem nie były nigdy oznaczane jako uruchamiane trwale, a tym samym nie były automatycznie uruchamiane przy restarcie środowiska Eclipse. W dokumentacji Javadoc dotyczącej metody Bundle.start()
wskazano, że przy wywoływaniu metody:
"Należy trwale zarejestrować, że pakunek został uruchomiony. Przy restarcie środowiska pakunek musi zostać uruchomiony automatycznie."
W środowisku Eclipse 3.2 metoda Bundle.start()
została skorygowana w sposób umożliwiający prawidłowe oznaczanie pakunku jako uruchamianego trwale, nawet jeśli jest to pakunek uruchamiany z opóźnieniem. Poprawka ta była niezbędna w celu zapewnienia zgodności ze specyfikacją środowiska OSGi. W rezultacie elementy wywołujące metodę Bundle.start()
będą wymuszały uruchamianie pakunku w przypadku restartu środowiska Eclipse. Zasadniczo działanie takie uznaje się za niewłaściwe, ponieważ powoduje ono aktywowanie zbędnych pakunków przy każdym uruchomieniu środowiska Eclipse. W niektórych przypadkach może to powodować nieoczekiwane rezultaty, takie jak w przypadku błędu 134412.
Wymagane działanie: W przypadku klientów korzystających z metody Bundle.start()
należy ocenić, czy pakunek ma być z założenia aktywowany trwale przy każdym restarcie. Jeśli nie jest to zamierzone działanie, należy określić inny sposób uruchamiania pakunku przez klienta. W większości przypadków można uniknąć wywołań metody Bundle.start()
, umożliwiając opóźnioną aktywację pakunku docelowego z chwilą ładowania zawartych w nim klas. Są to dosyć nietypowe sytuacje, w których wymaga się szybkiej aktywacji pakunku uruchamianego z opóźnieniem, nie ma natomiast potrzeby trwałego oznaczania tego pakunku jako aktywowanego po restarcie. W takich sytuacjach zamiast wywoływać metodę Bundle.start()
należy skorzystać z metody Bundle.loadClass()
, aby załadować klasę z pakunku, który ma zostać aktywowany.
W środowisku Eclipse 3.0 korzystanie ze znaku podkreślenia ("_") w segmencie kwalifikatora identyfikatora wersji nie było obsługiwane ani egzekwowane. Jeśli kwalifikator identyfikatora wersji wtyczki zawierał znak podkreślenia, podczas eksportowania wtyczki do systemu plików oraz instalowania wtyczki z serwisu z aktualizacjami znak ten był przekształcany w łącznik ("-").
W środowisku Eclipse 3.1 reguły dotyczące dozwolonych znaków w kwalifikatorach zostały rozluźnione, co pozwoliło uwzględnić znak podkreślenia. W związku z tym podczas eksportu lub instalacji wtyczki, której nazwa zawiera taki znak, kwalifikator nie ulega zmianie. Zmiana ta została przypadkowo pominięta w podręczniku migracji z wersji 3.0 do wersji 3.1.W późniejszych wersjach (także w wersji Eclipse 3.2) zachowywana jest zgodność z wersją Eclipse 3.1. W związku z tym w przypadku wspomnianych wcześniej wtyczek, których kwalifikatory wersji zawierają znaki podkreślenia, należy uwzględnić powyższe zmiany, ponieważ mają one wpływ na obsługę wcześniejszych wersji tych wtyczek (zarówno przy eksporcie, jak i przy pobieraniu z witryn z aktualizacjami). Oznacza to na przykład, że dostawcy wtyczek dysponujący wcześniejszymi wersjami wtyczek w serwisie z aktualizacjami powinni dopilnować, aby nazwy w systemie plików odpowiadały faktycznym nazwom wtyczek.