Add-In Visual Studio .NET vs Plug-In Eclipse 2/2 par Sami Jaber (jaber@ifrance.com)

L'environnement Eclipse

La plateforme Eclipse est composées de deux couches logicielles principales : la couche modèle et la couche d'interface utilisateur (IHM). Le modèle est également appelé Workspace. Il contient une collection de ressources identifiées par des projets, des répertoires ou des fichiers. L'interface utilisateur ou Workbench défini la présentation visuelle de ces ressources. A l'intérieur d'un Workbench, les perspectives sont utilisées pour contrôler la visibilité de chaque éléments du modèle et de l'interface utilisateur via le concept d'actions et de vues. Ces contrôles permettent de naviguer ou de modifier le Workspace courant tout en personnalisant l'environnement. Le développeur a également la possibilité d'implémenter de nouvelles perspectives et de nouvelles vues. A ce titre, il doit être en mesure d'identifier la nature exacte des composants qu'il souhaite développer ou étendre afin d'utiliser les API adéquates. 

  Le JDT est le Java Development Tool, il est décomposé en deux parties : le Core et l'UI et contient l'ensemble des classes constituant l'outil Eclipse. Des contrôles graphiques (SWT) en passant par le débogage ou encore l'éditeur de texte, tout y est. Pour plus d'informations à ce sujet, n'hésitez pas à consulter la liste des classes du JDT.

Le Plug-In DotNetGuruReader pour Eclipse

Le PlugIn DotNetGuruReader d'Eclipse possède les mêmes caractéristiques que son homologue Visual Studio .NET. La copie d'écran suivante illustre le résultat final obtenu dans l'IDE une fois l'installation effectuée.   

Paramétrer le plug-In 

L'application se paramètre de la même manière que VS.NET à l'aide d'un menu spécifique. 

 

Les Vues

Les vues représentent l'élément de base permettant de naviguer dans une hiérarchie d'informations. Elles sont typiquement utilisées pour ouvrir un éditeur de texte, afficher des propriétés sur la fenêtre active ou récupérer des informations spécifiques sur l'application. Par défaut, l'IDE propose un certain nombre de vues telles que l'explorateur de package, la fenêtre des propriétés, l'explorateur de classes, etc ... Notre Plug-In possède donc les mêmes caractéristiques que ces vues standards. 

Le Framework PDE (PlugIn Development Environment)

L'API PDE représente le Framework chargé de gérer le cycle de vie d'un Plug-In mais également de fournir toute l'infrastructure nécessaire à l'interaction entre le Plug-In et l'IDE. Il est constitué des packages suivants : org.eclipse.pde.internal, org.eclipse.pde.core, org.eclipse.pde.internal.runtime.

Cet environnement a pour rôle de contrôler l'exécution du Plug-In sans pour autant fournir les fonctionnalités de base permettant à l'application d'interagir avec l'IDE. Pour cela le Plug-In devra faire appel aux API sur lesquelles s'appuie Eclipse, c'est à dire JFace, SWT et UI. Ce principe est assez similaire à celui utilisé par Visual Studio .NET dans la mesure où l'outil ne rajoute aucune couche supplémentaire entre le Plug-In et l'environnement, il se contente de jouer le rôle de facilitateur en contrôlant le cycle de vie et le déploiement du Plug-In. Au passage, dans Eclipse, le Plug-In est avant tout un constituant de base de l'IDE au même titre que n'importe quel composant graphique d'origine. 

Voyons maintenant comment a été conçu le Plug-In DotNetGuruNewsReader.

Les dessous du Plug-In DotNetGuru News Reader pour Eclipse 

L'interface AbstractUIPlugin

