Incompatibilidades entre Eclipse 3.1 y 3.2

Entre las versiones 3.1 y 3.2, Eclipse ha cambiado de forma que presenta incompatibilidades que afectan a los plug-ins. Los siguientes puntos describen las áreas que han cambiado y suministran instrucciones para migrar plug-ins de la versión 3.1 a la versión 3.2. Tenga en cuenta que sólo necesita consultarlos si experimenta problemas al ejecutar el plug-in 3.1 en 3.2.

  1. Los recursos ya no están necesariamente en el sistema de archivos local
  2. Cambios de la API para MultiPageEditorSite
  3. Cambios de contenido en config.ini
  4. Cambios de contenido en aplicaciones desplegadas jnlp
  5. Las llamadas explícitas a Bundle.start() fuerzan la activación del paquete compuesto en el próximo reinicio
  6. El subrayado ya no se sustituye por un guión en los números de versión de plug-in

1. Los recursos ya no están necesariamente en el sistema de archivos local

Elementos afectados: los clientes de la API IWorkspace que presuponen que los recursos están almacenados en el sistema de archivos local.

Descripción: antes de Eclipse 3.2, cada IResource existente tenía un archivo o un directorio correspondiente en un sistema de archivos al que podía acceder java.io.File. En Eclipse 3.2 se añadió soporte para crear recursos cuyos contenidos se almacenan en un sistema de archivos de respaldo arbitrario. Los recursos que utilizan este soporte ya no pueden representarse directamente como un java.io.File.

Acción necesaria: el antiguo método IResource.getLocation() devuelve la vía de acceso del sistema de archivos local de un recurso. Este método devuelve nulo para los recursos que no se han almacenado en el sistema de archivos local. La mayoría de llamadores de getLocation() lo hacían así para obtener una instancia de java.io.File que ya no puede utilizarse para recursos que no están almacenados en el sistema de archivos local.

El plug-in org.eclipse.core.filesystem nuevo proporciona una API del sistema de archivos genérico que puede utilizarse en lugar de java.io.File. En concreto, una instancia de org.eclipse.core.filesystem.IFileStore proporciona la mayoría de los mismos métodos que están disponibles en java.io.File. El fragmento de código siguiente obtiene una instancia de IFileStore para un recurso dado:

   IResource resource = ...;//algún recurso
   IFileStore store = EFS.getStore(resource.getLocationURI());

La tabla siguiente proporciona métodos equivalente en IFileStore para operaciones que normalmente se realizan con java.io.File:

java.io.FileIFileStore
deletedelete
getNamegetName
getParentgetParent
listchildNames
mkdirmkdir(EFS.SHALLOW, null)
mkdirsmkdir(EFS.NONE, null)
renameTomove
new FileInputStream(file)openInputStream
new FileOutputStream(file)openOutputStream

En la API IFileStore, la mayoría de la información acerca de un archivo se almacena en una estructura llamada IFileInfo que se obtiene llamando a IFileStore.fetchInfo(). Este diseño permite obtener una mayor optimización del código utilizando java.io.File, porque muchos atributos de un archivo pueden obtenerse a menudo con una sola llamada de sistema de archivos. Tenga en cuenta que la información de un IFileInfo se volverá obsoleta si el archivo subyacente se cambia por lo que las instancias solo deben mantenerse mientras sean necesarias. A continuación se proporcionan algunos métodos de java.io.File que tienen métodos equivalentes en IFileInfo:

java.io.FileIFileInfo
canWriteisReadOnly
existsexists
getNamegetName
isDirectoryisDirectory
isFile!isDirectory()
isHiddenisHidden
lastModifiedgetLastModified
lengthgetLength
setLastModifiedsetLastModified
setReadOnlysetAttribute(EFS.ATTRIBUTE_READ_ONLY, true)

