Cambios necesarios al adoptar los mecanismos y las API de la versión 3.0

Esta sección describe los cambios que deben realizarse si intenta cambiar el conector 2.1 para adoptar los mecanismos y las API de 3.0.

Escapar de org.eclipse.core.runtime.compatibility

El entorno de ejecución de Eclipse 3.0 es significativamente diferente. La implementación subyacente se basa en la especificación de la infraestructura de OSGi. El entorno de ejecución de Eclipse 3.0 incluye una capa de compatibilidad (en el conector org.eclipse.core.runtime.compatibility) que mantiene las API de 2.1. Los desarrolladores de conectores interesados en conseguir un rendimiento y funciones adicionales deben estudiar la posibilidad de adoptar las API de 3.0 y librarse de su dependencia de la capa de compatibilidad. El código de compatibilidad se muestra en tres lugares:

El texto que aparece más abajo proporciona más detalles sobre las clases y métodos que están presentes por razones de compatibilidad, así como de orientación acerca de cómo actualizar el conector.

Conectores y paquetes compuestos

El entorno de ejecución de Eclipse se ha refactorizado en dos componentes: gestión de carga de clases y requisitos previos y gestión de extensión/punto de extensión. Esta división permite una adopción natural y sin fisuras de la especificación de la infraestructura de OSGi para la gestión de carga de clases y requisitos previos. A su vez, esto permite un rango de nuevas posibilidades en el entorno de ejecución, desde la instalación/actualización/desinstalación dinámica de conectores a la seguridad y una mayor configurabilidad.

Mientras seguimos hablando de conectores, en el nuevo entorno de ejecución un conector es en realidad un paquete más algunas extensiones y puntos de extensión. El término paquete está definido por la especificación de infraestructura de OSGi y hace referencia a una colección de tipos y recursos e información asociada de requisitos previos entre paquetes. El registro de extensiones es el nuevo formato del registro de conectores y sólo detalla información de extensiones y puntos de extensión. En general, la API de registro de extensiones es la misma que la correspondiente API de registro de conectores (para obtener más información, consulte Registros).

En el entorno de ejecución de Eclipse 2.x, el objeto de conector tiene varios cometidos y responsabilidades:

En el marco del entorno de ejecución de Eclipse 3.0, estos cometidos y responsabilidades se factorizan en objetos distintos.

Paquete compuesto
Los paquetes son la unidad de modularidad de OSGi. Hay un cargador de clases por paquete y pueden construirse gráficos de dependencia de carga de clase entre paquetes semejantes a los de Eclipse. Los paquetes tienen un ciclo de vida de inicio y detención y la infraestructura de OSGi emite eventos relativos a los paquetes (por ejemplo, install, resolve, start, stop, uninstall, ...) a las partes interesadas. A diferencia de la clase Plugin de Eclipse, la clase Bundle de OSGi no es ampliable. Es decir, los desarrolladores no tienen la oportunidad de definir su propia clase de paquete.
BundleActivator
BundleActivator es una interfaz definida por la infraestructura OSGi. Cada paquete puede definir una clase de activador de paquete de manera semejante a como un conector puede definir su clase Plugin. La infraestructura genera la instancia de la clase especificada, que se utiliza para implementar el proceso de ciclo de vida start() y stop(). No obstante, hay una diferencia importante en la naturaleza de este proceso de ciclo de vida. En Eclipse, es habitual (aunque no se recomienda) hacer que las clases Plugin realicen tanto la inicialización como el registro. En OSGi, los activadores deben hacer sólo el registro. Si se realizan grandes cantidades de inicialización (o de cualquier otro trabajo) en BundleActivator.start() se amenaza la pervivencia del sistema.
BundleContext
BundleContexts son el mecanismo de OSGi para exponer funciones generales del sistema a paquetes individuales. Cada paquete tiene una instancia exclusiva y privada de BundleContext que pueden utilizar para acceder a la función del sistema (por ejemplo, getBundles() para descubrir todos los paquetes del sistema).
Plugin
El nuevo Plugin es muy semejante a la clase Plugin de Eclipse original, con las siguientes excepciones: los objetos Plugin ya no son necesarios para el entorno de ejecución ni están gestionados por él, y se han desechado varios métodos. Es esencialmente un mecanismo práctico que proporciona un conjunto de funciones y mecanismos útiles pero que ya no es totalmente necesario. Buena parte de las funciones proporcionadas aquí están disponibles también en la clase Platform en el entorno de ejecución.

Plugin también implementa BundleActivator. Esto implica reconocer que es práctico tener un objeto central que represente el ciclo de vida y la semántica de un conector. Tenga en cuenta que, sin embargo, esto no sanciona la inicialización ansiosa de estructuras de datos que actualmente es común en los conectores. No podemos insistir lo bastante en que los conectores pueden activarse porque una clase en cierto modo periférica se ha referenciado durante la verificación de una clase en otro conector. Es decir, sólo porque se haya activado el conector no quiere decir necesariamente que su función sea necesaria. Tenga en cuenta también que es libre de definir una clase BundleActivator diferente o de no tener ningún activador de paquete.