Tout Plug-In Eclipse s'intégrant au workspace courant doit implémenter une classe qui dérive de org.eclipse.ui.plugin.AbstractUIPlugIn. Comme on pourrait s'y attendre, cette classe est très proche que la classe Connect.cs de .NET. Elle contient des méthodes telles que loadPreferenceStore(), startup() ou shutdown() sur le principe de OnConnection() et OnDisconnection() de Connect.cs. Cependant, contrairement à .NET qui observe une séparation claire entre les préférences d'un projet et la classe principale du Plug-In, Eclipse lie étroitement ces deux notions. Cela est dû au caractère plus "graphique" de la classe principale du Plug-In Eclipse qui hérite de AbstractUIPlugIn.   

 

Par ailleurs, sur le principe de .NET les méthodes déclarées dans AbstractPlugIn correspondent essentiellement à des évènements qui surviennent tout au long du cycle de vie de l'application.  

L'application DotNetGuruNewsReader

Après ces quelques explications, rentrons dans le détail de l'implémentation technique de notre petit Plug-In. La classe DotNetGuruNewsReaderPlugin est illustrée ci-dessous : 

package DotNetGuruNewsReader;
import
org.eclipse.ui.plugin.*;  
import
org.eclipse.core.Runtime.*;
import
org.eclipse.core.resources.*;
import
java.util.*;

/**
 
* The main plugin class to be used in the desktop.
 
*/
 
public
class DotNetGuruNewsReaderPlugin extends AbstractUIPlugin {       
   
//The shared instance.
   
public static final String REFRESH_INTERVAL_PREFERENCE = "refreshinterval";
   
public static final String BACKENDS_PREFERENCE = "backends";
   
public static final String BROWSER_PREFERENCE = "browser";
   
public static final String BROWSER_TYPE_PREFERENCE = "type";
  
   
//Preferences concerning proxy
   
public static final String USE_HTTP_PROXY_PREFERENCE = "httpproxy.use";
   
public static final String HTTP_PROXY_HOST_PREFERENCE = "httpproxy.host";
   
public static final String HTTP_PROXY_PORT_PREFERENCE = "httpproxy.port";
   
public static final String HTTP_PROXY_LOGIN_PREFERENCE = "httpproxy.login";
   
public static final String HTTP_PROXY_USER_PREFERENCE = "httpproxy.user";
   
public static final String HTTP_PROXY_PASSWD_PREFERENCE = "passwd";
 
   
//Default values
   
public static final int DEFAULT_REFRESH_INTERVAL = 30;
  
  public static final String DEFAULT_BROWSER_TYPE = "2";
 
   
private static DotNetGuruNewsReaderPlugin plugin;
 
   
//Resource bundle.
    private ResourceBundle resourceBundle;
    
     
/** The constructor. */
 
     
public DotNetGuruNewsReaderPlugin(IPluginDescriptor descriptor) {
           
super(descriptor);
           
plugin = this;
           
try {
                 
resourceBundle= ResourceBundle.getBundle("DotNetGuruNewsReader.DotNetGuruNewsReaderPluginResources");
                 
System.out.println(ResourceBundle.class);
            
           
} catch (MissingResourceException x) {
                 
resourceBundle = null;
           
}
     
}
     
/**
     
 * Returns the shared instance.
     
 */
     
public static DotNetGuruNewsReaderPlugin getDefault() {
           
return plugin;
     
}
 
     
/**
     
 * Returns the workspace instance.
     
 */
     
public static IWorkspace getWorkspace() {
           
return ResourcesPlugin.getWorkspace();
     
}
  
     
/**
     
 * Returns the string from the plugin's resource bundle,
     
 * or 'key' if not found.
     
 */
     
public static String getResourceString(String key) {
           
ResourceBundle bundle= DotNetGuruNewsReaderPlugin.getDefault().getResourceBundle();
           
try {
                 
return bundle.getString(key);
           
} catch (MissingResourceException e) {
                 
return key;
           
}
     
}
  
     
/**
     
 * Returns the plugin's resource bundle,
     
 */
     
public ResourceBundle getResourceBundle() {

           
return resourceBundle;
     
}

    
public void startup() throws CoreException {
           
super.startup();
           
System.out.println("Plug-In derramé");
     
}
 
     
public void shutdown() throws CoreException {
           
super.shutdown();
           
System.out.println("Plug-In detruit");
     
}
 
}

