mercredi 28 avril 2010

XULRunner embarqué dans une application Java

Dans cet article, je vais vous montrer comment intégrer le moteur XULRunner dans une application JAVA Swing.
SWT intégrant en natif la gestion d'un moteur web externe dont XULRunner.

1. Fichier IDL
Créer le fichier IDL comme expliquer dans l'article précédent (rf XULRunner C++, IDL et XPCOM, compiler le avec le mode « typelib » de xpidl puis copier le fichier xpt généré dans le répertoire components.
Compiler ensuite ce même fichier avec le mode « java » afin de générer les interfaces java à utiliser.

2. Librairie à insérer au projet
MozillaGlue.jar et MozillaInterface.jar de la version 1.9.0.5.

Attention : La dll javaxpcomglue.dll de la version 1.9.0.5 possède apparemment une erreur de dépendance. Par contre elle peut être remplacée par une dll d’une version antérieur de XULRunner (testé avec la version 1.8.1.3).


3. Exemple de code ouvrant une fenêtre XUL
Cet exemple partage un objet XPCOM Java et ouvre une fenètre XULRunner (en sélectionnant le moteur XULRunner installé sur le système) et partage un objet XPCOM qui affiche des infos sur la console JAVA.
Les composants, ainsi que les pages XUL, devront se trouver dans le répertoires chrome et components de XULRunner.

package cs.ihmMozilla;

import java.io.File;
import java.io.FileNotFoundException;

import org.mozilla.interfaces.*;
import org.mozilla.xpcom.GREVersionRange;
import org.mozilla.xpcom.IAppFileLocProvider;
import org.mozilla.xpcom.Mozilla;
import org.mozilla.xpcom.XPCOMException;


public class MBMSPanel {
 private static final long serialVersionUID = 1L;
 private static boolean s_init = false;
 
 /**
  * Constructeur
  */
 public MBMSPanel(String page) {    
  if (!s_init) {
   MBMSPanel.init();
  }
  
  try{
    Mozilla moz = Mozilla.getInstance();
    
       nsIServiceManager serviceManager = moz.getServiceManager();
    
       // Now we need to get the @mozilla.org/toolkit/app-startup;1 service:
       nsIAppStartup appStartup = (nsIAppStartup)serviceManager.getServiceByContractID("@mozilla.org/toolkit/app-startup;1", nsIAppStartup.NS_IAPPSTARTUP_IID);
   
       // Get the nsIWindowWatcher interface to the above
       nsIWindowCreator windowCreator = (nsIWindowCreator)appStartup.queryInterface(nsIWindowCreator.NS_IWINDOWCREATOR_IID);
   
       // Get the window watcher service
       nsIWindowWatcher windowWatcher = (nsIWindowWatcher)serviceManager.getServiceByContractID("@mozilla.org/embedcomp/window-watcher;1", nsIWindowWatcher.NS_IWINDOWWATCHER_IID);
   
       // Set the window creator (from step 6)
       windowWatcher.setWindowCreator(windowCreator);
   
       // Create the root XUL window:
       nsIDOMWindow win = windowWatcher.openWindow(null, page, "MB", "chrome,resizable,centerscreen", null);
       
       windowWatcher.setActiveWindow(win);
             
       // Hand over the application to xpcom/xul, this will block:
       appStartup.run();
       
  }
  catch (Exception e) {
   System.out.println("MBMSPanel Error: "+e.getMessage());
  }
 }