Los pasos necesarios para portar una clase Plugin de 2.x a Eclipse 3.0 depende de lo que haga la clase. Como se ha esbozado antes, la mayor parte del trabajo del ciclo de vida de arranque corresponde a una de las categorías siguientes:

Inicialización
La inicialización de la estructura de datos y del modelo suele realizarse en Plugin.startup(). La correlación natural u obvia sería el realizar este trabajo en un BundleActivator.start(), es decir, dejar la función en Plugin. Esto no es recomendable en absoluto. Con ocurre con los conectores de 2.x, los conectores/paquetes de 3.0 pueden iniciarse por muchos motivos diferentes en numerosas circunstancias distintas.
Esta situación se aclara con un ejemplo real de los tiempos de Eclipse 2.0. Había un conector que inicializaba un modelo grande que necesitaba la carga de unos 11 MB de código y muchos megabytes de datos. Había muchos casos normales en que este conector se activaba para descubrir si el icono del proyecto presentado en el navegador debía decorarse con un código concreto. Esta prueba no necesitaba para nada la inicialización efectuada en startup(), pero pese a ello todos los usuarios, en todos los casos, sufrían una penalización en memoria y tiempo por esta inicialización ansiosa.
El enfoque alternativo consiste en realizar esa inicialización en el estilo tranquilo clásico. Por ejemplo, en vez de que los modelos se inicialicen cuando se activa el conector/paquete, hágalo cuando sean realmente necesarios (por ejemplo, en un método de accesor de modelos centralizado). En muchos casos, esto equivale a hacerlo casi en el mismo momento, pero en otras situaciones este enfoque retardará la inicialización (tal vez indefinidamente). Recomendamos que se tome un tiempo para volver a estudiar la estrategia de inicialización utilizada mientras porta los conectores de 2.1.
Registro
El arranque de conector es un momento oportuno para registrar escuchadores, servicios, etc. e iniciar hebras de proceso en segundo plano (por ejemplo, escuchar en un zócalo). Plugin.start() puede ser un lugar razonable para realizar esta labor. También puede ser una buena idea que lo retarde hasta que se active otro desencadenante (por ejemplo, el uso de una función o elemento de datos en particular).
Datos globales de conector
La clase Plugin puede seguir realizando este cometido. El problema principal es que ya no se puede acceder globalmente a los objetos Plugin a través de una lista gestionada por el sistema. En Eclipse 2.x puede descubrir un objeto Plugin de cualquier objeto a través del registro de conectores. Esto ya no es posible. En la mayor parte de las circunstancias, este tipo de acceso no es necesario. Los Plugins a los que se accede a través del registro suelen utilizarse normalmente como Plugins genéricos en lugar de llamar a métodos específicos de cada dominio. El nivel equivalente de posibilidad puede alcanzarse si se accede a los objetos Bundle correspondientes y se manejan.

Registros y el modelo de conector

En el entorno de ejecución nuevo existe una separación entre la información y las estructuras necesarias para ejecutar un conector y las relativas a las extensiones y puntos de extensión de un conector. La primera está definida y gestionada por la especificación de la infraestructura de OSGi. Las últimas son conceptos específicos de Eclipse y las añade el código de entorno de ejecución de Eclipse. Por consiguiente, el registro de conector original y los objetos relacionados se han dividido en paquetes de OSGi y el registro de extensiones de Eclipse.

Los componentes de IPluginRegistry que trata con la especificación de ejecución (por ejemplo, se han desechado IPluginDescriptor, ILibrary, IPrequisite) y los componentes restantes relacionados con extensiones y puntos de extensión se han movido a IExtensionRegistry. Además, los llamados objetos modelo relacionados con el registro de conector en general se han desechado. Estos tipos se presentaban e instanciaban por el entorno de ejecución principalmente para dar soporte a herramientas tales como PDE. Lamentablemente, suele ocurrir que el nivel de información necesario sobrepase las posibilidades o los intereses del entorno de ejecución (por ejemplo, al recordar los números de línea para elementos plugin.xml) y, en definitiva, los consumidores potenciales de información del entorno de ejecución tenían que mantener sus propias estructuras.

En el nuevo entorno de ejecución hemos vuelto a evaluar los recursos proporcionados por el entorno de ejecución y sólo proporciona aquéllos que son esenciales para la ejecución del entorno de ejecución o son extraordinariamente difíciles para que los hagan otros. Como se ha mencionado anteriormente, los objetos de modelo de registro de conector se han desechado, al igual que la API de análisis de conectores. El nuevo registro de extensiones mantiene la información esencial relacionada con extensiones. Un nueva estructura de estado (consulte org.eclipse.osgi.service.resolver.State y amigos) representa y permite la manipulación de la información esencial relacionada con la ejecución.

Estructura de fragmentos de NL