Vous ne trouverez pas le code lié à la logique fonctionnelle du Plug-In dans cette classe. En effet, notre application représentant une Vue, il nous faudra développer une seconde classe dérivant du contrôle graphique Vue ou plutôt org.eclipse.ui.part.ViewPart. Voici cette classe. 

package DotNetGuruNewsReader.views;   
import
org.eclipse.swt.SWT;
import
org.eclipse.swt.SWTException;
import
org.eclipse.swt.ole.win32.OLE;
import
org.eclipse.swt.ole.win32.OleAutomation;
import
org.eclipse.swt.ole.win32.OleControlSite;
import
org.eclipse.swt.ole.win32.OleFrame;
import
org.eclipse.swt.widgets.Composite;
import
org.eclipse.ui.part.ViewPart;   
public
class OleBrowserView extends ViewPart {  
     
private Composite      displayArea;
     
private OleFrame       webFrame;
     
private OleWebBrowser  webBrowser;
  
     
private OleControlSite webControlSite;
     
private boolean activated = false;
 
     
/**
     
 * Constructs the OLE browser view.
     
 */
     
public OleBrowserView() {
}  
     
/**
     
 * Creates the example.
     
 * 
     
 * @see ViewPart#createPartControl
     
 */
     
public void createPartControl(Composite parent) {
           
displayArea = parent ;
           
// We generate HTML file by transforming XLS predefined resource file with DNG rss
           
RSSReader.processXSLTransformation();
           
// while the html temp file is created, we call the browser and open it

           
// if the file transformation has failed, you will a customized error ... 
           
createBrowserControl();
     
}
      
     
/**
     
 * Cleanup
     
 */
     
public void dispose() {
           
if (webBrowser != null) webBrowser.dispose();
           
webBrowser = null;
           
super.dispose();
     
}
      
     
public void setFocus() {}
       
     
/**
     
 * Creates Web browser control.
     
 */
     
private void createBrowserControl() {
           
// Every control must have an associated OleFrame:
           
webFrame = new OleFrame(displayArea, SWT.CENTER);
           
try {
                 
// Create an Automation object for access to extended capabilities
                 
webControlSite = new OleControlSite(webFrame, SWT.CENTER, "Shell.Explorer");
                 
OleAutomation oleAutomation = new OleAutomation(webControlSite);
                 
webBrowser = new OleWebBrowser(oleAutomation);
                 
webBrowser.Navigate(RSSReader.htmlFile);
                 
webControlSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);

            } catch (SWTException ex) { ex.printStackTrace();
              
return;
           
}
     
}

}

La méthode CreatePartControl() est la plus importante. Elle est invoquée par le PDE à chaque fois que vous demandez l'affichage de la fenêtre "DotNetGuru News Reader". Son fonctionnement est très proche de son équivalent .NET à travers la méthode Exec() de Connect.cs. Nous effectuons en premier lieu la transformation XSL via la classe RSSReader. Puis dans la méthode CreateBrowserControl() nous réalisons l'instanciation du contrôle graphique Navigateur Web via l'API Ole. C'est tout l'avantage d'un tel Plug-In, les fonctionnalités et les composants utilisés de part et d'autres sont exactement les mêmes, les versions C# et Java faisant appel à l'API COM pour instancier le même composant situé dans la bibliothèque SHDocVW.dll. Ne vous étonnez donc pas si l'apparence graphique (ou Look & Feel) des deux Plug-Ins est très proche.

