Rastrear los cambios de recursos

El conector de recursos incluye un mecanismo de eventos para notificar los cambios en los recursos a las partes interesadas. Si necesita hacer un seguimiento de los cambios en el árbol de recursos mientras el conector está en ejecución, puede registrar un IResourceChangeListener con el área de trabajo. Al escuchador se le notificarán los cambios mediante un objeto IResourceChangeEvent, que describe los cambios.

Proceso de cambio de recursos

Para hacer un seguimiento de los cambios en los recursos, debe registrar un escuchador de cambio de recursos con el área de trabajo.

IResourceChangeListener listener = new MyResourceChangeReporter();
ResourcesPlugin.getWorkspace().addResourceChangeListener(
    listener, IResourceChangeEvent.POST_CHANGE);

Al escuchador se le notificará que se han efectuado las modificaciones en los recursos del área de trabajo. Los métodos de API de recurso que modifican recursos activan estos eventos como una de sus funciones documentadas. El comentario de un método de API de recurso indica explícitamente si dicho método activa o no un evento de cambio de recursos. Por ejemplo, el comentario IFile.createContents() contiene lo siguiente:

Este método cambia recursos; estos cambios se notificarán en un evento de cambio de recursos correspondiente, que indica que el contenido de este archivo ha sido modificado.

Generalmente, los métodos que crean, eliminan o modifican un recurso activan estos eventos. Los métodos que leen, pero no escriben, recursos no suelen activar estos eventos.

Cambios por lotes y deltas de recursos

Si ha de modificar una serie de recursos a la vez, puede establecer un proceso por lotes para las llamadas de API de cambio de recursos de manera que sólo se envíe un evento de cambio de recursos al conjunto de cambios completo. Para que las operaciones se realicen por lotes se utiliza IWorkspace.run(runnable, monitor). Los eventos de cambio de recursos sólo se envían a escuchadores registrados cuando se ha completado el ejecutable especificado. Cualquier ejecutable adicional (jerarquizado) creado en el ejecutable será considerado parte de la operación por lotes padre y los cambios de recursos hechos en estos ejecutables aparecerán en la notificación de cambio de recursos del padre.

Siempre que le sea posible, debe establecer un proceso por lotes para los cambios a fin de reducir la sobrecarga en la difusión de muchos cambios granulares.  En caso contrario, es probable que el sistema se desborde con notificaciones de cambio de recursos y construcciones automáticas.

El evento de cambio de recursos describe los detalles específicos del cambio (o del conjunto de cambios) que se ha producido en el área de trabajo. El evento contiene un delta de recursos que describe el efecto final de los cambios. Por ejemplo, si añade un recurso y más adelante lo elimina durante un proceso por lotes de cambios, el recurso no aparecerá en el delta.

El delta de recursos está estructurado como un árbol cuya raíz está en el directorio raíz del área de trabajo. El árbol del delta de recursos describe estos tipos de cambios:

Para visitar un árbol de delta de recursos, puede implementar la interfaz IResourceDeltaVisitor o visitar el árbol de manera explícita utilizando IResource.getAffectedChildren. Los visitantes del delta de recursos implementan un método visit al que el delta de recursos llama a medida que identifica cada cambio en el árbol.

Nota:  Los cambios efectuados en las propiedades de sesión de recursos o en las propiedades de persistencia de recursos no se identifican en el delta de recursos.

Eventos de cambio de recursos

Los eventos de cambio de recursos se envían siempre que se hace un cambio (o conjunto de cambios por lotes) en el área de trabajo. Los eventos de cambio de recursos también se envían cuando se realizan operaciones de área de trabajo específicas. La tabla siguiente contiene un resumen de los tipos de eventos de cambios de recursos y de cuándo se notifican.

Tipo de evento

Descripción

PRE_CLOSE

Notifica a los escuchadores que se va a cerrar un proyecto. Este evento puede utilizarse para extraer y guardar información necesaria de la representación en la memoria (por ejemplo, propiedades de sesión) de un proyecto antes de cerrarlo. (Cuando se cierra un proyecto, se desecha la representación en la memoria). Durante este evento, el área de trabajo está bloqueada (no se puede actualizar ningún recurso). El evento PRE_CLOSE también se activa durante la conclusión del área de trabajo ya que se cerrarán todos los proyectos abiertos. El evento contiene el proyecto que se está cerrando.

PRE_DELETE

Notifica a los escuchadores que se va a eliminar un proyecto. Este evento puede utilizarse para efectuar operaciones de borrar, como suprimir cualquier estado guardado relacionado con el proyecto, desde el directorio del conector.  Durante este evento, el área de trabajo está bloqueada (no se puede actualizar ningún recurso). El evento contiene el proyecto que se está eliminando.

