Modifications requises lors de l'adoption des API et des mécanismes de la version 3.0

La présente section décrit les modifications à apporter obligatoirement pour que votre plug-in 2.1 adopte les API et les mécanismes de la version 3.0.

Suppression d'org.eclipse.core.runtime.compatibility

L'environnement d'exécution d'Eclipse 3.0 est très différent. L'implémentation sous-jacente repose sur la spécification de la structure OSGi. Il inclut une couche de compatibilité (dans le plug-in org.eclipse.core.runtime.compatibility) qui permet de conserver les API de la version 2.1. Les développeurs de plug-in qui sont intéressés par des fonctions supplémentaires et de meilleures performances devraient envisager d'adopter les API de la version 3.0 et de supprimer leur dépendance dans la couche de compatibilité. Le code de compatibilité apparaît à trois endroits :

Vous trouverez ci-après des détails sur la façon dont les classes et les méthodes apparaissent pour la compatibilité et des instructions relatives à la mise à jour de votre plug-in.

Plug-ins et regroupements

L'environnement d'exécution Eclipse a été restructuré en deux parties : le chargement des classes et la gestion des prérequis d'une part et la gestion des extensions et des points d'extension d'autre part. Cette division permet une adoption naturelle et transparente de la spécification de la structure OSGi pour le chargement des classes et la gestion des prérequis. Ainsi, de nouvelles fonctionnalités sont disponibles dans l'environnement d'exécution, comme l'installation, la mise à jour et la désinstallation dynamiques d'un plug-in, la sécurité et une meilleure configurabilité.