Nous vous faisons grâce de la classe OleWebBrowser qui est en réalité un décorateur de la DLL précédente. N'hésitez cependant pas à parcourir son contenu, elle est assez symptomatique de la différence existante entre le monde Java et Microsoft lorsqu'il s'agit de faire appel à Ole. Sous Visual Studio, l'intégration de ce dernier a consisté à faire un simple glisser/déplacer du composant vers le formulaire WinForm alors que l'environnement Eclipse est relativement plus contraignant à ce niveau. En effet, l'outil propose un pont Java/COM dans le package org.eclipse.swt.ole.win32.OleAutomation sur laquelle s'appuie notre Plug-In. 

Nous ne revenons pas sur le fonctionnement de la classe RSSReader dans laquelle nous avons essayé de reproduire le même fonctionnement que la version .NET.

package DotNetGuruNewsReader.views;
import
java.io.DataOutputStream;
import
java.io.File;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
java.net.URL;
import
java.net.URLConnection;   
import
javax.xml.transform.Source;
import
javax.xml.transform.Transformer;
import
javax.xml.transform.TransformerFactory;
import
javax.xml.transform.stream.StreamResult;
import
javax.xml.transform.stream.StreamSource;   
public
class RSSReader {
     
public RSSReader() {
     
}
     
public static String htmlFile;
     
public final static String ERROR_MSG = "<html>Le plug-In n'arrive pas à se connecter au site, 
                        <br>vérifiez que votre connection est active</html>"
;
 
     
public static void processXSLTransformation() {
           
InputStream stream = null;
           
URLConnection conn = null;
           
try {
                 
htmlFile =
                             
File.createTempFile("rss", ".html").getAbsolutePath();
                 
Source xsltSource =
                       
new StreamSource(
                        
      RSSReader.class.getClassLoader().getResourceAsStream(
                                  
"RSS.xslt"));
                 
TransformerFactory lc_factory = TransformerFactory.newInstance();
                 
Transformer lc_transformer = lc_factory.newTransformer(xsltSource);
                 
try {
                       
// Should be improved by getting site list in preferences 
                       
conn =
                             
new URL("http://www.dotnetguru.org/backend.php")
                                  
.openConnection();
                       
stream = conn.getInputStream();
                 
} catch (IOException e) {

                        
                  DataOutputStream outs = new DataOutputStream(new FileOutputStream(htmlFile));
                  outs.writeBytes(ERROR_MSG);
                 
throw e ;
                 
}
 
                 
System.out.println(htmlFile);
                 
lc_transformer.transform(
                       
new StreamSource(stream),
                       
new StreamResult(new FileOutputStream(htmlFile)));
                 
stream.close();
           
} catch (Exception e) {
                 
e.printStackTrace();
           
} finally {
                 
try {
                       
if (stream != null)
                             
stream.close();
                 
} catch (Exception e) {
                 
}
           
}
     
}

}

 Implémenter les préférences

La dernière étape et non des moindres consiste à fournir l'interface graphique pour le paramétrage du Plug-In. Rappelez vous que Visual Studio proposait cette opération sous la forme d'un simple formulaire WinForm intégré dans une classe d'un type particulier : IDTToolsOptionsPage. Sous Eclipse, là encore le fonctionnement est très proche. Il est nécessaire de dériver de l'interface org.eclipse.ui.IWorkbenchPreferencePage et de la classe abstraite org.eclipse.jface.preference.FieldEditorPreferencePage intégrant les fonctionnalités graphiques de base nécessaires au cycle de vie du contrôle. Cette approche n'est pas sans rappeler le modèle de .NET avec System.Windows.Form.UserControl

Le résultat auquel on souhaite aboutir est illustré par la copie d'écran suivante.  

La classe FieldEditorPreferencePage est la super classe de notre formulaire de préférences. Vous pourrez constater que les méthodes présentes dans cette classe ressemblent à s'y méprendre aux méthodes de la classe OptionsForm.cs de Visual Studio. Ainsi .NET propose GetProperties() et Eclipse GetPreferenceStore(), .NET propose OnOk() et Eclipse PerformOk() .. Si vous avez encore des doutes sur les similitudes entre les deux environnements ...

Vous êtes sûrement impatient de lire le source de la page des préférences, la voici : 

