Työtilan tallennuksen käsittely liipaistaan, kun käyttäjä lopettaa työympäristön tai muulloin säännöllisesti ympäristön itsensä toimesta. Lisäosat voivat osallistua työtilan tallennuksen käsittelyyn, jotta tärkeät lisäosatiedot tallennetaan levyyn aina, kun työtilan muut pysyvät tiedot tallennetaan.
Työtilan tallennuksen avulla voi myös jäljittää muutoksia, jotka ovat tapahtuneet lisäosan aktivointien välillä.
Jotta tallennuksen osapuoli voisi osallistua työtilan tallennukseen, se on lisättävä työtilaan. Yleensä tämä tapahtuu lisäosan aloitusmetodin aikana. Tässä kohtaa voit myös lukea tilan, joka on ehkä tallennettu, kun lisäosa viimeksi lopetettiin.
Seuraavassa tarkastellaan yksinkertaista lisäosaa, joka havainnollistaa tallennuksen käsittelyä.
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; // lisäosan ilmentymän on luettava tärkeät tilat tiedostosta. File f = getStateLocation().append(location).toFile(); readStateFrom(f); } protected void writeImportantState(File target) { } }
ISaveParticipant määrittää käytännön työtilan tallennuksen osapuolelle. Tämän rajapinnan toteuttajat voivat määrittää tallennuksen eri vaiheiden toiminnan. Seuraavassa tarkastellaan näitä vaiheita ja sitä, kuinka luokka WorkspaceSaveParticipant toteuttaa kunkin vaiheen.
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(); // tallenna lisäosan tila int saveNumber = context.getSaveNumber(); String saveFileName = "save-" + Integer.toString(saveNumber); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); // jos kirjoitus ei onnistu, aiheutuu poikkeus eikä polkua päivitetä myPluginInstance.writeImportantState(f); context.map(new Path("save"), new Path(saveFileName)); context.needSaveNumber(); break; case ISaveContext.PROJECT_SAVE: // nouda tähän tallennustoimintoon liittyvä projekti IProject project = context.getProject(); // tallenna tarvittaessa sen tiedot break; case ISaveContext.SNAPSHOT: // Tämän toiminnon on oltava todella nopea, koska // työtila voi pyytää vedoksia // usein. break; } }
ISaveContext kuvaa tallennustoiminnon tietoja. Tallennustoimintoja on kolmea lajia: FULL_SAVE, SNAPSHOT ja PROJECT_SAVE. Tallennuksen osapuolten on oltava huolellisia, että toteuttavat vastaanottamaansa tallennustapahtumaan sopivan käsittelyn. Esimerkiksi vedostapahtumia (snapshot) voi sattua melko usein, ja niiden avulla lisäosien on tarkoitus voida tallentaa tärkeä tilansa. Jos käyttöhäiriössä uudelleen laskettavan tilan tallennukseen menee kauan, ympäristö hidastuu.
Tallennusnumeron avulla luodaan tietojen tallennustiedostoja, jotka nimetään peräkkäisten numeroiden avulla (save-1, save-2 jne.). Kullekin tallennustiedostolle määritetään vastaavuus loogiseen tiedostonimeen (save), joka ei määräydy tallennuksen numeron mukaan.Lisäosatiedot kirjoitetaan vastaavaan tiedostoon, josta ne voi noutaa myöhemmin tietämättä viimeisimmän onnistuneen tallennustoiminnon tallennusnumeroa. Tämä menettelyä käytettiin viimeksi lisäosan aloituskoodissa:
IPath location = lastState.lookup(new Path("save"));Kun tiedot on tallennettu ja tiedostonimen vastaavuus määritetty, kutsutaan kohdetta needSaveNumber työtilan tallennukseen osallistumisen osoittamiseksi ja tallennustoiminnon numeron määrittämiseksi. Tallennusnumeroiden avulla voi luoda datatiedostoja, kuten edellä.
public void doneSaving(ISaveContext context) { MyPlugin myPluginInstance = MyPlugin.getDefault(); // poista vanha tallennettu tila, koska se ei enää ole tarpeen int previousSaveNumber = context.getPreviousSaveNumber(); String oldFileName = "save-" + Integer.toString(previousSaveNumber); File f = myPluginInstance.getStateLocation().append(oldFileName).toFile(); f.delete(); }
Seuraavassa puhdistetaan edellisen tallennustoiminnon tallennustiedot. Kohteen getPreviousSaveNumber avulla noudetaan tallennusnumero, joka edellisessä tallennustoiminnossa on määritetty (ei siinä joka juuri valmistui). Tämän numeron avulla muodostetaan poistettavan tiedoston nimi. Huomaa, että tallennustilan loogisen tiedoston vastaavuusmääritystä ei käytetä, koska nykyisen tallennustiedoston numeron vastaavuus on jo määritetty.
public void rollback(ISaveContext context) { MyPlugin myPluginInstance = MyPlugin.getDefault(); // koska vanha tallennustoiminto ei onnistunut, poista juuri kirjoitettu tallennettu tila int saveNumber = context.getSaveNumber(); String saveFileName = "save-" + Integer.toString(saveNumber); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); f.delete(); }
Tässä poistetaan juuri tallennettu tila. Huomaa, että tässä käytetään nykyistä tallennusnumeroa, jonka avulla muodostetaan juuri tallennetun tiedoston tiedostonimi. Siitä ei tarvitse huolehtia, että tälle tiedostonimelle on määritetty vastaavuus kohteeseen ISaveContext. Ympäristö hylkää kontekstin, kun tallennustoiminto ei onnistu.
Jos lisäosa aiheuttaa poikkeuksen missä tahansa vaiheessa tallennuksen elinkaaren aikana, se poistetaan nykyisestä tallennustoiminnosta eikä se saa seuraavia elinkaaren metodeja. Jos esimerkiksi saving-metodi ei onnistu, et saa rollback- tai doneSaving-sanomaa.
Kun lisäät tallennuksen osapuolen työtilaan, se palauttaa ISavedState-objektin, joka kuvaa, mitä lisäosa on tallentanut viimeisimmän tallennuksensa yhteydessä (tai null, jos lisäosa ei ole aiemmin tallentanut yhtäkään tilaa). Tämän objektin avulla voi käyttää aiemman tallennustiedoston tietoja (tallennusnumeron ja tiedostokartan avulla) tai käsitellä muutoksia, jotka ovat sattuneet lisäosan aktivointien välillä.
Jos tiedostokartan avulla on viimeksi tallennettu tiedostonimet loogisesti tallennusnumeron mukaan, saman kartan avulla voi noutaa tiedot viimeisestä tunnetusta tallennustilasta.
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(); // lisäosan ilmentymän on luettava tärkeät tilat tiedostosta. myPluginInstance.readStateFrom(f); }
Muista, että kuinka monta resurssien muutostapahtumaa tahansa voi tapahtua työtilassa, ennen kuin lisäosa aktivoidaan. Jos haluat tietää, mitä muutoksia on sattunut sen jälkeen, kun lisäosa poistettiin toiminnasta, voit tehdä sen tallennuksen avulla, vaikka muita tietoja ei olisi tarpeen tallentaa.
Tallennuksen osapuolen on pyydettävä, että ympäristö säilyttää resurssien deltaa puolestaan. Tämä tapahtuu osana tallennustoimintoa.
public void saving(ISaveContext context) throws CoreException { // lisäosa ei voi tallentaa mitään tilaa, vaan pyytää // resurssien deltaa käytettäväksi seuraavan aktivoinnin yhteydessä. context.needDelta(); }
Lisäosan aloituksen aikana edellistä tallennettua tilaa voi käyttää, ja muutostapahtumat luodaan kaikille muutoksille, jotka ovat tapahtuneet edellisen tallennuksen jälkeen.
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant(); ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant); if (lastState != null) { lastState.processResourceChangeEvents(new MyResourceChangeReporter()); }
Annetun luokan on toteutettava kohde IResourceChangeListener, kuten kohdassa Resurssimuutosten jäljitys kuvataan. Edellisen tallennuksen jälkeiset muutokset raportoidaan osana POST_AUTO_BUILD-resurssimuutostapahtumaa.
Huomautus: Merkintöjen muutoksia ei raportoida muutostapahtumissa, jotka on tallennettu kohteeseen ISavedState. On oletettava, että jotkin tai kaikki merkinnät ovat muuttuneet edellisen tilan tallennuksen jälkeen.