Participação no salvamento na área de trabalho

O processo de salvamento na área de trabalho é disparado quando ela é encerrada pelo usuário e às vezes periodicamente pela plataforma.  Os plug-ins podem participar do processo de salvamento na área de trabalho para que seus dados críticos sejam salvos em disco toda vez que os demais dados persistentes na área de trabalho forem salvos.

O processo de salvamento na área de trabalho também pode ser utilizado para controlar as alterações que ocorrem entre as ativações do plug-in.

Implementando um participante do salvamento

Para participar do salvamento na área de trabalho, você deve nela incluir um participante do salvamento. Geralmente, isso é feito durante o método de inicialização do plug-in.  Observemos um plug-in simples que demonstrará o processo de salvamento.

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 plug-in;

    public MyPlugin(IPluginDescriptor descriptor) {
        super(descriptor);
        plug-in = this;
    }

    public static MyPlugin getDefault() {
        return plug-in;
    }

    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;
        // a ocorrência do plug-in deve ler qualquer estado importante do arquivo.
        File f = getStateLocation().append(location).toFile();
        readStateFrom(f);

    }

    protected void writeImportantState(File target) {
    }
}

Para participar do salvamento na área de trabalho, você deve nela incluir um participante do salvamento.  Geralmente, isso é feito durante o método de inicialização.  É também o local no qual você lê qualquer estado que talvez tenha sido salvo durante a última vez que o plug-in foi encerrado.

ISaveParticipant define o protocolo de um participante do salvamento na área de trabalho. Os implementadores dessa interface podem fornecer comportamento para diferentes estágios do processo de salvamento.  Observemos os estágios e como a nossa classe WorkspaceSaveParticipant implementa cada uma dessas etapas.

    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();
                // salve o estado do plug-in
                int saveNumber = context.getSaveNumber();
                String saveFileName = "save-" + Integer.toString(saveNumber);
                File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
               
// se falharmos em gravar, uma exceção será lançada e não atualizaremos o caminho
                myPluginInstance.writeImportantState(f);
                context.map(new Path("save"), new Path(saveFileName));
                context.needSaveNumber();
                break;
            case ISaveContext.PROJECT_SAVE:
                // obtenha o projeto relacionado a esta operação de salvamento
                IProject project = context.getProject();
                // salve essa informação, se necessário
                break;
            case ISaveContext.SNAPSHOT:
                // Esta operação precisa ser realmente rápida, porque
                // os instantâneos podem ser solicitados com freqüência pela
                // área de trabalho.
                break;
        }
    }

ISaveContext descreve informações sobre a operação de gravação.  Há três tipos de operações de gravação:  FULL_SAVE, SNAPSHOT e PROJECT_SAVE.  Os participantes do salvamento devem ser cuidadosos ao realizar o processamento apropriado ao tipo de evento de salvamento que receberam.  Por exemplo, eventos de instantâneo podem ocorrer com bastante freqüência e existem para permitir que os plug-ins salvem seu estado crítico.  Demorar muito para salvar o estado que pode ser recomputado no caso de uma falha deixará a plataforma lenta.

Um número do salvamento é utilizado para criar arquivos de salvamento de dados que são nomeados utilizando os números seqüenciais salvamento-1, salvamento-2, etc.)  Cada arquivo salvo é mapeado para um nome de arquivo lógico (salvamento), o qual não depende do número do salvamento. Os dados do plug-in são gravados no arquivo correspondente e podem ser recuperados posteriormente, sem que se saiba o número do salvamento da última operação de gravação bem-sucedida.  Lembre-se de que vimos essa técnica no código de inicialização  do nosso plug-in:

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

