Deelnemen aan werkgebiedopslag

Het werkgebied wordt opgeslagen als de workbench wordt afgesloten door de gebruiker. Het kan ook periodiek door het platform gebeuren. Plugins kunnen deelnemen aan het opslagproces, zodat kritische plugingegevens op schijf worden opgeslagen als de rest van de permanente gegevens van het werkgebied wordt opgeslagen.

Het proces van het opslaan van het werkgebied kan ook worden gebruikt om wijzigingen te traceren die optreden tussen activeringen van uw plugin.

Een opslagdeelnemer implementeren

Voor deelname aan het opslaan van het werkgebied moet u een opslagdeelnemer toevoegen aan het werkgebied. Doorgaans gebeurt dit tijdens de opstartmethode van de plugin. Hier leest u ook de versie die u eventueel hebt opgeslagen toen de plugin de laatste keer werd afgesloten.

Hier volgt een voorbeeld van een eenvoudige plugin die aan het opslagproces deelneemt.

   package com.example.saveparticipant;

   import org.eclipse.core.runtime.*;
   import org.eclipse.core.resources.*;
   import java.io.File;
   import java.util.*;

   public class MyPlugin extends Plugin {
      private static MyPlugin plugin;

      public MyPlugin(IPluginDescriptor descriptor) {
         super(descriptor);
         plugin = this;
      }

      public static MyPlugin getDefault() {
         return plugin;
      }

      protected void readStateFrom(File target) {
      }

      public void startup() throws CoreException {
         super.startup();
   ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
   ISavedState lastState =
            ResourcesPlugin.getWorkspace().addSaveParticipant(this, saveParticipant);
         if (lastState == null)
            return;
         IPath location = lastState.lookup(new Path("save"));
         if (location == null)
            return;
         // de plugininstance moet belangrijke versies van het bestand lezen.
         File f = getStateLocation().append(location).toFile();
         readStateFrom(f);
      }

      protected void writeImportantState(File target) {
      }
   }

In ISaveParticipant wordt het protocol voor een werkgebiedopslagdeelnemer gedefinieerd. Implementors van deze interface kunnen gedrag aanleveren voor verschillende stadia van het opslagproces.  Wij kijken nu naar de stadia en hoe de klasse WorkspaceSaveParticipant deze stappen implementeert.

      public void prepareToSave(ISaveContext context) throws CoreException {
      }
   public void saving(ISaveContext context) throws CoreException {
         switch (context.getKind()) {
            case ISaveContext.FULL_SAVE:
         MyPlugin myPluginInstance = MyPlugin.getDefault();
               // pluginversie opslaan
               int saveNumber = context.getSaveNumber();
         String saveFileName = "save-" + Integer.toString(saveNumber);
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
               // als we niet schrijven, wordt een uitzondering verworpen en werken we het pad niet bij
               myPluginInstance.writeImportantState(f);
               context.map(new Path("save"), new Path(saveFileName));
               context.needSaveNumber();
      break;
            case ISaveContext.PROJECT_SAVE:
               // project bij deze opslagbewerking ophalen
               IProject project = context.getProject();
               // indien nodig informatie opslaan
      break;
            case ISaveContext.SNAPSHOT:
               // deze bewerking moet zeer snel zijn omdat
               // regelmatig snapshots aangevraagd kunnen worden
               // door het werkgebied.
      break;
         }
      }

De ISaveContext bevat informatie over de opslagbewerking.  Er zijn drie soorten opslagbewerkingen:  FULL_SAVE, SNAPSHOT en PROJECT_SAVE.  Opslagdeelnemers moeten zorgen dat ze het juiste verwerking uitvoeren voor het soort opslagevent. Snapshotevents kunnen bijvoorbeeld zeer vaak optreden en maken het mogelijk dat plugins hun kritische versie opslaan. Het opslaan van een versie die na een crash opnieuw berekend kan worden, maakt het platform langzamer.

Er wordt een opslagnummer gebruikt om gegevensopslagbestanden te maken die volgens een reeks getallen worden benoemd (save-1, save-2 enz.) Ieder opslagbestand krijgt een logische bestandsnaam (save) die onafhankelijk is van het opslagnummer. Plugingegevens worden naar het corresponderende bestand geschreven en kunnen later weer worden opgehaald zonder dat u het specifieke opslagnummer van de laatste succesvolle opslagbewerking kent.  We hebben deze techniek eerder gezien in de opstartcode van de plugin: 

IPath location = lastState.lookup(new Path("save"));