package DotNetGuruNewsReader.views;   
import
DotNetGuruNewsReader.DotNetGuruNewsReaderPlugin;
import
org.eclipse.jface.preference.FieldEditorPreferencePage;
import
org.eclipse.jface.preference.FileFieldEditor;
import
org.eclipse.jface.preference.IntegerFieldEditor;
import
org.eclipse.jface.preference.RadioGroupFieldEditor;
import
org.eclipse.jface.preference.StringFieldEditor;
import
org.eclipse.jface.util.PropertyChangeEvent;
import
org.eclipse.swt.widgets.Composite;
import
org.eclipse.ui.IWorkbench;
import
org.eclipse.ui.IWorkbenchPreferencePage;   
public
class PreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {  
   
protected SiteListEditor fe1;
   
protected FileFieldEditor fe2;
   
protected BooleanFieldEditor fe3;
   
protected StringFieldEditor fe4;
   
protected IntegerFieldEditor fe5;
   
protected BooleanFieldEditor fe6;
   
protected StringFieldEditor fe7;
   
protected PasswordFieldEditor fe8;
   
protected FileFieldEditor fe9; 
   
protected IntegerFieldEditor fe10;
  
   
public PreferencePage() {
       
super("DotNetGuru Options", FieldEditorPreferencePage.GRID);
   
}
  
   
/**
    
* @see FieldEditorPreferencePage#createFieldEditors()
    
*/
   
protected void createFieldEditors() {
       
fe1 = new SiteListEditor(DotNetGuruNewsReaderPlugin.BACKENDS_PREFERENCE, "Sites", getFieldEditorParent());
       
fe3 = new BooleanFieldEditor(DotNetGuruNewsReaderPlugin.USE_HTTP_PROXY_PREFERENCE, "Use proxy", getFieldEditorParent());
       
fe4 = new StringFieldEditor(DotNetGuruNewsReaderPlugin.HTTP_PROXY_HOST_PREFERENCE, "Proxy Host", getFieldEditorParent());
       
fe5 = new IntegerFieldEditor(DotNetGuruNewsReaderPlugin.HTTP_PROXY_PORT_PREFERENCE, "Proxy Port", getFieldEditorParent());
       
fe6 = new BooleanFieldEditor(DotNetGuruNewsReaderPlugin.HTTP_PROXY_LOGIN_PREFERENCE, "Proxy Login", getFieldEditorParent());
       
fe7 = new StringFieldEditor(DotNetGuruNewsReaderPlugin.HTTP_PROXY_USER_PREFERENCE, "Proxy user", getFieldEditorParent());
     
  fe8 = new PasswordFieldEditor(DotNetGuruNewsReaderPlugin.HTTP_PROXY_PASSWD_PREFERENCE, "Proxy password", getFieldEditorParent());
       
fe9 = new FileFieldEditor("Fichier","XSL File",true,getFieldEditorParent());
  
       
fe10 = new IntegerFieldEditor(DotNetGuruNewsReaderPlugin.REFRESH_INTERVAL_PREFERENCE,"Refresh interval (minutes)", getFieldEditorParent());
       
fe10.setValidRange(0,10000);
  
       
addField(fe1);addField(fe3);addField(fe4);addField(fe5);addField(fe6);addField(fe7);addField(fe8);addField(fe9);addField(fe10);
 
       
initUI();
   
}
   
/**
    
* @see IWorkbenchPreferencePage#init(IWorkbench)
    
*/
 
   
public void init(IWorkbench workbench) {
       
setPreferenceStore(DotNetGuruNewsReaderPlugin.getDefault().getPreferenceStore());
   
}
  
   
public void propertyChange(PropertyChangeEvent event) {
       
super.propertyChange(event);
       
updateUI();
   
}
   
void initUI() {
       
boolean proxy = DotNetGuruNewsReaderPlugin.getDefault().getPluginPreferences().getBoolean(DotNetGuruNewsReaderPlugin.USE_HTTP_PROXY_PREFERENCE);
       
boolean authent =
DotNetGuruNewsReaderPlugin.getDefault().getPluginPreferences().getBoolean(DotNetGuruNewsReaderPlugin.HTTP_PROXY_LOGIN_PREFERENCE);

 
        updateFieldStatus(proxy, authent);
   
}
   
void updateUI() {
       
boolean proxy = fe3.getBooleanValue();
        
boolean authent = fe6.getBooleanValue();
       
updateFieldStatus(proxy, authent);
 
   
}
 
   
void updateFieldStatus(boolean proxy, boolean authent) {
       
Composite comp = getFieldEditorParent();
       
fe4.getTextControl(comp).setEditable(proxy);
       
fe4.getLabelControl(comp).setEnabled(proxy);
       
fe5.getTextControl(comp).setEditable(proxy);
       
fe5.getLabelControl(comp).setEnabled(proxy);
       
fe6.setEnabled(comp, proxy);
       
fe7.getTextControl(comp).setEditable(authent && proxy);
       
fe7.getLabelControl(comp).setEnabled(authent && proxy);
       
fe8.getTextControl(comp).setEditable(authent && proxy);
       
fe8.getLabelControl(comp).setEnabled(authent && proxy);
 
   
}
 
   
/**
    
* @see org.eclipse.jface.preference.IPreferencePage#performOk()
    
*/
   
public boolean performOk() {
       
return true;
   
}

}