 /**
  * Initialisation de XULRunner
  * @author Marc BUILS
  *
  */
 private static void init() { 
      // Note, on linux, gtk has to be already initialized for this code to work
      Mozilla moz = Mozilla.getInstance();
  
      GREVersionRange[] range = new GREVersionRange[1];
      range[0] = new GREVersionRange("1.9.0", true, "2.9", false);
        // work with trunk nightly version 1.9a1  ^^
      
      try {
        File grePath = Mozilla.getGREPathWithProperties(range, null);
        LocationProvider locProvider = new LocationProvider(grePath);

        moz.initialize(grePath);
        moz.initEmbedding(grePath, grePath, locProvider);
      } catch (FileNotFoundException e) {
       System.out.println("File: "+e.getMessage());
        // this exception is thrown if greGREPathWithProperties cannot find a GRE
      } catch (XPCOMException e) {
       System.out.println("XPCOM: "+e.getMessage());
        // this exception is thrown if initEmbedding failed
      }

      try {
       // Enregistre les factory
    nsIComponentRegistrar registrar = Mozilla.getInstance ().getComponentRegistrar ();
    registrar.autoRegister(null);
    registrar.registerFactory ("{1c5dff00-f741-11dd-87af-0800200c9a66}", "Gestion des Variables Partagees", "@thalesgroup.com/mbmsvariables;1", new nsIFactory() {
     public nsISupports queryInterface (String uuid) {
      if (uuid.equals (nsIFactory.NS_IFACTORY_IID) ||
       uuid.equals (nsIFactory.NS_ISUPPORTS_IID)) return this;
      return null;
     }
     public nsISupports createInstance (nsISupports outer, String iid) {
      return new MBMSVariables() {
       public void setVariable(MBMSVariableStruct variable) {
        System.out.println("Name: " + variable.getBlockName());
        System.out.println("BusName: " + variable.getBusName());
       }
       
       public nsISupports queryInterface(String iid) {
        if (iid.equals(MBMSVariables.MBMSVARIABLES_IID) || iid.equals(MBMSVariables.NS_ISUPPORTS_IID))
         return this;
        return null;
       }
      };
     }
     public void lockFactory (boolean lock) {}
    });

  } catch (Exception e) {
   System.out.println(e.getMessage());
  }     
 }
 
 public static class LocationProvider implements IAppFileLocProvider {
     private final File libXULPath;
     int counter = 0;
 
     public LocationProvider(File grePath) {
     this.libXULPath = grePath;
     }
 
     public File getFile(String aProp, boolean[] aPersistent) {
      File file = null;
      if (aProp.equals("GreD") || aProp.equals("GreComsD")) {
          file = libXULPath;
          if (aProp.equals("GreComsD")) {
              file = new File(file, "components");
          }
      }
      else if (aProp.equals("MozBinD") ||
               aProp.equals("CurProcD") ||
               aProp.equals("ComsD") ||
               aProp.equals("ProfD"))
          {
              file = libXULPath;
              if (aProp.equals("ComsD")) {
                  file = new File(file, "components");
              }
          }
      return file;
  }
 
  public File[] getFiles(String aProp) {
      File[] files = null;
      if (aProp.equals("APluginsDL")) {
          files = new File[1];
          files[0] = new File(libXULPath, "plugins");
      }
      return files;
  } 
 }
}


Cette classe s’utilise de la façon suivante dans une application swing :
       SwingUtilities.invokeLater(new Runnable() {
         public void run() {
        new MBMSPanel("chrome://mbms/content/main.xul");
         }
       });


XULRunner est surtout optimisé pour être utilisé avec les frameworks AWT ou SWT.

4. Liens utiles
- Documentation officielle https://developer.mozilla.org/en/XUL
- XULPlanet http://www.xulplanet.com/
http://www.xulplanet.com/references/xpcomref/
- XULFR http://xulfr.org/
- Générateur d’UUID http://www.somacon.com/p113.php
- Runtime et SDK XULRunner ftp://ftp.mozilla.org/pub/mozilla.org/xulrunner/releases/
- XULBooster (plugin Eclipse) http://cms.xulbooster.org/

1 commentaire:

  1. Je n'ai pas sous la main le fichier IDL qui correspond à cet article. Mais n'hésitez pas à me le demander si il peut vous aider ;)

    RépondreSupprimer