Tutorial sur OSGi basé sur OSCAR
par Didier DONSEZ (Version du 08/04/2005)

Installation et utilisation d'OSCAR

Installation d'OSCAR

OSCAR est une implémentation open-source de la spécification OSGi. Nous utiliserons celle-çi pour le tutoriel cependant ce tutoriel peut être utilisé avec d'autres plateformes libres ou commerciales. Il faut cependant adapter la syntaxe des commandes des shells existants.

Pour installer d’OSCAR, téléchargez le Jar d'installation d'OSCAR depuis le site http://oscar.objectweb.org puis lancez le avec la commande "java -jar oscar-1.0.4.jar". La fenêtre suivante apparait : choisissez le JRE et le répertoire d'installation.
Vous installez OSCAR dans le répertoire z:\osgi\oscar1.0.4

Installation wizard

Vous pouvez aussi vous reportez à la documentation d'OSCAR : http://oscar.objectweb.org/install.html

Prérequis pour le développement de bundles

Pour le développement de bundles, la spécification vous est nécessaire. Elle est téléchargeable le site http://www.osgi.org. après enregistrement.
La JavaDoc est également indispensable. Celle-ci n'est pas disponible cependant vous pouvez la générer grâce à ce build file à partir des sources relatives à la spécification qui sont téléchargeables le site http://www.osgi.org

Si vous développez vos bundles avec Eclipse, vous pouvez installer le plugin OSGiPlugin pour simplifier le développement et le déploiement de bundles.

Premières manipulations

Une fois que OSCAR est installé, lancez OSCAR avec le script oscar.bat (oscar.sh sur Unix).
Vous allez pouvoir tester quelques commandes depuis la console locale de la passerelle.
Voici le résultat de la commande help:
  Console
> z:
> cd \osgi\oscar1.0.4
> oscar

Welcome to Oscar.
=================

Enter profile name: hello1

-> help
bundlelevel <level> <id> ... | <id> - set or get bundle start level.
cd [<base-URL>]                     - change or display base URL.
headers [<id> ...]                  - display bundle header properties.
help                                - display shell commands.
install <URL> [<URL> ...]           - install bundle(s).
obr help                            - Oscar bundle repository.
packages [<id> ...]                 - list exported packages.
ps [-l]                             - list installed bundles.
refresh                             - refresh packages.
services [-u] [-a] [<id> ...]       - list registered or used services.
shutdown                            - shutdown Oscar.
start <id> [<id> <URL> ...]         - start bundle(s).
startlevel [<level>]                - get or set framework start level.
stop <id> [<id> ...]                - stop bundle(s).
uninstall <id> [<id> ...]           - uninstall bundle(s).
update <id> [<URL>]                 - update bundle.
version                             - display version of Oscar.
-> ps
START LEVEL 1
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (1.0.4)
[   1] [Active     ] [    1] Shell Service (1.0.0)
[   2] [Active     ] [    1] Shell TUI (1.0.0)
[   3] [Active     ] [    1] Table Layout (1.0.0)
[   4] [Active     ] [    1] Shell GUI (1.0.0)
[   5] [Active     ] [    1] Shell Plugin (1.0.2)
[   6] [Active     ] [    1] Bundle Repository (1.1.2)
->
Les commandes fournissant des informations sur les bundles installés sont:

Les commandes liées à l'installation/démarrage sont: Il est possible d'ajouter des commandes au shell. En effet, une commande est un service fournit implémentant l'interface org.ungoverned.osgi.service.shell.Command.
  Edit Command.java
package org.ungoverned.osgi.service.shell;

public interface Command {
    public String getName();
    public String getUsage();
    public String getShortDescription();
    public void execute(String line, PrintStream out, PrintStream err);
}
Par exemple, la commande run fourni par le bundle http://www-adele.imag.fr/~donsez/dev/osgi/scriptcmd/readme.html lance un train (batch) de commandes regroupées dans un fichier.
La commande waitfor permet de bloquer l'exécution du script jusqu'à la disponibilité du service fourni, d'un package exportée, d'une classe exportée, d'un serveur disponible, ... (elle s'inspire de la tâche waitfor de ANT)
  Console
-> obr start "Service Binder"
-> start http://www-adele.imag.fr/~donsez/dev/osgi/scriptcmd/scriptcmd.jar
-> services -a
...
-> start http://www-adele.imag.fr/~donsez/dev/osgi/scriptcmd/scriptcmd.jar
-> run -help
-> run -s -e -p http://www-adele.imag.fr/~donsez/dev/osgi/script/testruncmd.txt
-> run file:Z:osgi\script\testruncmd.txt

-> waitfor service -timeout 10 (objectClass=org.ungoverned.*)
a service matching (objectClass=org.ungoverned.*) is available
-> waitfor service -timeout 10 (objectClass=foo.*)
no service matching (objectClass=foo.*) are available after a 10 seconds wait
-> waitfor class -timeout 10 fr.imag.adele.bundle.hello.HelloService
class fr.imag.adele.bundle.hello.HelloService is available
-> waitfor class -timeout 10 foo.Bar
class foo.Bar is not available after a 10 seconds wait
-> waitfor bundle -timeout 10 4 STOP
-> waitfor package -timeout 10 toto
-> waitfor socket -timeout 60 localhost 8080 5
-> waitfor url -timeout 60 http://www-adele.imag.fr/~donsez/ 1
...
Vous pouvez vous reportez à la documentation d'OSCAR : http://oscar.objectweb.org/usage.html.

OBR (Oscar Bundle Repository)

OBR est un bundle qui offre une service de déploiement automatique d'un bundle et de ses dépendances. Les dépendances actuellement prises en compte par ce service sont les dépendances de code exprimées par les attributs Export-Package et Import-Package des fichiers Manifest des bundles.
Pour fonctionner, ce service utilise un index des bundles disponibles avec leurs attributs. Par défaut, cet index est à l'URL suivante (http://oscar-osgi.sourceforge.net/repo/repository.xml) mais il peut être changé ou complété au moyen de l'option urls
La commande obr dispose de plusieurs options:


