Participação no salvamento na área de trabalho

O processo de salvamento do espaço de trabalho é acionado quando o workbench é encerrado pelo usuário e às vezes periodicamente pela plataforma.  Os plug-ins podem participar do processo de salvamento do espaço de trabalho para que dados críticos do plug-in sejam salvos em disco toda vez que os demais dados persistentes do espaço 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.  É também o local onde você lê qualquer estado que possa ter salvo durante a última vez que o plug-in foi encerrado.

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

      protected void writeImportantState(File target) {
      }
   }

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();
               // salvar o estado do plug-in
               int saveNumber = context.getSaveNumber();
               String saveFileName = "save-" + Integer.toString(saveNumber);
               File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
               // se falharmos ao gravar, uma exceção será emitida e não atualizaremos o caminho
               myPluginInstance.writeImportantState(f);
               context.map(new Path("save"), new Path(saveFileName));
               context.needSaveNumber();
               break;
            case ISaveContext.PROJECT_SAVE:
               // obter o projeto relacionado a esta operação de gravação
               IProject project = context.getProject();
               // salvar suas informações, 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;
         }
      }

O 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 de salvamento devem ser cautelosos para executar o processamento apropriado para o tipo de evento de gravação que eles receberam.  Por exemplo, os eventos instantâneos podem ocorrer com certa freqüência e devem permitir que os plug-ins salvem seu estado crítico.  Levar um grande tempo para salvar o estado que pode ser calculado novamente no caso de uma falha fará a plataforma ficar mais 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 específico 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();

         // excluir 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 de salvamento que estava associado na operação de gravação anterior (não aquela que acabamos de concluir).  Utilizamos esse número para construir o nome do arquivo que precisamos excluir.  Observe que não utilizamos o mapa de arquivo lógico do estado de salvamento porque já mapeamos o número de 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 salvo 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 restantes do ciclo de vida.  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 instâ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 recurso 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 Monitorando 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.

Copyright IBM Corporation e outros 2000, 2003.