Participación de guardado del área de trabajo

El proceso de guardado del área de trabajo se activa cuando el usuario, y otras veces la plataforma de manera periódica, concluye el entorno de trabajo.  Los conectores pueden participar en el proceso de guardado del área de trabajo, de manera que los datos importantes del conector se guardan en el disco siempre que se guarden los demás datos persistentes del área de trabajo.

El proceso de guardado del área de trabajo también puede utilizarse para hacer un seguimiento de los cambios que se producen entre activaciones del conector.

Implementar un participante de guardado

Para participar en el guardado del área de trabajo, debe añadir un participante de guardado en dicha área. Generalmente, esto se lleva a cabo durante el método de inicio del conector.  A continuación, se presenta un conector que muestra el proceso de guardado.

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;
        // la instancia del conector debe leer cualquier estado importante del archivo.
        File f = getStateLocation().append(location).toFile();
        readStateFrom(f);

    }

    protected void writeImportantState(File target) {
    }
}

Para participar en el guardado del área de trabajo, debe añadir un participante de guardado en dicha área.  Esto se suele hacer durante el método de inicio del conector.  También es cuando se lee cualquier estado que se podría haber guardado la última vez que se concluyó el conector.

ISaveParticipant define el protocolo para un participante de guardado de área de trabajo. Los implementores de esta interfaz pueden proporcionar el funcionamiento de las diferentes fases del proceso de guardado.  A continuación, se muestra cómo la clase WorkspaceSaveParticipant implementa cada uno de estos pasos.

    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();
                // guardar el estado del conector
                int saveNumber = context.getSaveNumber();
                String saveFileName = "save-" + Integer.toString(saveNumber);
                File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
               
// si se producen errores de escritura, se lanza una excepción y no se actualiza la vía de acceso
                myPluginInstance.writeImportantState(f);
                context.map(new Path("save"), new Path(saveFileName));
                context.needSaveNumber();
                break;
            case ISaveContext.PROJECT_SAVE:
                // obtener el proyecto relacionado con la operación de guardar
                IProject project = context.getProject();
                // guardar esta información en caso necesario
                break;
            case ISaveContext.SNAPSHOT:
                // Esta operación debe ser realmente rápida porque
                // el área de trabajo puede solicitar instantáneas
                // frecuentemente.
                break;
        }
    }

El ISaveContext describe información sobre la operación de guardado.  Existen tres tipos de operaciones de guardado:  FULL_SAVE, SNAPSHOT y PROJECT_SAVE.  Los participantes de guardado deben actuar con precaución al efectuar el proceso adecuado para el tipo de evento de guardado que han recibido.  Por ejemplo, los eventos de instantánea pueden producirse con bastante frecuencia y están pensados para que los conectores puedan guardar su estado crítico.  Si se utiliza mucho tiempo para guardar un estado que puede reprogramarse en el caso de una situación anómala, disminuirá el rendimiento de la plataforma.

Para crear archivos de guardado de datos cuyo nombre contiene números secuenciales, se utiliza un número de guardado (save-1, save-2, etcétera.) Cada archivo de guardado se correlaciona con un nombre de archivo lógico (save) que es independiente del número de guardado. Los datos del conector se escriben en el archivo correspondiente y pueden recuperarse más adelante sin que sea necesario conocer el número de guardado específico de la última operación de guardado satisfactoria.  Recuerde que se utilizó este procedimiento en el  código de inicio del conector:

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

Después de haber guardado los datos y correlacionado el nombre de archivo, se llama a needSaveNumber para indicar que se ha participado de manera activa en un guardado de área de trabajo y que se desea asignar un número a la actividad de guardado. Los números de guardado pueden utilizarse para crear archivos de datos, tal como se ha mostrado anteriormente. 

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

        // eliminar el estado de guardado antiguo ya que no se va a volver a necesitar
        int previousSaveNumber = context.getPreviousSaveNumber();
        String oldFileName = "save-" + Integer.toString(previousSaveNumber);
        File f = myPluginInstance.getStateLocation().append(oldFileName).toFile();
        f.delete();
    }

Aquí se borrará la información de guardado de la operación de guardado anterior.  Se utiliza getPreviousSaveNumber para obtener el número de guardado que se ha asignado en la operación anterior (no la que se acaba de completar).  Este número permite crear el nombre del archivo que se necesita eliminar.  Observe que no se utiliza el mapa de archivos lógicos del estado de guardado puesto que ya se ha correlacionado el número del archivo de guardado actual. 

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

        // puesto que la operación de guardado no ha sido satisfactoria, elimine el estado de guardado que se acaba de escribir
        int saveNumber = context.getSaveNumber();
        String saveFileName = "save-" + Integer.toString(saveNumber);
        File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
        f.delete();
    }

Aquí se eliminará el estado que se acaba de guardar.  Observe que se utiliza el número de guardado actual para crear el nombre del archivo que se acaba de guardar.  No es necesario preocuparse de que se ha correlacionado este nombre de archivo en el ISaveContext. La plataforma descartará el contexto cuando una operación de guardado no sea satisfactoria.

Si el conector lanza una excepción en cualquier momento durante el ciclo de vida del guardado, se suprimirá de la operación de guardado actual y no obtendrá ninguno de los métodos de ciclo de vida restantes.  Por ejemplo, si se producen errores durante el método de guardado, no recibirá ningún mensaje rollback o doneSaving

Utilizar un estado de guardado previamente

Cuando añade un participante de guardado al área de trabajo, devolverá un objeto ISavedState, que describe lo que el conector guardó durante su última operación de guardado (o null si el conector no guardó previamente ningún estado). Este objeto puede utilizarse para acceder a información del archivo de guardado anterior (utilizando el número de guardado y la correlación de archivos) o para procesar cambios que se han producido entre activaciones de un conector.

Acceder a los archivos de guardado

Si se ha utilizado una correlación de archivos para guardar archivos a los que se ha asignado nombre de manera lógica de acuerdo al número de guardado, se puede utilizar esta misma correlación para recuperar los datos del último estado de guardado conocido.

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();
    // la instancia del conector debe leer cualquier estado importante del archivo.
    myPluginInstance.readStateFrom(f);
}

Procesar deltas de recursos entre activaciones

Recuerde que podría tener lugar cualquier número de eventos de cambio de recurso en el área de trabajo antes de que el conector se active. Si desea saber qué cambios se han producido desde que se desactivaron los conectores, puede utilizar el mecanismo de guardado para hacerlo, incluso si no necesita guardar ningún otro dato.

El participante de guardado debe pedir que la plataforma mantenga un delta de recursos en su nombre. Esto se lleva a cabo como parte de la operación de guardado.

public void saving(ISaveContext context) throws CoreException {
    // el conector no va a guardar ningún estado, pero se pide
    // un delta de recursos para utilizarse en la activación siguiente.
    context.needDelta();
}

Durante el inicio del conector, se puede acceder al estado anterior guardado y se crearán eventos de cambios en todos los cambios que se han producido desde el último guardado.

ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();

 

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

La clase que se proporciona debe implementar IResourceChangeListener, tal como se ha descrito en Rastrear los cambios de recursos.  Los cambios producidos desde el último guardado se incluyen en el evento de cambios de recursos de POST_AUTO_BUILD.

Nota:  Los cambios del marcador no se incluyen en los eventos de cambios almacenados en un ISavedState. Se debe presuponer que alguno o todos los marcadores se han modificado desde que se guardó el último estado.