Nadat de gegevens zijn opgeslagen en een bestandnaam is toegewezen, roepen we needSaveNumber aan om aan te geven dat dat we actief hebben deelgenomen aan het opslaan van het werkgebied en dat we een nummer willen toekennen aan de opslagactiviteit. De opslagnummers kunnen worden gebruikt om gegevensbestanden zoals hierboven te maken.  

      public void doneSaving(ISaveContext context) {
         MyPlugin myPluginInstance = MyPlugin.getDefault();

         // oude opgeslagen versie wissen omdat deze niet meer nodig is
         int previousSaveNumber = context.getPreviousSaveNumber();
         String oldFileName = "save-" + Integer.toString(previousSaveNumber);
         File f = myPluginInstance.getStateLocation().append(oldFileName).toFile();
         f.delete();
      }

We schonen nu de opslaginformatie uit de vorige opslagbewerking op. We gebruiken getPreviousSaveNumber om het opslagnummer van de vorige opslagbewerking op te halen (niet de bewerking die we zojuist hebben voltooid). Met dit nummer construeren we de naam van het bestand dat we moeten wissen. Let op: we gebruiken de logische bestandstoewijzing van de opslagversie niet, omdat we het huidige opslagbestandsnummer al hebben toegewezen. 

      public void rollback(ISaveContext context) {
         MyPlugin myPluginInstance = MyPlugin.getDefault();

         // omdat de opslag is mislukt, wissen we de zojuist geschreven versie
         int saveNumber = context.getSaveNumber();
         String saveFileName = "save-" + Integer.toString(saveNumber);
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
         f.delete();
      }

Hier wissen we de versie die we zojuist hebben opgeslagen. We gebruiken het huidige opslagnummer om de bestandsnaam te construeren van het bestand dat we zojuist hebben opgeslagen. We hoeven ons geen zorgen te maken over het feit dat we deze bestandsnaam aan een ISaveContext hebben toegewezen. Het platform negeert de context als een opslagbewerking mislukt.

Als de plugin een uitzondering verwerpt tijdens de levenscyclus van de opslagbewerking, wordt deze verwijderd uit de huidige opslagbewerking en haalt geen van de resterende levenscyclusmethoden op. Als er bijvoorbeeld iets fout gaat tijdens het uitvoeren van de methode saving, krijgt u geen rollback- of doneSaving-bericht. 

Vorige opgeslagen versie gebruiken

Als u een opslagdeelnemer toevoegt aan het werkgebied, retourneert dit een ISavedState-object, waarin beschreven is wat de plugin heeft opgeslagen tijdens de laatste opslagbewerking (of null als de plugin eerder nog geen versies heeft opgeslagen). U kunt dit object gebruiken voor toegang tot informatie uit het vorige opslagbestand (met het opslagnummer en de bestandstoewijzing) of om wijzigingen te verwerken die zijn uitgevoerd tussen verschillende activeringen van de plugin.

Toegang tot de opslagbestanden

Als er een bestandstoewijzing is gebruikt om logisch benoemde bestanden op te slaan volgens een reeks opslagnummers, kan dezelfde toewijzing worden gebruikt om de gegevens op te halen uit de laatste bekende opgeslagen versie.

   ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
   ISavedState lastState =
      ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant);

   if (lastState != null) {
      String saveFileName = lastState.lookup(new Path("save")).toString();
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
         // de plugininstance moet belangrijke versies van het bestand lezen.
      myPluginInstance.readStateFrom(f);
   }

Resourcedelta's tussen activeringen verwerken

Er kan een willekeurig aantal resourcewijzigingsevents in het werkgebied optreden voordat de plugin wordt ingeschakeld. Als u wilt weten welke wijzigingen zijn doorgevoerd na het deactiveren van de plugin, kunt u hiervoor het opslagmechnisme gebruiken, zelfs als u andere gegevens moet opslaan.

De opslagdeelnemer moet het platform vragen om een resourcedelta bij te houden. Dit gebeurt als onderdeel van de opslagbewerking.

   public void saving(ISaveContext context) throws CoreException {
      // geen versie om op te slaan door de plugin, maar aanvraag om
      // resourcedelta te gebruiken voor een volgende activering.
      context.needDelta();
   }

Tijdens het opstarten van de plugin is de vorige opgeslagen versie toegankelijk en worden wijzigingsevents gemaakt voor alle wijzigingen die sinds de laatste opslag zijn doorgevoerd.

   ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
   ISavedState lastState =
      ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant);
   if (lastState != null) {
      lastState.processResourceChangeEvents(new MyResourceChangeReporter());
   }

De aangeleverde klasse moet IResourceChangeListener implementeren, zoals is beschreven in Resourcewijzigingen traceren. De wijzigingen die na de laatste opslagactie zijn doorgevoerd, worden gemeld als onderdeel van de resourcewijzigingsevent POST_AUTO_BUILD.

Opmerking:  Merktekenwijzigingen worden niet gemeld als wijzigingsevent in een ISavedState. U moet aannemen dat enige of alle merktekens zijn gewijzigd nadat de laatste versie is opgeslagen.