Rien de bien sorcier, cette classe reprend les mêmes caractéristiques que .NET. Vous aurez au passage noté la présence des classes PasswordFieldEditor, StringFieldEditor, IntegerIFieldEditor qui représentent des contrôles prédéfinis permettant de stocker les préférences à l'aide d'un typage standard. Ceci est clairement un avantage par rapport à .NET qui impose à l'utilisateur de gérer les contraintes de type sur ses champs.

La configuration 

Pour rappel, sous Visual Studio, le déploiement nécessitait l'enregistrement préalable du Plug-In dans la base de registre. D'ailleurs, si précedemment nous n'avons pas caché notre préférence pour l'emploi d'un fichier de configuration XML, c'est la démarche utilisée par Eclipse au travers du fichier plugin.xml qui est assurément la brique logicielle la plus importante dans notre projet.   

<?xml version="1.0" encoding="UTF-8"?>
<plugin

  
id="DotNetGuruNewsReader"
  
name="DotNetGuruNewsReader Plug-in"
  
version="1.0.0"
  
provider-name=""
  
class="DotNetGuruNewsReader.DotNetGuruNewsReaderPlugin">
  
  
<runtime>
     
<library name="DotNetGuruNewsReader.jar"/>
  
</runtime>
  
<requires>
     
<import plugin="org.eclipse.core.boot"/>
     
<import plugin="org.eclipse.core.runtime"/>
     
<import plugin="org.eclipse.core.resources"/>
     
<import plugin="org.eclipse.ui"/>
     
<import plugin="org.eclipse.swt"/>
     
<import plugin="org.apache.xerces"/>
     
<import plugin="org.jnegre.xalanpack"/>
     
<import plugin="org.eclipse.update.ui"/>
  
</requires>
  
<extension
        
point="org.eclipse.ui.views">
     
<category
           
name="DotNetGuru Plug-In"
           
id="DotNetGuruNewsReader">
     
</category>
     
<view
           
name="DotNetGuru News Reader"
           
icon="icons/sample.gif"
           
category="DotNetGuruNewsReader"
           
class="DotNetGuruNewsReader.views.OleBrowserView"
           
id="DotNetGuruNewsReader.views.OleBrowserView">
     
</view>
  
</extension>
  
<extension
        
point="org.eclipse.ui.preferencePages">
     
<page
           
name="DotNetGuru"
           
class="DotNetGuruNewsReader.views.PreferencePage"
           
id="DotNetGuruNewsReader.views.PreferencePage">
     