La commande obrx complète les options de la commande obr pour utiliser des filtres LDAP sur les métadonnées des entrées de l'OBR : Cette commande est fournit par le bundle http://www-adele.imag.fr/~donsez/dev/osgi/obrextra/readme.html

Voici quelles exemples de commandes
  Console
-> obr start "Service Binder"
-> start http://www-adele.imag.fr/~donsez/dev/osgi/obrextra/obrextra.jar

-> obr list
liste les bundles disponibles

-> obr info "Log Service" "Http Service"
affiche les attributs (renseigné dans l'index) des deux bundles
"Log Service" et "Http Service" disponibles

-> obr install "Log Service";1.0.0
-> obrx finstall (&(bundle-name=Log Service)(bundle-version=1.0.0))
install le bundle "Log Service" dans sa version 1.0.0

-> obr list http
-> obrx flist (bundle-name=*HTTP*)
liste tous les bundles dont le nom contient la chaîne HTTP

-> obrx flist (bundle-srcurl=*)
liste tous les bundles dont l'attribut Bundle-SrcURL existe

-> obrx finfo (&(bundle-name=*HTTP*)(bundle-url=http://oscar-osgi.sf.net/*))
liste tous les bundles dont le nom contient la chaîne HTTP
et hébergé sur le site http://oscar-osgi.sf.net/

-> obrx finstall (bundle-category=Shell)
installe tous les bundles dont l'attribut bundle-category contient "Shell"
(pratique pour installer les commandes supplémentaires)

-> obrx finstall -nodeps (bundle-name=HTTP Service)
installe le bundle "HTTP Service" sans ces dependances

-> obr urls http://www.knopflerfish.org/repo/repository.xml
permet de changer de bundle repository

-> obr urls http://oscar-osgi.sourceforge.net/repo/repository.xml http://www.knopflerfish.org/repo/repository.xml http://www-adele.imag.fr/~donsez/dev/osgi/bundlerepository.xml
permet d'utiliser simultanément plusieurs bundle repositories 

Accès par la console locale et graphique de la passerelle

OSCAR dispose d'une console graphique pour lister les bundles installés et les administrer

Shell GUI - Bundle List plugin

Shell GUI - OBR plugin

Cette console requiert l'installation et le démarrage des 3 bundles suivants en plus du Shell Service (file:bundle\shell.jar) qui est déjà installé
  Console
-> install file:bundle\tablelayout.jar
-> start file:bundle\shellgui.jar
-> start file:bundle\shellplugin.jar
->

Il est aussi possible d'utiliser la console d'administration de Knopflerfish en lançant les commandes suivantes:
  Console
-> obr urls http://www.knopflerfish.org/repo/repository.xml
-> obr start "CM desktop"
...
-> 

KF Console

Console pour PDA

Si OSCAR tourne sur un PDA (un peu puissant sur Windows CE ou Linux Familiar), la console de contrôle sera plutôt la Tiny GUI dont vous pouvez voir un aperçu sur PC en lançant les commandes suivantes:
  Console
-> obr start "Tiny Shell Component"
-> obr start "Tiny Shell GUI"
-> 

Tiny GUI Console (on PC)    Tiny GUI Console (on PDA)

Comme il est difficile de rentrer des lignes de commandes sur votre PDA, vous pouvez pré-configurer le lancement de la Tiny Shell GUI au démarrage d'OSCAR en suivant les instructions suivantes.

Accès par la console distante (Telnet) de la passerelle

Généralement, une passerelle OSGi se trouve enfouie dans un equipement dépourvu de clavier et d'écran (comme par exemple, une station météo, une voiture, une centrale de surveillance dans votre maison secondaire, ...)
Il est donc nécessaire de pouvoir opérer celle-çi à distance. Pour cela, il est possible d'installer des consoles distantes d'accès comme Telnet ou Http.
Pour la console Telnet, vous devez au préalable configurer le fichier lib/bundle.properties d'OSCAR pour autoriser les accès par telnet en y ajoutant la ligne:

osgi.shell.telnet=on

Pensez à redémarrer OSCAR pour qu'il tienne compte de vos modifications.
Vous pouvez vous reportez à la documentation http://oscar-osgi.sourceforge.net/repo/telnetd/
  Console
-> obr start "Telnet Service"
Starting Telnet Service...
[19/nov./2004:02:25:50 CET] Listening to Port 6623 with a connectivity queue size of 5.
-> ps
START LEVEL 1
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (1.0.4)
[   1] [Active     ] [    1] Shell Service (1.0.0)
[   2] [Active     ] [    1] Shell TUI (1.0.0)
[   3] [Active     ] [    1] Table Layout (1.0.0)
[   4] [Active     ] [    1] Shell GUI (1.0.0)
[   5] [Active     ] [    1] Shell Plugin (1.0.2)
[   6] [Active     ] [    1] Bundle Repository (1.1.2)
[   7] [Active     ] [    1] Script Commands Bundle (0.2.0)
[   8] [Active     ] [    1] telnetd (1.0.0)
->
[19/nov./2004:02:27:18 CET] connection #1 made.
->

Ouvrez un client Telnet (telnet ou PuTTY par exemple) avec l'adresse IP ou DNS de la passerelle (localhost si la passerelle est locale) sur le port 6623 et choisissez le shell d'OSCAR:
  Telnet (host:ogw-56728.mycomp.com port:6623)
Welcome to the SoftSell OSGI Telnet Server

Available Services:

Oscar
Enter Choice> entrez Oscar

-> ps
...

Atention, l'accès par Telnet doit être sécurisé (par SSH par exemple) quand la passerelle est dans son environnement de production. Un bundle SSHD est en cours d'écriture par la communauté autour d'OSCAR.
Question: quels sont les risques potentiels si la liaison n'est pas sécurisée ?
Si vous ne trouvez pas la reponse, amusez vous à vous connectez sur la console de votre voisin et entrez la commande shutdown ! (ca y est, la centrale de surveillance de l'entreprise est arrêtée !, ...)

Accès distant à l'administration de la passerelle depuis un navigateur Web

Une autre manière d'administrer la passerelle à distance est d'utiliser un navigateur Web. Lancez la commande suivante:
  Console
-> obr start "Http Admin"
Starting dependency Servlet...
Starting dependency HTTP Service...
17:59:23.865 EVENT  Starting Jetty/4.2.x
17:59:23.985 EVENT  Started SocketListener on 0.0.0.0:80
17:59:23.995 EVENT  Started org.mortbay.http.HttpServer@1bca5f1
Starting HTTP Admin...
17:59:25.487 EVENT  Started ServletHttpContext[/]
17:59:25.517 EVENT  Started HttpContext[/admin/resource]
-> ps
->
Puis browsez l'URL http://localhost:80/admin

Remarque: il est possible que le serveur HTTP ne puisse pas obtenir le port 80 (parce qu'il est déjà pris ou que le processus n'est pas autorisé à le prendre: vous pouvez le vérifier quel est le processus qui utilise ce port avec la commande Windows netstat -ano) : il faut alors changer la configuration du serveur HTTP en lui affectant un autre numéro de port. Pour cela, ajoutez la propriété org.osgi.service.http.port=8080 dans lib\bundle.properties puis browsez l'URL http://localhost:8080/admin
Attention (même remarque), l'accès par HTTP doit être sécurisé (avec HTTPS "HTTP over SSL" par exemple) et l'opérateur doit être authentifié (username/password, certificat,...) quand la passerelle est dans son environnement de production.
Pour faire cela, suivez les instructions présentes dans la documentation du bundle "Http Service" d'OSCAR puis accédez à la console sécurisé en browsant l'URL https://localhost:443/admin

Configuration initiale d'OSCAR

A rédiger
Il est possible de modifier la liste des bundles à lancer à l'initialisation d'un profile d'OSCAR.
Pour cela, consultez la documentation
Puis créez le fichier suivant:
  Edit mysystem.properties
oscar.auto.start=file:z:/osgi/oscar1.0.4/bundle/shell.jar \
	file:z:/osgi/oscar1.0.4/bundle/tablelayout.jar \
	file:z:/osgi/oscar1.0.4/bundle/shellgui.jar \
	file:z:/osgi/oscar1.0.4/bundle/shellcomponent.jar \
	file:z:/osgi/oscar1.0.4/bundle/bundlerepository.jar
oscar.profile.name=myprofile
oscar.profile.dir=myprofiledir
oscar.bundle.properties=mybundle.properties
Et lancez OSCAR:
  Console
> set %OSCAR_HOME%=z:\osgi\oscar1.0.4
> %JAVA_HOME%\bin\java -Doscar.system.properties=mysystem.properties -jar %OSCAR_HOME%\lib\oscar.jar

Welcome to Oscar.
=================

OSCAR sous Windows CE

OSCAR fonctionne sous Windows CE. Pour cela, il faut installer une machine virtuelle Java comme la J9 d'IBM (Windows CE 4.2 (Windows M2003) sur seulement StrongARM/XScale) ou GEODE.
A rédiger

OSCAR sous Linux Familiar

OSCAR fonctionne sous Linux Familiar, une distribution de Linux adaptée aux PDA un peu costauds.

Pour cela, il faut installer une machine virtuelle Java adaptée comme la toute récente HotSpot CDC de SUN !
A rédiger

Programmation de bundles et construction d'applications dynamiques

Installation et démarrage de bundles

Nous allons installé et démarré les bundles qui compose l’application Hello World.
Cette application très simple se constitue d'un bundle HelloRequester qui requiert au moins un service HelloService pour démarrer.
Les 2 services HelloService disponibles sont configurés avec des propriétés différentes (ie language=fr et language=en)
  Edit HelloService.java
package fr.imag.adele.bundle.hello;
/**
 *@version 1.0
 */
public interface HelloService  {
	public String sayHello(String name);
}

Une fois démarré, le bundle HelloRequester demarre une thread qui invoque régulièrement la méthode sayHello() sur les services HelloService disponibles.
Les sources des 3 bundles sont disponibles sur
Lancez les commandes suivantes depuis la console:
  Console
-> install http://www-adele.imag.fr/~donsez/dev/osgi/hellorequester10/hellorequester10.jar
-> ps
-> start 4
 Question: pourquoi le démarrage du bundle 4 échoue ?
-> install http://www-adele.imag.fr/~donsez/dev/osgi/helloservice10/helloservice10.jar
-> packages
-> services
-> start 4
-> start 5
-> install http://www-adele.imag.fr/~donsez/dev/osgi/helloservice10en/helloservice10en.jar
Question: qui exporte le package requis par 4 ?
-> start 6
-> start 5
-> stop 5
-> services
Question: que s'est il passé ?
-> uninstall 5
-> ps
-> packages
Question: quel est le statut du bundle 5 après sa désintallation ?
Question: qui exporte le package requis par 4 et 6 ?
-> refresh
-> packages
Question: que produit la commande refresh ?

Versions de spécification

Les bundles OSGi indiquent la version des packages qu'ils exportent ou qu'ils importent.
Les manipulations suivantes montrent les problèmes qui peuvent subvenir.
Nous allons installé et démarré les bundles dans des versions de specifications plus recentes (1.1).
La version 1.1 de la spécification comporte une interface supplémentaire qui permet de changer la langue d'affichage du service HelloService.
  Edit LocaleService.java
package fr.imag.adele.bundle.hello;
/**
 *@version 1.1
 */
public interface LocaleService  {
	public String getLanguage();
	public void setLanguage(String language);
}

Lancez les commandes suivantes depuis la console:
  Console
-> install http://www-adele.imag.fr/~donsez/dev/osgi/helloservice11/helloservice11.jar
-> ps
Question: Quel est le statut du bundle 7 ? 
-> start 7
Question: Pourquoi le bundle 7 ne démarre t'il pas ? 
-> install http://www-adele.imag.fr/~donsez/dev/osgi/hellospec12/hellospec12.jar
Question: Quel est le statut du bundle 8 ? Pourquoi ? 
-> start 7
Question: pourquoi le bundle 7 ne démarre toujours pas ? 
-> install http://www-adele.imag.fr/~donsez/dev/osgi/hellorequester10/hellorequester10.jar
-> start 9
Question: pourquoi le bundle 8 ne démarre pas ? 
-> refresh
-> packages
Question: quel effet a eu la commande refresh ? 
Question: qui exporte le package requis par 4 ? quelle est sa version ?
-> start 7
-> start 9

Arrêtez et redémarrez la passerelle
  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: hello1

-> ps
...
-> packages
Question: qui exporte le package requis par 4 ?
-> services
...
->

Remarque: pour arrêter les traces des 2 bundles HelloRequester, arrêtez les (commande stop)

Evénements

L'installation, la mise à jour ou désinstallation de bundles, le démarrage ou l'arrêt de services provoquent des événements qui sont notifiés aux bundles qui ont positionné des listeners sur ceux-çi.
Le bundle http://www-adele.imag.fr/~donsez/dev/osgi/event/event.jar imprime la trace des événements qui sont notifiés.
Installez le puis recommencer l'installation de l'application Hello World, l'arrêt et le redémarrage puis la desintallation de bundles.

Service de Journalisation (Log)

Le service de journalisation permet de journaliser des événements se produisant au cours de la vie d'un service. Par exemple, les entrées du journal d'un serveur Web peuvent être les accès effectués sur le site servi.
Le chapître 9 de la spécification OSGi release 3 définit les 4 entités suivantes pour le service de jounalisation

Modifiez le bundle event pour qu'il puisse créer un entrée de journal pour chaque événement notifiée par le framework.
Utilisez le Log Service d'OSCAR http://oscar-osgi.sourceforge.net/repo/log/ pour tester votre bundle.

Commande hello

Nous allons compléter l'application Hello World d'une commande hello accessible depuis le shell d'OSCAR
Cette commande requière les services HelloService fournis par d'autres bundles et fournit un service org.ungoverned.osgi.service.shell.Command
Exercice: Développez le bundle HelloCommand qui fournit cette commande en repartant des sources de HelloRequester et à partir des sources de ScriptCmd
Installez ce bundle et testez le.

HelloServlet: accès par le Web

Nous allons compléter l'application Hello World d'une servlet HelloServlet activé et enregistré auprès du HttpService par le bundle http://www-adele.imag.fr/~donsez/dev/osgi/helloservlet/helloservlet.jar
Pour cela, lancez les commandes suivantes:
  Console
-> obr start "Http Service"
Starting dependency Servlet...
Starting HTTP Service...
17:59:23.865 EVENT  Starting Jetty/4.2.x
17:59:23.985 EVENT  Started SocketListener on 0.0.0.0:80
17:59:23.995 EVENT  Started org.mortbay.http.HttpServer@1bca5f1
-> ps
...
-> start http://www-adele.imag.fr/~donsez/dev/osgi/helloservlet/helloservlet.jar
...
->

Puis ouvrez un navigateur Web : http://localhost/hello/hello?css=style.css

La version actuelle de HelloServlet n'utilise pas les services HelloService fournis par d'autres bundles
Exercice: à partir des sources de HelloServlet, modifiez ceux-ci pour que la servlet utilise les services HelloService fournis par d'autres bundles

ServiceBinder

ServiceBinder permet de faciliter le développement de bundles OSGi en décrivant les services fournis et requis plutôt qu'en en programmant explicitement l'enregistrement et le courtage.
Exercice: Réécrivez les 2 bundles de HelloCommandImpl et HelloServlet avec ServiceBinder. Vous utilisez les fichiers de méta-données suivantes.
   Edit metadata.xml (hellocmd)
<?xml version="1.0" encoding="UTF-8"?>
<!--
Uncomment to check with DTD in your editor ONLY
<!DOCTYPE bundle SYSTEM "metadata.dtd">
-->

<!--
Metadata used by ServiceBinder 1.1 : http://www.humbertocervantes.net/servicebinder/jar/servicebinder1.1.jar
see the component description http://www.humbertocervantes.net/servicebinder/describingcomponents.html
-->
<!-- The author, The Date, The Version -->
<bundle>
	<component class="fr.imag.adele.bundle.hellocmdsb.impl.HelloCommandImpl">
		<!-- provided services -->
		<provides service="org.ungoverned.osgi.service.shell.Command"/>
		<!-- registration properties -->
		<property value="service.pid" id="oscar.shell.command.hello" type="string"/>
		<property value="type" id="cmd" type="string"/>
		
		<!-- required services -->
		<requires service="fr.imag.adele.bundle.hello.HelloService"
			filter="(language=*)"
			cardinality="1..n"
			policy="dynamic"
			bind-method="bindHelloService" 
			unbind-method="unbindHelloService"
		/>
	</component>
</bundle>

   Edit metadata.xml (helloservletsb)
<?xml version="1.0" encoding="UTF-8"?>
<!--
Uncomment to check with DTD in your editor ONLY
<!DOCTYPE bundle SYSTEM "metadata.dtd">
-->

<!--
Metadata used by ServiceBinder 1.1
see the component description http://www.humbertocervantes.net/servicebinder/describingcomponents.html
-->
<!-- The author, The Date, The Version -->
<bundle>
	<component class="fr.imag.adele.bundle.helloservletsb.impl.HelloServletWithSb">
		<!-- No provided services -->
		
		<!-- Required services -->
		<requires service="fr.imag.adele.bundle.hello.HelloService"
			filter="(language=*)"
			cardinality="1..n"
			policy="dynamic"
			bind-method="bindHelloService" 
			unbind-method="unbindHelloService"
		/>
		
		<requires service="org.osgi.service.http.HttpService"
			filter="" 
			cardinality="1..1"
			policy="static"
			bind-method="bindHttpService" 
			unbind-method="unbindHttpService"
		/>

		<requires service="org.osgi.service.log.LogService"
			filter="" 
			cardinality="0..1"
			policy="dynamic"
			bind-method="bindLogService" 
			unbind-method="unbindLogService"
		/>
		
	</component>
</bundle>

le code des méthodes de gestion des liaisons est :
   Edit HelloServletWithSb
public class HelloServletWithSb ...
{
    // callback methods for <requires service="fr.imag.adele.bundle.hello.HelloService" ...
    private ArrayList helloServices = new ArrayList();
    
    public void bindHelloService(HelloService ref){
        synchronized (helloServices){
            helloServices.add(ref);
        }
    }

    public void unbindHelloService(HelloService ref){
        synchronized (helloServices){
            helloServices.remove(ref);
        }
    }
    
    // callback methods for <requires service="org.osgi.service.http.HttpService" ...
    private HttpService httpService = null;
    private Servlet myServlet; // initialized in constructor
    private Dictionary myServletInitParams; // initialized in constructor
    private HttpContext myHttpContext; // initialized in constructor

    public void bindHttpService(HttpService ref){
	httpService=ref;
    	httpService.registerServlet(SERVLET_ALIAS, myServlet, myServletInitParams, myHttpContext);
	httpService.registerResources(WEBROOT_ALIAS, WEBROOT, myHttpContext );
    }

    public void unbindHttpService(HttpService ref){
    	httpService.unregister(SERVLET_ALIAS);
    	httpService.unregister(WEBROOT_ALIAS);
    	httpService=null;
    }

    // callback methods for <requires service="org.osgi.service.log.LogService" ...
    private LogService logService = null;

    public void bindLogService(LogService ref){
	logService=ref;
    }

    public void unbindLogService(LogService ref){
    	logService=null;
    }
    
    ...
}

Testez les en lançant les commandes suivantes:
  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: sb

-> obr start "Service Binder"
-> rem start http://www.humbertocervantes.net/servicebinder/jar/servicebinder1.1.jar
-> ps
...
-> start file:z:\osgi\mybundles\helloservletsb.jar
-> start file:z:\osgi\mybundles\hellocmdsb.jar
-> start http://www-adele.imag.fr/~donsez/dev/osgi/helloservicesb/helloservicesb.jar
...
-> obr start "Log Service"
-> obr start "Log Reader"
-> start http://www.humbertocervantes.net/servicebinder/jar/architectureviewer1.1.jar
La dernière commande lance une application graphique qui visualise les liaisons entre bundles (developpés avec ServiceBinder) qui constituent l'architecture d'une application

Service Binder

Que ce se passe t'il quand tous les services HelloService sont arrêtés ou quand le service HttpService est arrêté.
Exercice: Modifiez l'implémentation actuelle de helloservletsb.jar pour qu'elle journalise les requêtes traitées sur le service LogService quand celui-çi existe.

CronService

Le service CronService fournit par le bundle CronService permet de déclencher de façon périodique un objet implémentant l'interface TimerObject.
L'usage de ce service est documentée http://www-adele.imag.fr/~desertot/dev/osgi/cronservice/
L'exemple lancé par les commandes suivantes "cron" 2 TimerObjects (1 toutes les 10 sec., l'autre toutes les 20 sec.)
  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: cron

-> obr start "Service Binder"
Starting Service Binder...
-> start http://www-adele.imag.fr/~desertot/dev/osgi/cronservice/cronservice.jar
------------------ Cron Service activated ------------------
-> services
...
[Bundle 5, Service 0] fr.imag.cronservice.CronService
...
-> start http://www-adele.imag.fr/~desertot/dev/osgi/cronservice/crontest.jar
-> Case number one. time = Tue Apr 13 18:37:48 CEST 2004
Case number two. time = Tue Apr 13 18:37:58 CEST 2004
Case number one. time = Tue Apr 13 18:37:58 CEST 2004
Case number one. time = Tue Apr 13 18:38:08 CEST 2004
Case number two. time = Tue Apr 13 18:38:18 CEST 2004
Case number one. time = Tue Apr 13 18:38:18 CEST 2004
...

Exercice: Modifier le bundle HelloRequester pour qu’il utilise le service TimerService au lieu d'une thread

Fabrique d'instance de services

L'interface org.osgi.framework.ServiceFactory permet d'implémenter le patron de conception Fabrique (Factory de Gamma).
Cette interface comporte 2 méthodes:


La méthode getService() fabrique une instance quand le bundle demandeur invoque la méthode Object getService(ServiceReference reference) sur le bundle context.
Ainsi plusieurs différentes instances remplissent le même service pour des clients (requester) différents.
Les utilisations possibles du ServiceFactory sont:
Un exemple d'usage de ServiceFactory est le suivant: helloservice10factory avec son script d'utilisation.
Testez le
Que se passe avec les instances au moment des getService et ungetService ?

Bibliothèques Natives

A rédiger

Accès aux ressources et aux fichiers du cache

Il est possible de récuperer le contenu d'un fichier depuis le jarfile ou le cache du bundle.
Il est également possible de créer et écrire dans un fichier du cache du bundle.
La méthode java.lang.Class#getResourceAsStream(String path) permet à un bundle de récupérer le contenu d'un fichier présent dans le jarfile (ou une des jarfiles imbriqués) du bundle via son ClassLoader.
Cette méthode est très utile pour recupérer des informations de configuration du site Web ou pour exporter des ressources comme des pages Web, icones, ... (c'est ce qu'il se passe avec le HttpService !)
La méthode org.osgi.framework.BundleContext#getDataFile(String path) permet de récupérer un java.io.File sur un fichier du cache du bundle.
Cette dernière méthode est très utile pour faire persister des informations entre les arrêts/redemarrages du bundle ou du framework.
Testez le bundle rdrwrsc et son script associé
Question: pourquoi ne récupere pas t'on le fichier fileincache.txt lors de l'installation qui suit la desinstallation ?

Services avancés

WireAdmin

A rediger
Le WireAdmin est un service qui permet de construire des applications à base de capteurs (Sensor-based Services).
Les applications sont construites en reliant des services Producer avec des services Consumer par des objets appelés Wire.
Le script de commande suivant donne un exemple d'utilisation:
  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: wa

-> obr start "Service Binder"
...
-> http://www-adele.imag.fr/~donsez/dev/osgi/scriptcmd/scriptcmd.jar
-> run -e -p http://www-adele.imag.fr/~donsez/dev/osgi/script/wa.txt
...
-> start http://www.humbertocervantes.net/servicebinder/jar/architectureviewer1.1.jar
->

L'application résultante est partiellement représentée par la figure suivante:

Wire Admin Sample

Lancez un butineur Web sur http://localhost/wa/poll?css=style.css&refresh=10 pour obtenir la page suivante:
WireAdmin

WireAdminBinder

WireAdminBinder permet d'automatiser la création et les destruction des wires entre des producteurs et des consommateurs.
A rediger
Le script de commande suivant donne un exemple d'utilisation équivalent à l'application précédente.
  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: wab

-> http://www-adele.imag.fr/~donsez/dev/osgi/scriptcmd/scriptcmd.jar
-> run -e -p http://www-adele.imag.fr/~donsez/dev/osgi/script/wab.txt
...

IO Connector

A rediger
Le chapitre 13 de la release 3 de la spécification OSGi introduit un nouveau service org.osgi.service.io.ConnectionService qui est une fabrique de Connection vers des sources (input/output) externes.
Le script de commande suivant donne un exemple d'utilisation:
  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: io

-> obr start "Service Binder"
...
-> start http://www-adele.imag.fr/~donsez/dev/osgi/scriptcmd/scriptcmd.jar
-> run -e -p http://www-adele.imag.fr/~donsez/dev/osgi/script/io.txt
...
->

L'erreur est due au fait qu'il n'y a pas d'IO Connector pour le schema "mail:"

Mail IO Connector

Le bundle mailio permet d'envoyer des mails à un correspondant. Ce bundle peut être utilisé pour remonter des alarmes ou des rapports (logs, ...) vers la boite d'un opérateur.
Il fournit un service org.osgi.service.io.ConnectionFactory avec le 2 schemas : mail et mailto
Pour utiliser, le bundle http://www-adele.imag.fr/~donsez/dev/osgi/mailio/mailio.jar

  1. lisez attentivement http://www-adele.imag.fr/~donsez/dev/osgi/mailio/readme.html
  2. chargez les sources http://www-adele.imag.fr/~donsez/dev/osgi/mailio/mailio-src.jar
  3. configurez le fichier ./res/config.properties. votre serveur SMTP est ufrima.imag.fr
  4. reconstruisez votre projet avec "ant bundle"
  5. modifiez, recompilez et redémarrez testio.jar
  6. pour tester mailio.jar

Configuration avec l'interface Configurable et le ConfigurationService

A rédiger Exercice : Modifier la classe HelloServiceImpl pour qu’elle implemente aussi l’interface Configurable.
Ecrire: Ecrire un configurateur de services génériques

Configuration avec JMX

JMX (Java Management Extension) est une spécification Java pour administrer et superviser des applications Java. Initialement spécifié pour J2EE, elle est désormais dans le J2SE depuis la version 1.5.0.


Il existe plusieurs implémentations d'agents JMX pour OSGi. Ces agents permettent de superviser/administrer/configurer les bundles d'une passerelle OSGi.

JMX Agent

JMX Agent requière qu'OSCAR soit exécuté sur un JRE 1.5.
Exécutez les commandes d'installation du script jmxagent.txt.
Puis lancez depuis une autre terminal jconsole la console JMX du J2SE 1.5 ou la console JMX MC4J.
Le résultat est à peu près le suivant:
jconsole

Vous pouvez également votre agent JMX au moyen d'un navigateur Web à partir de l'url http://localhost:8000.
Remarque: le bundle AdminMBean publie un MBean qui permet de lister, installer, démarrer, arrêter, désinstaller les bundles de la passerelle.

INSA JMX

Installez et démarrez le bundle JMX à partir de l'OBR en suivant le tutoriel associé.
Installez et démarrez le bundle HelloMBean.
Téléchargez et installez la console JMX MC4J sur votre poste de travail.
Configurez à distance le bundle HelloMBean au moyen de la console MC4J.

JMood

Une implémentation alternative est JMood. Vous pouvez aussi la tester si J2SE1.5 est installé sur votre passerelle.
JMood implements OSGi remote management concepts to provide JMX based remote monitoring and control of OSGi service platforms, as well as providing a means of defining OSGi applications management model at runtime in a flexible way.
JMood provides MX4J's HTTP adaptor and RMI consoles, such as MC4J, XtremeJ or Jconsole remote access to the platform.
JMood is based in Java 5.0, in order to include its virtual machine monitoring and management capabilites.
JMood is available at os4os: http://jmood.forge.os4os.org

Shell XMLRPC pour OSGi

A rédiger

Shell SOAP pour OSGi

A rédiger

Serveur CORBA pour OSGi

CORBA (Common Object Request Broker Architecture) est un intergiciel de communication pour des objets répartis sur des plateformes hétérogènes (Windows, Unix) et pour des langages hétèrogènes (Java, C++, ADA, ... (voir même C# sur .NET)). Il existe de nombreuses implémentations dont celle de SUN (écrite en Java) qui est intégré au JDK.
Grâce au bundle Corba Service, un bundle peut enregistrer un objet pour le rendre accessible à distance à la manière du Http Service d'OSGi.
Le bundle de test Corba Service Test présente un exemple d'invocation à distance de ce service.
Si vous n'êtes pas familier de CORBA, vous trouverez un tutoriel sur CORBA ici.

JINI Device Driver

A rédiger

Un exemple d'usage de "JINI Device Driver" est présenté dans le script suivant.
Testez le

UPnP Device Driver

Universal Plug aNd Play (UPnP) Device Architecture (DA) spécifie les protocoles pour des réseaux spontanés des périphériques (devices). UPnP DA couvre aussi bien les périphiques des domaines comme la micro-informatique/burautique (imprimantes, appariel-photo, ...), l'électronique grand public (DVD, TV, radio, Media-Center, ...), la communication (téléphones, routeur ADSL, ...), la domotique (alarme anti intrusion, régulation du chauffage, ...) ou bien encore l'électro-menager (lave-linge, réfrigérateur, ...).
UPnP DA spécifie comment les périphériques joignent le réseau, comment sont ils découvert, et comment sont ils contrôlés au moyen de messages SOAP/HTTP. Contraitement à JINI, UPnP n'est pas lié à Java et les protocoles d'UPnP sont basés sur SOAP, HTTP, TCP, UDP, UDP Multicast.
La spécification "UPnP Device Driver" d'OSGi (R3 chapître 25) spécifie comment les bundles OSGi peuvent être développés pour intéropérer avec des périphériques UPnP et leurs points de contrôle (control point).

La démonstration comporte 3 instances d'OSCAR (ssdp, upnp1, upnp2) qui hébergent respectivement:

  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: ssdp

-> obr start "Service Binder"
...
-> start http://www-adele.imag.fr/~donsez/dev/osgi/upnpssdptrace/upnpssdptrace.jar
...
->

  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: upnp1

-> obr start "DomoWare UPnP Base Driver"
-> obr start "UPnP Control Point"
-> obr start "UPnP Clock Device"
...
-> services
...
->

  Console
> oscar

Welcome to Oscar.
=================

Enter profile name: upnp2

-> obr start "UPnP Standard Binary Light"
-> obr start "UPnP TV Device"
-> start http://www-adele.imag.fr/~donsez/dev/osgi/upnpthermometer/upnpthermometer.jar
-> obr start "DomoWare UPnP Base Driver"
...
-> services
...
->

Le resultat est à peu près le suivant sur une station de travail :

UPnP Device Driver Sample

Le resultat est à peu près le suivant sur un PDA (tournant OSCAR) :

Tiny UPnP Control Point (Device List Panel) Tiny UPnP Control Point (Thermometer Panel) Tiny UPnP Control Point (WebCam Panel)

Quelques explications:
UPnP Base Driver a 2 rôles. Premièrement, il exporte les services org.osgi.service.upnp.UPnPDevice à l'extérieur de la passerelle.
Deuxièmenent, UPnP Base Driver instancie un service org.osgi.service.upnp.UPnPDevice pour chaque device découvert sur le réseau UPnP.


Pour plus d'information, vous pouvez consulter la documentation Domoware:

Les commandes de cet exemple d'usage de "UPnP Device Driver" sont présentées dans le script suivant.
Listez les services fournis par les bundles.

Remarque 1
Le bundle UPnP Generated Device contient plusieurs devices générés automatiquement à partir des spécifications de devices et services standardisés par l'UPnP Forum. Vous pouvez vous appuyer dessus pour générer vos propres devices

Remarque 2
Si le framework .NET (1.1 et + ) est installé sur votre machine, il est fortement recommandé d'utiliser les outils UPnP d'Intel

Intel Device Sniffer for UPnP Technologies Intel Device Explorer for UPnP Technologies
Les outils d'Intel sont téléchargeables sur le site http://www.intel.com/technology/upnp/index.htm.
Il existe également d'autres Toolkits fournis par Siemens, MicroSoft, ...

User Admin

A rédiger

Permission pour MailIO

Le mécanisme des permissions en Java a pour objet de contrôler l'accès à une ressource (fichier, periphérique, ...) en fonction de l'origine du programme qui s'exécute et/ou de l'identité/rôle de l'utilisateur qui le lance.
Dans une passerelle OSGi, ce mécanisme sert à contrôler l'accès aux services du bundle ou à des ressources par les autres bundles.
A rédiger

Extra sur OSGi

Envoi d'un train de commandes par Telnet avec ANT

A rédiger
Modifiez votre configuration d'OSCAR (mysystem.properties) pour que le bundle Telnet soit lancer au démarrage
Utilisez des scripts de la forme suivante:"ant -f build.telnetinstaller.xml" pour automatiser l'installation d'une suite de bundles sur un grand nombre de passerelles

Il est possible de générer automatiquement le build.xml à partir d'une description XML des commandes à lancer au moyen de la feuille XSL-T.
La génération est produite par la commande "ant -f build.script.xml". Le build.xml produit fonctionne également avec SSH et le bundle HTTP Admin du OSCAR Bundle Repository

Test unitaire des services offerts par des bundles déployés avec JUnit

JUnit est un canevas pour développer des tests unitaires très répandu dans la communauté des développeurs Java.
Il peut être appliqué également au test unitaire des services offerts par des bundles déployés sur une passerelle grâce au bundle junit qui conditionne le canevas JUnit.
Vous pouvez tester une démonstration de ce bundle au moyen du script disponible ici.
Exercice: Ecrire un bundle de test pour tester le service HelloService.

Banc de performances (benchmark) de services

A rédiger
Voir le script suivant

Mini-Projets sur OSGi

Pour le développement de vos bundles, vous utiliserez le projet ANT http://www-adele.imag.fr/~donsez/dev/osgi/__BUNDLE_NAME__/__BUNDLE_NAME__-src.jar
Il vous suffit :

Exercice: Mail IO Connector et Commande

Développez une commande Shell mail permettant d'envoyer un mail depuis la console.
Vous vous baserez sur smscmd.jar
Vous utiliserez mailio.jar

Exercice: Mail IO Connector et Servlet

Développez un bundle IOServlet qui permette entre autre d'envoyer des mails ou des sms en passant par le service IOCOnnector
Vous reparti de smsservlet, ecrire une Servlet permettant d'ecrire dans un outputstream
Tester le avec mailio.jar depuis une page Web

Exercice: Mail IO Connector et Cron Service et Consumer

Développez un bundle MailConsumer qui fournit un service Consumer envoyant par mail un historique des mesures qui ont été poussées par des producers sur les Wires.
L'envoi est effectuée périodiquement par le bundle CronService précedenment utilisé.
Vous utiliserez mailio.jar

Exercice: Service de Journalisation (Log) et Mailio et CronService

Développez un bundle qui envoyer regulièrement les entrées d'un journal (log) par mail à un opérateur. Les entrées sont conversées de manière persistante dans un fichier du cache du bundle.

Exercice: WMA (JSR 120)

A rédiger

Exercice: Mail multimedia

Developpez un bundle qui envoie par mail une image capturée depuis la WebCam connectée à la passerelle. Vous vous baserez sur l'exemple WireAdmin.

Exercice: Usage Producer

(Sur Unix/Linux) A partir de l'exemple FreeVmMemProducer, écrire un producer qui remonte les informations sur le système en exploitant les données des fichier du répertoire /proc.
/proc est un système de fichiers très spécial puisqu'il contient des informations (lecture/écriture)

Cependant, sa structure peut variée d'un Unix à l'autre. Vous trouverez plus d'info sur /proc de votre système en utilisant la documentation (man proc) ou sur plusieurs sites Web comme Linux Forum, Die.Net, ...

Exercice: HistoryPortal

A partir de ConsumerServlet et StringConsumer, afficher l'historique des valeurs capturées sur des producers (Measurement, Usage, ...)
Pour cela, il est nécessaire de "poller" régulièrement les Producers (comme le fait StringConsumer) et d'historiser les valeurs "pollées".
Le nombre de valeurs à conserver dans l'historique est paramétrable.
Le fréquence du polling est paramétrable.
Pour l'affichage, vous utiliserez le grapheur JavaScript suivant: http://www-adele.imag.fr/~donsez/cours/exemplescourstechnoweb/js_graphimg/ ou les "plotters" de ce site.

Exercice: Ajout du commande au Shell

Ecrire une commande Shell cron permettant de déclencher de façon périodique n'importe quel service désigné par un filtre
Les informations concernant le fonctionnement du Shell sont disponibles sur http://oscar-osgi.sourceforge.net/shell.html

Exercice: Ajout d'un composant Shutdown à la console ShellGUI

Ajoutez un composant graphique à la console ShellGUI qui permet d'arrêter la passerelle (shutdown) soit immédiatement, soit au décompte d'un chronomêtre (de la forme de l'applet Clock fourni dans les exemples du JDK).

Exercice: Ajout d'un composant Script à la console ShellGUI

Ajoutez un composant graphique à la console ShellGUI qui permet de charger un script existant, de l'éditer puis de l'exécuter. Cette dernière opération est équivalente à la commande run

Exercice: Ajout d'un composant Cron à la console ShellGUI

Ajoutez un composant graphique à la console ShellGUI qui permet d'enregistrer et de superviser (affichage temps restant, supprimer, modifier, ajouter, ...) des déclenchements de services. Cette dernière opération est équivalente à la commande cron

Exercice: Commande MBean

Développez une commande Shell mbean permettant

Exercice: Commande JINI

Développez une commande Shell jini permettant

Exercice: Commande UPnP

Développez une commande Shell upnp permettant

Exercice: UPnPEventLogger

Développez un UPnPEventListener UPnPEventLogger qui jounalise avec le LogService les événements UPnP. Conseil : Utilisez ServiceBinder.
Ajoutez ensuite une interface UPnPEventListenerMBean (setUpnpFilter/getUpnpFilter) à cet UPnPEventLogger pour permettre la reconfiguration dynamique de la propriété d'enregistrement (upnp.filter) du service.

Exercice: UPnP Toaster (Grille-Pain)

A partir des sources des bundles de la démonstration UPnP de DomoWare, développez un bundle upnptoaster qui simule un grille-pain (toaster en anglais) qui a les fonctionnalités suivantes :

Exercice: UPnP Camera (Appareil-Photo)

A partir des sources du bundle UPnP-TV de la démonstration UPnP de DomoWare et de bundle WebcamProducer, développez un bundle upnpcamera qui pilote une vrai WebCam pour offrir les fonctionnalités suivantes :

Exercice: UPnP GPS Receiver

A partir des sources du bundle "Generated UPnP Device", développez un bundle UPnP Device qui retourne des positions GPS (lattitude, longitude, altitude, date, vitesse et cap).
Pour cela, vous proposerez une desciption XML du device et de ses services associés (ie SCDP), puis vous générerez et compléterez les classes d'implementation.
Vous écrirez ensuite un composant de visualisation d'un tel dévice pour le "Tiny UPnP Control Point".

Exercice: Telecommande universelle UPnP sur PDA

Développez une télécommande universelle UPnP avec une IHM adaptée à un PDA (WiFi par exemple) pour contrôler des devices UPnP exposés sur le réseau.
Chaque interface de contrôle d'un type de device (téléviseur, lampe, ...) sera gérée comme un plugin de cette télécommande
Ce bundle est fonctionnellement simimaire au bundle "UPnP Control Point" vu plus haut.
Ce bundle devra s'insérer dans le "Tiny Shell GUI" qui est la console d'OSCAR pour PDA et qui n'utilise que l'AWT.
  Console
-> obr start "Tiny Shell Component"
-> obr start "Tiny Shell GUI"
-> services
...
->

Ce bundle permet:


Par exemple, l'IHM de la télécommande d'un téléviseur permet de l'allumer et de l'arrêter de changer de chaîne, de baisser/monter le volume.

Exercice : CurrencyConvertorService et commande associée

A rédiger

Exercice : Motion Detector

Développez une bundle MotionDetector qui détecte des mouvements dans les images capturées par une WebCam.
Ce bundle utilise les bibliothéques de fonctions natives présentes dans http://motion.sourceforge.net/.
Ce bundle récupère les images produites par le bundle http://www-adele.imag.fr/~donsez/dev/osgi/webcamproducer/readme.html puis produit des images modifiées et des org.osgi.util.measurement.State (voir la section 20.6 de la spécification 3 d'OSGi).

Annexes

Ressources sur OSGi

Cours et tutorials:

Les plateformes OSGi disponibles:

Autres Ressources