Die Verarbeitung für das Speichern des Arbeitsbereichs wird ausgelöst, wenn die Workbench durch den Benutzer beendet wird. Zusätzlich wird diese Verarbeitung in regelmäßigen Abständen durch die Plattform ausgelöst. Plug-ins können in den Prozess für die Speicherung des Arbeitsbereichs einbezogen werden, damit kritische Plug-in-Daten ebenfalls auf Platte geschrieben werden, wenn die übrigen permanenten Daten des Arbeitsbereichs gespeichert werden.
Mit dem Prozess für die Speicherung des Arbeitsbereichs können außerdem Änderungen protokolliert werden, die zwischen Aktivierungen von Plug-ins erfolgt sind.
Damit ein Element bei der Speicherung des Arbeitsbereichs berücksichtigt wird, müssen Sie einen Speicherungsteilnehmer zum Arbeitsbereich hinzufügen. Dies wird normalerweise in der Startmethode für das Plug-in vorgenommen. Hier werden außerdem alle Statuswerte gelesen, die bei der letzten Beendigung des Plug-ins möglicherweise gespeichert wurden.
Das folgende Beispiel veranschaulicht den Speicherprozess anhand eines einfachen Plug-ins:
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; // the plugin instance should read any important state from the file. File f = getStateLocation().append(location).toFile(); readStateFrom(f); } protected void writeImportantState(File target) { } }
ISaveParticipant definiert das Protokoll für einen Teilnehmer an der Arbeitsbereichssicherung. Implementierungselemente dieser Schnittstelle können ein Verhalten für die unterschiedlichen Phasen des Sicherungsprozesses bereitstellen. Die einzelnen Phasen und die Implementierung dieser Schritte durch die Klasse WorkspaceSaveParticipant werden im Folgenden erläutert.
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(); // save the plug-in state int saveNumber = context.getSaveNumber(); String saveFileName = "save-" + Integer.toString(saveNumber); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); // if we fail to write, an exception is thrown and we do not update the path myPluginInstance.writeImportantState(f); context.map(new Path("save"), new Path(saveFileName)); context.needSaveNumber(); break; case ISaveContext.PROJECT_SAVE: // get the project related to this save operation IProject project = context.getProject(); // save its information, if necessary break; case ISaveContext.SNAPSHOT: // This operation needs to be really fast because // snapshots can be requested frequently by the // workspace. break; } }
ISaveContext beschreibt Informationen über die Sicherungsoperation. Es gibt drei Arten von Sicherungsoperationen: FULL_SAVE, SNAPSHOT und PROJECT_SAVE. Teilnehmer an der Speicherung sollten darauf achten, die geeignete Verarbeitung für die erhaltene Art von Speicherereignis auszuführen. Momentaufnahmenereignisse können beispielsweise recht oft auftreten. Ihr Zweck ist es, Plug-ins die Möglichkeit zu bieten, ihren kritischen Status zu speichern. Wenn es zu lange dauert, einen Status, der im Fall eines Absturzes erneut berechnet werden kann, zu speichern, so beeinträchtigt dies die Geschwindigkeit der Plattform.
Über eine Sicherungsnummer werden Sicherungsdateien für die Daten erstellt, die mit fortlaufenden Zahlen (save-1, save-2 usw.) benannt werden. Jeder Sicherungsdatei ist ein logischer Dateiname (save) zugeordnet, der von der Sicherungsnummer unabhängig ist. Die Plug-in-Daten werden in die entsprechende Datei geschrieben und können später abgerufen werden, ohne dass hierbei die spezifische Speicherungsnummer der letzten erfolgreichen Speicherungsoperation bekannt sein muss. Diese Methode kennen Sie bereits aus dem Startcode des Plug-ins:
IPath location = lastState.lookup(new Path("save"));Nachdem die Daten gesichert wurden und der Dateiname zugeordnet worden ist, wird durch einen Aufruf von needSaveNumber angegeben, dass eine Teilnahme an der Arbeitsbereichssicherung vorlag und der Sicherungsaktivität eine Nummer zugeordnet werden soll. Anhand der Sicherungsnummer können wie oben beschrieben Datendateien erstellt werden.
public void doneSaving(ISaveContext context) { MyPlugin myPluginInstance = MyPlugin.getDefault(); // delete the old saved state since it is not necessary anymore int previousSaveNumber = context.getPreviousSaveNumber(); String oldFileName = "save-" + Integer.toString(previousSaveNumber); File f = myPluginInstance.getStateLocation().append(oldFileName).toFile(); f.delete(); }
An dieser Stelle werden die Sicherungsinformationen der vorherigen Sicherungsoperation gereinigt. getPreviousSaveNumber wird verwendet, um die Sicherungsnummer abzurufen, die der vorherigen Sicherungsoperation zugeteilt worden war (nicht diejenige, die gerade ausgeführt wurde). Diese Nummer wird verwendet, um den Namen der Datei zu ermitteln, die gelöscht werden soll. Beachten Sie, dass nicht die logische Dateizuordnung des Status verwendet wird, da die aktuelle Sicherungsdateinummer bereits zugeordnet wurde.
public void rollback(ISaveContext context) { MyPlugin myPluginInstance = MyPlugin.getDefault(); // since the save operation has failed, delete the saved state we have just written int saveNumber = context.getSaveNumber(); String saveFileName = "save-" + Integer.toString(saveNumber); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); f.delete(); }
An dieser Stelle wird der gerade gespeicherte Status gelöscht. Hierbei wird die aktuelle Speicherungsnummer verwendet, um den Namen der soeben gespeicherten Datei zu konstruieren. Die Tatsache, dass dieser Dateiname der Schnittstelle ISaveContext zugeordnet wurde, ist nicht von Bedeutung. Die Plattform löscht den Kontext, wenn eine Sicherungsoperation fehlschlägt.
Falls Ihr Plug-in während des Sicherungslebenszyklus eine Ausnahmebedingung ausgibt, wird es aus der aktuellen Sicherungsoperation entfernt und erhält keine der verbleibenden Lebenszyklusmethoden. Wenn das Fehlschlagen beispielsweise während der Methode saving erfolgt, wird die Nachricht für rollback oder doneSaving nicht empfangen.
Wenn Sie einen Sicherungsteilnehmer zum Arbeitsbereich hinzufügen, gibt dieser ein Objekt ISavedState zurück. Dieses Objekt beschreibt, was während der letzten Sicherungsoperation durch das Plug-in gesichert wurde bzw. gibt null an, wenn das Plug-in noch keinen Status gesichert hat. Über dieses Objekt können Sie auf Informationen aus der vorherigen Sicherungsdatei zugreifen (mit Sicherungsnummer und Dateimaske) oder Änderungen verarbeiten, die zwischen Aktivierungen eines Plug-ins vorgenommen wurden.
Wenn eine Dateimaske verwendet wurde, um logisch benannte Dateien gemäß der Sicherungsnummer zu sichern, können Sie mit derselben Maske die Daten aus dem letzten bekannten Sicherungsstatus abrufen.
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(); // the plugin instance should read any important state from the file. myPluginInstance.readStateFrom(f); }
Wie Sie bereits wissen, können im Arbeitsbereich beliebig viele Ressourcenänderungen stattgefunden haben, bevor das Plug-in zum ersten Mal aktiviert wird. Wenn Sie wissen wollen, welche Änderungen seit der Inaktivierung des Plug-ins vorgenommen wurden, können Sie dies über den Sicherungsmechanismus ermitteln, und zwar auch dann, wenn keine anderen Daten sichern müssen.
Der Sicherungsteilnehmer muss die Anforderung ausgeben, dass die Plattform für ihn ein Ressourcendelta aufbewahrt. Dies erfolgt im Rahmen der Sicherungsoperation.
public void saving(ISaveContext context) throws CoreException { // no state to be saved by the plug-in, but request a // resource delta to be used on next activation. context.needDelta(); }
Während des Plug-in-Starts ist ein Zugriff auf die früheren Sicherungsstatus möglich, und für alle Änderungen, die seit der letzten Sicherung vorgenommen wurden, werden Änderungsereignisse erstellt.
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant(); ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant); if (lastState != null) { lastState.processResourceChangeEvents(new MyResourceChangeReporter()); }
Die bereitgestellte Klasse muss IResourceChangeListener, wie unter Ressourcenänderungen verfolgen beschrieben, implementieren. Die Änderungen seit der letzten Sicherung werden im Rahmen des Ereignisses POST_AUTO_BUILD für Ressourcenänderungen gemeldet.
Hinweise: Markierungsänderungen werden in den Änderungsereignissen, die in einem Objekt ISavedState gespeichert werden, nicht gemeldet. Sie müssen davon ausgehen, dass die Markierungen ganz oder teilweise seit der letzten Statussicherung geändert wurden.