Alors que le terme plug-ins est toujours employé, dans le nouvel environnement d'exécution, un plug-in est en fait un bundle associé à des extensions et des points d'extension. Le terme bundle est défini par la spécification de la structure OSGi et fait référence à une série de types et de ressources ainsi qu'à des informations relatives aux prérequis inter-bundle. Le registre des extensions est la nouvelle forme du registre des plug-ins et décrit uniquement les extensions et les points d'extension. Globalement, l'API du registre des extensions est identique à l'API du registre des plug-ins correspondant (pour plus d'informations, voir Registres).

Dans l'environnement d'exécution d'Eclipse 2.x, l'objet de plug-in possède un certain nombre de rôles et de responsabilités :

Dans l'environnement d'exécution d'Eclipse 3.0, ces rôles et ces responsabilités sont répartis dans différents objets.

Bundle
Les bundles correspondent à l'unité de modularité OSGi. Il existe un chargeur de classe par bundle et des graphes de dépendances de chargement de classe inter-bundle peuvent être construits sur le modèle Eclipse. Les bundles ont des cycles de vie pour le démarrage et l'arrêt et la structure OSGi transmet les événements qui leur sont liés (comme l'installation, la résolution, le démarrage, l'arrêt, la désinstallation, etc...) aux parties intéressées. A la différence de la classe Plugin d'Eclipse, la classe Bundle de la structure OSGi ne peut pas être étendue. En d'autres termes, les développeurs ne peuvent pas définir leur propre classe de bundle.
BundleActivator
BundleActivator est une interface définie par la structure OSGi. Chaque bundle peut définir une classe bundle activator tout comme un plug-in peut définir sa classe Plugin. La classe spécifiée est instanciée par la structure et permet d'implémenter le traitement des cycles de vie start() et stop(). Toutefois, ce traitement de cycle de vie est extrêmement différent. Dans Eclipse, il est fréquent (bien que non conseillé) que les classes Plugin procèdent à la fois à l'initialisation et à l'enregistrement. Dans la structure OSGi, les activateurs doivent uniquement effectuer l'enregistrement. Si de nombreuses initialisations (ou d'autres tâches) sont effectuées dans BundleActivator.start(), la réactivité du système est menacée.
BundleContext
BundleContexts est le mécanisme de la structure OSGi qui permet de signaler une fonction système globale à des bundles individuels. Chaque bundle dispose d'une instance unique et privée de BundleContext qui lui permet d'accéder aux fonctions système (commegetBundles() qui permet de rechercher tous les bundles sur un système).
Plugin
La nouvelle classe Plugin ressemble beaucoup à la classe d'origine Plugin d'Eclipse mais les objets Plugin ne sont plus requis ni gérés par l'environnement d'exécution et plusieurs méthodes sont désormais déconseillées. Il s'agit essentiellement d'un mécanisme hébergeant des mécanismes et des fonctions utiles mais qui n'est plus indispensable. La plupart des fonctions qu'il met à disposition sont également disponibles dans la classe Platform de l'environnement d'exécution.

Plugin implémente également BundleActivator. L'intérêt d'avoir un objet central représentant le cycle de vie et la sémantique d'un plug-in est reconnu. Toutefois, l'initialisation systématique de structures de données courantes dans les plug-ins aujourd'hui n'est pas sanctionnée. N'oubliez pas que des plug-ins peuvent être activés car une classe périphérique quelconque a été référencée lors de la vérification d'une classe dans un autre plug-in. En d'autres termes, ce n'est pas parce que votre plug-in a été activé que sa fonction est requise. De plus, vous êtes libre de définir une classe BundleActivator différente ou de ne pas en avoir du tout.

Les étapes de transfert d'une classe Plugin 2.x vers Eclipse 3.0 dépendent de la tâche de la classe. Comme indiqué plus haut, la plupart des travaux de cycle de vie de démarrage se trouvent dans l'une des catégories ci-dessous.

Initialisation
L'initialisation d'un modèle et d'une structure de données est souvent effectuée dans Plugin.startup(). Le mappage naturel/évident consisterait à effectuer la tâche dans BundleActivator.start(), c'est-à-dire de laisser la fonction sur la classe Plugin. Cette opération est fortement déconseillée. Comme les plug-ins 2.x, les plug-ins et les bundles 3.0 peuvent être démarrés pour différentes raisons dans diverses circonstances.
Prenons un exemple datant d'Eclipse 2.0. La version 2.0 contenait un plug-in qui initialisait un modèle de grande taille requérant le chargement d'11 Mo de code et de plusieurs mégaoctets de données. Souvent, ce plug-in était activé pour déterminer si l'icône du projet apparaissant dans le navigateur devait être associée à un marquage particulier. Ce test ne nécessitait aucune des initialisations effectuées dans startup() mais tous les utilisateurs, dans tous les cas d'emploi, devaient tout de même payer en mémoire et en temps l'initialisation systématique.
Une autre approche consiste à effectuer une telle initialisation dans un style classique de type lazy. Par exemple, plutôt que d'initialiser des modèles lorsque le plug-in ou le bundle est activé, initialisez-les uniquement lorsqu'ils sont nécessaires (c'est-à-dire dans une méthode d'accesseur de modèle centralisée). Dans la plupart des cas d'emploi, le temps sera le même, mais pour d'autres scénarios, cette approche diffère l'initialisation (peut-être indéfiniment). Nous vous conseillons de réfléchir sérieusement à la stratégie d'initialisation utilisée pour le portage des plug-ins 2.1.
Enregistrement
Il est judicieux d'enregistrer les programmes d'écoute, les services, etc, lors du démarrage d'un plug-in et de lancer les unités d'exécution de traitement en arrière-plan (comme l'écoute sur un socket). Vous pouvez effectuer ces opérations dans Plugin.start(). Il peut également être utile de différer les opérations jusqu'au prochain déclencheur (c'est-à-dire l'utilisation d'une fonction ou d'un élément de données particulier).
Données globales de plug-in
Votre classe Plugin peut continuer à jouer ce rôle. Le problème principal consiste en ce que les objets Plugin ne sont plus accessibles globalement via une liste gérée par le système. Dans Eclipse 2.x, vous pouviez rechercher l'objet Plugin d'un plug-in via le registre des plug-ins. Cette opération n'est plus possible. Dans certains cas, ce type d'accès n'est pas requis. Les objets Plugin accessibles via le registre sont généralement utilisés comme objets Plugin génériques à la place de l'appel de méthodes propres à un domaine. Vous pouvez ajouter le niveau de fonctionnalité équivalent en accédant aux objets Bundle correspondants et en les manipulant.

Registres et modèle de plug-in

Dans le nouvel environnement d'exécution, les informations et les structures nécessaires à l'exécution d'un plug-in et celles qui sont liées aux extensions et aux points d'extension d'un plug-in sont séparées. Les premières sont définies et gérées par la spécification de la structure OSGi. Les dernières sont des concepts propres à Eclipse et sont ajoutées par le code de l'environnement d'exécution d'Eclipse. De même, le registre des plug-ins d'origine et les objets liés sont répartis entre les bundles OSGi et le registre des extensions Eclipse.

Les parties d'IPluginRegistry relatives à la spécification de l'exécution (c'est-à-dire IPluginDescriptor, ILibrary et IPrequisite) sont déconseillées et les parties relatives aux extensions et aux points d'extension ont été déplacées dans IExtensionRegistry. De plus, les objets de modèle liés au registre des plug-ins entier sont désormais déconseillés. Ces types étaient présentés et instanciés par l'environnement d'exécution principalement pour prendre en charge des outils tels que PDE. Malheureusement, le niveau d'information nécessaire dépassait souvent les capacités ou les intérêts de l'environnement d'exécution (comme par exemple l'enregistrement des numéros de ligne pour les éléments de plug-in.xml) et à la fin, les consommateurs potentiels des informations de l'environnement d'exécution devaient de toute façon gérer leurs propres structures.

Dans le nouvel environnement d'exécution, les fonctionnalités mises à disposition par l'environnement d'exécution ont été redéfinies et ne sont désormais fournies que celles qui sont essentielles à l'exécution de l'environnement d'exécution ou qui sont extrêmement difficiles à effectuer pour d'autres. Comme indiqué plus haut, les objets de modèle du registre des plug-ins sont déconseillés, comme l'API d'analyse des plug-ins. Le nouveau registre des extensions gère les informations essentielles relatives aux extensions. Une nouvelle structure d'état (voir org.eclipse.osgi.service.resolver.State et plug-ins liés) représente et permet leur manipulation.

Structure des fragments NL

Dans Eclipse 3.0, la structure des fragments NL a été mise à jour en vue d'une plus grande cohérence. Avant, les traductions des fichiers tels que plugin.properties se trouvaient dans des fichiers Jar fournis par les fragments. Etant donné que les fichiers source se situent à la racine du plug-in hôte correspondant, il est plus judicieux de placer les fichiers traduits à la racine des fragments NL. Par exemple,

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

Remarque : avant, le fichier nl1.jar aurait contenu les traductions de plugin.properties. Ces fichiers se trouvent désormais à la racine du fragment et le fichier Jar contient les traductions de toutes les ressources pouvant être traduites (comme les fichiers chargés via le chargeur de classe) dans le plug-in hôte.

Evidemment, la structure des fragments NL d'Eclipse 2.1 est encore prise en charge pour les plug-ins hôte 2.1 exécutés dans Eclipse 3.0. Toutefois, vous ne pouvez pas utiliser de fragment NL 2.1 dans un plug-in 3.0. Vous devez mettre à jour le fragment de sorte qu'il soit adapté à la nouvelle structure.

Informations générales relatives aux modifications de l'API

org.eclipse.core.boot (package org.eclipse.core.boot)

Le package org.eclipse.core.boot entier est déconseillé. BootLoader a été fusionné avec org.eclipse.core.runtime.Platform car il n'est plus nécessaire que l'amorçage et l'environnement d'exécution soit séparés. En fait, le code du plug-in org.eclipse.core.boot a été déplacé dans le nouvel environnement d'exécution ou dans la couche de compatibilité.

IPlatformConfiguration a toujours été un type défini par et pour le composant d'installation et de mise à jour d'Eclipse. Grâce à la réorganisation de l'environnement d'exécution, nous pouvons placer ce type à l'endroit approprié. Cette classe reste en grande partie inchangée et a été remise en forme dans org.eclipse.update.configurator.IPlatformConfiguration.

IPlatformRunnable a été déplacé dans org.eclipse.core.runtime.IPlatformRunnable.

IExtension et IExtensionPoint (package org.eclipse.core.runtime)

La méthode getDeclaringPlugin() (sur les deux classes) fournit un lien (vers le haut) au plug-in qui déclare l'extension ou le point d'extension (respectivement). Le nouvel modèle de registre sépare les aspects liés à l'exécution des plug-ins des aspects liés aux extensions et aux points d'extension et ne contient plus IPluginDescriptors. Les utilisateurs de cette API doivent envisager d'utiliser la nouvelle méthode getParentIdentifier() qui se trouve sur IExtension et IExtensionPoint.

ILibrary, IPluginDescriptor, IPluginRegistry et IPrerequisite (package org.eclipse.core.runtime)

Dans l'environnement d'exécution d'origine, le registre des plug-ins conservait une image complète de la configuration de l'environnement d'exécution. Dans Eclipse 3.0, cette image est répartie entre la structure OSGi et le registre des extensions. Ainsi, ces classes sont déconseillées. Les remarques y relatives détaillent la façon dont vous devez mettre à jour votre code.

Platform et Plugin (package org.eclipse.core.runtime)

Dans le nouvel environnement d'exécution, les objets Plugin ne sont plus gérés par l'environnement d'exécution et par conséquent, ne sont pas accessibles de façon générique via Platform. De même, le registre des plug-ins n'existe plus et ne permet plus l'accès aux descripteurs de plug-ins. Cependant, des méthodes de remplacement sont disponibles et détaillées dans la documentation Java (Javadoc) des méthodes déconseillées de ces classes.

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

Tous les types de ce package sont désormais déconseillés. Pour plus d'informations, voir l'article relatif aux registres.

IWorkspaceRunnable et IWorkspace.run (package org.eclipse.core.resources)

Nous conseillons aux clients de la méthode IWorkspace.run(IWorkspaceRunnable,IProgressMonitor) de revoir leurs utilisations de cette méthode et d'envisager d'utiliser la méthode plus riche IWorkspace.run(IWorkspaceRunnable,ISchedulingRule,int,IProgressMonitor). L'ancienne méthode IWorkspace.run verrouille l'espace de travail entier pour toute la durée d'IWorkspaceRunnable. En d'autres termes, une opération effectuée à l'aide de cette méthode ne pourra pas s'exécuter en même temps que d'autres opérations qui modifient l'espace de travail. Dans Eclipse 3.0, de nombreuses opérations de longue durée ont été déplacées dans des unités d'exécution en arrière-plan, c'est pourquoi la probabilité de conflits entre les opérations est accrue. Si une opération modale en avant-plan est bloquée par une opération en arrière-plan de longue durée, l'interface utilisateur est bloquée jusqu'à ce que l'opération en arrière-plan se termine ou jusqu'à ce que l'une des opérations soit annulée.

Nous suggérons de modifier toutes les références à l'ancienne méthode IWorkspace.run de sorte qu'elles utilisent la nouvelle méthode avec un paramètre de règle de planification. La règle de planification doit correspondre à la règle la plus précise qui englobe les règles pour toutes les modifications effectuées par cette opération. Si vous essayez de modifier des ressources qui se trouvent hors de la portée de la règle de planification, une exception d'exécution survient. La règle de planification spécifique requise par une opération d'espace de travail donnée n'est pas indiquée et peut varier selon le fournisseur de référentiel installé sur un projet précis. Utilisez la fabrique IResourceRuleFactory afin d'obtenir la règle de planification pour une opération de modification de ressource. Vous pouvez également utiliser une règle MultiRule afin de spécifier plusieurs règles de ressource et la méthode MultiRule.combine pour combiner des règles provenant d'opérations de modification de ressource différentes.

Si le verrouillage n'est pas nécessaire, vous pouvez utiliser la règle de planification null. Elle permet à l'exécutable de modifier toutes les ressources de l'espace de travail mais n'empêche par d'autres unités d'exécution de modifier l'espace de travail simultanément. Pour des changements simples de l'espace de travail, il s'agit souvent de la solution la plus facile et la plus adaptée à la simultanéité.

IWorkbenchPage (package org.eclipse.ui)

IEditorDescriptor (package org.eclipse.ui)

ISharedImages (package org.eclipse.ui)

IWorkbenchActionConstants (package org.eclipse.ui)

IWorkbenchPreferenceConstants (package org.eclipse.ui)

IExportWizard (package org.eclipse.ui)

IImportWizard (package org.eclipse.ui)

INewWizard (package org.eclipse.ui)

WorkbenchHelp (package org.eclipse.ui.help)

IHelp (package org.eclipse.help)

ITextEditorActionConstants (package org.eclipse.ui.texteditor)

IAbstractTextEditorHelpContextIds (package org.eclipse.ui.texteditor)

BasicTextEditorActionContributor (package org.eclipse.ui.texteditor)

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

Point d'extension annotationTypes (plug-in org.eclipse.ui.editors)

Il existe désormais la notion explicite de type d'annotation. Voir Annotation.getType() et Annotation.setType(). Le type d'une annotation peut changer. Un nouveau point d'extension a été ajouté pour la déclaration des types d'annotation : "org.eclipse.ui.editors.annotationTypes". Un type d'annotation est associé à un nom et peut être déclaré en tant que sous-type d'un autre type d'annotation déclaré. Une déclaration de type d'annotation peut aussi utiliser les attributs "markerType" et "markerSeverity" pour spécifier que les marqueurs d'un type et d'une sévérité donnés doivent être représentés dans les éditeurs de texte sous la forme d'annotations d'un type d'annotation particulier. N'utilisez plus les attributs "markerType" et "markerSeverity" de "org.eclipse.ui.editors.markerAnnotationSpecification". Les spécifications des annotations de marqueurs sont désormais indépendantes des marqueurs et leur nom n'est plus significatif. Ce dernier est cependant conservé afin d'assurer la compatibilité amont.

Les instances des sous-classes d'AbstractMarkerAnnotationModel détectent et définissent automatiquement les types d'annotation appropriés pour les annotations créées à partir de marqueurs. Pour extraire via un programme le type d'annotation pour un marqueur donné ou pour une paire spécifique markerType et markerSeverity, utilisez org.eclipse.ui.texteditor.AnnotationTypeLookup.

IAnnotationAccessExtension permet l'accès à la hiérarchie des types d'annotation. Pour un type d'annotation donné, vous pouvez obtenir la chaîne des supertypes et vérifier si un type d'annotation est un sous-type d'un autre type d'annotation. DefaultMarkerAnnotationAccess implémente cette interface.

Point d'extension markerAnnotationSpecification (plug-in org.eclipse.ui.editors)

Le type d'annotation est la clé qui permet de rechercher la spécification de l'annotation de marqueur associée. Etant donné que les types d'annotation peuvent étendre d'autres types d'annotation, il existe également une relation implicite entre les spécifications des annotations de marqueur. Par conséquent, une spécification d'annotation de marqueur pour un type d'annotation donné est complété par les spécifications d'annotations de marqueurs données pour le supertype du type d'annotation donné. Ainsi, il n'est plus nécessaire qu'une spécification d'annotation de marqueur soit complète. Les spécifications d'annotations de marqueurs sont extraites par AnnotationPreferences. Avec org.eclipse.ui.texteditor.AnnotationPreferenceLookup, vous pouvez extraire une préférence d'annotation pour un type d'annotation donné qui complète la préférence de façon transparente ainsi que la chaîne des supertypes de l'annotation.

La spécification d'annotation de marqueur a été étendue et comprend désormais trois nouveaux attributs qui permettent de personnaliser l'apparence d'un type d'annotation donné dans la règle verticale. Il s'agit d'"icon", de "symbolicIcon" et de "annotationImageProvider". La valeur d'"icon" correspond au chemin d'accès à un fichier contenant l'image de l'icône. La valeur de "symbolicIcon" peut être "error", "warning", "info", "task", "bookmark". L'attribut "symbolicIcon" permet d'indiquer à la plateforme que l'annotation doit être représentée par les images utilisées par la plateforme pour présenter les erreurs, les avertissements, les informations, les tâches et les signets, respectivement. La valeur d'"annotationImageProvider" correspond à une classe implémentant org.eclipse.ui.texteditor.IAnnotationImageProvider, qui permet de personnaliser entièrement la présentation d'une annotation.

La règle verticale utilise les éléments IAnnotationAccess/IAnnotationAccessExtension associés pour dessiner les annotations. Elle n'appelle plus Annotation.paint. En général, les annotations ne se dessinent plus elles-mêmes. Les méthodes "paint" et "getLayer" ont été rendues obsolètes pour que les annotations ne soient finalement plus dépendantes de l'interface utilisateur. DefaultMarkerAnnotationAccess sert d'implémentation par défaut d'IAnnotationAccess/IAnnotationAccessExtension. DefaultMarkerAnnotationAccess implémente la stratégie suivante pour le dessin des annotations : si une annotation implémente IAnnotationPresentation, IAnnotationPresentation.paint est appelé. Sinon, le fournisseur des images d'annotation est consulté dans les préférences de l'annotation. Le fournisseur des images de l'annotation n'est disponible que s'il a été spécifié et si le plug-in qui définit la spécification d'annotation de marqueur conteneur a déjà été chargé. Si un fournisseur d'images d'annotation est indiqué, l'appel lui est transmis. Sinon, l'"icône" spécifié est recherché. "symbolicIcon" est utilisé comme image de remplacement finale. Pour le dessin des annotations, la couche de présentation des annotations est pertinente. DefaultMarkerAnnotationAccess consulte la couche de présentation à l'aide de la stratégie suivante : si les préférences de l'annotation spécifie un couche de présentation, la couche indiquée est utilisée. Si aucune couche n'est spécifiée et si l'annotation implémente IAnnotationPresentation, IAnnotationPresentation.getLayer est utilisé. Dans les autres cas, la couche de présentation par défaut (qui est 0) est renvoyée.

Migration vers le point d'extension annotationTypes (plug-in org.eclipse.ui.editors)

Les types d'annotation suivants sont déclarés par le plug-in org.eclipse.ui.editors :

   <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>

L'extension markerAnnotationSpecification définie ne fournit plus les attributs "markerType" et "markerSeverity". Elle associe l'attribut "symbolicIcon" à la valeur appropriée. Par conséquent, les méthodes MarkerAnnotation.paint et MarkerAnnotation.getLayer ne sont plus appelées ; en d'autres termes, leur remplacement n'a aucun impact. Les clients affectés doivent implémenter IAnnotationPresentation.

ILaunchConfigurationType (package org.eclipse.debug.core)

Avec l'introduction des modes de lancement extensibles dans la version 3.0, plusieurs délégations de lancement peuvent exister pour un type de configuration de lancement. Avant la version 3.0, une délégation de lancement uniquement était prise en charge par type de configuration de lancement. La méthode ILaunchConfigurationType.getDelegate() est désormais déconseillée. A la place, utilisez la méthode getDelegate(String mode) pour extraire la délégation de lancement pour un mode de lancement spécifique. La méthode déconseillée a été modifiée de sorte à renvoyer la délégation de lancement pour le mode exécution.

ILaunchConfigurationTab et ILaunchConfigurationTabGroup (package org.eclipse.debug.ui)

Les groupes d'onglets de lancement et les onglets de lancement ne sont plus notifiés lorsqu'un lancement aboutit. La méthode launched(ILaunch) dans les interfaces ILaunchConfigurationTab et ILaunchConfigurationTabGroup est déconseillée et n'est plus appelée. L'utilisation de cette méthode pour le lancement a toujours été problématique, car les onglets n'existent que lorsque le lancement est effectué à partir de la boîte de dialogue de lancement. De plus, avec l'introduction du lancement en arrière-plan, cette méthode ne peut plus être appelée car la boîte de dialogue de lancement est fermée avant que l'objet de lancement résultant n'existe.

ILaunchConfigurationTab et AbstractLaunchConfigurationTab (package org.eclipse.debug.ui)

Deux méthodes ont été ajoutées à l'interface ILaunchConfigurationTab - activated et deactivated. Ces nouvelles méthodes de cycle de vie sont appelées lorsque vous accédez à un onglet et que vous le quittez, respectivement. Les implémentations existantes d'ILaunchConfigurationTab qui sous-classent la classe de type "abstract" mise à disposition par le plug-in de débogage (AbstractLaunchConfigurationTab) sont compatibles de façon binaire car les méthodes sont implémentées dans la classe de type "abstract".

Dans les versions précédentes, un onglet recevait le message initializeFrom lorsqu'il était activé et le message performApply lorsqu'il était désactivé. De cette façon, la structure des onglets de configuration du lancement permettait la communication entre les onglets via une configuration de lancement (en mettant à jour la configuration avec les valeurs d'attribut en cours lorsqu'un utilisateur quittait l'onglet et en mettant à jour l'onglet nouvellement accédé). Toutefois, étant donné que plusieurs onglets ne permettent pas la communication entre les onglets, il se peut que cette méthode ne soit pas efficace. De plus, il était impossible de distinguer un onglet activé d'un onglet affichant une configuration de lancement sélectionnée pour la première fois. Les nouvelles méthodes permettent aux onglets de distinguer l'activation, l'initialisation et la désactivation et de sauvegarder les valeurs en cours.

L'implémentation par défaut de la méthode activated, mise à disposition par l'onglet Abstrait, appelle initializeFrom. L'implémentation par défaut de la méthode deactivated appelle performApply. Les onglets qui veulent profiter de la nouvelle API doivent remplacer ces méthodes selon leurs besoins. En général, pour les onglets qui ne permettent pas la communication entre onglets, il est conseillé d'implémenter à nouveau ces méthodes de sorte qu'elles n'effectuent aucune opération.

Type de point d'extension launchConfigurationTabGroup (package org.eclipse.debug.ui)

Dans les versions précédentes, le passage d'une perspective à l'autre était spécifié dans une configuration de lancement, par le biais des attributs de configuration de lancement ATTR_TARGET_DEBUG_PERSPECTIVE et ATTR_TARGET_RUN_PERSPECTIVE. Avec l'ajout de modes de lancement extensibles dans la version 3.0, l'échelonnement n'est plus pris en compte. Le passage d'une perspective à l'autre est désormais spécifié en fonction du type de configuration de lancement, par mode de lancement qu'un type de configuration de lancement prend en charge. Une API a été ajoutée à DebugUITools pour définir et obtenir la perspective associée à un type de configuration de lancement pour un mode de lancement spécifique.

Un élément supplémentaire facultatif launchMode a été ajouté au point d'extension launchConfigurationTabGroup, pour qu'un groupe d'onglets ajouté puisse spécifier une perspective par défaut pour un mode et un type de configuration de lancement.

A partir de l'interface utilisateur Eclipse, les utilisateurs peuvent éditer la perspective associée à un type de configuration de lancement en ouvrant la boîte de dialogue de type de configuration de lancement et en sélectionnant un noeud de type de configuration de lancement dans l'arborescence (plutôt qu'une configuration individuelle). Un onglet apparaît, qui permet à l'utilisateur de définir une perspective pour chaque mode de lancement pris en charge.

[JDT uniquement] IVMRunner (package org.eclipse.jdt.launching)

Deux méthodes ont été ajoutées à la classe VMRunnerConfiguration pour prendre en charge la définition et l'extraction des variables d'environnement. Les implémenteurs d'IVMRunner doivent appeler VMRunnerConfiguration.getEnvironment() et transmettre cet environnement à la machine virtuelle Java (JVM) en cours d'exécution. Pour ce faire, les clients qui utilisent DebugPlugin.exec(String[] cmdLine, File workingDirectory) peuvent appeler DebugPlugin.exec(String[] cmdLine, File workingDirectory, String[] envp) à la place. Le simple fait de transmettre le résultat de getEnvironment() suffit.

[JDT uniquement] Classes VMRunnerConfiguration et Bootstrap (package org.eclipse.jdt.launching)

Dans les versions précédentes, la classe VMRunnerConfiguration décrivait un chemin d'amorçage à l'aide d'un attribut. Il s'agissait d'une série de chaînes figurant dans l'argument -Xbootclasspath. Trois nouveaux attributs ont été ajoutés à VMRunnerConfiguration pour prendre en charge les machines virtuelles Java (JVM) qui autorisent l'ajout sous la forme de suffixe ou de préfixe à un chemin d'amorçage. Les nouvelles méthodes/attributs sont les suivantes :

L'ancien attribut, getBootClassPath(), existe encore et contient un chemin complet équivalent à celui des trois nouveaux attributs. Toutefois, la classe VMRunners qui prend en charge les nouvelles options du chemin d'amorçage devrait profiter des nouveaux attributs.

[JDT uniquement] Prise en charge améliorée des copies de travail (package org.eclipse.jdt.core)

La fonction de copie d'un modèle Java a été améliorée dans la version 3.0. Avant la version 3.0, le modèle Java permettait la création de copies de travail individuelles d'unités de compilation. L'utilisateur pouvait modifier la copie de travail puis valider les changements. La fonction d'analyse limitée d'une copie de travail dans le contexte du reste du modèle Java était prise en charge. Cependant, ces analyses étaient incapables de prendre en compte plusieurs copies de travail à la fois.

Les modifications apportées à la version 3.0 permettent de créer et de gérer des ensembles de copies de travail d'unités de compilation et d'effectuer des analyses pour toutes les copies de travail d'un ensemble. Par exemple, un client comme JDT refactoring peut désormais créer des copies de travail pour une ou plusieurs unités de compilation qu'il envisage de modifier puis résoudre les références des types entre les copies de travail. Avant, cette opération n'était possible qu'après validation des modifications apportées aux copies de travail de l'unité de compilation.

Deux modifications ont été apportées à l'API du modèle Java en vue de l'amélioration de la prise en charge :

(1) la fonctionnalité qui se trouvait dans IWorkingCopy et héritée par ICompilationUnit a été consolidée dans ICompilationUnit. L'interface IWorkingCopy était uniquement utilisée à cet emplacement et était plus générale que nécessaire. Cette modification simplifie l'API. La classe IWorkingCopy est déconseillée. D'autres emplacements dans l'API où IWorkingCopy est utilisée comme paramètre ou type de résultat ont été déconseillés également ; les méthodes de l'API de remplacement indiquent ICompilationUnit au lieu d'IWorkingCopy.

(2) L'interface IBufferFactory a été remplacée par WorkingCopyOwner. La prise en charge améliorée des copies de travail requiert qu'un objet soit propriétaire des copies de travail. Bien qu'IBufferFactory soit bien situé, son nom n'indique pas la façon dont le nouveau mécanisme de copie fonctionne. WorkingCopyOwner est plus suggestif. De plus, WorkingCopyOwner est déclarée en tant que classe de type "abstract", et non comme interface, pour que la notion de propriétaire de copie de travail puisse évoluer. La méthode d'IBufferFactory est déplacée vers WorkingCopyOwner sans subir de modification. WorkingCopyOwner n'implémente pas IBufferFactory pour qu'il soit clair qu'IBufferFactory est obsolète. La classe IBufferFactory est déconseillée. D'autres emplacements dans l'API où IBufferFactory apparaît sous la forme d'un paramètre ou d'un type de résultat sont également déconseillés ; les méthodes de l'API de remplacement indiquent WorkingCopyOwner à la place d'IBufferFactory.

Ces modifications n'ont pas d'effet sur la compatibilité binaire.

Lors de la migration, toutes les références au type IWorkingCopy doivent pointer vers ICompilationUnit à la place. L'implémentation d'IWorkingCopy implémente aussi ICompilationUnit, c'est-à-dire que des objets de type IWorkingCopy peuvent être transmis en toute sécurité vers ICompilationUnit.

Une classe qui implémente IBufferFactory doit être remplacée par une sous-classe de WorkingCopyOwner. Bien que WorkingCopyOwner n'implémente pas la classe IBufferFactory elle-même, vous pouvez déclarer la sous-classe de WorkingCopyOwner qui implémente IBufferFactory et crée un pont entre l'ancienne et la nouvelle classe (IBufferFactory déclare createBuffer(IOpenable) alors que WorkingCopyOwner déclare createBuffer(ICompilationUnit) ; ICompilationUnit étend IOpenable).

Etant donné que les modifications qui impliquent IWorkingCopy et IBufferFactory sont liées, nous vous conseillons de traiter les deux en même temps. Vous trouverez les détails des obsolescences ci-dessous.

Restructuration du plug-in org.eclipse.help

Le plug-in org.eclipse.help, qui conservait les API et les points d'extension permettant l'ajout d'éléments au système d'aide et son extension, ainsi qu'à afficher l'aide, ne contient plus désormais que des API et des points d'extension pour l'ajout et l'accès aux ressources d'aide. Une partie de l'implémentation de l'interface utilisateur d'aide par défaut contenue dans ce plug-in a été déplacée dans un nouveau plug-in, org.eclipse.help.base, avec des API permettant l'extension de l'implémentation. Les API et les points d'extension permettant l'ajout de l'interface utilisateur d'aide et l'affichage de l'aide ont été déplacés dans le plug-in org.eclipse.ui. Cette restructuration permet aux applications de disposer d'une plus grande souplesse par rapport au système d'aide ; les applications reposant sur le plan de travail générique peuvent fournir leur propre implémentation de l'interface utilisateur d'aide et/ou de l'aide, ou ignorer complètement le système d'aide.

Etant donné que les points d'extension et les packages d'API affectés sont conçus uniquement pour être utilisés par le système d'aide lui-même, il est peu probable que des plug-ins existants soit touchés par cette modification. Ils sont répertoriés ici uniquement pour que la liste soit exhaustive :

Nouvelle API d'interface utilisateur de recherche

Une nouvelle API pour l'implémentation des recherches personnalisées a été ajoutée dans la version 3.0. L'API d'origine est déconseillée dans la version 3.0 et il est plus judicieux que les clients utilisent la nouvelle API dans les packages org.eclipse.search.ui et org.eclipse.search.ui.text.

Les clients doivent créer des implémentations d'ISearchQuery, ISearchResult et ISearchResultPage. L'implémentation d'ISearchResultPage doit ensuite être ajoutée au nouveau point d'extension org.eclipse.search.searchResultViewPages.

Les implémentations par défaut de ISearchResult et ISearchResultPage se trouvent dans le package org.eclipse.search.ui.text.

Messages null dans MessageBox et DirectoryDialog (package org.eclipse.swt.widgets)

Avant la version 3.0, l'appel de DirectoryDialog.setMessage(String string) ou de MessageBox.setMessage(String string) avec une valeur null pour la chaîne entraînait l'apparition d'une boîte de dialogue sans titre. Ce comportement n'était pas défini (la transmission de la valeur null n'a jamais été autorisée) et crée des problèmes pour getMessage qui ne peut pas renvoyer de valeur null. Dans la version 3.0, la transmission de la valeur null entraîne désormais une exception IllegalArgumentException ; les spécifications ont été modifiées et le mentionnent sur la ligne de la méthode dans la superclasse Dialog.setMessage. Si vous utilisez Dialog.setMessage, vérifiez que la valeur de la chaîne transmise n'est pas "null". Transmettez simplement une chaîne vide pour afficher une boîte de dialogue sans titre.

Amélioration des commentaires sur la progression modale

La prise en charge d'opérations simultanées requiert des méthodes sophistiquées pour l'affichage de la progression modale. Dans le cadre des efforts relatifs à la réactivité, la prise en charge supplémentaire de la progression a été implémentée dans la classe IProgressService. La méthode existante permettant d'afficher la progression avec ProgressMonitorDialog fonctionne encore. Toutefois, pour améliorer votre expérience, nous vous conseillons de migrer vers la nouvelle méthode IProgressService.

Le document Showing Modal Progress in Eclipse 3.0 explique comment procéder à la migration vers la nouvelle méthode IProgressService.

Groupes d'actions de débogage supprimés

Le point d'extension des groupes d'actions de débogage (org.eclipse.debug.ui.debugActionGroups) a été supprimé. Dans Eclipse 3.0, le plan de travail prend en charge les activités via le point d'extension org.eclipse.platform.ui.activities. Il fournit tous les éléments que le point d'extension des groupes d'actions de débogage mettait à disposition et son utilisation est plus facile (il prend en charge les masques ce qui évite de spécifier toutes les actions de façon exhaustive) et est associé à une API de prise en charge par programme. Aucune erreur ne survient si vous ne supprimez pas les références à l'ancien point d'extension. Ces dernières seront simplement ignorées. Nous encourageons les fournisseurs des produits à utiliser la prise en charge des activités du plan de travail pour l'association d'actions de débogage propres à un langage aux activités propres à ce langage (par exemple, les actions de débogage C++ peuvent être associées à une activité appelée "Développement C++").

BreakpointManager peut être désactivé

IBreakpointManager définit désormais les méthodes setEnabled(boolean) et isEnabled(). Lorsque le gestionnaire des points d'arrêt est désactivé, les débogueurs doivent ignorer tous les points d'arrêt enregistrés. La plateforme de débogage fournit également un nouveau mécanisme de programme d'écoute, IBreakpointManagerListener, qui permet à un client de s'enregistrer auprès du gestionnaire des points d'arrêt afin d'être notifié lorsque son activation change. La vue Points d'arrêt appelle cette API à partir d'une nouvelle action d'activation/désactivation qui permet à l'utilisateur d'"ignorer tous les points d'arrêt". Les débogueurs qui ne respectent pas l'activation du gestionnaire des points d'arrêt ne fonctionneront pas si l'utilisateur tente d'utiliser cette fonction.

[JDT uniquement] Participants à la recherche Java (package org.eclipse.jdt.core.search)

Les langages proche de Java (comme JSP, SQLJ, JWS, etc.) doivent pouvoir participer à la recherche Java. Les implémenteurs de tels langages, notamment, doivent pouvoir :

Un tel implémenteur est appelé participant à la recherche. Il étend la classe SearchParticipant. Les participants à la recherche sont transmis à de requêtes de recherche (voir SearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor)).

Pour l'indexation ou la localisation d'occurrences, un participant à la recherche doit définir une sous-classe de SearchDocument qui peut extraire le contenu du document en écrasant getByteContents() ou getCharContents(). Une instance de cette sous-classe est renvoyée dans getDocument(String).

Un participant à la recherche qui souhaite indexer un document utilise SearchParticipant.scheduleDocumentIndexing(SearchDocument, IPath) pour planifier l'indexation du document indiqué dans l'index donné. Une fois que le document est prêt pour l'indexation, la structure sous-jacente appelle SearchParticipant.indexDocument(SearchDocument, IPath). Le participant à la recherche extrait ensuite le contenu du document, l'analyse et ajoute des entrées d'index à l'aide de SearchDocument.addIndexEntry(char[], char[]).

Une fois l'indexation terminée, un utilisateur peut interroger les index et rechercher des occurrences avec SearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor). Cette méthode demande d'abord à chaque participant à la recherche quels sont les index nécessaires à la requête avec SearchParticipant.selectIndexes(SearchPattern, IJavaSearchScope). Pour chaque entrée d'index qui correspond au modèle donné, un document de recherche est créé après demande au participant à la recherche (voir getDocument(String)). Tous ces documents sont transmis au participant à la recherche pour qu'il puisse localiser des occurrences à l'aide de locateMatches(SearchDocument[], SearchPattern, IJavaSearchScope, SearchRequestor, IProgressMonitor). Le participant à la recherche notifie l'objet SearchRequestor des occurrences trouvées avec acceptSearchMatch(SearchMatch) et en transmettant une instance d'une sous-classe de SearchMatch.

Un participant à la recherche peut déléguer une partie de son travail au participant à la recherche Java par défaut. Vous pouvez obtenir une instance du participant par défaut à l'aide de SearchEngine.getDefaultSearchParticipant(). Par exemple, lorsqu'il doit rechercher des occurrences, un participant SQLJ peut créer des documents .java à partir de ses documents .sqlj et déléguer le travail au participant par défaut en lui transmettant les documents .java.