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. Das folgende Beispiel veranschaulicht, wie ein einfaches Plug-in den Speicherprozess implementiert:
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;
// Das Plug-in-Exemplar sollte alle wichtigen Statuswerte aus der Datei lesen.
File f =
getStateLocation().append(location).toFile();
readStateFrom(f);
}
protected void writeImportantState(File target) {
}
}
Damit ein Element bei der Speicherung des Arbeitsbereichs berücksichtigt wird, müssen Sie einen Speicherungsteilnehmer zum Arbeitsbereich hinzufügen. Dies erfolgt normalerweise in der Startmethode des Plug-ins. Hier werden außerdem alle Statuswerte gelesen, die bei der letzten Beendigung des Plug-ins möglicherweise gespeichert wurden.
Die Schnittstelle ISaveParticipant definiert das Protokoll für einen Teilnehmer an der Arbeitsbereichsspeicherung. Objekte, die diese Schnittstelle implementieren, können ein Verhalten für die unterschiedlichen Abschnitte des Speicherungsprozesses bereitstellen. Die einzelnen Abschnitte 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();
// Plug-in-Status speichern.
int saveNumber = context.getSaveNumber();
String saveFileName = "save-" + Integer.toString(saveNumber);
File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
// Falls das Schreiben fehlschlägt, wird eine Ausnahmebedingung ausgegeben und der Pfad nicht aktualisiert
myPluginInstance.writeImportantState(f);
context.map(new Path("save"), new Path(saveFileName));
context.needSaveNumber();
break;
case
ISaveContext.PROJECT_SAVE:
// Projekt für diese Speicherungsoperation abrufen
IProject project = context.getProject();
// Projektinformationen ggfs. speichern
break;
case
ISaveContext.SNAPSHOT:
// Diese Operation muss sehr schnell sein, da durch
// den Arbeitsbereich häufig Momentaufnahmen
// angefordert werden.
break;
}
}
Die Schnittstelle ISaveContext beschreibt Informationen über die Speicherungsoperation. Es gibt drei Arten von Speicherungsoperationen: FULL_SAVE, SNAPSHOT und PROJECT_SAVE. Die Speicherungsteilnehmer sollten die entsprechende Verarbeitung für die empfangene Art des Speicherungsereignisses sorgfältig ausführen. Ereignisse für Momentaufnahmen können relativ häufig eintreten und sollten Plug-ins die Speicherung des kritischen Status ermöglichen. Wenn das Speichern eines Status, der im Falle eines Systemabsturzes neu berechnet werden kann, sehr lange dauert, wirkt sich dies negativ auf die Leistung der Plattform aus.
Über eine Speicherungsnummer werden Speicherungsdateien für die Daten erstellt, die mit fortlaufenden Zahlen (save-1, save-2 usw.) benannt werden. Jeder Speicherungsdatei ist ein logischer Dateiname (save) zugeordnet, der von der Speicherungsnummer 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 gespeichert wurden und der Dateiname zugeordnet worden ist, wird durch einen Aufruf der Methode needSaveNumber angegeben, dass eine Teilnahme an der Arbeitsbereichsspeicherung vorlag und der Speicherungsaktivität eine Nummer zugeordnet werden soll. Anhand der Speicherungsnummer können wie oben beschrieben Datendateien erstellt werden.
public void doneSaving(ISaveContext context) {
MyPlugin myPluginInstance =
MyPlugin.getDefault();
// Alten
Speicherungsstatus löschen, da er nicht mehr benötigt wird
int previousSaveNumber = context.getPreviousSaveNumber();
String oldFileName = "save-" +
Integer.toString(previousSaveNumber);
File f =
myPluginInstance.getStateLocation().append(oldFileName).toFile();
f.delete();
}
An dieser Stelle können die Speicherungsdaten aus der letzten Speicherungsoperation bereinigt werden. Mit der Methode getPreviousSaveNumber wird die Speicherungsnummer abgerufen, die der vorherigen (nicht der soeben abgeschlossenen!) Speicherungsoperation zugeordnet war. Anhand dieser Nummer wird der Name der Datei konstruiert, die gelöscht werden muss. Die Zuordnung der logischen Datei für den Speicherungsstatus wird hierbei nicht verwendet, da die aktuelle Nummer der Speicherungsdatei bereits zugeordnet wurde.
public void rollback(ISaveContext context) {
MyPlugin myPluginInstance =
MyPlugin.getDefault();
// Soeben geschriebenen
Speicherungsstatus löschen, weil die Speicherungsoperation fehlgeschlagen ist
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 in der Schnittstelle ISaveContext zugeordnet wurde, ist nicht von Bedeutung. Die Plattform löscht den Kontext, wenn eine Speicherungsoperation fehlschlägt.
Falls Ihr Plug-in während des Speicherungslebenszyklus eine Ausnahmebedingung ausgibt, wird es aus der aktuellen Speicherungsoperation 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 Speicherungsteilnehmer zum Arbeitsbereich hinzufügen, gibt dieser ein Objekt ISavedState zurück. Dieses Objekt beschreibt, was während der letzten Speicherungsoperation durch das Plug-in gespeichert wurde bzw. gibt null an, wenn das Plug-in noch keinen Status gespeichert hat. Über dieses Objekt können Sie auf Informationen aus der vorherigen Speicherungsdatei zugreifen (mit Speicherungsnummer und Dateimaske) oder Änderungen verarbeiten, die zwischen Aktivierungen eines Plug-ins vorgenommen wurden.
Wenn eine Dateimaske verwendet wurde, um logisch benannte Dateien anhand der Speicherungsnummer zu speichern, können Sie mit derselben Maske die Daten aus dem letzten bekannten Speicherungsstatus 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();
// Das Plug-in-Exemplar sollte alle wichtigen Statuswerte aus der Datei lesen.
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 Speicherungsmechanismus ermitteln, und zwar auch dann, wenn keine anderen Daten gespeichert werden müssen.
Der Speicherungsteilnehmer muss die Anforderung ausgeben, dass die Plattform für ihn ein Ressourcendelta aufbewahren soll. Dies erfolgt im Rahmen der Speicherungsoperation.
public void saving(ISaveContext context) throws CoreException {
// Es soll kein Status im Plug-in gespeichert,
aber ein
// Ressourcendelta für die nächste Aktivierung angefordert werden.
context.needDelta();
}
Während des Plug-in-Starts ist ein Zugriff auf den früheren Speicherungsstatus möglich, und für alle Änderungen, die seit der letzten Speicherung vorgenommen wurden, werden Änderungsereignisse erstellt.
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
ISavedState lastState =
ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance,
saveParticipant);
if (lastState != null) {
lastState.processResourceChangeEvents(new
MyResourceChangeReporter());
}
Die zur Verfügung gestellte Klasse muss die Schnittstelle IResourceChangeListener wie unter Ressourcenänderungen protokollieren beschrieben, implementieren. Die Änderungen seit der letzten Speicherung werden im Rahmen des Ereignisses POST_AUTO_BUILD für Ressourcenänderungen gemeldet.
Hinweis: Markierungsänderungen werden in den Änderungsereignissen, die in einem Objekt ISavedState gespeichert werden, nicht gemeldet. Sie müssen davon ausgehen, dass die Markierungen seit der letzten Statusspeicherung ganz oder teilweise geändert wurden.