En Eclipse 3.0, la estructura de fragmentos de NL se ha actualizado para que sea más coherente. Anteriormente se suponía que las conversiones de archivos como plugin.properties se realizaban por fragmentos dentro de los JAR suministrados. Dado que los archivos originales se encuentran en la raíz del conector de host relevante, una ubicación más coherente tendría los archivos convertidos ubicados en la raíz de los fragmentos de NL. Por ejemplo:

  org.eclipse.ui.workbench.nl/
     fragment.xml
     plugin_fr.properties
     plugin_pt_BR.properties
     ...
     nl1.jar

Tenga en cuenta que anteriormente el archivo nl1.jar habría contenido las conversiones de plugin.properties. Estos archivos se encuentran ahora en la raíz del fragmento y el JAR contiene conversiones de los recursos convertibles (es decir, archivos cargados a través del cargador de clases) en el conector de host.

Naturalmente, la estructura de fragmentos de NL de Eclipse 2.1 sigue estando soportada para conectores de host 2.1 que se ejecutan en Eclipse 3.0. Sin embargo, no puede utilizar un fragmento de NL 2.1 en un conector 3.0. El fragmento debe actualizarse con la nueva estructura.

Visión general de los cambios de API

org.eclipse.core.boot (paquete org.eclipse.core.boot)

Todo el paquete org.eclipse.core.boot ha quedado obsoleto. BootLoader se ha fusionado con org.eclipse.core.runtime.Platform, puesto que ya no tiene sentido mantener una división entre el arranque y el entorno de ejecución. Tenga en cuenta que, de hecho, el conector org.eclipse.core.boot se ha quebrado y todo su código se ha trasladado al nuevo entorno de ejecución o a la capa de compatibilidad.

IPlatformConfiguration ha sido siempre un tipo definido por y para el componente Instalar/Actualizar de Eclipse. Con la reorganización del entorno de ejecución, podemos devolver este tipo al lugar que le corresponde. Esta clase permanece inalterada en gran medida y se ha vuelto a empaquetar como org.eclipse.update.configurator.IPlatformConfiguration.

IPlatformRunnable se ha transferido a org.eclipse.core.runtime.IPlatformRunnable.

IExtension e IExtensionPoint (paquete org.eclipse.core.runtime)

El método getDeclaringPlugin() (en ambas clases) proporciona un enlace hacia un nivel superior hasta el conector que declara la extensión o el punto de extensión (respectivamente). El nuevo modelo de registro separa los aspectos de ejecución de los conectores de los aspectos de extensión/punto de extensión y ya no contiene IPluginDescriptors. Los usuarios de esta API deben estudiar el nuevo método getParentIdentifier() que se encuentra en IExtension y en IExtensionPoint.

ILibrary, IPluginDescriptor, IPluginRegistry e IPrerequisite (paquete org.eclipse.core.runtime)

En el entorno de ejecución original, el registro de conector ha mantenido una imagen completa de la configuración del entorno de ejecución. En Eclipse 3.0, esta imagen se divide entre la infraestructura de OSGi y el registro de extensiones. Por tanto, estas clases han quedado obsoletas. Los avisos de desechado contienen detalles sobre cómo debe actualizarse el código.

Platform y Plugin (paquete org.eclipse.core.runtime)

En el nuevo entorno de ejecución, los objetos Plugin ya no están gestionados por el entorno de ejecución y no se puede acceder genéricamente a ellos a través de la plataforma. De forma similar, el registro de conectores ya no existe ni da acceso a los descriptores de conectores. No obstante, hay métodos de sustitución adecuados disponibles y detallados en el Javadoc de los métodos desechados de estas clases.

org.eclipse.core.runtime.model (paquete org.eclipse.core.runtime.model)

Ahora se han desechado todos los tipos de este paquete. Vea la descripción de los registros para obtener más información.

IWorkspaceRunnable e IWorkspace.run (paquete org.eclipse.core.resources)

Los clientes del método IWorkspace.run(IWorkspaceRunnable,IProgressMonitor) deben volver a visitar sus usos de este método y estudiar el uso del método más rico IWorkspace.run(IWorkspaceRunnable,ISchedulingRule,int,IProgressMonitor). El antiguo método IWorkspace.run adquiere un bloqueo en todo el área de trabajo mientras dure el IWorkspaceRunnable. Esto quiere decir que una operación realizada con este método nunca podrá ejecutarse de manera simultánea con otras operaciones que cambian el área de trabajo. En Eclipse 3.0, muchas operaciones de ejecución larga se han trasladado a hebras de segundo plano, de tal forma que la probabilidad de conflictos entre operaciones ha aumentado en gran medida. Si una operación de segundo plano de ejecución larga bloquea una operación modal de primer plano, la UI queda bloqueada hasta que se completa la operación de segundo plano o hasta que se cancela una de las operaciones.

La solución sugerida es conmutar todas las referencias al antiguo IWorkspace.run y utilizar el nuevo método con un parámetro de regla de planificación. La regla de planificación debe ser la más ajustada que abarque las reglas de todos los cambios efectuados por esa operación. Si la operación intenta modificar recursos situados fuera del ámbito de la regla de planificación, se producirá una excepción de entorno de ejecución. No se especifica la regla de planificación exacta que necesita una operación de área de trabajo determinada y puede cambiar según el proveedor de repositorios instalado en un proyecto dado. Debe utilizarse la fábrica IResourceRuleFactory para obtener la regla de planificación para una operación de cambio de recursos. Si se desea, puede utilizarse MultiRule para especificar varias reglas de recursos y el método práctico MultiRule.combine puede utilizarse para combinar reglas de diversas operaciones de cambio de recursos.

