Incompatibiliteit tussen Eclipse 3.1 en 3.2

Tussen Eclipse 3.1 en 3.2 komen enige punten van incompatibiliteit voor die van invloed op plugins zijn. In de volgende secties worden de aspecten besproken die zijn gewijzigd en vindt u instructies voor de migratie van 3.1-plugins naar 3.2. U hoeft de informatie alleen te raadplegen als u problemen ondervindt met het uitvoeren van 3.1-plugins in 3.2.

  1. Resources hoeven zich niet langer in het lokale bestandssysteem te bevinden
  2. API-wijzingen van MultiPageEditorSite
  3. Contentwijzigingen in config.ini
  4. Contentwijzigingen in applicaties die via jnlp worden gebruikt
  5. Expliciete aanroepen van Bundle.start() dwingen de bundel tot activering bij opnieuw starten
  6. Liggend streepje niet langer vervangen door koppelteken in versienummers van plugins

1. Resources hoeven zich niet langer in het lokale bestandssysteem te bevinden

Van toepassing op: clients van de IWorkspace-API die ervanuit gaan dat resources in het lokale bestandssysteem zijn opgeslagen.

Beschrijving: Vóór Eclipse 3.2 was elk IResource-item gekoppeld aan een bestand of een directory in een bestandssysteem, waartoe toegang kon worden verkregen via java.io.File. In Eclipse 3.2 is ondersteuning toegevoegd voor het maken van resources waarvan de inhoud is opgeslagen in een willekeurig onderliggend bestandssysteem. Resources op basis van deze ondersteuning zijn niet langer toegankelijk via java.io.File.

Vereiste actie: De oude methode IResource.getLocation() retourneert het lokale bestandssysteempad van een resource. Deze methode retourneert null voor resources die niet in het lokale bestandssysteem zijn opgeslagen. Meestal werd getLocation() aangeroepen om een instance van java.io.File te kunnen ophalen, maar dit is niet meer mogelijk voor resources die zich niet in het lokale bestandssysteem bevinden.

De nieuwe plugin org.eclipse.core.filesystem biedt generieke bestandssysteem-API die u in plaats van java.io.File kunt gebruiken. Een instance van org.eclipse.core.filesystem.IFileStore biedt vrijwel alle methoden die ook in java.io.File beschikbaar zijn. In het volgende codefragement wordt een instance van IFileStore gemaakt voor een bepaalde resource:

   IResource resource = ...; // een resource
   IFileStore store = EFS.getStore(resource.getLocationURI());

De volgende tabel bevat equivalente methoden van IFileStore voor bewerkingen die meestal met java.io.File worden uitgevoerd:

java.io.FileIFileStore
Wissen Wissen
getName getName
getParentgetParent
listchildNames
mkdirmkdir(EFS.SHALLOW, null)
mkdirsmkdir(EFS.NONE, null)
renameTomove
new FileInputStream(file)openInputStream
new FileOutputStream(file)openOutputStream

In de API van IFileStore zijn de meeste gegevens van een bestand opgeslagen in de structuur IFileInfo, die kan worden opgehaald door IFileStore.fetchInfo() aan te roepen. Deze methode biedt betere optimalisatie dan code van java.io.File, omdat tal van bestandskenmerken vaak met één systeemaanroep kunnen worden opgehaald. De gegevens van IFileInfo raken verouderd als het onderliggende bestand wordt gewijzigd, en dus moeten de instances niet langer worden behouden dan nodig is. Dit zijn enkele methoden van java.io.File waarvoor een equivalent beschikbaar is in IFileInfo:

java.io.FileIFileInfo
canWriteisReadOnly
existsexists
getName getName
isDirectoryisDirectory
isFile!isDirectory()
isHiddenisHidden
lastModifiedgetLastModified
lengthgetLength
setLastModifiedsetLastModified
setReadOnlysetAttribute(EFS.ATTRIBUTE_READ_ONLY, true)

Een concreet voorbeeld: Een aanroep van java.io.File.exists() kan nu worden vervangen door IFileStore.fetchInfo().exists(). Als IFileInfo wordt gewijzigd, moet het resultaat worden doorgegeven met de methode IFileStore.putInfo. In het volgende codefragment verandert het kenmerk alleen-lezen van een bestand:

   IFileStore store = ...; // een bestandsarchief
   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);