Após salvarmos nossos dados e mapearmos o nome do arquivo, chamamos needSaveNumber para indicar que participamos ativamente em um salvamento da área de trabalho e que desejamos atribuir um número à atividade de salvamento. Os números do salvamento podem ser utilizados para criar arquivos de dados, como acima. 

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

        // exclua o estado salvo anteriormente, pois ele não será mais necessário
        int previousSaveNumber = context.getPreviousSaveNumber();
        String oldFileName = "save-" + Integer.toString(previousSaveNumber);
        File f = myPluginInstance.getStateLocation().append(oldFileName).toFile();
        f.delete();
    }

Aqui, limpamos as informações de salvamento da operação de gravação anterior.  Utilizamos getPreviousSaveNumber para obter o número do salvamento que foi atribuído à operação de gravação anterior (não a que acabamos de concluir).  Utilizamos esse número para formar o nome do arquivo que precisamos excluir.  Observe que não utilizamos o mapeamento do arquivo lógico do estado do salvamento, pois já tínhamos mapeado o número do nosso arquivo de salvamento atual. 

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

        // como a operação de gravação falhou, exclua o estado do salvamento que acabamos de gravar
        int saveNumber = context.getSaveNumber();
        String saveFileName = "save-" + Integer.toString(saveNumber);
        File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
        f.delete();
    }

Aqui, excluímos o estado que acabamos de salvar.  Observe que utilizamos o número do salvamento atual para formar o nome do arquivo que acabamos de salvar.  Não precisamos nos preocupar com o fato de que mapeamos o nome desse arquivo para ISaveContext. A plataforma descartará o contexto quando uma operação de gravação falhar.

Se o plug-in lançar uma exceção em qualquer momento do ciclo de vida do salvamento, ele será removido da operação de gravação atual e não obterá qualquer um dos métodos do ciclo de vida restante.  Por exemplo, se você falhar durante o método saving, não receberá uma mensagem de rollback ou doneSaving

Utilizando o estado salvo anteriormente

Quando incluímos um participante do salvamento na área de trabalho, ele retornará um objeto ISavedState, o qual descreve o que o plug-in salvou durante sua última operação de gravação (ou null se o plug-in não salvou nenhum estado anteriormente). Esse objeto pode ser utilizado para acessar informações do arquivo de salvamento anterior (utilizando o número do salvamento e o mapeamento do arquivo) ou para processar alterações que ocorreram entre as ativações de um plug-in.

Acessando os arquivos de salvamento

Se o mapeamento de um arquivo foi utilizado para salvar arquivos nomeados logicamente, de acordo com o número do salvamento, esse mesmo mapeamento pode ser utilizado para recuperar os dados do último estado de salvamento conhecido.

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();
    // a ocorrência do plug-in deve ler qualquer estado importante no arquivo.
    myPluginInstance.readStateFrom(f);
}

Processando deltas de recurso entre ativações

Lembre-se de que qualquer número de eventos de alteração de recurso poderia ocorrer na área de trabalho antes do plug-in ser ativado. Para saber quais alterações ocorreram desde a desativação do plug-in, utilize o mecanismo de salvamento, mesmo que não seja necessário salvar qualquer outro dado.

O participante do salvamento deve solicitar que a plataforma mantenha um delta de recursos em seu benefício. Isso é feito como parte da operação de gravação.

public void saving(ISaveContext context) throws CoreException {
    // nenhum estado a ser salvo pelo plug-in, mas solicite um
    // delta de recursos a ser utilizado na próxima ativação.
    context.needDelta();
}

Durante a inicialização do plug-in, o estado salvo anteriormente pode ser acessado e os eventos de alteração serão criados para todas as alterações ocorridas desde o último salvamento.

ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();

 

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

A classe fornecida deve implementar IResourceChangeListener, conforme descrito em Controlando alterações do recurso.  As alterações desde o último salvamento são relatadas como parte do evento de alteração de recurso POST_AUTO_BUILD.

Nota:  as alterações do marcador não são relatadas nos eventos de alteração armazenados em um ISavedState. Você deve assumir que todo e qualquer marcador foi alterado quando seu último estado foi salvo.