Si no se necesita ningún bloqueo, puede utilizarse la regla de planificación null. Esto permitirá que el ejecutable modifique todos los recursos en el área de trabajo, pero no impedirá que otras hebras modifiquen también el área de trabajo de manera simultánea. Para realizar cambios simples en el área de trabajo, suele ser la solución más sencilla y más amigable para la concurrencia.

IWorkbenchPage (paquete org.eclipse.ui)

IEditorDescriptor (paquete org.eclipse.ui)

ISharedImages (paquete org.eclipse.ui)

IWorkbenchActionConstants (paquete org.eclipse.ui)

IWorkbenchPreferenceConstants (paquete org.eclipse.ui)

IExportWizard (paquete org.eclipse.ui)

IImportWizard (paquete org.eclipse.ui)

INewWizard (paquete org.eclipse.ui)

WorkbenchHelp (paquete org.eclipse.ui.help)

IHelp (paquete org.eclipse.help)

ITextEditorActionConstants (paquete org.eclipse.ui.texteditor)

IAbstractTextEditorHelpContextIds (paquete org.eclipse.ui.texteditor)

BasicTextEditorActionContributor (paquete org.eclipse.ui.texteditor)

TextEditorActionContributor (paquete org.eclipse.ui.editors.text)

Punto de extensión annotationTypes (conector org.eclipse.ui.editors)

Ahora existe la noción explícita de un tipo de anotación. Consulte Annotation.getType() y Annotation.setType(). El tipo de una anotación puede cambiar a lo largo de su existencia. Se ha añadido un punto de extensión nuevo para la declaración de tipos de anotación: "org.eclipse.ui.editors.annotationTypes". Un tipo de anotación tiene un nombre y puede declararse como subtipo de otro tipo de anotación declarado. Una declaración de tipo de anotación también puede utilizar los atributos "markerType" y "markerSeverity" para especificar que los marcadores de un tipo y una gravedad determinados deben representarse en editores de texto como anotaciones de un tipo de anotación determinado. Los atributos "markerType" y "markerSeverity" en "org.eclipse.ui.editors.markerAnnotationSpecification" ya no deben utilizarse más. Por consiguiente, las especificaciones de anotación de marcadores se vuelven independientes de los marcadores y el nombre puede causar confusión. No obstante, se ha mantenido el nombre para asegurar la compatibilidad inversa.

Las instancias de las subclases de AbstractMarkerAnnotationModel detectan automáticamente y establecen los tipos de anotación correctos para las anotaciones que crean de marcadores. Para recuperar programáticamente el tipo de anotación para un marcador determinado o un par determinado de markerType y markerSeverity, utilice org.eclipse.ui.texteditor.AnnotationTypeLookup.

IAnnotationAccessExtension proporciona acceso a la jerarquía de tipos de anotación. Para un tipo de anotación determinado, puede obtener la cadena de supertipos y comprobar si un tipo de anotación es un subtipo de otro tipo de anotación. DefaultMarkerAnnotationAccess implementa esta interfaz.

Punto de extensión markerAnnotationSpecification (conector org.eclipse.ui.editors)

El tipo de anotación es la clave con la que se encuentra la especificación de anotación de marcador asociada. Como los tipos de anotaciones pueden ampliar otros tipos de anotaciones, también existe una relación implícita entre especificaciones de anotaciones de marcadores. Por lo tanto, las especificaciones de anotaciones de marcadores dadas para los supertipos del tipo de anotación determinado completan la especificación de anotación de marcador para un tipo de anotación dado. Así pues, aunque antes era algo obligatorio, ahora no es necesario completar la especificación de anotación de marcador. AnnotationPreferences recupera las especificaciones de anotaciones de marcador. Si utiliza org.eclipse.ui.texteditor.AnnotationPreferenceLookup, puede recuperar una preferencia de anotación para un tipo de anotación determinado que realice de forma transparente la finalización de la preferencia a lo largo de la cadena de supertipos de anotaciones.

La especificación de anotación de marcador se ha ampliado con tres atributos adicionales para permitir la definición de aspectos personalizados de un tipo de anotación dado en la regla vertical. Estos atributos son: "icon", "symbolicIcon" y "annotationImageProvider". El valor de "icon" es la vía de acceso a un archivo que contenga la imagen del icono. El valor de "symbolicIcon" puede ser uno de los siguientes: "error", "warning", "info", "task", "bookmark". El atributo "symbolicIcon" se utiliza para indicar a la plataforma que la anotación debe describirse con las mismas imágenes que utiliza la plataforma para presentar errores, avisos, informaciones, tareas y marcadores de páginas respectivamente. El valor de "annotationImageProvider" es una clase que implementa org.eclipse.ui.texteditor.IAnnotationImageProvider, que permite una presentación de anotación totalmente personalizada.