A modo de ejemplo, el código que antes llamaba a java.io.File.exists(), ahora puede llamar a IFileStore.fetchInfo().exists(). Cuando se modifica IFileInfo, el resultado debe volver a almacenarse utilizando el método IFileStore.putInfo. Por ejemplo, este fragmento de código invierte el atributo de solo lectura en un archivo

   IFileStore store = ...;//un almacén de archivos
   IFileInfo info = store.fetchInfo();
   boolean readOnly = info.getAttribute(EFS.ATTRIBUTE_READ_ONLY);
   info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, !readOnly);
   store.putInfo(info, EFS.SET_ATTRIBUTES, null);

IProjectDescription.getLocation()

Como en el método getLocation(), la ubicación de la descripción del proyecto ya no estará en el sistema de archivos local. El método IProjectDescription.getLocationURI() puede utilizarse para obtener la ubicación de un recurso en un sistema de archivos arbitrario.

Almacenamiento en la memoria caché local

Algunos clientes deben tener necesariamente una representación local de un archivo. Por ejemplo, pueden estar lanzando una herramienta nativa contra ese archivo o utilizando bibliotecas desconocidas para Eclipse que solo puedan manejar recursos del sistema de archivos (como por ejemplo java.util.zip.ZipFile). En estos casos, puede pedir un IFileStore para devolver una copia local en memoria caché del contenido:

   IFileStore store = ...;//un almacén de archivos
   //ver si puede representarse directamente como archivo local
   java.io.File local = store.toLocalFile(EFS.NONE, null);
   //si no, preguntar por una copia local del archivo en memoria caché
   if (local == null)
      local = store.toLocalFile(EFS.CACHE, null);

Tenga en cuenta que una vez se obtiene una copia en memoria caché de un archivo, no permanece en sincronía con el sistema de archivos local del que provenía. Al modificar la copia en memoria caché no se modificará el archivo subyacente.

Anomalía elegante

Los clientes que no pueden manejar recursos fuera del sistema de archivos local querrán adaptar su código para que la anomalía sea más elegante. Los clientes pueden comprobar si un recurso está en el sistema de archivos local e ignorar el recurso o alertar al usuario cuando encuentran un recurso que no pueden manejar. Para determinar si un recurso está en el sistema de archivos local, necesita descubrir su esquema de sistema de archivos. Puede obtener esto a partir de un recurso de la manera siguiente:

   IResource resource = ...;//algún recurso
   URI uri = resource.getLocationURI();
   if (uri != null && EFS.SCHEME_LOCAL.equals(uri.getScheme())) {
      //el archivo está en el sistema de archivos local
   } else {
      //el archivo no está en el sistema de archivos local
   }

Si tiene a mano una instancia IFileStore, puede obtener el esquema de la manera siguiente:

   IFileStore store = ...;//un almacén de archivos
   store.getFileSystem().getScheme();

2. Cambios de la API para MultiPageEditorSite

Elementos afectados: los clientes que llaman a MultiPageEditorSite.progressStart() MultiPageEditorSite.progressEnd().

Descripción: durante el desarrollo de Eclipse 3.0, estos métodos se añadieron como parte del trabajo de soporte del progreso. Antes del release 3.0, la forma en que se manejaba el progreso cambió y este método ya no resultaba necesario. Por error del programador, estos métodos públicos quedaron en el release 3.0. Estos dos métodos nunca han dado servicio a ninguna función en un release de Eclipse y por lo tanto se han suprimido.

Acción necesaria: los clientes que llaman a MultiPageEditorSite.progressStart() o MultiPageEditorSite.progressEnd() deben pasar a utilizar IWorkbenchSiteProgressService en su lugar.

3. Cambios de contenido en config.ini

Elementos afectados: los clientes que tienen un archivo config.ini personalizado y migran sus aplicaciones a 3.2.

Descripción: antes de 3.2, el valor habitual para osgi.bundles contenido en el archivo config.ini era org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start. Debido a la refactorización del entorno de ejecución, este valor debe actualizarse para que la aplicación se inicie satisfactoriamente.

Acción necesaria: cambie el valor de osgi.bundles para que incluya org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start.

4. Cambios de contenido en aplicaciones desplegadas jnlp

Elementos afectados: los clientes que despliegan aplicaciones RCP y han especificado un valor para osgi.bundles.

