Partecipazione al salvataggio dell'area di lavoro

Il processo di salvataggio dell'area di lavoro viene attivato dall'utente alla chiusura del workbench e periodicamente in altri momenti dalla piattaforma.  I plug-in possono essere compresi in questo processo in modo che anche i dati importanti dei plug-in verranno salvati sul disco al momento del salvataggio degli altri dati dell'area di lavoro.

Il processo di salvataggio dell'area di lavoro può anche essere utilizzato per tracciare le modifiche che si verificano tra le diverse attivazioni del plug-in.

Implementazione di un partecipante al salvataggio

Per partecipare all'operazione di salvataggio dell'area di lavoro, è necessario aggiungere a quest'ultimo un partecipante al salvataggio. Ciò avviene generalmente durante il metodo di avvio del plug-in dell'utente.  Di seguito viene illustrato un semplice plug-in che descrive il processo di salvataggio.

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;
        // l'istanza del plugin deve leggere qualsiasi stato importante dal file.
        File f = getStateLocation().append(location).toFile();
        readStateFrom(f);

    }

    protected void writeImportantState(File target) {
    }
}

Per prendere parte al salvataggio dell'area di lavoro, è necessario aggiungere all'area di lavoro un partecipante al salvataggio.  Ciò avviene generalmente nel corso del metodo di avvio dei plug-in.  In questo stesso punto è possibile esaminare lo stato salvato dal momento dell'ultima chiusura del plug-in.

ISaveParticipant definisce il protocollo per un partecipante al salvataggio dell'area di lavoro. Gli implementor di questa interfaccia possono fornire la funzionalità per differenti fasi del processo di salvataggio.  Di seguito vengono descritte tali fasi e il modo in cui la classe WorkspaceSaveParticipant implementa ciascuna fase.

    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();
                // salvare lo stato del plug-in
                int saveNumber = context.getSaveNumber();
                String saveFileName = "save-" + Integer.toString(saveNumber);
                File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
               
// se la scrittura non è corretta, viene attivata un'eccezione e il percorso non verrà aggiornato
                myPluginInstance.writeImportantState(f);
                context.map(new Path("save"), new Path(saveFileName));
                context.needSaveNumber();
                break;
            case ISaveContext.PROJECT_SAVE:
                // richiamare il progetto relativo a questa operazione di salvataggio
                IProject project = context.getProject();
                // salvare le relative informazioni, se necessario
                break;
            case ISaveContext.SNAPSHOT:
                // Questa operazione deve essere effettivamente rapida poiché
                // gli snapshot possono essere richiesti con frequenza
                // dall'area di lavoro.
                break;
        }
    }

ISaveContext descrive le informazioni relative all'operazione di salvataggio.  Esistono tre tipi di operazioni di salvataggio:  FULL_SAVE, SNAPSHOT e PROJECT_SAVE.  I partecipanti al salvataggio devono fare attenzione ad eseguire l'elaborazione adatta al tipo di evento di salvataggio ricevuto.  Ad esempio, gli eventi snapshot potrebbero verificarsi abbastanza frequentemente e consentono ai plug-in di salvare il proprio stato critico.  L'impiego di molto tempo per salvare uno stato che può essere ricalcolato in caso di malfunzionamento rallenterà la piattaforma.

Un numero di salvataggio viene utilizzato per creare file di salvataggio dati denominati mediante numeri sequenziali (save-1, save-2, etc.)  Ogni file di salvataggio è associato a un nome file logico (save) che è indipendente dal numero di salvataggio. I dati del plug-in vengono inseriti nel file corrispondente e possono essere successivamente richiamati, anche senza conoscere il numero di salvataggio specifico dell'ultima operazione di salvataggio riuscita.  Questa tecnica è già stata illustrata nel  codice di avvio del plug-in dell'utente:

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

Dopo aver salvato i dati e associato il nome file, viene richiamato needSaveNumber per indicare che l'utente ha partecipato attivamente ad un'operazione di salvataggio dell'area di lavoro e desidera assegnare un numero a tale attività. I numeri di salvataggio possono essere utilizzati per creare file di dati, come descritto in precedenza. 

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

        // cancellare il vecchio stato salvato dato che non è più necessario
        int previousSaveNumber = context.getPreviousSaveNumber();
        String oldFileName = "save-" + Integer.toString(previousSaveNumber);
        File f = myPluginInstance.getStateLocation().append(oldFileName).toFile();
        f.delete();
    }