La regla vertical utiliza su IAnnotationAccess/IAnnotationAccessExtension asociado para trazar anotaciones. La regla vertical ya no llama a Annotation.paint. En general, ya no se supone que las anotaciones deban trazarse a sí mismas. Los métodos "paint" y "getLayer" se han desechado para que la anotación sea finalmente independiente de la UI. DefaultMarkerAnnotationAccess sirve como implementación por omisión de IAnnotationAccess/IAnnotationAccessExtension. DefaultMarkerAnnotationAccess implementa la siguiente estrategia para pintar anotaciones: si una anotación implementa IAnnotationPresentation, se llama a IAnnotationPresentation.paint. En caso contrario, se busca el proveedor de imágenes de la anotación en la preferencia de anotación. El proveedor de imágenes de anotación sólo está disponible si se especifica y si ya se ha cargado el conector que define la especificación de anotación de marcador que lo incluye. Si existe un proveedor de imágenes de anotación, la llamada se reenvía al mismo. En caso contrario, se busca el "icono" especificado. Se utiliza "symbolicIcon" como retraso final. Para trazar anotaciones, la capa de presentación de anotación es importante. DefaultMarkerAnnotationAccess busca la capa de presentación utilizando la siguiente estrategia: si la preferencia de anotación especifica una capa de presentación, se utiliza la capa especificada. Si no hay ninguna capa y la anotación implementa IAnnotationPresentation, se utiliza IAnnotationPresentation.getLayer; de lo contrario, se devuelve la capa de presentación por omisión (que es 0).

Migración al punto de extensión annotationTypes (conector org.eclipse.ui.editors)

El conector org.eclipse.ui.editors declara los siguientes tipos de anotaciones:

   <extension point="org.eclipse.ui.editors.annotationTypes">
      <type
         name="org.eclipse.ui.workbench.texteditor.error"
         markerType="org.eclipse.core.resources.problemmarker"
         markerSeverity="2">
      </type>
      <type
         name="org.eclipse.ui.workbench.texteditor.warning"
         markerType="org.eclipse.core.resources.problemmarker"
         markerSeverity="1">
      </type>
      <type
         name="org.eclipse.ui.workbench.texteditor.info"
         markerType="org.eclipse.core.resources.problemmarker"
         markerSeverity="0">
      </type>
      <type
         name="org.eclipse.ui.workbench.texteditor.task"
         markerType="org.eclipse.core.resources.taskmarker">
      </type>
      <type
         name="org.eclipse.ui.workbench.texteditor.bookmark"
         markerType="org.eclipse.core.resources.bookmark">
      </type>
   </extension>

La extensión markerAnnotationSpecification definida ya no proporciona atributos "markerType" y "markerSeverity". Definen el atributo "symbolicIcon" con el valor correspondiente. Así, ya no se llama a MarkerAnnotation.paint y MarkerAnnotation.getLayer, es decir, alterar temporalmente estos métodos no tiene ningún efecto. Los clientes afectados deben implementar IAnnotationPresentation.

ILaunchConfigurationType (paquete org.eclipse.debug.core)

Con la introducción de modalidades de lanzamiento extensibles en 3.0, puede existir más de un delegado de lanzamiento para un tipo de configuración de lanzamiento. Los releases anteriores a la versión 3.0 sólo daban soporte a un delegado de lanzamiento por tipo de configuración de lanzamiento. El método ILaunchConfigurationType.getDelegate() se ha desechado. El método getDelegate(String mode) debe utilizarse en su lugar para recuperar el delegado de lanzamiento para una modalidad de lanzamiento específica. El método desechado se ha modificado para devolver el delegado de lanzamiento para la modalidad run.

ILaunchConfigurationTab e ILaunchConfigurationTabGroup (paquete org.eclipse.debug.ui)

Las pestañas de lanzamiento y los grupos de pestañas de lanzamiento ya no se notifican cuando se completa un lanzamiento. El método launched(ILaunch) en las interfaces ILaunchConfigurationTab y ILaunchConfigurationTabGroup se ha desechado y ya no se llama. Basarse en este método para la función de lanzamiento fue siempre problemático, ya que las pestañas sólo existen si se realiza el lanzamiento desde el diálogo de lanzamiento. Además, con la introducción del lanzamiento en segundo plano, ya no es posible llamar a este método, puesto que el diálogo de lanzamiento debe cerrarse antes de que exista el objeto de lanzamiento resultante.

ILaunchConfigurationTab y AbstractLaunchConfigurationTab (paquete org.eclipse.debug.ui)

Se han añadido dos métodos a la interfaz ILaunchConfigurationTab: activated y deactivated. Se llama a estos nuevos métodos de ciclo de vida cuando se entra y se sale de una pestaña respectivamente. Las implementaciones existentes de ILaunchConfigurationTab que crean subclases de la clase abstracta proporcionada por el conector de depuración (AbstractLaunchConfigurationTab) son compatibles en binario, ya que los métodos se implementan en la clase abstracta.