IProjectDescription.getLocation()

Net als voor de methode getLocation() hoeft de locatie van de projectbeschrijving niet meer in het lokale bestandssysteem te zijn. De locatie van een resource in een willekeurig bestandssysteem kan worden opgehaald met de methode IProjectDescription.getLocationURI().

Lokale cache

Enkele clients vereisen dat een bestand lokaal is. Er kan bijvoorbeeld een standaard ingebouwde tool worden gestart voor het bestand of er kunnen bibliotheken worden gebruikt die niet gekoppeld zijn aan Eclipse en alleen met bestandssysteemresources kunnen werken (zoals java.util.zip.ZipFile). In dergelijke situaties kunt u via IFileStore een lokale in de cache geplaatste kopie van de inhoud ophalen:

   IFileStore store = ...; // een bestandsarchief
   // controleren of het archief direct als lokaal bestand kan worden gezien
   java.io.File local = store.toLocalFile(EFS.NONE, null);
   // zo niet, lokale in cache geplaatste kopie van bestand ophalen
   if (local == null)
      local = store.toLocalFile(EFS.CACHE, null);

Nadat u een cachekopie van een bestand hebt opgehaald, wordt deze niet gesynchroniseerd met het bestandssysteem waarin het oorspronkelijke bestand zich bevindt. Het aanbrengen van wijzigen in de cachekopie is niet van invloed op het onderliggende bestand.

Rekening houden met onvoorziene situaties

Voor clients die niet met resources buiten het lokale bestandssysteem kunnen werken is het wellicht een goed idee de code aan te passen om rekening te houden met onvoorziene situaties. Indien wordt vastgesteld dat een resource zich buiten het lokale bestandssysteem bevindt, kan de resource worden genegeerd of kan de gebruiker worden gewaarschuwd over het feit dat de resource niet geschikt is. Om te bepalen of een resource in het lokale bestandssysteem staat moet u het bestandssysteemschema achterhalen. U kunt dit als volgt voor een resource opvragen:

   IResource resource = ...; // een resource
   URI uri = resource.getLocationURI();
   if (uri != null && EFS.SCHEME_LOCAL.equals(uri.getScheme())) {
      // bestand is in lokaal bestandssysteem
        } else {
      // bestand is niet in lokaal bestandssysteem
   }

Als u over een instance van IFileStore beschikt, kunt u het schema als volgt ophalen:

   IFileStore store = ...; // een bestandsarchief
   store.getFileSystem().getScheme();

2. API-wijzigingen van MultiPageEditorSite

Van toepassing op: clients die MultiPageEditorSite.progressStart() of MultiPageEditorSite.progressEnd() aanroepen.

Beschrijving: Tijdens de ontwikkeling van Eclipse 3.0 zijn deze methoden toegevoegd in het kader van voortgangsondersteuning. Vóór release 3.0 is de afhandeling van voortgang gewijzigd, waardoor deze methode overbodig is geraakt. Vanwege programmeursfouten zijn deze openbare methoden achtergebleven in release 3.0. De twee methoden hebben nooit een functie gehad in Eclipse-releases en zijn daarom gewist.

Vereiste actie: Clients die MultiPageEditorSite.progressStart() of MultiPageEditorSite.progressEnd() aanroepen moeten IWorkbenchSiteProgressService gaan gebruiken.

3. Contentwijzigingen in config.ini

Van toepassing op: Clients met een aangepaste config.ini die hun applicatie upgraden naar 3.2.

Beschrijving: Vóór 3.2 was de waarde voor osgi.bundles in de config.ini meestal org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start. Door de runtimeherstructurering moet deze waarde worden gewijzigd om de toepassing nog te kunnen starten.

Vereiste actie: Wijzig de waarde van osgi.bundles zodat deze org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start bevat.

4. Contentwijzigingen in applicaties die via jnlp worden gebruikt

Van toepassing op: Clients die RCP-applicaties gebruiken en een waarde hebben opgegeven voor osgi.bundles.

