O processamento de salvaguarda do espaço de trabalho é desencadeado quando a área de trabalho é encerrada pelo utilizador e noutras alturas periodicamente pela plataforma. Os plug-ins podem participar no processo de salvaguarda do espaço de trabalho de modo a que os dados críticos de plug-in sejam guardados em disco sempre que forem guardados os restantes dados persistentes do espaço de trabalho.
O processamento de salvaguarda do espaço de trabalho também pode ser usado para acompanhar alterações que ocorram entre activações do plug-in.
Para participar na salvaguarda do espaço de trabalho, é necessário adicionar um participante na salvaguarda ao espaço de trabalho. Tal realiza-se geralmente durante o método de arranque do plug-in. É também aqui que se lêem estados que se podem ter guardado aquando do último encerramento do plug-in.
Vejamos um simples plug-in para demonstrar o processo de salvaguarda.
package com.exemplo.participantesalvaguarda;
import org.eclipse.core.runtime.*;
import org.eclipse.core.resources.*;
import java.io.File;
import java.util.*;
public class oMeuPlugin extends Plugin {
private static oMeuPlugin plugin;
public oMeuPlugin(IPluginDescriptor descriptor) {
super(descriptor);
plugin = this;
}
public static oMeuPlugin 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 de plug-in deve ler qualquer estado importante do ficheiro.
File f = getStateLocation().append(location).toFile();
readStateFrom(f);
}
protected void writeImportantState(File target) {
}
}
O ISaveParticipant define o protocolo para um participante na salvaguarda do espaço de trabalho. Os implementadores desta interface podem facultar comportamento para diferentes fases do processo de salvaguarda. Vejamos as fases e como a classe WorkspaceSaveParticipant implementa cada um destes passos.
public void prepareToSave(ISaveContext context) throws CoreException {
}
public void saving(ISaveContext context) throws CoreException {
switch (context.getKind()) {
case ISaveContext.FULL_SAVE:
oMeuPlugin aMinhaInstânciaPlugin = oMeuPlugin.getDefault();
// guardar o estado do plug-in
int saveNumber = context.getSaveNumber();
String saveFileName = "save-" + Integer.toString(saveNumber);
File f = aMinhaInstânciaPlugin.getStateLocation().append(saveFileName).toFile();
// se a escrita falhar, é devolvida uma excepção e não actualizamos o caminho
aMinhaInstânciaPlugin.writeImportantState(f);
context.map(new Path("save"), new Path(saveFileName));
context.needSaveNumber();
break;
case ISaveContext.PROJECT_SAVE:
// obter o projecto relacionado com esta operação de salvaguarda
IProject project = context.getProject();
// guardar as suas informações, se necessário
break;
case ISaveContext.SNAPSHOT:
// Esta operação precisa de ser muito rápida porque
// podem ser frequentemente pedidos instantâneos pelo
// espaço de trabalho.
break;
}
}
O ISaveContext descreve informações sobre a operação de salvaguarda. Há três tipos de operações de salvaguarda: FULL_SAVE, SNAPSHOT e PROJECT_SAVE. Os participantes na salvaguarda devem ter cuidado ao realizar o processamento apropriado ao tipo de evento de salvaguarda que receberam. Por exemplo, podem ocorrer eventos de instantâneo com frequência e destinam-se a permitir aos plug-ins guardarem o seu estado crítico Demorar muito tempo a guardar estado que pode ser recalculado em caso de avaria irá atrasar a plataforma.
É utilizado um número de salvaguarda para criar ficheiros de salvaguarda de dados que são denominados save-1, save-2, etc.) Cada ficheiro de salvaguarda é correlacionado com um nome de ficheiro lógico (save) que é independente do número de salvaguarda. Os dados de plug-in são escritos no ficheiro correspondente e podem ser obtidos mais tarde sem conhecimento do número de salvaguarda específico da última operação de salvaguarda bem sucedida. Lembre-se que vimos esta técnica no código de arranque do nosso plug-in:
IPath location = lastState.lookup(new Path("save"));Depois de guardar os dados e correlacionar o nome do ficheiro, chamamos needSaveNumber para indicar que participámos activamente numa salvaguarda de espaço de trabalho e queremos atribuir um número à actividade de salvaguarda. Os números de salvaguarda podem ser utilizados para criar ficheiros de dados como se descreve supra.
public void doneSaving(ISaveContext context) {
oMeuPlugin aMinhaInstânciaPlugin = oMeuPlugin.getDefault();
// eliminar o antigo estado guardado dado que já não é necessário
int previousSaveNumber = context.getPreviousSaveNumber();
String oldFileName = "save-" + Integer.toString(previousSaveNumber);
File f = aMinhaInstânciaPlugin.getStateLocation().append(oldFileName).toFile();
f.delete();
}
Aqui limpamos as informações de salvaguarda da anterior operação de salvaguarda. Utilizamos getPreviousSaveNumber para obter o número da salvaguarda que foi atribuído na operação de salvaguarda anterior (e não daquela que acabámos de concluir). Utilizamos este número para construir o nome do ficheiro que temos de eliminar. Repare que não utilizamos a correlação com o ficheiro lógico do estado de salvaguarda dado que já correlacionámos o nosso actual número de ficheiro de salvaguarda.
public void rollback(ISaveContext context) {
oMeuPlugin aMinhaInstânciaPlugin = oMeuPlugin.getDefault();
// dado que a operação de salvaguarda falhou, eliminar o estado guardado que acabámos de escrever
int saveNumber = context.getSaveNumber();
String saveFileName = "save-" + Integer.toString(saveNumber);
File f = aMinhaInstânciaPlugin.getStateLocation().append(saveFileName).toFile();
f.delete();
}
Aqui eliminamos o estado que acabámos de guardar. Repare que utilizamos o actual número de salvaguarda para construir o nome do ficheiro que acabámos de guardar. Não temos de nos preocupar com o facto de que correlacionámos este nome de ficheiro com ISaveContext. A plataforma irá descartar o contexto quando uma operação de salvaguarda falhar.
Se o plug-in devolver uma excepção em qualquer altura durante o ciclo de vida da salvaguarda, será removido da actual operação de salvaguarda e não poderá obter nenhum dos métodos do ciclo de vida restante. Por exemplo, se falhar durante o método saving, não receberá nenhuma mensagem de rollback nem doneSaving.
Ao adicionar um participante de salvaguarda ao espaço de trabalho, este devolve um objecto ISavedState, o qual descrebe o que o plug-in guardou durante a última operação de salvaguarda (ou null se o plug-in não tiver guardado estado algum). Este objecto pode ser usado para aceder a informações do anterior ficheiro de salvaguarda (através do número de salvaguarda e da correlação de ficheiros) ou para processar alterações que tenham ocorrido entre activações de um plug-in.
Se tiver sido usada uma correlação de ficheiros para guardar ficheiros denominados logicamente segundo o número de salvaguarda, esta mesma correlação poderá ser usada para obter os dados do último estado de salvaguarda conhecido.
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
ISavedState lastState =
ResourcesPlugin.getWorkspace().addSaveParticipant(aMinhaInstânciaPlugin, saveParticipant);
if (lastState != null) {
String saveFileName = lastState.lookup(new Path("save")).toString();
File f = aMinhaInstânciaPlugin.getStateLocation().append(saveFileName).toFile();
// a instância de plug-in deve ler qualquer estado importante do ficheiro.
aMinhaInstânciaPlugin.readStateFrom(f);
}
Recorde que podem ocorrer quaisquer eventos de alteração a recursos no espaço de trabalho antes de o plug-in começar por ser activado. Se quiser saber que alterações ocorreram desde que o plug-in foi desactivado, poderá utilizar o mecanismo de salvaguarda para o fazer, mesmo que não precise de guardar mais dados nenhuns.
O participante na salvaguarda deve pedir que a plataforma mantenha um delta de recursos em seu nome. Tal realiza-se como parte da operação de salvaguarda.
public void saving(ISaveContext context) throws CoreException {
// não há estado para guardar com o plug-in, mas pede-se um
// delta de recursos para utilizar na próxima activação.
context.needDelta();
}
Durante o arranque do plug-in, o anterior estado guardado pode ser acedido e serão criados eventos de alteração para todas as alterações que tenham ocorrido desde a última salvaguarda.
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
ISavedState lastState =
ResourcesPlugin.getWorkspace().addSaveParticipant(aMinhaInstânciaPlugin, saveParticipant);
if (lastState != null) {
lastState.processResourceChangeEvents(new oMeuRelatorAlteraçãoRecurso());
}
A classe facultada deve implementar IResourceChangeListener, como se descreve em Acompanhar alterações a recursos. As alterações desde a última salvaguarda sãom reportadas como parte do evento de alteração a recursos POST_AUTO_BUILD.
Nota: As alterações a marcadores não são reportadas nos eventos de alteração armazenados em ISavedState. Terá de partir do princípio de que alguns ou todos os marcadores foram alterados desde a última salvaguarda de estado.