En releases, anteriores se enviaba el initializeFrom a la pestaña cuando se activaba y performApply cuando se desactivaba. De esta manera, la infraestructura de pestañas de configuración de lanzamiento proporcionaba una comunicación entre pestañas a través de una configuración de lanzamiento (actualizando la configuración con valores de atributo actuales cuando se sale de una pestaña y actualizando la pestaña recién entrada). Sin embargo, ya que muchas pestañas no realizan la comunicación entre pestañas, esto puede ser ineficaz. Además, no era posible distinguir entre una pestaña activada y una pestaña que mostrarse una configuración de lanzamiento seleccionada por primera vez. Los métodos recién añadidos permiten a las pestañas distinguir entre activación e inicialización, y entre desactivación y guardado de los valores actuales.

La implementación por omisión de activated, proporcionada por la pestaña abstracta, llama a initializeFrom. A su vez, la implementación por omisión de deactivated llama a performApply. Las pestañas que quieran aprovechar la nueva API deben alterar temporalmente estos métodos como sea necesario. En general, para las pestañas que no establecen una comunicación entre pestañas, el enfoque recomendado consiste en volver a implementar estos métodos para que no hagan nada.

Tipo de punto de extensión launchConfigurationTabGroup (paquete org.eclipse.debug.ui)

En releases anteriores, la conmutación de perspectiva se especificaba en una configuración de lanzamiento a través de los atributos de configuración de lanzamiento ATTR_TARGET_DEBUG_PERSPECTIVE y ATTR_TARGET_RUN_PERSPECTIVE. Con la adición de modalidades de lanzamiento ampliables en la versión 3.0, este enfoque ya no sirve para escalar. Ahora, la conmutación de perspectiva se especifica según el tipo de configuración de lanzamiento, por cada modalidad de lanzamiento soportada por un tipo de configuración de lanzamiento. Se ha añadido una API a DebugUITools para establecer y obtener la perspectiva asociada a un tipo de configuración de lanzamiento para una modalidad de lanzamiento específica.

Un elemento launchMode adicional opcional se ha añadido al punto de extensión launchConfigurationTabGroup, lo que permite que un grupo de pestañas contribuido especifique una perspectiva por omisión para un tipo y modalidad de configuración de lanzamiento.

Desde la interfaz de usuario de Eclipse, los usuarios pueden editar la perspectiva asociada a un tipo de configuración de lanzamiento abriendo el diálogo de configuración de lanzamiento y seleccionando un nodo de tipo de configuración de lanzamiento en el árbol (en vez de utilizar una configuración individual). Se visualiza una pestaña que permite al usuario establecer una perspectiva con cada modalidad de lanzamiento soportada.

[Sólo JDT] IVMRunner (paquete org.eclipse.jdt.launching)

Se han añadido dos métodos a la clase VMRunnerConfiguration para dar soporte al establecimiento y recuperación de variables de entorno. Los implementadores de IVMRunner deben llamar a VMRunnerConfiguration.getEnvironment() y pasar dicho entorno a la JVM ejecutada. Los clientes que utilizan DebugPlugin.exec(String[] cmdLine, File workingDirectory) pueden hacerlo llamando en su lugar a DebugPlugin.exec(String[] cmdLine, File workingDirectory, String[] envp). Basta con pasar el resultado de getEnvironment().

[Sólo JDT] Clases VMRunnerConfiguration y Bootstrap (paquete org.eclipse.jdt.launching)

En releases anteriores, VMRunnerConfiguration tenía un solo atributo para describir una vía de acceso de arranque. El atributo es una colección de Series que deben especificarse en el argumento Xbootclasspath. Se han añadido tres nuevos atributos a VMRunnerConfiguration para dar soporte a las JVM que permiten anteponer y agregar a la vía de acceso de arranque. Los nuevos métodos/atributos añadidos son:

El antiguo atributo, getBootClassPath(), sigue existiendo y contiene una vía de acceso completa equivalente a la de los tres atributos nuevos. Sin embargo, los VMRunners que den soporte a las nuevas opciones de vía de acceso de arranque deben aprovechar los nuevos atributos.

[Sólo JDT] Mejora en el soporte de copias de trabajo (paquete org.eclipse.jdt.core)

El recurso de copias de trabajo de modelo Java se ha reelaborado en la versión 3.0 para proporcionar una funcionalidad muy aumentada. Antes de 3.0, el modelo java permitía la creación de copias de trabajo individuales de las unidades de compilación. Los cambios podían realizarse en la copia de trabajo y posteriormente confirmarse. Había soporte para un análisis limitado de una copia de trabajo en el contexto del resto del modelo Java. No obstante, no era posible que estos análisis pudiesen tener en cuenta más de una de las copias de trabajo al mismo tiempo.

Los cambios presentes en la versión 3.0 permiten crear y gestionar conjuntos de copias de trabajo de unidades de compilación y realizar análisis en presencia de todas las copias de trabajo de un conjunto. Por ejemplo, ahora es posible que un cliente como la refactorización de JDT cree copias de trabajo para una o más unidades de compilación que estudie modificar y luego resolver las referencias de tipos entre las copias de trabajo. Antes, esto sólo era posible después de haber confirmado los cambios en las copias de trabajo de las unidades de compilación.