PRE_AUTOBUILD

Notifica a los escuchadores que se va a producir una construcción automática.  Este evento se difunde cuando la plataforma detecta que es preciso que tenga lugar una construcción automática, independientemente de si ésta está habilitada realmente.  El área de trabajo no está bloqueada durante este evento (se pueden actualizar recursos). El evento contiene un delta de recursos que describe los cambios que se han producido desde que se notificó el último evento POST_CHANGE.

POST_AUTOBUILD

Notifica a los escuchadores que se ha producido una construcción automática. Este evento se difunde después de que la plataforma ha efectuado una construcción automática, independientemente de si ésta está habilitada realmente.  El área de trabajo no está bloqueada durante este evento (se pueden actualizar recursos). El evento contiene un delta de recursos que describe los cambios que se han producido desde que se notificó el último evento POST_CHANGE.

POST_CHANGE

Describe un conjunto de cambios que se han producido en el área de trabajo desde que se notificó el último evento POST_CHANGE. Se activa después de haber utilizado una API de cambio de recursos de manera individual o en un conjunto de cambios de área de trabajo por lotes. También se activa una vez completada la notificación PRE_AUTOBUILD o POST_AUTOBUILD. El evento contiene un delta de recursos que describe los cambios definitivos desde el último evento POST_CHANGE.  Durante este evento, el área de trabajo está bloqueada (no se puede actualizar ningún recurso).

Implementar un escuchador de cambio de recursos

En el ejemplo siguiente se implementa un escuchador de cambio de recursos basado en la consola. El escuchador de cambio de recursos se registra para tipos de eventos específicos y la información sobre estos eventos se imprime en la consola:

IResourceChangeListener listener = new MyResourceChangeReporter();
ResourcesPlugin.getWorkspace().addResourceChangeListener(listener,
    IResourceChangeEvent.PRE_CLOSE
    | IResourceChangeEvent.PRE_DELETE
    | IResourceChangeEvent.PRE_AUTO_BUILD
    | IResourceChangeEvent.POST_AUTO_BUILD
    | IResourceChangeEvent.POST_CHANGE);

El escuchador comprueba cada tipo de evento e informa sobre el recurso que se ha modificado y los tipos de cambios que se han producido.  Aunque este ejemplo está diseñado para mostrar un escuchador genérico que maneja todos los tipos de eventos de recursos, un escuchador común se registraría para un solo tipo de evento.

La implementación para POST_CHANGE utiliza otra clase que puede utilizarse para visitar los cambios en el delta de recursos.

import org.eclipse.resources.*;
import org.eclipse.runtime.*;
public class MyResourceChangeReporter 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;

        }
    }
}

La clase DeltaPrinter implementa la IResourceDeltaVisitor interfaz para preguntar al delta de recursos. Se llama al método visit() cada vez que se modifica un recurso en el delta de recursos. El visitante utiliza un valor de retorno para indicar si deben visitarse los deltas para recursos hijo.

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; // visitar el hijo
    }
}

Puede obtenerse más información del delta de recursos suministrado. El segmento siguiente muestra cómo podría implementarse el caso IResourceDelta.CHANGED para describir los cambios de recursos de manera más detallada.

...
case IResourceDelta.CHANGED:
    System.out.print("Resource ");
    System.out.print(delta.getFullPath());
    System.out.println(" has changed.");
    switch (delta.getFlags()) {
        case IResourceDelta.CONTENT:
            System.out.println("--> Content Change");
            break;
        case IResourceDelta.REPLACED:
            System.out.println("--> Content Replaced");
            break;
        case IResourceDelta.REMOVED:
            System.out.println("--> Removed");
            break;
        case IResourceDelta.MARKERS:
            System.out.println("--> Marker Change");
            IMarkerDelta[] markers = delta.getMarkerDeltas();
            // si está interesado en marcadores, compruebe estos deltas
            break;
    }
    break;
...

Para obtener una descripción completa de deltas de recursos, visitantes y deltas de marcadores, consulte la especificación de API para IResourceDelta, IResourceDeltaVisitor y IMarkerDelta.

Nota:  Los escuchadores de cambio de recursos resultan satisfactorios para el rastreo de cambios que se producen en los recursos mientras el conector está activado. Si el conector registra un escuchador de cambio de recursos durante su código de arranque, es posible que muchos eventos de cambio de recursos se hayan activado antes de activarse el conector. El delta de recursos contenido en el primer evento de cambio de recursos que ha recibido el conector no contendrá todos los cambios efectuados desde la última vez que se activó el conector. Si necesita hacer un seguimiento de los cambios hechos entre activaciones del conector, debe utilizar el soporte que se proporciona para la operación de guardar del área de trabajo. Esto se describe en Participación de guardado del área de trabajo.