El proveedor de repositorios (RepositoryProvider) es la clase central de la implementación del repositorio. Esta clase es la que se encarga de configurar un proyecto para la gestión de repositorios, y de proporcionar los ganchos necesarios para la modificación de recursos. Los proveedores se correlacionan con un proyecto utilizando las propiedades persistentes del proyecto. El mecanismo que correlaciona los proveedores con un proyecto no es central para la API del equipo, pero deberá tenerlo presente cuando filtre los recursos de la UI. La mayoría de las veces, utilizará la API del equipo para trabajar con los proyectos y asociarlos al proveedor.
Para implementar un proveedor, debe definir un repositorio mediante el punto de extensión org.eclipse.team.core.repository y suministrar una clase derivada de RepositoryProvider. Utilizaremos el cliente CVS como ejemplo para ver cómo funciona todo esto.
El punto de extensión org.eclipse.team.core.repository permite añadir una definición de repositorio. Los códigos XML para el cliente CVS son los siguientes:
<extension
point="org.eclipse.team.core.repository">
<repository
class="org.eclipse.team.internal.ccvs.core.CVSTeamProvider"
id="org.eclipse.team.cvs.core.cvsprovider">
</repository>
</extension>
Esto registra el proveedor del equipo en el conector de soporte de equipo y asigna un id que debe utilizarse cuando el proveedor se asocia a un proyecto. La clase (atributo class) especificada para el repositorio debe ampliar la clase RepositoryProvider.
La clase identificada en la extensión debe ser una subclase de RepositoryProvider. Las responsabilidades primarias de esta clase son las de configurar y desconfigurar un proyecto para el soporte de repositorio y suministrar los ganchos de modificación de recursos que se necesiten. El cliente CVS es un buen ejemplo de ello. Su proveedor de repositorios es CVSTeamProvider.
public class CVSTeamProvider extends RepositoryProvider {
...
RepositoryProvider define dos métodos abstractos, configureProject y deconfigure. Todos los proveedores deben implementar estos métodos.
Un proyecto se configura cuando se asocia por primera vez con un proveedor de repositorios determinado. Esto se produce generalmente cuando el usuario selecciona un proyecto y utiliza los asistentes de equipo para asociarlo con el repositorio. Independientemente de cómo se desencadene la operación, este es el momento adecuado para calcular o almacenar en antememoria los datos relativos al proyecto que necesitará para suministrar la función del repositorio. (Supongamos que la correlación entre el proyecto y el proveedor ya ha tenido lugar. El usuario se encargará de ello en el asistente de configuración).
El proveedor de CVS tan solo difunde el hecho de que ya se ha configurado un proyecto:
public void configureProject() throws CoreException {
CVSProviderPlugin.broadcastProjectConfigured(getProject());
}
No seguiremos con la implementación del mecanismo de difusión del conector. Basta con decir que las partes que deben calcular o inicializar los datos específicos del proyecto pueden hacerlo en este momento.
Un proyecto se desconfigura cuando el usuario ya no quiere que el proveedor del equipo esté asociado al proyecto. El conector es el que se encarga de implementar la acción de usuario que hace que esto suceda (y en ese momento se producirá la descorrelación entre el proyecto y el proveedor del equipo). Cuando se llama al método deconfigure, ha llegado el momento de suprimir las antememorias que estén relacionadas con el proyecto o de eliminar las referencias que se hagan al proyecto en la UI. El proveedor de CVS vacía las antememorias relacionadas con el proyecto que se guardaban en las vistas, y difunde el hecho de que el proyecto se haya desconfigurado.
public void deconfigure() throws CoreException {
...
try {
EclipseSynchronizer.getInstance().flush(getProject(), true, true /*flush deep*/, null);
} catch(CVSException e) {
throw new CoreException(e.getStatus());
} finally {
CVSProviderPlugin.broadcastProjectDeconfigured(getProject());
}
}
Generalmente, el primer paso de la construcción de una UI de equipo consiste en implementar una página de asistente que permita a los usuarios configurar un proyecto para el soporte de equipo del conector. En ella, el ID del proveedor del equipo se añadirá a las propiedades del proyecto. Participará en la configuración del proyecto efectuando contribuciones al punto de extensión org.eclipse.team.ui.configurationWizards. Este asistente se muestra cuando el usuario elige Equipo->Compartir proyecto...
Todo esto lo veremos en el contexto de la implementación del cliente CVS. A continuación figuran los códigos XML del asistente de configuración procedentes de la UI de CVS.
<extension
point="org.eclipse.team.ui.configurationWizards">
<wizard
name="%SharingWizard.name"
icon="icons/full/wizards/newconnect_wiz.png"
class="org.eclipse.team.internal.ccvs.ui.wizards.SharingWizard"
id="org.eclipse.team.ccvs.ui.SharingWizard">
</wizard>
</extension>
Como de costumbre, los conectores suministran una clase (atributo class) que implementa la extensión, y un id exclusivo que identifica la extensión. El nombre y el icono (atributos name e icon) se muestran en la primera página del asistente de configuración del proyecto, por si se puede elegir de entre varios proveedores.
Una vez que el usuario ha seleccionado un proveedor, la página siguiente muestra información de configuración específica del proveedor. (Si su proveedor es el único conector de proveedor de equipo instalado, el asistente pasa directamente a su página). El asistente debe implementar la interfaz IConfigurationWizard, que inicializa el asistente para un entorno de trabajo y un proyecto especificados. El resto de la implementación depende del diseño del asistente. Deberá reunir toda la información necesaria para asociar el proyecto al soporte del equipo.
Una vez completado el asistente, debe correlacionar el proveedor del equipo con el proyecto utilizando el método RepositoryProvider.map(IProject, String). La correlación maneja el proceso de asignar a su proyecto la propiedad persistente del proyecto correcto.
El cliente CVS realiza este proceso en el método setSharing del correspondiente proveedor, método al que se llama en el momento de finalizar el asistente:
public void setSharing(IProject project, FolderSyncInfo info, IProgressMonitor monitor) throws TeamException {
// Asegurarse de que la información proporcionada coincide con la del proyecto
...
// Asegurarse de que la ubicación proporcionada está gestionada
...
// Registrar el proyecto en el equipo
RepositoryProvider.map(project, CVSProviderPlugin.getTypeId());
}
Los métodos estáticos de RepositoryProvider hacen que a los clientes les resulte fácil correlacionar los proyectos con los proveedores y localizar los proveedores asociados a un proyecto dado.
Si un producto elige añadir un conector de repositorio a una posibilidad, debe enlazar la posibilidad con el ID del repositorio. A continuación se indican los dos pasos necesarios para habilitar un proveedor de repositorios como posibilidad:
<activityPatternBinding
activityId="org.eclipse.team.cvs"
pattern="org\.eclipse\.team\.cvs\.core/.*cvsnature">
</activityPatternBinding>
<activityPatternBinding
activityId="org.eclipse.team.cvs"
pattern="org\.eclipse\.team\.cvs\.ui/.*">
</activityPatternBinding>
Existen dos puntos desencadenantes de posibilidades definidos por los conectores de equipo. El primero es el asistente Equipo > Compartir proyecto..., que permite filtrar los proveedores de repositorios en función del estado de habilitación/inhabilitación de las posibilidades del entorno de trabajo, y el otro es el desencadenante de habilitación automática del conector de equipo.
La mayor parte de la función interesante asociada con un proveedor de repositorios ocurre cuando el usuario trabaja con los recursos del proyecto configurado para el proveedor. Para poder estar al corriente de los cambios que el usuario efectúa en un recurso, el proveedor puede implementar ganchos de modificación de recursos. El conector de recursos suministra estos ganchos en forma de puntos de extensión. la documentación de IMoveDeleteHook, IFileModificationValidator y ResourceRuleFactory describe los detalles de implementación de estos ganchos.
El conector del equipo optimiza y simplifica la asociación entre el gancho y los recursos apropiados a base de registrar ganchos genéricos en el conector de recursos. Los ganchos genéricos no hacen otra cosa que buscar un determinado recurso en el proveedor de repositorios y obtener el gancho del recurso. La ventaja de este procedimiento es que únicamente se llama al gancho de un solo proveedor, en lugar de hacer que cada implementación de proveedor registre un gancho que primero deba comprobar si el proveedor gestiona el recurso.
Lo que esto supone para el conector es que el usuario proporciona los ganchos necesarios alterando temporalmente los métodos de la clase RepositoryProvider. La implementación por omisión de estos métodos devuelve el valor null, lo que indica que no hace falta ningún gancho (excepto en el caso de la fábrica de normas de recursos, que se describe más adelante):