Descripción: antes de 3.2, el valor habitual para osgi.bundles contenido en el archivo jnlp principal era org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start. Debido a la refactorización del entorno de ejecución, este valor debe actualizarse; de lo contrario, se lanzarán excepciones de tipo NullPointerException que impedirán el inicio de la aplicación.

Acción necesaria: cambie el valor de osgi.bundles para que incluya org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start.

5. Las llamadas explícitas a Bundle.start() fuerzan la activación del paquete compuesto en el próximo reinicio

Elementos afectados: los clientes que llaman a Bundle.start().

Descripción: en Eclipse, un paquete compuesto se especifica como paquete compuesto de inicio poco activo mediante la cabecera Eclipse-LazyStart (o la cabecera obsoleta Eclipse-AutoStart). En Eclipse 3.1, el método org.osgi.framework.Bundle.start() no marcaba los paquetes compuestos de inicio poco activo como iniciados de forma persistente. Dado que los paquetes compuestos de inicio poco activo nunca se marcaban como iniciados de forma persistente, no se iniciaban automáticamente cuando se reiniciaba Elipse. El javadoc de Bundle.start() indica que debe producirse lo siguiente cuando se llama al método:

"Registrar de forma persistente que este paquete compuesto se ha iniciado. Cuando se reinicie la infraestructura, este paquete compuesto debe iniciarse automáticamente."

En Eclipse 3.2 el método Bundle.start() se ha modificado para marcar adecuadamente el paquete compuesto como iniciado de forma persistente aunque sea un paquete compuesto de inicio poco activo. Este arreglo debía ajustarse a la especificación de la infraestructura OSGi. Como resultado, los llamadores de Bundle.start() forzarán el inicio del paquete compuesto cuando se reinicie Eclipse. En general esto se considera un mal procedimiento, ya que provocará la activación de paquetes compuestos innecesarios cada vez que se inicie Eclipse. En algunos casos puede provocar resultados inesperados, como por ejemplo el error 134412.

Acción necesaria: los clientes de Bundle.start() deben evaluar si su propósito es activar de forma persistente el paquete compuesto en todos los reinicios. Si no es así, los clientes deben encontrar otra forma de activar el paquete compuesto. En la mayoría de los casos, las llamadas a Bundle.start() pueden evitarse permitiendo simplemente que el paquete compuesto destino se active en modalidad diferida cuando se cargan las clases desde él. En raras ocasiones, puede ser necesaria una activación agresiva de un paquete compuesto de inicio poco activo, pero sin marcarlo persistentemente para activación durante el reinicio. En estos casos, debe utilizarse Bundle.loadClass() para cargar una clase del paquete compuesto que debe activarse, en lugar de llamar a Bundle.start().

5. El subrayado ya no se sustituye por un guión en los números de versión de plug-in

En Eclipse 3.0, el uso de un carácter de subrayado ('_') en el segmento calificador de un identificador de versión no estaba soportado, pero tampoco se aplicaba. Si un identificador de versión de plug-in contenía un subrayado en el calificador, este carácter se transformaba en un guión ('-') al exportar el plug-in al sistema de archivos y también al instalar el plug-in desde un sitio de actualizaciones.
En Eclipse 3.1, las normas de los caracteres permitidos en los calificadores se relajaron para incluir el carácter de subrayado, de forma que cuando se exportara o instalara un plug-in especificado incorrectamente, el calificador no se modificara con respecto a su estado original. Este pequeño cambio se omitió accidentalmente de la guía de migración de 3.0 a 3.1. La continuación de la historia es que (para Eclipse 3.2) se mantiene la compatibilidad con Eclipse 3.1 y los plug-ins que utilicen caracteres de subrayado en sus calificadores de versión deben tener en cuenta los cambios mencionados anteriormente al tratar con versiones antiguas de plug-in (tanto al exportar como si existen en sitios de actualizaciones). Esto significa, por ejemplo, que los proveedores de plug-ins que tengan versiones antiguas de su plug-in en un sitio de actualizaciones deben asegurarse de que el nombre que figura en el sistema de archivos coincide con el nombre que figura en el plug-in.