Já vimos como constituir lotes de alterações a recursos num executável (Constituir lotes de alterações a recursos). Vamos abordar agora o reverso da medalha. E se quisermos acompanhar todas as alterações ao espaço de trabalho que acontecem enquanto o plug-in está em execução? Poderemos registar um IResourceChangeListener junto do espaço de trabalho. O ouvinte será notificado das alterações através de um objecto IResourceChangeEvent, o qual descreve as alterações.
Primeiro, é necessário registar um ouvinte de alterações a recursos junto do espaço de trabalho.
IResourceChangeListener listener = new oMeuRelatorAlteraçãoRecurso(); ResourcesPlugin.getWorkspace().addResourceChangeListener( listener, IResourceChangeEvent.POST_CHANGE);
O ouvinte será notificado após serem efectuadas modificações aos recursos de espaço de trabalho. Os métodos de APIs de recursos que modificam recursos desencadeiam estes eventos como parte do seu comportamento documentado. O comentário de método para um método de API de recursos afirma explicitamente se desencadeia ou não um evento de alterações a recursos. Por exemplo, o seguinte está incluído no comentário IFile.setContents():
Este método altera recursos; estas alterações serão reportadas num evento de alterações a recursos subsequente, incluindo indicação de que o conteúdo deste ficheiro foi alterado.
Os métodos que criam, eliminam ou alteram um recurso desencadeiam geralmente estes eventos. Os métodos que lêem mas não escrevem recursos geralmente não desencadeiam estes eventos.
O evento de alterações a recursos descreve as especificidades da alteração (ou conjunto de alterações) ocorrida no espaço de trabalho. O evento contém um delta de recursos que descreve o efeito real das alterações. Por exemplo, se adiciona rum recurso e o eliminar mais tarde durante um lote de alterações, o recurso não aparece no delta.
O delta de recursos está estruturado como árvore sediada na raiz do espaço de trabalho. A árvore do delta de recursos descreve estes tipos de alterações:
Para percorrer uma árvore de delta de recursos, poderá implementar a interface IResourceDeltaVisitor ou percorrer a árvore explicitamente com IResource.getAffectedChildren. Os visitantes de delta de recursos implementam um método visit que é chamado pelo delta de recursos à medida que vai enumerando cada alteração na árvore.
Nota: As alterações feitas a propriedades de sessão de recursos ou propriedades persistentes de recursos não estão identificadas no delta de recursos.
Os eventos de alterações a recursos são enviados sempre que seja feita uma alteração (ou um conjunto de alterações em lote) ao espaço de trabalho. Além disso, os eventos de alterações a recursos são enviados para certas operações de espaço de trabalho específicas. A tabela a seguir resume os tipos de eventos de alterações a recursos e quando são reportados.
Tipo de evento |
Descrição |
---|---|
PRE_CLOSE |
Notifica ouvintes do fecho iminente de um projecto. Este evento pode ser usado para extrair e guardar informações necessárias da representação em memória (p.ex., propriedades de sessão) de um projecto antes deste ser fechado. (Quando se fecha um projecto, a representação em memória é inutilizada.)O espaço de trabalho é bloqueado (não se pode actualizar recursos) durante este evento. O evento contém o projecto que estiver a ser fechado. |
PRE_DELETE |
Notifica ouvintes da eliminação iminente de um projecto. Este evento pode ser usado para realizar operações de limpeza como, por exemplo remoção de estados guardados relacionados com o projecto do directório do plug-in. O espaço de trabalho é bloqueado (não se pode actualizar recursos) durante este evento. O evento contém o projecto que estiver a ser eliminado. |
PRE_AUTOBUILD |
Notifica os ouvintes antes de ocorrer construção automática. Este evento é difundido quando a plataforma detecta a necessidade de uma construção automática, independentemente de a dita estar realmente activada ou não. O espaço de trabalho não é bloqueado durante este evento (podem actualizar-se recursos). O evento contém um delta de recursos que descreve as alterações ocorridas desde que o último evento POST_CHANGE foi reportado. |
POST_AUTOBUILD |
Notifica os ouvintes depois ocorrer construção automática. Este evento é difundido depois de a plataforma realizar uma construção automática, independentemente de a dita estar realmente activada ou não. O espaço de trabalho não é bloqueado durante este evento (podem actualizar-se recursos). O evento contém um delta de recursos que descreve as alterações ocorridas desde que o último evento POST_CHANGE foi reportado. |
POST_CHANGE |
Descreve um conjunto de as alterações ocorridas no espaço de trabalho desde que o último evento POST_CHANGE foi reportado. Desencadeado depois de uma API de alteração de recursos ser utilizada individualmente ou num conjunto em lote de alterações ao espaço de trabalho. Desencadeado também depois de uma notificação PRE_AUTOBUILD ou POST_AUTOBUILD ser concluída. O evento contém um delta de recursos que descreve as alterações reais desde o último evento POST_CHANGE. O espaço de trabalho é bloqueado (não se pode actualizar recursos) durante este evento. |
O exemplo seguinte implementa um ouvinte de alterações a recursos baseado em consola. Um ouvinte de alterações a recursos é registado para tipos de eventos específicos e as informações sobre estes eventos são impressas na consola:
IResourceChangeListener listener = new oMeuRelatorAlteraçãoRecurso(); ResourcesPlugin.getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_AUTO_BUILD | IResourceChangeEvent.POST_AUTO_BUILD | IResourceChangeEvent.POST_CHANGE);
O ouvinte verifica cada tipo de evento e reporta informações sobre o recurso alterado e as espécies de alterações ocorridas. Embora este exemplo esteja concebido para mostrar um ouvinte genérico que trata todos os tipos de eventos de recursos, um ouvinte habitual registar-se-ia para um único tipo de evento.
A implementação de POST_CHANGE utiliza outra classe que pode ser usada para visitar as alterações no delta de recursos.
import org.eclipse.resources.*; import org.eclipse.runtime.*; public class oMeuRelatorAlteraçãoRecurso implements IResourceChangeListener { public void resourceChanged(IResourceChangeEvent event) { IResource res = event.getResource(); switch (event.getType()) { case IResourceChangeEvent.PRE_CLOSE: System.out.print("Project "); System.out.print(res.getFullPath()); System.out.println(" is about to close."); break; case IResourceChangeEvent.PRE_DELETE: System.out.print("Project "); System.out.print(res.getFullPath()); System.out.println(" is about to be deleted."); break; case IResourceChangeEvent.POST_CHANGE: System.out.println("Resources have changed."); event.getDelta().accept(new DeltaPrinter()); break; case IResourceChangeEvent.PRE_AUTO_BUILD: System.out.println("Auto build about to run."); event.getDelta().accept(new DeltaPrinter()); break; case IResourceChangeEvent.POST_AUTO_BUILD: System.out.println("Auto build complete."); event.getDelta().accept(new DeltaPrinter()); break; } } }
A classe DeltaPrinter implementa a interface IResourceDeltaVisitor para interrogar o delta de recursos. O método visit() é chamado para cada alteração a recursos no delta de recursos. O visitante utiliza um valor de retorno para indicar se devem ser visitados deltas de recursos descendentes.
class DeltaPrinter implements IResourceDeltaVisitor { public boolean visit(IResourceDelta delta) { IResource res = delta.getResource(); switch (delta.getKind()) { case IResourceDelta.ADDED: System.out.print("Resource "); System.out.print(res.getFullPath()); System.out.println(" was added."); break; case IResourceDelta.REMOVED: System.out.print("Resource "); System.out.print(res.getFullPath()); System.out.println(" was removed."); break; case IResourceDelta.CHANGED: System.out.print("Resource "); System.out.print(res.getFullPath()); System.out.println(" has changed."); break; } return true; // visit the children } }
Podem encontrar-se mais informações no delta de recursos fornecido. A porção de código seguinte mostra como o caso IResourceDelta.CHANGED poderia ser implementado para descrever melhor as alterações a recursos.
... case IResourceDelta.CHANGED: System.out.print("Resource "); System.out.print(delta.getFullPath()); System.out.println(" has changed."); int flags = delta.getFlags(); if ((flags & IResourceDelta.CONTENT) != 0) { System.out.println("--> Content Change"); } if ((flags & IResourceDelta.REPLACED) != 0) { System.out.println("--> Content Replaced"); } if ((flags & IResourceDelta.MARKERS) != 0) { System.out.println("--> Marker Change"); IMarkerDelta[] markers = delta.getMarkerDeltas(); // if interested in markers, check these deltas } break; ...
Para uma descrição completa de deltas de recursos, visitantes e deltas de marcadores, consulte a especificação de API para IResourceDelta, IResourceDeltaVisitor e IMarkerDelta.
Nota: Os ouvintes de alterações a recursos são úteis para acompanhar alterações que ocorram em recursos enquanto o plug-in estiver activado. Se o plug-in registar um ouvinte de alterações a recursos durante o seu código de arranque, é possível que tenham sido desencadeados muitos eventos de alterações a recursos antes da activação do plug-in. O delta de recursos contido no primeiro evento de alterações a recursos recebido pelo plug-in não contém todas as alterações efectuadas desde a última activação do plug-in. Se precisar de acompanhar alterações efectuadas entre activações do plug-in, deve utilizar o suporte facultado para salvaguarda de espaço de trabalho. Este procedimento está descrito em Participação na salvaguarda do espaço de trabalho.
Nota: Alguns eventos de alterações a recursos são desencadeados durante o processamento que ocorre num módulo em segundo plano. Os ouvintes de alterações a recursos devem estar protegidos contra módulos. Consulte Questões de módulos para ver uma abordagem da segurança contra módulos com a UI.