Účast na uložení pracovního prostoru

Zpracování uložení pracovního prostoru se spouští, když uživatel zavře pracovní plochu, a také jej periodicky spouští platforma.  Moduly plug-in se mohou podílet na procesu ukládání pracovního prostoru tak, aby byla kritická data modulu plug-in uložena na disk, kdykoli je ukládán zbytek trvalých dat pracovního prostoru.

Proces ukládání pracovního prostoru je možné použít také ke sledování změn, k nimž dochází mezi aktivacemi vašeho modulu plug-in.

Implementace účastníka ukládání

Chcete-li se podílet na ukládání pracovního prostoru, musíte do pracovního prostoru přidat účastníka ukládání. To se zpravidla dělá během spouštěcí metody vašeho modulu plug-in.  Zde také načtete jakýkoli stav, který jste si mohli uložit, když byl váš plug-in naposledy vypnut.

Podívejme se na jednoduchý plug-in, který demonstruje proces ukládání.

   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;
      // instance modulu plug-in má načíst ze souboru jakýkoli důležitý stav.
         File f = getStateLocation().append(location).toFile();
         readStateFrom(f);
      }

      protected void writeImportantState(File target) {
      }
   }

ISaveParticipant definuje protokol pro účastníka ukládání pracovního prostoru. Implementátory tohoto rozhraní mohou zajistit chování pro různé fáze procesu ukládání.  Podívejme se na tyto fáze a na to, jak naše třída WorkspaceSaveParticipant implementuje jednotlivé kroky.

      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();
               // uložit stav modulu plug-in
               int saveNumber = context.getSaveNumber();
         String saveFileName = "save-" + Integer.toString(saveNumber);
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
               // pokud nelze zapisovat, dojde k vyvolání výjimky a nebudeme aktualizovat cestu
               myPluginInstance.writeImportantState(f);
               context.map(new Path("save"), new Path(saveFileName));
               context.needSaveNumber();
      break;
            case ISaveContext.PROJECT_SAVE:
               // zapojit projekt do této operace uložení
               IProject project = context.getProject();
               // uložit své informace, je-li to nutné
      break;
            case ISaveContext.SNAPSHOT:
               // Tato operace musí být opravdu rychlá, protože
               // pracovní prostor může vyžadovat časté
               // snímkování.
      break;
         }
      }

ISaveContext popisuje informace o operaci uložení.  Existují tři typy operací uložení:  FULL_SAVE, SNAPSHOT a PROJECT_SAVE.  Účastníci ukládání by měli dávat pozor, aby provedli zpracování odpovídající tomu druhu události uložení, který obdrželi.  Například k událostem snímkování, které mají modulům plug-in umožnit ukládat jejich kritický stav, může docházet vcelku často.  Dlouhé ukládání stavu, který může být v případě zhroucení znovu vypočítán, zpomaluje systém.

Při vytváření záložních datových souborů se používá číslo uložení a tyto soubory jsou pak pojmenovány s využitím pořadových čísel (save-1, save-2 apod.)  Každý záložní soubor je mapovaný na název logického souboru (save), který je nezávislý na čísle uložení. Data modulu plug-in jsou zapsána do příslušného souboru a později mohou být načtena bez znalosti konkrétního čísla uložení poslední úspěšné operace uložení.  Vzpomeňte si, že jsme tuto techniku viděli ve spouštěcím kódu našeho  modulu plug-in:

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

Po uložením svých dat a namapování názvu souboru voláme needSaveNumber, abychom ukázali, že jsme se aktivně podíleli na uložení pracovního prostoru a chceme této aktivitě uložení přiřadit číslo. Čísla uložení lze použít k vytvoření datových souborů, viz výše. 

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

         // odstranit starý uložený stav, protože už není zapotřebí
         int previousSaveNumber = context.getPreviousSaveNumber();
         String oldFileName = "save-" + Integer.toString(previousSaveNumber);
         File f = myPluginInstance.getStateLocation().append(oldFileName).toFile();
         f.delete();
      }

Zde vyčistíme informace o uložení z předcházející operace uložení.  Použijeme getPreviousSaveNumber, abychom získali číslo uložení přiřazené v předchozí operaci uložení (nikoli v té, která právě skončila).  Toto číslo používáme při vytváření názvu souboru, který potřebujeme odstranit.  Všimněte si, že nepoužíváme mapování logického souboru stavu uložení, protože jsme již namapovali číslo svého aktuálního záložního souboru. 

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

         // protože operace uložení selhala, odstranit uložený stav, který jsme právě zapsali
         int saveNumber = context.getSaveNumber();
         String saveFileName = "save-" + Integer.toString(saveNumber);
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
         f.delete();
      }

Zde odstraníme stav, který jsme práce uložili.  Všimněte si, že k vytvoření názvu souboru, který jsme právě uložili, používáme aktuální číslo uložení.  Se skutečností, že jsme tento název souboru namapovali do ISaveContext, si nemusíme dělat starosti. Když operace uložení selže, platforma kontext sama vyřadí.

Pokud váš plug-in kdykoli během životního cyklu uložení způsobí výjimku, bude odebrán z aktuální operace uložení a neobdrží žádnou ze zbývajících metod daného životního cyklu.  Pokud například selže během své metody saving, nedostane už zprávu rollback ani doneSaving

Použití dříve uloženého stavu

Když do pracovního prostoru přidáte účastníka uložení, vrátí pracovní prostor objekt ISavedState, který popisuje, co váš plug-in uložil během své poslední operace uložení (nebo hodnotu null, pokud váš plug-in dosud neuložil žádný stav). Tento objekt lze použít pro přístup k informacím z předchozího ukládacího souboru (pomocí čísla uložení a mapy souboru) nebo při zpracování změn, k nimž došlo mezi aktivacemi modulu plug-in.

Přístup k ukládacím souborům

Pokud byla k uložení logicky pojmenovaných souborů podle čísla uložení použita mapa souboru, je možné použít tuto mapu k načtení dat z posledního známého stavu uložení.

   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();
      // instance modulu plug-in má načíst ze souboru jakýkoli důležitý stav.
      myPluginInstance.readStateFrom(f);
   }

Zpracování rozdílových dat prostředků mezi aktivacemi

Uvědomte si, že než je váš plug-in vůbec aktivován, může v pracovním prostoru dojít k libovolnému počtu událostí změn prostředků. Pokud chcete vědět, k jakým změnám došlo od chvíle, kdy byl váš plug-in deaktivován, můžete k tomu použít mechanizmus uložení, i když nepotřebujete uložit žádná jiná data.

Účastník uložení musí požádat, aby platforma jeho jménem udržovala rozdílová data prostředku. To se provádí jako součást operace uložení.

   public void saving(ISaveContext context) throws CoreException {
      // modul plug-in nemá žádný stav k uložení, ale požaduje,
      // aby při příští aktivaci byla použita rozdílová data prostředku.
      context.needDelta();
   }

Během spouštění modulu plug-in je možné přistupovat k dříve uloženému stavu a budou vytvořeny události změn pro všechny změny, k nimž došlo od posledního uložení.

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

Poskytovaná třída musí implementovat IResourceChangeListener, jak je popsáno v tématu Sledování změn prostředků.  Změny od posledního uložení jsou hlášeny jako součást události změny prostředků POST_AUTO_BUILD.

Poznámka:  V událostech změn uložených v ISavedState nejsou hlášeny změny značek. Musíte předpokládat, že od okamžiku uložení vašeho posledního stavu se mohly změnit jakékoli značky, možná dokonce všechny.