Beschrijving: Vóór 3.2 was de waarde voor osgi.bundles in het jnlp-bestand meestal org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start. Als gevolg van de runtimeherstructurering moet deze waarde worden gewijzigd om te voorkomen dat er NullPointerExceptions optreden die ervoor zorgen dat de applicatie niet kan worden gestart.

Vereiste actie: Wijzig de waarde van osgi.bundles zodat deze org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start bevat.

5. Expliciete aanroepen van Bundle.start() dwingen de bundel tot activering bij opnieuw starten

Van toepassing op: clients die Bundle.start() aanroepen.

Beschrijving: In Eclipse wordt een bundel aangeduid als een lazy start-bundel door de header Eclipse-LazyStart te gebruiken (of de gedeprecieerde header Eclipse-AutoStart). In Eclipse 3.1 markeerde de methode org.osgi.framework.Bundle.start() de lazy start-bundels niet als permanent gestart. Dit betekende dat de lazy start-bundels niet automatisch opnieuw werden gestart wanneer Eclipse opnieuw werd gestart. De javadoc for Bundle.start() geeft aan dat er het volgende moet gebeuren wanneer de methode wordt aangeroepen.

"Persistently record that this bundle has been started. When the Framework is restarted, this bundle must be automatically started."

In Eclipse 3.2 is de methode Bundle.start() aangepast zodat de bundel, zelfs als het een lazy start-bundel is, is gemarkeerd als permanent gestart. Deze correctie was vereist om te kunnen voldoen aan de OSGi Framework-specificatie. Het resultaat is dat items die Bundle.start() aanroepen, ervoor zorgen dat de bundel wordt gestart wanneer Eclipse wordt gestart. Over het algemeen wordt dit gezien als een slechte methode omdat het ervoor zorgt dat er overbodige bundels worden gestart wanneer Eclipse wordt gestart. In sommige gevallen kan het zorgen voor onverwachte resultaten zoals bug 134412.

Vereiste actie: Clients van Bundle.start() moeten evalueren of het hun bedoeling is om de bundel elke keer wanneer Eclipse opnieuw wordt gestart, te activeren. Als dat niet de bedoeling is, moeten clients een andere manier bedenken om de bundel te activeren. In de meeste gevallen kan het aanroepen van Bundle.start() worden vermeden door toe te staan dat de doelbundel volgens de lazy start-methode wordt geactiveerd wanneer er klassen uit deze bundel worden geladen. Er zijn uitzonderlijke situaties waarin het nodig is dat een lazy start-bundel expliciet wordt geactiveerd, maar niet wordt gemarkeerd om permanent te worden gestart wanneer Eclipse opnieuw wordt gestart. In dit soort situaties moet niet Bundle.start() worden aangeroepen, maar moet Bundle.loadClass() worden gebruikt om een klasse te laden uit de bundel die moet worden geactiveerd.

5. Liggend streepje niet langer vervangen door koppelteken in versienummers van plugins

In Eclipse 3.0 was het gebruik van het liggend streepje ('_') in het versienummer van plugins niet ondersteund, maar ook niet afgedwongen. Als het versienummer van een plugin een liggend streepje bevatte, werd dit omgezet in een koppelteken ('-') wanneer de plugin naar het bestandssysteem werd geëxporteerd en ook wanneer de plugin vanaf een updatesite werd geïnstalleerd.
In Eclipse 3.1 mochten er wel liggende streepjes in het versienummer worden gebruikt, dus werden de versienummers van plugins met liggende streepjes niet gewijzigd wanneer een dergelijke plugin werd geëxporteerd of geïnstalleerd. Deze wijziging is niet opgenomen in de handleiding bij de migratie van 3.0 naar 3.1. De stand van zaken is dat we de compatibiliteit met Eclipse 3.1 behouden en plugins met liggende streepjes in hetversienummer moeten rekening houden met de bovengenoemde wijzigingen wanneer ze te maken krijgen met oude pluginversies (zowel bij het exporteren als bij het gebruik van updatesites). Dit betekent bijvoorbeeld dat pluginleveranciers die oude versies van hun plugin op een updatesite hebben staan, ervoor moeten zorgen dat de naam in het bestandssysteem overeenkomt met de naam van de plugin.