La API de modelo Java ha cambiado de 2 maneras para añadir esta mejora en el soporte:

(1) La funcionalidad que se encontraba anteriormente en IWorkingCopy y que ICompilationUnit heredaba se ha fusionado en ICompilationUnit. La interfaz IWorkingCopy sólo se utilizaba en este lugar y era más genérica de lo necesario. Este cambio simplifica la API. IWorkingCopy se ha desechado. Otros lugares de la API en que se utilizaba IWorkingCopy como parámetro o tipo de resultado también se han desechado; los métodos de API de sustitución indican ICompilationUnit en lugar de IWorkingCopy.

(2) La interfaz IBufferFactory se ha sustituido por WorkingCopyOwner. La mejora del soporte de copias de trabajo requiere que exista un objeto que posea las copias de trabajo. Aunque IBufferFactory está en el lugar correcto, el nombre no explica adecuadamente cómo funciona el nuevo mecanismo de copias de trabajo. WorkingCopyOwner es mucho más revelador. Además, WorkingCopyOwner está declarado como clase abstracta y no como interfaz, lo que permite que la noción de propietario de copia de trabajo evolucione en el futuro. El único método de IBufferFactory se mueve a WorkingCopyOwner sin verse afectado. WorkingCopyOwner no implementa IBufferFactory para dejar claro que IBufferFactory es un elemento del pasado. IBufferFactory se ha desechado. Otros lugares de la API donde IBufferFactory aparecía como parámetro o tipo de resultado también se han desechado; los métodos de API de sustitución indican WorkingCopyOwner en lugar de IBufferFactory.

Estos cambios no quiebran la compatibilidad binaria.

Al realizar la migración, todas las referencias al tipo IWorkingCopy deben referirse a ICompilationUnit en su lugar. La implementación única de IWorkingCopy también implementa ICompilationUnit, lo que quiere decir que los objetos del tipo IWorkingCopy pueden difundirse con seguridad a ICompilationUnit.

Una clase que implemente IBufferFactory tendrá que ser sustituida por una subclase de WorkingCopyOwner. Aunque WorkingCopyOwner no implementa propiamente IBufferFactory, sería posible declarar la subclase de WorkingCopyOwner que implementa IBufferFactory, creando así un puente entre la antigua y la nueva (IBufferFactory declara createBuffer(IOpenable) mientras que WorkingCopyOwner declara createBuffer(ICompilationUnit); ICompilationUnit amplía IOpenable).

Dado que los cambios que implican IWorkingCopy e IBufferFactory están entrelazados, recomendamos trabajar con ambas al mismo tiempo. Los detalles de los elementos obsoletos son los siguientes:

Reestructuración del conector org.eclipse.help

El conector org.eclipse.help, que se utilizó para contener los API y los puntos de extensión para contribuir al sistema de ayuda y ampliarlo, así como para visualizar ayuda, ahora sólo contiene las API y los puntos de extensión para contribuir y acceder a los recursos de ayuda. Una parte de la implementación de UI de ayuda por omisión contenida en este conector se ha movido a un nuevo conector, org.eclipse.help.base, junto con las API para ampliar la implementación. Las API y el punto de extensión para contribuir a la UI de ayuda y visualizar la ayuda se han movido al conector org.eclipse.ui. Esta reestructuración permite una mayor flexibilidad a las aplicaciones respecto al sistema de ayuda; la nueva estructura permite que las aplicaciones basadas en el entorno de trabajo genérico proporcionen su propia implementación de ayuda o de UI de ayuda, o bien omitir por completo el sistema de ayuda.

Dado que los puntos de extensión y los paquetes de API afectados sólo están previstos para su uso por el propio sistema de ayuda, es improbable que los conectores existentes se vean afectados por este cambio. Sólo se incluyen aquí para dar la lista completa:

Nueva API de UI de búsqueda

En la versión 3.0 se ha añadido una API para implementar búsquedas personalizadas. La API original se ha desechado en 3.0 y recomendamos que los clientes la porten a la nueva API en los paquetes org.eclipse.search.ui y org.eclipse.search.ui.text.

Los clientes tendrán que crear implementaciones de ISearchQuery, ISearchResult e ISearchResultPage. La implementación ISearchResultPage debe contribuirse al nuevo punto de extensión org.eclipse.search.searchResultViewPages.

Las implementaciones por omisión para ISearchResult e ISearchResultPage se proporcionan en el paquete org.eclipse.search.ui.text.

Mensajes nulos en MessageBox y DirectoryDialog (paquete org.eclipse.swt.widgets)

Antes de la versión 3.0, llamar a DirectoryDialog.setMessage(String serie) o MessageBox.setMessage(String serie) de SWT con un valor nulo para serie daba como resultado que ningún texto apareciera en el título. Este comportamiento no estaba especificado (pasar un valor nulo no ha estado permitido nunca) y crea problemas con getMessage, con el que no se permite devolver un valor nulo. En 3.0, pasar un valor nulo da como resultado el lanzamiento de una excepción IllegalArgumentException y las especificaciones se han modificado para indicar esto y ajustarlo al método en su superclase Dialog.setMessage. Si utiliza Dialog.setMessage, asegúrese de que la serie pasada no es nunca un valor nulo. Si desea un diálogo sin texto en el título, simplemente pase una serie vacía.