A questo punto, le informazioni di salvataggio della precedente operazione di salvataggio vengono eliminate.  Viene utilizzato getPreviousSaveNumber per ottenere il numero di salvataggio assegnato alla precedente operazione di salvataggio (non quella appena completata).  Questo numero viene utilizzato per ricostruire il nome del file da cancellare.  Notare che non viene utilizzato il map del file logico dello stato di salvataggio poiché il numero del file di salvataggio corrente è già stato associato. 

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

        // poiché l'operazione di salvataggio non è riuscita, cancellare lo stato salvato appena scritto
        int saveNumber = context.getSaveNumber();
        String saveFileName = "save-" + Integer.toString(saveNumber);
        File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
        f.delete();
    }

A questo punto verrà cancellato lo stato appena salvato.  Notare che viene utilizzato il numero di salvataggio corrente per ricostruire il nome del file appena salvato.  Non è importante che questo nome file sia stato associato in ISaveContext. La piattaforma eliminerà il contesto quando un'operazione di salvataggio non riesce.

Se il plug-in dell'utente attiva un'eccezione in un qualsiasi momento del ciclo di vita del salvataggio, verrà rimosso dall'operazione di salvataggio corrente e non riceverà nessuno dei restanti metodi del ciclo di vita.  Ad esempio, se il metodo di salvataggio non riesce, l'utente non riceverà alcun messaggio rollback o doneSaving

Utilizzo dello stato precedentemente salvato

Quando si aggiunge un partecipante al salvataggio all'area di lavoro, questo restituirà un oggetto ISavedState che descrive ciò che è stato salvato dal plug-in durante l'ultima operazione di salvataggio (oppure restituirà null se nessuno stato del plug-in è stato salvato in precedenza). Questo oggetto può essere utilizzato per accedere alle informazioni del file di salvataggio precedente (mediante il map del file e il numero di salvataggio) o per elaborare le modifiche apportate tra le varie attivazioni di un plug-in.

Accesso ai file di salvataggio

Se un map del file è stato utilizzato per salvare file denominati in modo logico in base al numero di salvataggio, questo stesso map può essere utilizzato per richiamare i dati dall'ultimo stato di salvataggio conosciuto.

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();
    // l'istanza del plugin deve leggere qualsiasi stato importante dal file.
    myPluginInstance.readStateFrom(f);
}

Elaborazione dei delta di risorse tra le attivazioni

Ricordare che qualsiasi numero di eventi di modifica delle risorse dovrebbe verificarsi nell'area di lavoro prima dell'attivazione del plug-in. Se si desidera individuare le modifiche che sono state apportate dall'ultima disattivazione del plug-in, è possibile utilizzare il meccanismo di salvataggio, anche se non si desidera salvare altri dati.

Il partecipante al salvataggio deve richiedere alla piattaforma di conservare un delta delle risorse. Ciò avviene come parte dell'operazione di salvataggio.

public void saving(ISaveContext context) throws CoreException {
    // nessuno stato da salvare mediante il plug-in, ma è richiesto un
    // delta delle risorse da utilizzare alla successiva attivazione.
    context.needDelta();
}

Durante l'avvio del plug-in, è possibile accedere allo stato salvato in precedenza e verranno creati eventi di modifica per tutte le modifiche occorse a partire dall'ultimo salvataggio.

ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();

 

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

La classe fornita deve implementare IResourceChangeListener, come descritto in Traccia delle modifiche delle risorse.  Le modifiche avvenute a partire dall'ultimo salvataggio vengono riportate come parte dell'evento di modifica delle risorse POST_AUTO_BUILD.

Nota:  le modifiche di indicatori non vengono riportate negli eventi di modifica memorizzati in un ISavedState. È necessario presupporre che, a partire dall'ultimo salvataggio dello stato, tutti gli indicatori sono stati modificati oppure nessun indicatore è stato modificato.