Cuando el núcleo de la plataforma está en ejecución y el conector de recursos está activo, el área de trabajo se representa mediante una instancia de IWorkspace, que proporciona el protocolo para acceder a los recursos que contiene. Una instancia de IWorkspace representa un conjunto de archivos y directorios asociados del sistema de archivos local. Se puede acceder al área de trabajo desde la clase de conector de recursos en org.eclipse.core.resources.
ResourcesPlugin.getWorkspace();
Cuando el conector de recursos no está en ejecución, el área de trabajo solo existe en el sistema de archivos local y el usuario la ve o la manipula por medio de herramientas estándar basadas en archivos. Cuando expliquemos la API del conector de recursos, veremos el aspecto del área de trabajo en el disco.
Cuando instaló el SDK de la plataforma, extrajo los archivos en un directorio que eligió para tal fin. Este directorio es el directorio raíz de la plataforma. En él está el directorio plugins, entre otros. Dentro del directorio raíz de la plataforma, existe el directorio workspace, que se utiliza para conservar los recursos que la plataforma ha creado y manipulado. Si mira en el directorio workspace, verá subdirectorios diferentes para cada proyecto que exista en el área de trabajo. En estos subdirectorios se encuentran las carpetas y los archivos que hay en cada proyecto.
Si el SDK del ejemplo se instaló en c:\MySDK, el directorio c:\MySDK\workspace contendrá subdirectorios denominados según los proyectos del área de trabajo, MyWeb y MyServlet. Estos son los directorios de contenido del proyecto. La plataforma es la que crea los directorios de contenido cuando el usuario crea un proyecto.
Dentro de cada directorio están los archivos y las carpetas del proyecto, dispuestas exactamente igual que en el árbol de recursos del área de trabajo. Todos los nombres de archivo coinciden, y el contenido de los archivos es el mismo tanto si se accede desde el sistema de archivos como desde el área de trabajo. La única diferencia la presenta el archivo .project, que pasaremos a explicar dentro de un momento.
C:\MySDK\workspace (directorio raíz del área de trabajo) .metadata\ (directorio de los metadatos de la plataforma) MyWeb\ (directorio de contenido del proyecto MyWeb) .project index.html images\ logo.gif MyServlet\ (directorio de contenido del proyecto MyServlet) .project src\ main.java bin\ main.class
La plataforma tiene un directorio .metadata especial en el que se guarda la información interna de la plataforma. El directorio .metadata de un área de trabajo podría compararse con una "caja negra". La información importante sobre la estructura del área de trabajo, como las referencias de un proyecto o las propiedades de un recurso, se almacena en la parte de los metadatos del área de trabajo y solo deben acceder a ella las herramientas a través de la API de la plataforma. Estos archivos no deben editarse ni manipularse nunca utilizando la API del sistema de archivos genérico.
Además, cada proyecto tiene su propio archivo .project, donde se guardan los metadatos sobre el proyecto. Este archivo es básicamente el equivalente en disco de la información que hay en la interfaz IProjectDescription de un proyecto.
Aparte del directorio .metadata y de los archivos .project, las carpetas y archivos del directorio workspace son adecuados para otras herramientas. Las herramientas no integradas, como por ejemplo los editores de texto y los programas de utilidad del sistema de archivos, pueden manipular los archivos y carpetas. Lo único que hay que tener en cuenta es que el usuario debe tener cuidado al editar estos archivos tanto en el entorno de trabajo como externamente. (Esto no ofrece ninguna diferencia con respecto a la edición por parte del usuario de un archivo mediante dos herramientas autónomas independientes). El entorno de trabajo proporciona operaciones de renovación para conciliar la vista de recursos del área de trabajo con el estado real del sistema de archivos.
La API de recursos permite manipular este árbol de recursos en el código. Aquí se mostrarán algunos fragmentos de código para obtener una visión rápida de cómo funciona la API de recursos. La API de recursos está definida en una serie de interfaces de org.eclipse.core.resources. Existen interfaces para todos los tipos de recursos, como IProject, IFolder e IFile. El protocolo común extensivo está definido en IResource. También se utiliza la interfaz IPath de org.eclipse.core.runtime, que representa vías de acceso segmentadas, como las vías de acceso de los recursos o del sistema de archivos.
La manipulación de los recursos es muy similar a la manipulación de archivos mediante java.io.File. La API se basa en handles. Cuando se utiliza una API como getProject o getFolder, de devuelve al usuario un handle del recurso. No existe ninguna garantía ni requisito de que exista el recurso hasta que el usuario intenta realizar alguna acción con el handle. Si espera que un recurso exista, puede utilizar el método exists para asegurarse de que es así.
Para navegar por el área de trabajo desde un conector, hay que obtener en primer lugar la interfaz IWorkspaceRoot, que representa el nivel superior de la jerarquía de recursos del área de trabajo.
IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
Una vez que tengamos el directorio raíz de un área de trabajo, podremos acceder a los proyectos que hay en ella.
IProject myWebProject = myWorkspaceRoot.getProject("MyWeb"); // abrir si es necesario if (myWebProject.exists() && !myWebProject.isOpen()) myWebProject.open(null);
Para poder manipular un proyecto, primero tendremos que abrirlo. Al abrir un proyecto se lee la estructura del proyecto desde el disco y se crea la representación de objeto en memoria del árbol de recursos del proyecto. La apertura de un proyecto es una operación explícita, porque cada proyecto abierto utiliza memoria para representar el árbol de recursos internamente, y los proyectos abiertos participan en diversos eventos del ciclo de vida de los recursos (como la construcción) que pueden durar bastante tiempo. En general, no se puede acceder a los proyectos cerrados, que aparecerán vacíos aunque los recursos sigan estando presentes en el sistema de archivos.
Se dará cuenta de que muchos de estos ejemplos de recursos pasan un parámetro null al manipular recursos. Muchas de las operaciones de los recursos tienen potencialmente la duración necesaria para garantizar el informe de su progreso y la cancelación por parte del usuario. Si el código tiene una interfaz de usuario, generalmente pasará una interfaz IProgressMonitor, que permite al conector de recursos informar del progreso a medida que se manipula el recurso y que permite al usuario cancelar la operación si lo desea. Por ahora, tan solo pasaremos null, lo que indica que no hay supervisión del progreso.
Una vez que tengamos un proyecto abierto, podremos acceder a sus carpetas y a sus archivos, así como crear otros adicionales. En el siguiente ejemplo, creamos un recurso de tipo archivo a partir del contenido de un archivo situado fuera del área de trabajo.
IFolder imagesFolder = myWebProject.getFolder("images"); if (imagesFolder.exists()) { // crear un archivo nuevo IFile newLogo = imagesFolder.getFile("newLogo.gif"); FileInputStream fileStream = new FileInputStream( "c:/MyOtherData/newLogo.gif"); newLogo.create(fileStream, false, null); // No hay que preocuparse porque el método create cierra la corriente de datos del archivo. }
En el ejemplo anterior, la primera línea obtiene un handle de la carpeta de imágenes. Para poder utilizar la carpeta, primero debemos comprobar que existe (con el método exists). Asimismo, cuando obtenemos el archivo newLogo, el handle no representa un archivo real hasta que lo creamos en la última línea. En este ejemplo, creamos el archivo llenándolo con el contenido de logo.gif.
El siguiente fragmento de código se parece al anterior, excepto que copia el archivo newLogo del logotipo original, en lugar de crear uno nuevo a partir de su contenido.
IFile logo = imagesFolder.getFile("logo.gif"); if (logo.exists()) { IPath newLogoPath = new Path("newLogo.gif"); logo.copy(newLogoPath, false, null); IFile newLogo = imagesFolder.getFile("newLogo.gif"); ... }
Por último, crearemos otra carpeta de imágenes y trasladaremos a ella el archivo recién creado. Como efecto colateral de mover el archivo, lo redenominaremos.
... IFolder newImagesFolder = myWebProject.getFolder("newimages"); newImagesFolder.create(false, true, null); IPath renamedPath = newImagesFolder.getFullPath().append("renamedLogo.gif"); newLogo.move(renamedPath, false, null); IFile renamedLogo = newImagesFolder.getFile("renamedLogo.gif");
Muchos de los métodos de la API de recursos incluyen un distintivo force booleano que especifica si se forzará la actualización de los recursos que no estén sincronizados con los correspondientes archivos del sistema de archivos local. Hallará más información en el tema IResource. También puede utilizar la API IResource.isSynchronized() para determinar si un determinado recurso está sincronizado con el sistema de archivos.
En el árbol de recursos de ejemplo, hemos presupuesto que todos los directorios de contenido del proyecto están en el directorio workspace, debajo del directorio raíz de la plataforma (C:\MySDK\workspace). Esta es la configuración por omisión. Sin embargo, el directorio del contenido de un proyecto puede correlacionarse de nuevo con un directorio arbitrario del sistema de archivos, tal vez con una unidad de disco diferente.
La capacidad de correlacionar la ubicación de un proyecto con independencia de los otros proyectos permite al usuario almacenar el contenido de un proyecto en un lugar que tenga sentido para el proyecto y para el equipo del proyecto. El directorio de contenido de un proyecto debe considerarse "abierto al descubierto". Esto significa que los usuarios pueden crear, modificar y suprimir recursos utilizando el entorno de trabajo y conectores, o utilizando directamente un sistema de archivos basado en herramientas y editores.
Los nombres de las vías de acceso de recursos no son vías de acceso completas del sistema de archivos. Las vías de acceso siempre están basadas en la ubicación del proyecto (que suele ser el directorio workspace). Para obtener la vía de acceso completa del sistema de archivos a un recurso, debe consultar su ubicación con el método IResource.getLocation. Sin embargo, no puede utilizar IProjectDescription.setLocation para cambiar su ubicación, ya que ese método sólo establece una estructura de datos.
Y, a la inversa, si desea obtener el correspondiente objeto recurso dada una vía de acceso del sistema de archivos, puede utilizar el método IWorkspaceRoot.getFileForLocation o el método IWorkspaceRoot.getContainerForLocation.
Cuando utilizamos la API de recursos para modificar el árbol de recursos del área de trabajo, además de actualizar los objetos recurso, cambian los archivos del sistema de archivos. ¿Qué ocurre con los cambios realizados en los archivos de recursos que tienen lugar fuera de la API de la plataforma?
Los cambios externos realizados en los recursos no se reflejarán en el área de trabajo ni en los objetos recurso hasta que los detecte el conector de recursos. Los clientes pueden utilizar una API de recursos para conciliar el área de trabajo y los objetos recurso con el sistema de archivos local de manera silenciosa y sin la intervención del usuario. El usuario siempre puede forzar una renovación de manera explícita en la vista Navegador de recursos del entorno de trabajo.
Nota: muchos de los métodos de las API de recursos incluyen un parámetro force que especifica cómo deben manejarse los recursos que no están sincronizados con el sistema de archivos. El manual de consulta de las API para cada método proporciona información específica sobre este parámetro. Los métodos adicionales de la API permiten el control programático de la renovación del sistema de archivos, como IResource.refreshLocal(int depth, IProgressMonitor monitor). Consulte IResource para obtener información sobre su utilización correcta y el coste que supone.