Mejorar los comentarios de progreso modal

El soporte de operaciones simultáneas requiere maneras más sofisticadas de mostrar progreso modal. Como parte del esfuerzo de capacidad de respuesta, se ha implementado un soporte de progreso adicional en la clase IProgressService. La manera existente consiste en mostrar el progreso mientras ProgressMonitorDialog sigue funcionando. Sin embargo, para mejorar la experiencia del usuario recomendamos migrar al nuevo IProgressService.

El documento Showing Modal Progress in Eclipse 3.0 describe cómo migrar al nuevo IProgressService.

Grupos de acciones de depuración eliminados

Se ha eliminado el punto de extensión Grupos de acciones de depuración (org.eclipse.debug.ui.debugActionGroups). En Eclipse 3.0, el entorno de trabajo ha introducido el soporte de Actividades a través del punto de extensión org.eclipse.platform.ui.activities. Este soporte proporciona todo lo que suministraba Grupos de acciones de depuración y también es más sencillo de utilizar (da soporte a patrones en vez de especificar exhaustivamente todas las acciones) y tiene una API programática para darle soporte. Si no se eliminan las referencias al punto de extensión antiguo no se producirán anomalías. Las referencias al punto de extensión simplemente se pasarán por alto. Se anima a los proveedores de producto que utilicen el soporte de Actividades del entorno de trabajo para asociar acciones de depurador específicas del lenguaje a actividades específicas del lenguaje (por ejemplo, las acciones de depuración de C++ podrían asociarse a una actividad denominada "Desarrollar C++").

BreakpointManager puede inhabilitarse

IBreakpointManager define ahora los métodos setEnabled(boolean) e isEnabled(). Cuando se inhabilita el gestor de puntos de interrupción, los depuradores deben pasar por alto todos los puntos de interrupción registrados. La plataforma de depuración proporciona también un nuevo mecanismo de escuchador, IBreakpointManagerListener, que permite que los clientes se registren con el gestor de puntos de interrupción para recibir notificaciones cuando cambie su habilitación. La vista Puntos de interrupción llama a esta API desde una nueva acción de conmutación que permite al usuario "Saltarse todos los puntos de interrupción". Así, los depuradores que no respeten la habilitación del gestor de puntos de interrupción aparecerán un poco deformados si el usuario intenta utilizar esta característica.

[Sólo JDT] Participantes en la búsqueda Java (paquete org.eclipse.jdt.core.search)

Los lenguajes próximos a Java (como, por ejemplo, JSP, SQLJ, JWS, etc.) deben poder participar en la búsqueda Java. En particular, los implementadores de esos lenguajes deberían poder:

Un implementador semejante se denomina participante de búsqueda. Amplía la clase SearchParticipant. Los participantes de búsqueda se pasan a consultas de búsqueda (consulte SearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor)).

Para indexar o localizar coincidencias, un participante de búsqueda tiene que definir una subclase de SearchDocument que pueda recuperar el contenido del documento alterando temporalmente getByteContents() o getCharContents(). Una instancia de esta subclase se devuelve en getDocument(String).

Un participante de búsqueda que desee indexar un documento utilizará SearchParticipant.scheduleDocumentIndexing(SearchDocument, IPath) para planificar la indexación de un documento determinado en el índice dado. Una vez que el documento esté listo para indexarse, la infraestructura subyacente llamará a SearchParticipant.indexDocument(SearchDocument, IPath). A continuación, el participante de búsqueda obtendrá el contenido del documento, lo analizará y añadirá entradas de índice utilizando SearchDocument.addIndexEntry(char[], char[]).

Una vez que se haya realizado el índice, pueden consultarse los índices y localizar coincidencias utilizando SearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor). El primero solicita a cada participante de búsqueda los índices que esta consulta necesita utilizando SearchParticipant.selectIndexes(SearchPattern, IJavaSearchScope). Para cada entrada de índice que coincida con el patrón dado, se creará un documento de búsqueda preguntando el participante de búsqueda (vea getDocument(String)). Todos estos documentos se pasan al participante de búsqueda para que pueda localizar coincidencias utilizando locateMatches(SearchDocument[], SearchPattern, IJavaSearchScope, SearchRequestor, IProgressMonitor). El participante de búsqueda notifica las coincidencias de búsqueda a SearchRequestor mediante acceptSearchMatch(SearchMatch) y pasando una instancia de una subclase de SearchMatch.

Un participante de búsqueda puede delegar parte de su trabajo al participante de búsqueda Java por omisión. Una instancia de este participante por omisión se obtiene utilizando SearchEngine.getDefaultSearchParticipant(). Por ejemplo, si se solicita que se localicen coincidencias, un participante SQLJ puede crear documentos .java a partir de sus documentos .sqlj y delegar el trabajo en el participante por omisión pasándole los documentos .java.