Le traitement de sauvegarde de l'espace de travail est déclenché lorsque ce dernier est arrêté par l'utilisateur et à d'autres moments, périodiquement par la plateforme. Les plug-ins peuvent participer au processus de sauvegarde de l'espace de travail de telle sorte que les données de plug-in sensibles sont sauvegardées sur le disque chaque fois que le reste des données persistantes de l'espace de travail est sauvegardé.
Le processus de sauvegarde de l'espace de travail peut être également utilisé pour effectuer le suivi des modifications qui surviennent entre les activations de votre plug-in.
Pour participer à la sauvegarde de l'espace de travail, vous devez ajouter un participant de sauvegarde à l'espace de travail. Ceci s'effectue généralement au cours de la méthode de démarrage du plug-in. Examinons un simple plug-in qui va nous montrer le processus de sauvegarde.
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) {
}
}
Pour participer à la sauvegarde de l'espace de travail, vous devez lui ajouter un participant de sauvegarde. Ceci s'effectue généralement au cours de la méthode startup (démarrage) du plug-in. C'est là également que vous lisez l'état éventuellement sauvegardé lors du dernier arrêt du plug-in.
ISaveParticipant définit le protocole pour un participant à la sauvegarde de l'espace de travail. Les classes d'implémentation de cette interface peuvent fournir le comportement de différents niveaux du processus de sauvegarde. Examinons ces niveaux et voyons comment la classe WorkspaceSaveParticipant implémente chacune de ces étapes.
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 décrit les informations relatives à l'opération de sauvegarde. Il existe trois types d'opérations de sauvegarde : FULL_SAVE, SNAPSHOT et PROJECT_SAVE. Les participants à la sauvegarde doivent être attentifs à l'exécution du traitement approprié au type d'événement de sauvegarde qu'ils ont reçus. Par exemple, des événements instantanés peuvent se produire assez fréquemment et sont destinés à permettre aux plug-ins de sauvegarder leur état critique. Si la sauvegarde d'un état pouvant être recalculé dans l'éventualité d'une panne dure longtemps, la plateforme s'en trouve ralentie.
Un numéro de sauvegarde est utilisé pour créer des fichiers de sauvegarde des données, désignés à l'aide de numéros séquentiels (save-1, save-2, etc.). Chaque fichier de sauvegarde est mappé sur un nom de fichier logique (save), indépendant du numéro de sauvegarde. Les données du plug-in sont écrites dans le fichier correspondant et peuvent être extraites ultérieurement sans savoir le numéro de sauvegarde spécifique de la dernière opération de sauvegarde réussie. N'oubliez pas que nous avons vu cette technique dans le code de démarrage de notre plug-in.
IPath location = lastState.lookup(new Path("save"));
Une fois les données sauvegardées et le nom de fichier mappé, nous appelons needSaveNumber pour indiquer que nous avons activement participé à la sauvegarde de l'espace de travail et souhaitons assigner un numéro à l'activité de sauvegarde. Les numéros de sauvegarde peuvent être utilisés pour créer des fichiers de données comme ci-dessus.
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();
}
A ce point, nous nettoyons les informations de sauvegarde. Nous utilisons getPreviousSaveNumber pour extraire le numéro de sauvegarde attribué au cours de l'opération de sauvegarde précédente (pas celle que nous venons de terminer). Nous utilisons ce numéro pour élaborer le nom du fichier à supprimer. Il est à noter que nous n'utilisons pas la mappe du fichier logique de l'état de sauvegarde du fait que nous avons déjà mappé notre numéro de fichier de sauvegarde courant.
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();
}
A ce point, nous supprimons l'état que nous venons de sauvegarder. Il est à noter que nous utilisons le numéro de sauvegarde courant pour élaborer le nom du fichier que nous venons de sauvegarder. Il n'est pas nécessaire de s'inquiéter sur le fait que nous avons mappé ce nom de fichier dans ISaveContext. La plateforme supprime le contexte lorsqu'une opération de sauvegarde échoue.
Si votre plug-in lance une exception à n'importe quel moment du cycle de vie de sauvegarde, il sera supprimé de l'opération de sauvegarde courante et ne recevra aucune des méthodes du cycle de vie restantes. Par exemple, si votre méthode de sauvegarde échoue, vous ne recevrez pas de message d'annulation ou de succès de sauvegarde (doneSaving).
Lorsque vous ajoutez un participant de sauvegarde à l'espace de travail, il renvoie un objet ISavedState qui décrit ce que votre plug-in a sauvegardé au cours de sa dernière opération de sauvegarde (ou null si votre plug-in n'a pas enregistré de précédent état). Cet objet peut être utilisé pour accéder aux informations à partir du fichier de sauvegarde précédent (à l'aide du numéro de sauvegarde et de la mappe du fichier) ou pour traiter les changements qui se sont produits entre les activations d'un plug-in.
Si une mappe de fichier a été utilisée pour sauvegarder des fichiers désignés logiquement en fonction du numéro de sauvegarde, cette même mappe peut être utilisée pour extraire les données du dernier état de sauvegarde connu.
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);
}
N'oubliez pas qu'un certain nombre d'événements de changement de ressources peut se produire dans l'espace de travail avant que votre plug-in ne soit activé. Si vous souhaitez connaître les changements qui ont eu lieu depuis la désactivation de votre plug-in, vous pouvez utiliser le mécanisme de sauvegarde, même si vous n'avez pas besoin de sauvegarder d'autres données.
Le participant à la sauvegarde doit demander que la plateforme conserve un delta des ressources en son nom. Ceci fait partie de l'opération de sauvegarde.
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();
}
Au cours du démarrage du plug-in, il est possible d'accéder au précédent état sauvegardé et des événements sont créés pour tous les changements qui se sont produits depuis la dernière sauvegarde.
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
ISavedState lastState =
ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance,
saveParticipant);
if (lastState != null) {
lastState.processResourceChangeEvents(new
MyResourceChangeReporter());
}
La classe fournie doit implémenter IResourceChangeListener, comme décrit à la section Suivi des modifications des ressources. Les changements survenus depuis la dernière sauvegarde sont rapportés comme faisant partie de l'événement de modification des ressources POST_AUTO_BUILD.
Remarque : Les modifications de marqueur ne sont pas rapportées dans les événements de modification stockés dans un ISavedState. Vous devez présumer que certains marqueurs ou leur totalité ont changé depuis la dernière sauvegarde de votre état.