</page>
  
</extension>

</plugin>

Vous trouverez dans ce fichier l'ensemble des informations nécessaires à l'IDE pour la configuration du Plug-In. Du nom logique utilisé dans la fenêtre jusqu'aux dépendances avec des bibliothèques ou Plug-In tiers. Notre programme requiert la présence d'un parseur XML et XSL, il vous faudra donc posséder les archives adéquates. Remarquez également la manière dont Eclipse gère notre extension. La page de préférence est vue comme une extension au même titre que notre vue. Une extension est un enrichissement de l'éditeur qui se traduit par l'ajout d'une fonctionnalité dans les menus, les barres d'outils, l'éditeur, etc ...

Tests et déploiement final

Les tests sont du même ordre que ceux de Visual Studio. Eclipse lance une seconde instance de l'éditeur contenant le Plug-In et le debogage est réalisée à partir de la première instance. Quant au déploiement il est d'une simplicité déconcertante. Il vous suffit de créer le fichier archive Jar contenant toute l'application (équivalent du MSI .NET) à partir des menus et de le copier dans un répertoire sous <EclipseHome>/plugin.

 

Conclusion

Après un tel article, il serait bien aventureux d'affirmer lequel des deux environnements est le plus propice au développement de Plug-In. Visual Studio se prête avec brio aux exercices de conception graphique et de génération automatique de code alors qu'Eclipse nécessite de bonnes connaissances des API internes. A l'inverse, Visual Studio pêche dans l'homogénéité de son Framework encore dépendant de COM alors qu'Eclipse repose sur un ensemble cohérent et homogène de classes et d'interfaces. Malgré cela, ces quelques défauts mineures n'enlèvent strictement rien à la grandeur des deux environnements qui seront indéniablement au coeur des débats dans les années à venir. Il y a fort à parier que la différence se fera entre autre dans la richesse des Plug-Ins qu'ils proposeront chacun. A ce sujet, cet article vous démontre une chose, le développement d'un Plug-In n'est pas l'apanage d'un éditeur logiciel ou d'un expert technique quelconque. Aujourd'hui n'importe quel développeur peut écrire une extension personnalisée pour son éditeur préféré. Si l'exemple du lecteur de News n'est pas le plus judicieux en terme d'Architecture d'entreprise, rien n'empêche d'imaginer des outils tels que des générateurs dynamiques de code ou simplement des programmes destinés à veiller au bon respect des principes architecturaux établis dans le cadre d'un projet. Plus encore, bien malin sera celui qui écrira le premier Plug-In chargé d'avertir en temps réel l'ensemble des développeurs d'un projet lorsqu'un fichier commun est modifié avec la possibilité pour l'auteur de dialoguer en direct avec ses collègues au travers d'un Chat. Autant d'exemples et d'outils qu'il reste à créer ...

Enfin, cet article nous démontre qu'une fois encore, la double compétence est plus que jamais nécessaire, mais était-il encore besoin de le rappeler ....  

 

Auteur : Sami Jaber 

Copyright © Janvier 2003

Ressources

Site officiel d'Eclipse : www.eclipse.org

Tutorial sur les Plug-Ins Visual Studio : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsintro7/html/vxprodteproperty.asp

Exemples de Plug-In Eclipse : http://www.improve-technologies.com/pages/Java/IDE/Eclipse/Plug-ins/

Téléchargez les sources et les binaires

Visual Studio Plug-In (Binaires) : DotNetGuruPlugIn_0.1.msi (116 Ko, Installer automatique)

Visual Studio Plug-In (Sources) : DNGVSPlugInSrc_0.1.zip (116 Ko, Fichier zip contenant la solution VS.NET)

Eclipse Plug-In : (Binaires et sources ) DotNetGuruNewsReader_0.1.zip (1,8 Mo avec les bibliothèques XSL, Voir fichier install.txt)

Licence GPL

Tous les fichiers sont fournis sous la licence GPL