Nicolas Mérat - Centre Universitaire d`Informatique

Transcription

Nicolas Mérat - Centre Universitaire d`Informatique
Nicolas Mérat
Professeur G. Falquet
automne 2001
Département de Système d’Information
Stockage de
données multimédias
et conception de
présentations
dynamiques avec
SMIL et Lazy
Table de matières
1.
Introduction..................................................................................................................... 4
2.
Objectifs du travail .......................................................................................................... 4
3.
Outils utilisés .................................................................................................................. 5
3.1 SMIL (Synchronized Multimedia Integration Language) ............................................... 5
3.1.1 Généralités ............................................................................................................ 5
3.1.2 Caractéristiques..................................................................................................... 6
3.1.3 Structure d’un document SMIL............................................................................... 6
3.1.4 Les principaux players SMIL .................................................................................. 9
3.2 Oracle et les LOBs ..................................................................................................... 10
3.2.1 Généralités .......................................................................................................... 10
3.2.2 Le type BLOB ...................................................................................................... 10
3.2.3 Le type BFILE ...................................................................................................... 11
3.2.4 Manipulation de BLOB ......................................................................................... 11
3.2.4.1 Fonctionnement du type BLOB...................................................................... 11
3.2.4.2 Exemple de création de table contenant le type BLOB.................................. 12
3.2.4.3 Exemple d’initialisation et d’écriture d’un BLOB............................................. 12
3.2.4.4 Exemple de lecture d’un BLOB...................................................................... 13
3.2.5 Manipulation de BFILE......................................................................................... 14
3.2.5.1 Fonctionnement du type BFILE ..................................................................... 14
3.2.5.2 Exemple de création de table contenant le type BFILE ................................. 15
3.2.5.3 Exemple de création de répertoire................................................................. 15
3.2.5.4 Exemple de création d’un BFILE ................................................................... 15
3.2.5.6 Exemple de lecture d’un BFILE ..................................................................... 16
3.3 Servlet........................................................................................................................ 17
3.3.1 Généralités .......................................................................................................... 17
3.3.2 Servlet et formulaire............................................................................................. 18
3.3.3 Structure d’un servlet ........................................................................................... 18
3.3.4 Exemple d’utilisation de servlet ............................................................................ 19
3.4 Lazy ........................................................................................................................... 19
3.4.1 Généralités .......................................................................................................... 19
3.4.2 Fonctionnement ................................................................................................... 20
3.4.3 Création de nœuds .............................................................................................. 20
4.
Solution ........................................................................................................................ 22
4.1 Choix du domaine ...................................................................................................... 22
4.2 Modélisation du domaine ........................................................................................... 23
4.2.1 Modèle relationnel ............................................................................................... 24
4.3 Liste des relations et création des différentes tables .................................................. 25
2
4.4 Insertion des données dans la base de données........................................................ 25
4.5 Conception d’un servlet pour la récupération des données ........................................ 26
4.5.1 Installation d’un serveur HTTP............................................................................. 26
4.5.2 Création du formulaire ......................................................................................... 26
4.5.3 Elaboration du servlet .......................................................................................... 27
4.5.4 Modification du fichier web.xml ............................................................................ 30
4.5.5 Vue d’ensemble ................................................................................................... 31
4.5.6 Exemple de requête............................................................................................. 31
4.6 Choix d’un player ....................................................................................................... 31
4.6.1 HTML+TIME ........................................................................................................ 32
4.6.1.1 Structure d’un document HTML+TIME .......................................................... 32
4.6.2 RealONE ............................................................................................................. 33
4.7 Installation de Lazy..................................................................................................... 33
4.8 Conception de nœuds SMIL en Lazy.......................................................................... 34
4.8.1 Modification du serveur de nœuds ....................................................................... 34
4.8.2 Conception de nœuds SMIL ................................................................................ 35
4.9 Présentation finale ..................................................................................................... 35
4.9.1 Détails des nœuds créés ..................................................................................... 35
4.9.2 Problèmes rencontrés.......................................................................................... 36
5.
Conclusion.................................................................................................................... 36
6.
Bibliographie................................................................................................................. 37
7.
Annexes ....................................................................................................................... 38
3
1. Introduction
Au cours de ces dernières années, il y a eu une prise de conscience générale du besoin et
de l’utilité des technologies multimédias, ceci dans de nombreux domaines, comme la
médecine et l’éducation. En effet, le multimédia améliore la qualité de l’information et fournit
un meilleur moyen de la représenter et d’interagir avec elle. Ainsi, les applications
multimédias enrichissent les applications existantes en intégrant des images, du son, ou
encore de la vidéo. Ces différents types de données et leur manipulation apportent de
nouveaux défis : par exemple, les bases de données doivent être remises à jour pour
supporter ces différents types ; de même, les réseaux doivent réévaluer leurs besoins pour
des bandes passantes plus flexibles et plus larges, et on peut par exemple voir l’importance
du multimédia avec l’apparition de réseaux à large bande comme ATM, ISDN, ou encore
ADSL.
Je vais m’intéresser, dans un premier temps, au stockage de ces données multimédias. Les
exigences de stockage sont élevées, et il est inconcevable de stocker toutes ces données
localement. Ainsi, les bases de données multimédias offre une possibilité de stockage, mais
aussi de partage et d’interrogation de ces différentes informations. Elles permettent de
manipuler des données de type texte, image, son, vidéo, contrairement aux bases de
données traditionnelles qui permettent seulement de manipuler des données numériques et
des caractères. Ainsi, des fonctionnalités ont du être ajoutées dans les systèmes de gestion
de base de données afin de permettre le stockage pour ces données qui peuvent être de
taille considérable. De même, il a fallu étendre les langages d’interrogation comme SQL qui
n’étaient pas appropriés pour les flux continus qui surviennent lors de la manipulation de
données multimédias.
Ensuite, je vais m’intéresser à la conception de présentations dynamiques à partir de
données stockées dans une base de données multimédia. En effet, nombreuses sont les
sources d’intérêt dans la création de présentations multimédias, comme par exemple les
livres électroniques, les cours à distances ou encore les pages webs dynamiques ; de ce fait,
plusieurs modèles et standards correspondant à ces besoins apparaissent, permettant de
répondre à des questions du type : quels objets doivent être inclus dans la présentation ? à
quel moment les objets doivent-ils être affichés ? où doivent apparaître les objets sur
l’écran ?
2. Objectifs du travail
L’ objectif final du travail est de pouvoir créer des présentations SMIL dynamiques à partir de
diverses données multimédias – photos, vidéos, sons, textes – stockés dans une base de
données, à l’aide du langage Lazy. Ces présentations doivent pouvoir interagir entre elles ;
l’utilisateur doit pouvoir se « promener » dans l’information en suivant les liens qui
l’intéressent.
Différentes étapes intermédiaires sont nécessaires pour en arriver là, parmi lesquelles :
•
Comprendre SMIL et apprendre à utiliser ce langage
•
Trouver le(s) type(s) de donnée adéquat pour stocker des données multimédias dans
une base de données
4
•
Établir une connexion JDBC avec la base de données
•
Tester le(s) type(s) de données trouvé(s) pour le stockage des données multimédias, au
moyen de JDBC
•
Stocker des données multimédias de manière « automatique » à partir de leur répertoire
•
Étudier les servlets afin d’un concevoir un permettant de récupérer une donnée
multimédia et de l’envoyer sur le navigateur client
•
Comprendre Lazy et apprendre à utiliser ce langage (savoir créer des nœuds)
•
Trouver un domaine pour concevoir un exemple de présentation multimédia, ainsi que
des données (photos, images, vidéos, sons) le concernant
•
Définir le modèle relationnel pour l’exemple de présentation : quelle(s) relation(s) et
quel(s) attribut(s) choisir
•
Créer les différentes tables (d’après le modèle relationnel)
3. Outils utilisés
3.1 SMIL (Synchronized Multimedia Integration Language)
3.1.1 Généralités
Une présentation multimédia est composé dans l’espace et dans le temps d’objets euxmêmes mono ou multimédias qui peuvent être de type continu (temporel) comme le son ou
la vidéo ou de type discret (non temporel) comme l’image et le texte. Lors de la conception
de la présentation vont se poser des problèmes de synchronisation entre les différents
médias, et de prise en compte des dépendances spatio-temporelles. En effet, comment
définir quel vidéo A doit se jouer à la suite de telle autre vidéo B, et à tel endroit dans la
fenêtre de présentation ? Ou encore, comment définir qu’une séquence vidéo C doit
commencer en même temps qu’un commentaire D ?
C’est à ce genre de questions qu’ont tenté de répondre les membres du W3C (consortium
mondial regroupant des industriels et des centres de recherche, dont l'objectif est de
développer et promouvoir le Web) en proposant un format de documents multimédia nommé
SMIL (Synchronized Multimedia Integration Language). L'objectif de ce format est de
permettre à toute personne de spécifier les aspects temporels et visuels de documents
multimédias tout en permettant à l’utilisateur d’interagir avec la présentation au moyen de
liens hypertextes. On peut voir ce langage comme une extension du standard HTML (SMIL
est un langage de balisage basé sur XML), qui permet de résoudre le problème de
coordination et de synchronisation dans l’affichage de différents médias sur des sites webs,
en utilisant une seule ligne temporelle. Du fait qu’elle est basée sur un langage de balisage,
une présentation SMIL peut être créée avec un simple éditeur de texte pour tout outil.
5
3.1.2 Caractéristiques
Une présentation SMIL possède les caractéristiques suivantes :
•
La présentation est composée de un ou plusieurs objets multimédias accessibles au
moyen d’un URL ; les objets ne sont donc pas physiquement insérés dans le document
SMIL et peuvent être de différents types de médias (son, vidéo, image, texte, animation).
Ainsi, les composants peuvent être indépendants et se trouver sur différents serveurs
webs (ils ne sont récupérés par l’application que lors de son exécution) ce qui permet de
diviser le contenu multimédia en flux et fichiers séparés et de les jouer comme un seul et
unique flux multimédia. De ce fait, la taille d’une présentation SMIL est assez réduite.
•
On peut définir le placement temporel ainsi que le placement géométrique des objets
multimédias. On peut par exemple définir le temps de début et le temps de fin d’un
média, ou encore sa durée. On peut également définir la présentation parallèle de deux
ou plusieurs médias, ou la présentation en séquence. Un document SMIL possède une
seule horloge pour tous ses composants, une seule ligne temporelle.
•
On peut associer des liens hypertextes aux différents composants multimédias ;
l’utilisateur pourra donc suivre les liens placés dans la présentation et interagir avec cette
présentation par le biais des liens proposés. Ainsi, deux utilisateurs visualisant la même
présentation, et n’ayant pas les mêmes centres d’intérêt, pourront accéder aux
informations qui les intéressent en suivant simplement les liens qui les concernent.
•
SMIL permet d’afficher le média selon les préférences de l’utilisateur et les capacités de
son système. Il adapte donc la présentation à la bande passante de l’utilisateur, et à ses
préférences linguistiques. Par exemple, l’auteur d’une présentation SMIL pourra indiquer
quel fichier vidéo jouer selon la bande passante de l’utilisateur : « si la bande est
supérieure à 56 kbits/s jouer zzz, sinon jouer xxx ».
•
La production d’une présentation multimédia avec SMIL ne requiert aucune compétence
particulière en programmation. C’est un langage facile à apprendre, et pour créer et
modifier des présentations multimédias, un simple éditeur de texte suffit.
•
SMIL utilise la technologie du streaming, c’est à dire qu’un média commence à être jouer
sans avoir à attendre le téléchargement complet du fichier. Ainsi, par exemple, une
application commence à jouer un son avant même qu’elle ait chargé la totalité du fichier.
Cependant cette technique n’est possible que si le serveur web utilisé repose sur un
protocole RSTP (Real-time Stream Transport Protocol), et non HTTP.
3.1.3 Structure d’un document SMIL
Un document SMIL a pour racine l’élément <smil>, et se compose d’une en-tête et d’un
corps. La partie <head> contient toutes les informations descriptives et relatives à la mise en
page, alors que la partie <body> contient le corps du document, les informations sur les
médias et sur leur comportement, la partie dynamique de la présentation. La structure type
d’un document SMIL ressemble à ceci :
<smil>
<head>
<meta/>
6
<layout>
<root-layout/>
<region/>
</layout>
</head>
<body>
<switch> … </switch>
<par> … </par>
<seq> … </seq>
</body>
</smil>
A l’intérieur de la section <head>, nous avons une partie <meta> qui contient des
informations descriptives, comme l’auteur ou la date de conception de la présentation, et une
partie <layout> qui définit le positionnement et la mise en page de la fenêtre dans laquelle va
se jouer la présentation. Cette section contient elle-même deux types de balises. En premier
lieu, la balise <root-layout> qui permet de définir les propriétés de la fenêtre de présentation,
comme sa dimension et sa couleur de fond. Enfin, la balise <region> permet de définir des
zones dans la fenêtre de présentation dans lesquelles les différents médias seront affichés ;
chaque région doit avoir un identificateur, un emplacement, et peut avoir une couleur. Dans
l’exemple suivant, deux régions sont définies, une pour le texte, et une pour l’image :
<layout>
<root-layout id="exemple" title="exemple" width="800" height="600"/>
<region id="image" title="image" top="15" left="290"/>
<region id="text" title="texte" top="270" left="290"/>
</layout>
La balise <body> et ses descendants permettent de placer les composants dans les régions
définies dans l’élément <layout> décrit ci-dessus. Deux balises de base de cette section
permettent de contrôler la ligne temporelle : <par> et <seq>. Les différents médias
référencés dans un tag <par> sont joués en parallèle, simultanément. En revanche, les
médias se trouvant à l’intérieur d’une balise <seq> sont joués en séquence, c’est-à-dire les
uns après les autres. Il est possible d’imbriquer ces deux types de tag les uns dans les
autres pour créer des sous-présentations. Dans l’exemple suivant, les images sont affichées
en séquence (les unes à la suite des autres) mais en même temps qu’un texte descriptif :
<body>
<seq>
<par>
<text region="text"
<img region="image"
</par>
<par>
<text region="text"
<img region="image"
</par>
</seq>
</body>
src="./media/text1.txt" dur="10s"/>
src="./media/img1.gif" dur="10s"/>
src="./media/text2.txt" dur="10s"/>
src="./media/img2.gif" dur="10s"/>
Maintenant, si on regarde plus précisément comment sont introduits les différents médias
dans la présentation, on peut remarquer que chaque média possède sa propre balise. Ainsi
sept éléments XML correspondant chacun à un type de média vont permettre de placer les
composants dans une présentation. On distingue deux catégories de médias : les médias
continus qui ont une durée intrasèque (son, vidéo) et les médias discrets qui n’ont pas de
durée prédéfinie (images, texte) mais qui pourront en avoir une dans le cadre de la
présentation. Les différentes balises sont les suivantes :
7
<audio> pour les composants sonores (voix, son …)
<video> pour les séquences vidéos
<textstream> pour les textes dynamiques, avec déroulement automatique, par exemple
<animation> pour les animations, en Flash par exemple
<ref> pour tout média continu qui n’est pas compris dans un des types ci-dessus
<img> pour des images
<text> pour des composants textuels
Pour tous ces différents tags, l’attribut src permet de spécifier l’emplacement du média, qu’il
se trouve dans le répertoire courant ou sur un serveur web distant, et l’attribut region permet
de définir l’emplacement dans lequel le média va se jouer (cet emplacement doit avoir été
créé préalablement, voir partie <head>) . Il est important de noter qu’à l’intérieur de balises
<par> ou <seq> le temps se déroule de manière automatique ; en effet, un média référencé
dans un tag <seq> va se jouer directement à la suite de celui qui le précède. Cependant, si
l’auteur de la présentation veut contrôler lui-même la ligne temporelle, il est possible de
définir le début, la fin ou la durée d’un média. Tous les intervalles de temps sont mesurés par
rapport à la ligne temporelle de SMIL, qui est propre à l’application de présentation. C’est
l’utilisateur qui la contrôle : il a le choix de jouer la présentation, de la faire revenir en arrière,
de l’avancer ou encore de la stopper. Voici la syntaxe permettant de définir des durées en
SMIL :
-
15s = 15 secondes
2.5h = 2 heures 30 minutes
1.5 min = 1 minute 30
600 ms = 600 millisecondes
Dans l’exemple suivant, les médias sont un texte et une image qui se trouvent sur un serveur
web (HTTP) ; l’image apparaît dans une région appelée image et définie dans la partie
<head> du document, de même, le texte apparaît dans une région appelée text. La durée de
présentation de chaque média est de 10 secondes :
<par>
<text region="text" src="http://localhost:8080/media/text1.txt"
dur="10s"/>
<img region="image" src=" http://localhost:8080/media/img1.gif"
dur="10s"/>
</par>
La balise <switch> permet de définir plusieurs options parmi lesquelles le player SMIL en
choisira une lors de l’exécution. Ainsi, on peut inclure plusieurs fichiers sons dans une
présentation, et celui qui sera jouer sera définit par les préférences linguistiques de
l’utilisateur. De même, on peut inclure plusieurs images de différentes résolution qui seront
jouées selon la bande passante de l’utilisateur. A l’exécution, dès qu’une option est évaluée
à "vrai", elle est choisie et on sort du <switch> ; pour cette raison, il est important de définir
les élément dans l’ordre de préférence, en commençant par ceux qui offrent la présentation
de la meilleure qualité. Par exemple, on peut jouer un fichier son différent en fonction de la
vitesse de la connexion :
<switch>
<audio src="manu_chao.mp3" system-bit-rate="56000"/>
<audio src="noir_desir.mp3"/>
</switch>
Jusqu’à maintenant, il n’y a pas d’interaction possible pour l’utilisateur, ce dernier est passif.
Mais une présentation multimédia n’est pas une simple animation que l’on doit regarder, elle
offre à l’utilisateur un choix d’itinéraire dans son déroulement au moyen de liens hypertextes.
Un lien définit dans une présentation SMIL peut être défini sur tout type de média, et peut
8
renvoyer à une autre présentation, à un autre point d’entrée dans la présentation, à une
page HTML … Deux balises peuvent être utilisées pour définir un lien sur un média : <a> et
<anchor>. L’élément <a> correspond à celui du même nom présent en HTML avec un
attribut supplémentaire permettant de contrôler la présentation lorsque le lien est activé.
Ainsi, la présentation cible peut remplacer la présentation source ou peut être démarrée
dans une nouvelle fenêtre ; de même, si la présentation cible commence dans une nouvelle
fenêtre, la présentation source peut continuer de se jouer ou être arrêtée. Cet exemple nous
montre comment placer un lien sur une image ; lien qui s’ouvrira dans une nouvelle fenêtre
et arrêtera la présentation :
<a href="exemple.smi" external="true" sourcePlaystate="pause">
<img region="image" src="./media/img1.gif" dur="10s"/>
</a>
La balise <anchor> (renommée <area> en SMIL 2.0) permet, quand à elle, d’associer des
liens sur des parties d’un média ; par exemple, le coin supérieur gauche d’une image
possède un lien vers une page HTML, et le coin inférieur droit possède un lien vers une
autre présentation SMIL. De plus, cette balise permet d’associer des liens selon des
intervalles de temps ; par exemple, un lien est associé à une image pendant les dix première
secondes de présentation, alors qu’un autre lien est associé pendant le reste de la
présentation. Dans l’exemple suivant, un lien est associé seulement avec une partie
(rectangulaire) de l’image :
<img region="image" src="./media/img1.gif" dur="10s">
<area shape="rect" coords="0,0,50,50" href="exemple.smi"/>
</img>
Je viens de présenter les bases nécessaires à la conception d’un document SMIL, mais pour
plus de détails je vous conseille vivement d’aller voir toutes les possibilités offertes par SMIL
sur le site du W3C. Il est bon de savoir, que le W3C a sorti une nouvelle recommandation de
SMIL (nommée SMIL 2.0) en août dernier. La grande nouveauté de SMIL 2.0 provient de
l’introduction d’un module d’animation qui permet de bouger et de donner des effets aux
divers médias apparaissant dans une présentation SMIL. Cependant, à l’heure actuelle, et
vu la nouveauté de SMIL 2.0, un nombre très restreint de players supportent ce langage.
3.1.4 Les principaux players SMIL
Les players ne supportent pas tous complètement les spécifications de SMIL, et il est bon de
tester sa présentation SMIL dans différents players car elle peut se jouer sans problème
dans certains, et ne pas se jouer du tout dans d’autres ! ! !
SMIL 1.0 :
-
GriNS, d’Oratrix
QuickTime 4.1, d’Apple
RealPlayer 8, de RealNetworks
Soja, applet java conçue par Helio
SMIL 2.0 :
-
RealONE, de RealNetworks
GriNS, d’Oratrix
Internet Explorer 5.5 et 6, de Microsoft
9
3.2 Oracle et les LOBs
3.2.1 Généralités
Les bases de données multimédias permettent le partage, l’accès, et l’interrogation de
grandes collections d’informations multimédias.
Ainsi, le second outil utilisé est un système de gestion de bases de données – Oracle – pour
stocker les données utilisées dans les présentations multimédias. Une fois le système de
gestion de bases de données choisi, il faut regarder quel(s) sont le(s) type(s) de données
adéquat(s) pour stocker des photos, ou tout autre type de données multimédias. A partir de
sa version 8, Oracle fournit un certain nombre de types de données qui supportent le
stockage de grandes quantités d’information – jusqu’à quatre gigabytes – tel que texte,
images, vidéo, et son. Ces Larges Objets (ou LOBs) sont stockés soit dans la base, ce sont
alors des LOBs internes, soit dans un fichier externe, ce sont des LOBs externes. Ces
différents types LOBs sont utilisés pour les données qui sont trop grandes pour être
stockées directement dans une table de la base de données ; de ce fait, un locator (un
pointeur logique) est stocké dans la table et pointe sur l’emplacement des données, qu’elles
soient à l’intérieur, ou hors de la base de données. Comme nous le verrons par la suite,
toutes les manipulations de LOBs se font à travers de streams java.
Pour stocker des données multimédias dans les versions précédentes d’Oracle, il existe
diverses manière de faire. Soit il faut utiliser le type Long Raw qui permet de stocker des
données binaires de forme quelconque ; cependant, les données déclarées ainsi ne peuvent
pas être indexés, ni affichées, ni même interrogées au moyen de SQL*Plus. Soit il faut
référencer chaque image en stockant son URL dans la base.
Il est facile de voir comment la présence des différents médias est devenue prépondérante
dans les applications actuelles, et les concepteurs d’Oracle s’en sont très bien rendus
compte en permettant ce stockage de données binaires de taille variable. Prenons l’exemple
d’un professeur qui pourrait enregistrer des versions audio des cours qu’il doit donner, et les
stocker dans la base, tout comme les présentations qui les accompagnent. Le jour du cours
(ou la veille), il pourrait récupérer un certain nombre de ces données dans un fichier SMIL
(au moyen d’un langage comme LAZY), et mettre son cours en ligne, sa présence en classe
n’est même pas indispensable ! ! !
Je vais seulement m’attarder sur les deux types de LOBs qui conviennent particulièrement
pour le stockage de données multimédias – ou pour tout autre type de données binaires nonstructurées – en laissant de côté le type permettant le stockage de textes (les CLOBs). Deux
types de données conviennent particulièrement : les BLOBs qui sont des LOBs internes et
les BFILEs qui sont des LOBs externes.
3.2.2 Le type BLOB
Permet de stocker des données binaires brutes (non structurées) dont la taille ne dépasse
pas les 4 gigabytes. Les données sont stockées dans la base de données, ce qui permet
d’optimiser l’espace et de fournir un accès plus rapide à ces dernières. Les données BLOB
sont accédées et référencées au moyen d’un pointeur logique qui est stocké dans la table de
la base de données et qui pointe vers les données.
10
3.2.3 Le type BFILE
Permet de stocker un fichier binaire dans un fichier externe à la base de données Oracle (sur
disque dur, CDROM, CdPhoto, …). Le fichier peut avoir une taille maximale de 4 gigabytes
également. Une colonne ou un attribut BFILE stocke un locator de fichier qui pointe vers le
fichier externe contenant les données. L’accès aux données n’est possible qu’en lecture, il
n’est donc pas possible de modifier un BFILE. Le système d’exploitation sous-jacent doit
maintenir la durabilité et l’intégrité du fichier ; l’administrateur de la base de données doit
assurer que le fichier existe et que les divers processus Oracle ont la permission de lire le
fichier.
3.2.4 Manipulation de BLOB
Cette section décrit comment utiliser JDBC, et plus particulièrement les classes de
oracle.sql.* pour travailler avec les BLOBs. En effet, les principales méthodes permettant la
lecture et l’écriture de données BLOBs sont définies dans le package oracle.sql.*
(téléchargeable sur le site d’Oracle), tout comme la plupart des méthodes permettant la
manipulations de données BFILEs, qui sont le sujet de la prochaine section. Pour que le
compilateur java trouve ce package, il est nécessaire de le définir dans le classpath (SET
CLASSPATH=k:\memoire\oracle817\classes12.zip).
3.2.4.1 Fonctionnement du type BLOB
Pour travailler avec des données BLOBs, on doit tout d’abord obtenir leur locator (sorte de
pointeur logique); ensuite, il est possible de lire des données ou d’écrire des données dans
un BLOB, et d’effectuer toutes sortes de manipulations sur ces données. Le locator,
équivalent d’un pointeur en programmation, est stocké dans la table de la base. Ainsi, lors de
chaque nouvelle entrée dans la table – après avoir préalablement créé la table contenant un
attribut de type BLOB – il faut initialiser la valeur du BLOB à « vide », ce qui va créer le
locator du BLOB ; ensuite seulement on pourra insérer la donnée multimédia au moyen de
son locator. On peut récupérer le pointeur du BLOB grâce à la méthode getBLOB() ; en effet,
le résultat fourni par une requête SELECT nous renvoie le locator et non pas directement
les données binaires. Une fois que l’on a le pointeur logique, on peut lire et écrire les
données BLOBs au moyen de JDBC. Les données BLOBs sont représentées sous forme de
streams java ; contrairement aux principaux streams, il est possible d’accéder aux données à
n’importe quel moment durant la connexion du fait que le locator des données BLOBs est
stocké dans la table. Pour lire des données, on utilise tout d’abord la méthode
getBinaryStream() pour récupérer le BLOB sous forme de stream, puis on utilise la méthode
read() pour le lire. De même, pour écrire un BLOB, on utilise tout d’abord la méthode
getBinaryOutputStream() pour le récupérer sous forme de stream de sortie, puis on utilise la
méthode write() pour l’écrire. A noter que la méthode write() écrit directement dans la base
de données lorsque l’on écrit sur le stream de sortie : il n’est pas nécessaire d’exécuter un
UPDATE/COMMIT pour écrire les données. De même, la suppression d’un BLOB supprime
à la fois les données BLOBs et leur pointeur logique.
Pour illustrer ces explications je vais expliquer chacune des différentes étapes au moyen
d’un exemple. Tous les exemples suivants sont des méthodes qui peuvent être appelées
dans le code de la connexion [7], après la création de la connexion, et avant sa fermeture,
bien entendu.
11
3.2.4.2 Exemple de création de table contenant le type BLOB
Je n’ai créé qu’une seule table, nommée MULTIMEDIA, avec comme clé primaire un numéro
(No_Blob) qui est incrémenté à chaque nouvelle entrée dans la table. Les autres attributs
sont le nom, la description, le type de la donnée multimédia, et bien sûr la donnée ellemême. A noter que le type est le type MIME ; par exemple, si l’on insère une image jpeg
dans la base de données, son type sera image/jpeg.
private void creerTableBlob(){
try{
Statement stmt=conn.createStatement();
stmt.execute("create table MULTIMEDIA(No_blob Number(5) not null
primary key, Nom Varchar2(80), Donnee Blob, Description Varchar2(500), Type
Varchar2(50))");
stmt.close();
}
catch(SQLException e){
System.out.println("requete ERROR:
"+e.getMessage()+e.getSQLState()+e.getErrorCode());
}
}
NB : Lorsque l’on définit un attribut de type BLOB dans une table, on peut spécifier les
différentes caractéristiques de stockage de l’objet.
3.2.4.3 Exemple d’initialisation et d’écriture d’un BLOB
Cet exemple montre comment insérer dans un BLOB un fichier passé en paramètre, fichier
qui doit se trouver dans le répertoire courant. Tout d’abord, on récupère le nom du fichier
ainsi que le plus grand identificateur de BLOB (No_blob) présent dans la table, que l’on
incrémente de un.
private void insererUnBlob(File fichier){
try{
Statement stmt=conn.createStatement();
ResultSet result=stmt.executeQuery("SELECT max(No_blob) from
MULTIMEDIA");
int test=0;
String name="";
String typ="none";
name=fichier.getName();
if(result.next()){
test=result.getInt(1);
}
result.close();
test=test+1;
Puis, on regarde l’extension du fichier grâce à son nom, ce qui va nous permettre de définir
son type MIME. Ainsi, pour un fichier dont l’extension commence par j (pour jpeg) sont type
sera : image/jpeg.
for(int z=0;z<name.length();z++){
if(name.charAt(z)=='.'){
if((name.charAt(z+1)=='j')||(name.charAt(z+1)=='J'))
typ="image/jpeg";
if((name.charAt(z+1)=='g')||(name.charAt(z+1)=='G'))
12
typ="image/gif";
…
break;
}
}
Ensuite, on insère une nouvelle entrée dans la table avec ces différentes données, tout en
initialisant la valeur du BLOB à « vide » au moyen de empty_blob(), ce qui va créer son
locator.
stmt.execute("INSERT INTO MULTIMEDIA values
('"+test+"','"+name+"',empty_blob(),null,'"+typ+"')");
Finalement, on récupère la valeur du locator du BLOB créé grâce à une requête SQL du type
SELECT et à la méthode getBLOB(), puis on ouvre un stream de sortie sur ce dernier
(OutputStream) dans lequel on écrit le fichier, qui a préalablement été ouvert sous forme de
stream (InputStream). Les méthodes read() et write() sont utilisées pour la lecture et
l’écriture, et la taille du buffer idéale est déterminée grâce à la méthode getChunkSize() ; une
fois l’écriture complète, on ferme les deux streams.
ResultSet results=stmt.executeQuery("SELECT Donnee FROM MULTIMEDIA
WHERE No_blob='"+test+"' FOR UPDATE");
//on prend le locator du blob
if(results.next()){
BLOB blobloc=((OracleResultSet)results).getBLOB(1);
try{
InputStream entree=new FileInputStream(fichier);
//on ouvre un stream de sortie pour le blob
OutputStream sortie=blobloc.getBinaryOutputStream();
int chunk=blobloc.getChunkSize() ;
byte[] buffer=new byte[chunk];
int nbread=0 ; //nombres de bytes lus
while ((nbread=entree.read(buffer)) != -1) //lecture
sortie.write(buffer,0,nbread); //ecriture
entree.close();
sortie.close();
}
NB : Il est bien sûr possible d’insérer tout un répertoire de données multimédias dans la base
de données, en passant son nom en paramètre, et selon les mêmes procédés.
3.2.4.4 Exemple de lecture d’un BLOB
Cet exemple montre comment récupérer un BLOB dont le nom est passé en paramètre, en
le copiant dans un répertoire temporaire sous le même nom. Dans un premier temps, on
récupère le nom et le locator du BLOB au moyen d’une requête SQL du type SELECT et
aux méthodes getBLOB() et getString().
private void recupererUnBlob(String name){
try{
Statement stmt=conn.createStatement();
ResultSet results=stmt.executeQuery("SELECT Donnee,Nom FROM MULTIMEDIA
WHERE Nom='"+name+"'");
//on prend le locator du blob
if(results.next()){
BLOB blobloc=((OracleResultSet)results).getBLOB(1);
String n=results.getString(2);
13
Puis on ouvre un stream d’entrée sur ce dernier (InputStream) afin de permettre la lecture
des données BLOBs, que l’on va écrire dans un fichier (FileOutputStream) qui porte le même
nom que celui du BLOB, et qui va se trouver dans le répertoire C:\temp. Finalement, une fois
l’écriture complète, on ferme les deux streams. Il ne nous reste qu’à regarder dans le
répertoire temporaire pour vérifier que le fichier a bien été créé.
try{
InputStream entree=blobloc.getBinaryStream();
FileOutputStream sortie=new FileOutputStream("C:\\temp\\"+n);
int chunk=blobloc.getChunkSize() ;
byte[] buffer=new byte[chunk];
int nbread=0 ; //nombres de bytes lus
while ((nbread=entree.read(buffer)) != -1) //lecture
sortie.write(buffer,0,nbread); //ecriture
sortie.flush();
sortie.close();
entree.close();
}
3.2.5 Manipulation de BFILE
Cette section décrit comment utiliser JDBC et les classes de oracle.sql.* pour travailler avec
les BFILEs.
3.2.5.1 Fonctionnement du type BFILE
Dans le cas des BFILEs, c’est également un locator qui se trouve stocké dans la base de
données, mais celui-ci pointe vers un fichier externe à la base de données, stocké quelque
part dans le système de fichiers. Ainsi, pour la lecture, on procède de la même manière que
pour un BLOB : on récupère le pointeur logique au moyen d’une requête SQL du type
SELECT, puis on ouvre un stream pour lire les données. Les BFILEs sont read-only : on ne
peut donc pas insérer de données ni écrire dans un BFILE, ce qui est possible avec un
BLOB (voir section précédente). Avant de définir un BFILE, il est donc nécessaire de
s’assurer que le fichier que l’on veut référencer existe préalablement, et il faut créer un objet
répertoire qui est un alias du chemin d’accès au fichier. Ainsi, lors de la création d’un BFILE,
on doit spécifier le nom du fichier et le répertoire dans lequel le fichier se trouve ; il n’y a pas
d’écriture des données dans la base de données. L’administrateur de la base de données
doit s’assurer que la lecture est permise sur le fichier, et vérifier que les déplacements et/ou
suppression de fichiers ne porte pas atteinte à l’intégrité de la base de données. Il est à noter
que la plupart des méthodes applicables aux BFILEs, comme getDirAlias() et getName() ne
nécessitent pas l’ouverture du fichier ; seules les méthodes permettant de le lire et de
l’afficher requièrent son ouverture. A noter que la suppression d’un BFILE supprime
seulement le pointeur logique, mais pas le fichier qui était référencé.
Pour illustrer ces explications je vais expliquer chacune des différentes étapes au moyen
d’un exemple. Tous les exemples suivants sont des méthodes qui peuvent être appelées
dans le code de la connexion [7], après la création de la connexion, et avant sa fermeture,
bien entendu.
14
3.2.5.2 Exemple de création de table contenant le type BFILE
Comme dans le cas des BLOBs, je n’ai créé qu’une seule table, nommée PHOTO, avec
comme clé primaire un numéro (No_bfile) qui est incrémenté à chaque nouvelle entrée dans
la table. Les autres attributs sont similaires à ceux présents dans la table MULTIMEDIA.
private void creerTableBfile(){
try{
Statement stmt=conn.createStatement();
stmt.execute("create table PHOTO(No_bfile Number(5) not null primary
key, Nom Varchar2(80), Photo Bfile, Description Varchar2(500), Type
Varchar2(25))");
stmt.close();
}
catch(SQLException e){
System.out.println("requete ERROR:
"+e.getMessage()+e.getSQLState()+e.getErrorCode());
}
}
3.2.5.3 Exemple de création de répertoire
Cet exemple montre comment définir le répertoire dans lequel le fichier se trouve ; ce
répertoire est un alias du chemin d’accès au fichier.
private void creerRepertoireBfile(){
try{
Statement stmt=conn.createStatement();
stmt.execute("CREATE OR REPLACE DIRECTORY img AS
'/user/l1/merat7/memoire/multimedia'");
System.out.println("Repertoire cree...");
stmt.close();
}
catch(SQLException e){
System.out.println("requete ERROR:
"+e.getMessage()+e.getSQLState()+e.getErrorCode());
}
}
NB : A noter que le répertoire ainsi créé se nomme IMG et non pas img, car Oracle convertit
tout en majuscules. De plus, pour pouvoir créer un répertoire, il faut avoir la permission
CREATE ANY DIRECTORY de l’administrateur de la base de données ; de même pour
supprimer un répertoire, il faut avoir la permission DROP ANY DIRECTORY.
3.2.5.4 Exemple de création d’un BFILE
Cet exemple montre comment créer un BFILE d’un fichier passé en paramètre, fichier qui
doit se trouver dans le répertoire définit au point précédent. Tout d’abord, on récupère le
nom du fichier ainsi que le plus grand identificateur de BFILE (No_bfile) présent dans la
table, que l’on incrémente de un.
private void insererUnBfile(File fichier){
try{
Statement stmt=conn.createStatement();
ResultSet result=stmt.executeQuery("SELECT max(No_bfile) from PHOTO");
int test=0;
15
String name="";
String typ="none";
name=fichier.getName();
if(result.next()){
test=result.getInt(1);
}
result.close();
test=test+1;
Puis, on regarde l’extension du fichier grâce à son nom, ce qui va nous permettre de définir
son type MIME. Ainsi, pour un fichier dont l’extension commence par j (pour jpeg) sont type
sera : image/jpeg.
for(int z=0;z<name.length();z++){
if(name.charAt(z)=='.'){
if((name.charAt(z+1)=='j')||(name.charAt(z+1)=='J'))
typ="image/jpeg";
if((name.charAt(z+1)=='g')||(name.charAt(z+1)=='G'))
typ="image/gif";
…
break;
}
}
Enfin, on insère une nouvelle entrée dans la table avec ces différentes données. Il n’y a pas
besoin d’ouvrir de streams d’entrée et de sortie car on n’écrit pas le fichier, on le référence;
ainsi, la création d’un BFILE est beaucoup plus simple que celle d’un BLOB, elle s’effectue
simplement au moyen de bfilename(’nom_répertoire’,’nom_donnee’).
stmt.execute("INSERT INTO PHOTO values
('"+test+"','"+name+"',bfilename('IMG','"+name+"'),null,'"+typ+"')");
System.out.println("BFILE :"+name+" ok");
stmt.close();
}
NB : Une conséquence de cette sémantique : il est possible d’avoir
enregistrements BFILEs différents qui référencent tous le même fichier.
plusieurs
3.2.5.6 Exemple de lecture d’un BFILE
Cet exemple montre comment récupérer un BFILE dont le nom est passé en paramètre, en
le copiant dans un répertoire temporaire sous le même nom. Dans un premier temps, on
récupère le nom et le locator du BFILE au moyen d’une requête SQL du type SELECT et
aux méthodes getBFILE() et getString().
private void recupererUnBfile(String name){
try{
Statement stmt=conn.createStatement();
ResultSet results=stmt.executeQuery("SELECT Photo,Nom FROM PHOTO WHERE
Nom='"+name+"'");
//on prend le locator du bfile
if(results.next()){
BFILE bfileloc=((OracleResultSet)results).getBFILE(1);
String n=results.getString(2);
Puis, on ouvre le fichier grâce à la méthode openFile(), et on ouvre un stream d’entrée sur ce
dernier (InputStream) afin de permettre la lecture des données BFILEs, que l’on va écrire
16
dans un fichier (FileOutputStream) qui porte le nom du BFILE et qui va se trouver dans le
répertoire C:\temp. Finalement, une fois l’écriture complète, on ferme les deux streams ainsi
que le fichier. Il nous reste qu’à regarder dans le répertoire temporaire pour vérifier que le
fichier a bien été créé.
try{
bfileloc.openFile();
InputStream entree=blobloc.getBinaryStream();
//on ouvre un stream de sortie pour le blob
FileOutputStream sortie=new FileOutputStream("C:\\temp\\"+n);
byte[] buffer=new byte[10];
int nbread=0 ; //nombres de bytes lus
while ((nbread=entree.read(buffer)) != -1) //lecture
sortie.write(buffer,0,nbread); //ecriture
sortie.flush();
sortie.close();
entree.close();
bfileloc.closeFile();
}
3.3 Servlet
3.3.1 Généralités
Une fois le langage à utiliser pour la conception de présentations multimédias ainsi qu’un
système de gestion de bases de données choisis, il faut maintenant s’intéresser à l’outil qui
va permettre de récupérer les données multimédias de la base de données pour les afficher
dans une présentation. Pour ce faire, j’ai choisi comme outil les servlets qui permettent de
gérer des requêtes HTTP et de fournir au client une réponse dynamique.
Les servlets sont des programmes java basés sur les packages javax.servlet.* et
javax.servlet.http.* Un servlet peut générer dynamiquement une page HTML ou toute autre
ressource web comme une image, un son, un texte … Cela permet de construire une page
en fonction des souhaits du client, par exemple au moyen d’informations saisies dans un
formulaire, en utilisant une base de données ou toute autre sorte de ressources locales ou
distantes. Ils permettent donc de remédier à certains défauts des pages statiques, comme
l’impossibilité de renvoyer une page personnalisée selon le visiteur ou encore l’impossibilité
de créer une page dynamiquement selon les entrées d’une base de données. Un servlet
peut être comparé à un applet mais s’exécutant du côté du serveur (comme les CGI, les
scripts ASP ou PHP). Les servlets s’exécutent à l’aide d’un moteur de servlet qui établit le
lien entre le serveur web et le servlet ; ces derniers ne sont chargés qu’une fois par le
serveur, au démarrage du serveur ou lors de la première requête du client. Les servlets sont
donc actifs en permanence, il n’y a pas besoin de créer un processus à chaque requête
HTTP.
Un servlet possède les principaux avantages suivants :
•
Il est indépendant du système d’exploitation.
•
Il est indépendant du serveur web utilisé (Tomcat, IIS, …).
•
Il est facile à développer, car en java ; possibilité de réutilisation car encapsulation de
composants similaires possible, et possibilité d’utiliser toutes les API java.
17
3.3.2 Servlet et formulaire
Les servlets rendent très simple la récupération de données envoyées par un formulaire
HTML, et l’envoi d’informations sur le navigateur client en fonction de ces données reçues.
Pour utiliser un formulaire avec un servlet, il suffit de mettre le nom du servlet qui
réceptionnera les informations comme valeur de l’attribut action de la balise <form> et de
spécifier la méthode HTTP à utiliser au moyen de l’attribut method. Dans l’exemple cidessous, le formulaire sera traité par un servlet nommé req et envoyé au moyen de la
méthode GET.
<form action="req" method=GET>
Requete SQL:
<input type=text size=80 name=donnee>
<br>
<input type=submit>
</form>
Deux méthodes permettent de définir sous quelle forme seront envoyées les données d’un
formulaire :
•
Premièrement, la méthode GET qui permet d’envoyer les éléments du formulaire au
moyen de l’URL du script, en ajoutant l’ensemble des paires nom/valeur à l’URL du
script, séparé de celui-ci par un point d’interrogation, ce qui donne une URL du type:
http://localhost :8080/examples/req ?donnee=blablabla
•
La méthode POST est une alternative à la méthode GET, elle code les informations de la
même manière que la méthode GET mais envoie les données dans le corps de la
requête.
3.3.3 Structure d’un servlet
Maintenant, intéressons-nous à la structure du servlet permettant de traiter un formulaire.
Vous avez pu lire qu’un servlet n’est chargé qu’une fois par le serveur, au démarrage du
serveur ou lors de la première requête du client ; en fait, c’est la méthode init() qui est
invoquée à chaque instantiation du servlet. De même, la méthode destroy() est appelée lors
du déchargement du servlet. Ainsi, si notre servlet doit effectuer toute sorte de manipulations
sur une base de données, on écrira le code de la connexion dans la méthode init(), ce qui
permettra d’établir la connexion à la base de donnée au démarrage du serveur, et non à
chaque requête d’un utilisateur. La structure de base du servlet java traitant un formulaire,
avec accès à une base de données, est la suivante :
Import java.io.* ;
Import javax.servlet.* ;
Import javax.servlet.http.* ;
Public class req extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
//connexion a la base de donnée
}
public void destroy() {
//fermeture de la connexion
18
}
public void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
//analyse de la requête (request)
//lecture des données de formulaire HTML
//production de la réponse (response)
//envoi de la réponse au navigateur
}
}
L’objet HTTPServletRequest encapsule la requête du client ; il contient l’ensemble des
paramètres (champs de formulaire) passés au servlet. L’objet HTTPServletResponse permet
quant à lui de renvoyer une réponse au client. La requête est traitée au moyen d’une des
deux méthodes doGet() et doPost(), selon la méthode utilisée pour l’envoi du formulaire
(GET et POST).
3.3.4 Exemple d’utilisation de servlet
L’utilisation de servlets peut se résumer dans l’exemple suivant:
Requête HTTP
(par formulaire)
Serveur web
Requête SQL
servlet
Navigateur client
réponse
Moteur de
servlets
(Tomcat)
réponse
Base de
données
(Oracle)
Dans un premier temps, l’utilisateur rempli un formulaire dans son navigateur web, et
l’envoie. Le servlet, tournant sur un serveur web grâce à un moteur de servlets, récupère les
données du formulaire et envoie une requête SQL à la base de donnée en fonction des
informations remplies par l’utilisateur. La base de données exécute la requête puis donne la
réponse au servlet, qui se charge de la retourner au client.
3.4 Lazy
3.4.1 Généralités
Le dernier outil utilisé est le langage Lazy (développé par le groupe de recherche ISI du
Centre Universitaire d’Informatique de l’Université de Genève) qui permet la publication de
bases de données sur le web ; en d’autres termes, de présenter le contenu de bases de
données sous forme d’hyperdocuments. Lazy est un langage déclaratif qui offre la possibilité
de créer plusieurs vues différentes de données similaires, selon le point de vue de
l’utilisateur, ce qui permet de personnaliser les documents hypertextes. Par exemple, des
mêmes données pourront se trouver sous forme d’un tableau dans une page HTML et sous
19
forme d’une liste dans une autre page selon les besoins et l’usage que vont en faire les
différents groupes d’utilisateurs.
3.4.2 Fonctionnement
Chaque page web est une instance d’un nœud Lazy ; une vue hypertextuelle est un
ensemble d’instances de nœud (et des liens qui existent entre ces instances). Un nœud est
produit à partir d’une ou de plusieurs tables de la base de données, et se compose
d’éléments qui vont former le contenu du nœud, ainsi que de liens vers d’autres nœuds. Les
nœuds sont écrits en Lazy, et les instances de nœuds (les pages web) sont générées
dynamiquement grâce à un serveur de nœud qui prend comme entrée une forme compilée
de chacun des nœuds.
Ainsi, le système Lazy est composé de :
•
Un langage déclaratif pour définir le contenu de chaque nœud et les liens que le nœud
peut avoir avec d’autres noeuds. L’utilisateur va donc créer un nœud portant sur un ou
plusieurs attributs d’une (ou de plusieurs) table(s) de la base de données (il faut donc
préalablement connaître le schéma des tables de la base de données), en respectant la
sémantique du langage Lazy et en donnant l’extension .lz (ou .lazy) à son fichier.
•
Un compilateur pour traduire les nœuds en interrogation de la base de données. Il faut
donc compiler le nœud en lançant la commande java lc nom_du_noeud ; là, le
compilateur va produire une requête SQL du type SELECT … FROM ... WHERE ... qu'il
va mettre dans la table nodes (qui se trouve dans la base de données) avec pour nom le
nom du noeud.
•
Un serveur de nœuds qui va récupèrer la requête (produite par le compilateur) dans la
table nodes et va l’exécuter pour produire un document XML, HTML, SMIL ... selon les
tags insérés dans le nœud lors de sa conception.
3.4.3 Création de nœuds
Comme je l’ai déjà mentionné ci-dessus, un nœud permet de décrire comment sera générée
une page web à partir de données stockées dans la base de données. Ainsi, à l’intérieur de
chaque nœud il faut spécifier :
-
La table(s) sur laquelle porte le noeud
Les critères de sélection et d’ordonencement des données
Les éléments qui forment le contenu du nœud
Les liens éventuels vers d’autres noeuds
A noter que le nœud doit être créer dans un fichier source Lazy, qui est un simple fichier
texte muni de l’extension .lz ou .lazy. La définition d’un nœud prend la forme suivante :
define
Node name [paramètres…]
Elements …
From table_name
Selected by expression
20
Order by expression
end
Un élément peut être un string, un nombre, un attribut ou encore une expression
arithmétique. Les éléments peuvent être des tags d’un langage de balisage (comme HTML
ou SMIL), et ils prennent la syntaxe suivante :
<title> (Petit exemple) équivaut à la notation HTML <title> Petit exemple </title>
Tous les éléments spécifiés entre accolades {} sont répétés pour chaque tuple de la table qui
satisfait aux exigences du selected by. Les éléments placés avant et après les accolades {}
ne sont, quant à eux, générés qu’une seule fois.
define
node SMIL_image
<smil> (
<head>(
<meta name="title" content="Petit Exemple fait avec SMIL">(),
<layout> (
<region id="image1" title="image1" top="0" left="0">()
)
),
<body> (
<seq>(
{<img region="image1" src=nom dur="5s">()}
)
)
)
from Multimedia
selected by type="image/jpeg"
order by no_blob
end
L’exemple de nœud précédent, une fois compilé, puis exécuté par le serveur de nœuds,
produira un document SMIL contenant toutes les images de la base de données qui sont du
type image/jpeg et qui se trouvent dans la table Multimedia. L’attribut src de la balise <img>
prendra la valeur de l’attribut nom de la table Multimedia pour chacune des images. Ainsi, si
les éléments de la table Multimedia et de type image/jpeg ont pour nom : a.jpg, b.jpg, c.jpg,
le résultat ressemblera à ceci :
<smil>
<head>
<meta name="title" content="Petit Exemple fait avec SMIL"/>
<layout>
<region id="image1" title="image1" top="0" left="0"/>
</layout>
</head>
<body>
<seq>
<img src="a.jpg" dur="5s"/>
<img src="b.jpg" dur="5s"/>
<img src="c.jpg" dur="5s"/>
</seq>
</body>
</smil>
La définition d’un nœud peut prendre un certain nombre de paramètres. L’exemple de nœud
suivant prend un paramètre a qui va permettre de définir quelles images afficher. Ainsi,
21
seules les images ayant un identificateur supérieur au paramètre a (qui doit donc être de
type numérique) vont être affichées :
define
node test[a]
<p> ("Liste des images à partir de",a)
{…}
…
from multimedia
selected by no_blob>=a
end
On peut également spécifier qu’un élément est l’origine d’un autre nœud en utilisant la
notation href, et même que le contenu d’un autre nœud est inclus dans le nœud que l’on
définit, à l’endroit indiqué par la notation include. Ainsi, le nœud suivant possède un lien vers
le nœud SMIL_image et contient le contenu du nœud test :
define
node essai[a]
href SMIL_image("clickez ici pour les images"),
include test[a]
{…}
…
from multimedia
selected by no_blob>=a
end
4. Solution
Une fois les différents outils trouvés, compris et appris, je peux maintenant m’attaquer à
l’objectif final du travail qui est de pouvoir présenter le contenu d’une base de données
multimédia sous la forme de documents SMIL générés à partir des images, photos, sons,
textes, et autres vidéos stockés dans la base de données Oracle, aux moyen de nœuds
Lazy.
4.1 Choix du domaine
La première étape du travail a été celle du choix d’un domaine pour ma présentation. J’ai
tout naturellement choisi comme sujet le hockey sur gazon, sport que je pratique depuis plus
d’une dizaine d’années ; il se joue avec une canne et une balle, et oppose deux équipes de
onze joueurs. Il m’a donc fallu dans un premier temps rechercher des données multimédias
concernant ce sport. Cela n’a pas été une mince affaire car ce loisir, bien qu’il soit un des
plus vieux sports olympiques, est encore très peu connu, et j’ai mis un certain temps à
trouver des vidéos, photos et autres images sur le web. Une fois le domaine choisi, il m’a
fallu le modéliser.
22
4.2 Modélisation du domaine
J’ai défini un modèle du domaine très vaste (cf. page suivante), dont certaines relations ne
seront pas utilisées lors de l’élaboration de l’exemple de présentation multimédia. Je suis
parti de l’idée que tout joueur fait partie d’une (ou de plusieurs) équipe(s), qu’il possède son
propre matériel (cannes, chaussures, …) et qu’il participe à un certain nombre
d’entraînements durant la semaine ; chaque entraînement étant composé de diverses
phases de jeu. Chaque équipe est inscrite à un championnat, qui est régi par différentes
règles, et va donc jouer un certain nombre de matchs. Les photos peuvent représenter un ou
plusieurs joueurs, une ou plusieurs équipes, ainsi que du matériel. Les vidéos quant à elles
ne concernent que des règles ou des phases de jeu. Enfin, un son peut correspondre au
commentaire d’un match.
Il est bon de noter que les équipes peuvent être des équipes nationales (hommes ou
femmes) participant à des championnats du monde ou à des Jeux Olympiques, tout comme
des équipes amateurs participant à un championnat régional dans leur pays. J’en suis donc
arrivé à la conception du modèle relationnel suivant.
23
4.2.1 Modèle relationnel
Application_règles
Règles
Matchs
Championnat
Vidéo
Image
Son
Inscription
Matériel
Phases_de_jeu
Affectation
Equipe
Entrainement
Possède
Est_conposé
Participe
Joueur
Fait_partie
4.3 Liste des relations et création des différentes tables
La liste des relations découlant du modèle relationnel est la suivante :
REGLE
CHAMPIONNAT
APPLICATION_REGLE
EQUIPE
INSCRIPTION
MATCH
SON
JOUEUR
FAIT_PARTIE
IMAGE
MATERIEL
POSSEDE
ENTRAINEMENT
PHASE_DE_JEU
EST_COMPOSE
VIDEO
AFFECTATION
PARTICIPE
(NoRegle // Nom, Description, DateRegle)
(NoChampionnat // Categorie, Annee, Lieu)
(NoChampionnat, NoRegle //)
(NoEquipe // Nom, Adresse, Pays, NoTel, Categorie)
(NoChampionnat, NoEquipe //)
(NoMatch // Lieu, DateMatch, Heure, NoEquipe1, NoEquipe2)
(NoSon // Nom, Description, Donnee, Type, NoMatch)
(NoJoueur // Nom, Prenom, Adresse, Pays, NoTel)
(NoJoueur, NoEquipe //)
(NoImage // Nom, Description, Donnee, Type, NoMatch)
(NoMateriel // Nom, TypeMateriel, Description)
(NoJoueur, NoMateriel //)
(NoEntrainement // JourSemaine, HeureDebut, HeureFin,
DateEntr, Lieu)
(NoPhase // Nom, Description)
(NoEntrainement, NoPhase //)
(NoVideo // Nom, Description, Donnee, Type, NoRegle,
NoPhase)
( NoAffectation // NoImage, TypeImage, NoEquipe, NoJoueur,
NoMateriel)
(NoJoueur, NoEntrainement //)
Les clés primaires définies dans les relations ci-dessus, ne sont pas définies au niveau de la
création des tables [13]. En effet, je n’ai défini aucune contrainte ni règle d’intégrité, car elles
ne sont pas nécessaires pour la conception de la présentation, et elles m’auraient fait perdre
beaucoup de temps.
4.4 Insertion des données dans la base de données
Une fois les différentes tables créées, j’ai inséré un certain nombre de valeurs (pour la
plupart fictives) dans la base de donnée. Dans un premier temps, je me suis concentré sur
les données textuelles, puis j’ai utilisé mon fichier java contenant la connexion à la base de
données [7] pour insérer les données multimédias que j’avais trouvé. N’ayant pas trouvé de
documents sonores sur le hockey sur gazon, j’ai décidé d’insérer quelques chansons. La
plupart des photos trouvées concernant des matchs de hockey ayant eu lieu aux Jeux
Olympiques de Sydney, les principales équipes insérées dans la bases sont des équipes
nationales.
Une fois les données textuelles et multimédias dans la base, j’ai rempli les attributs des
différentes tables permettant de les associer entre elles. (Par exemple, l’image de nom
sydney_all.gif est affectée à l’équipe dont le nom est Allemagne). Cette étape m’a pris un
certain temps, car il fallait à chaque fois visualiser l’image (ou la vidéo) afin de savoir avec
quelle(s) équipe(s), quel(s) joueur(s), quel(s) matériel(s), quelle règle ou encore quelle phase
de jeu l’associer. De plus, n’ayant défini aucune règle d’intégrité, j’ai dû effectuer un certain
nombre de vérifications permettant de m’assurer de l’intégrité des données. Toutes sortes de
requêtes SQL peuvent maintenant être effectuées sur la base de données au moyen
d’SQL*PLUS. Cependant, SQL*PLUS ne permet pas d’interroger directement des données
25
de type BLOB, et j’ai donc dû trouver un moyen permettant d’afficher ces données. J’en suis
donc venu à la conception d’un servlet.
4.5 Conception d’un servlet pour la récupération des données
L’étape suivante a été la conception d’un servlet traitant un formulaire rempli par l’utilisateur ;
le formulaire va posséder un seul champ permettant à l’utilisateur d’effectuer une requête
SQL sur les différentes données multimédias stockées dans la base de données. L’objectif
du servlet est de récupérer les données de la base correspondant à la requête, et de les
afficher dans le navigateur du client. Mais, comme je l’ai expliqué dans la partie sur les
servlets (cf. point 3.3), un servlet nécessite un moteur de servlets et un serveur HTTP pour
pouvoir s’exécuter.
4.5.1 Installation d’un serveur HTTP
Il a donc fallu d’abord installer un serveur web, en l’occurrence Tomcat (à télécharger du site
http://jakarta.apache.org), qui est un serveur HTTP et un moteur de servlets. J’ai choisi le
produit d’Apache, car le serveur de nœuds utilisé par Lazy tourne également sur Tomcat.
Pour l’installation sous Windows95 et 98, il ne faut pas oublier d’augmenter dans les
propriétés des commandes MS-DOS la mémoire conventionnelle et de fixer l’environnement
initial à 2048 ; sinon, un message d’erreur : « espace d’environnement initial insuffisant »
apparaîtra lorsque l’on fixe les variables d’environnement. Ensuite, il faut définir des
variables d’environnement ; la première doit pointer sur le répertoire où se trouve la JDK : set
JAVA_HOME=H:\jdk1.2.2 et la seconde doit pointer sur le répertoire où l’on vient d’installer
Tomcat : set TOMCAT_HOME=K:\memoire\tomcat. Ceci étant fait, il suffit d’exécuter
bin/startup.bat pour lancer le serveur, et bin/shutdown.bat pour l’arrêter. On peut vérifier que
le serveur a bien été installé avec http://localhost:8080, c’est la page d’accueil de notre
serveur Tomcat.
Une fois l’installation terminée, j’en suis venu à la conception du servlet. Trois fichiers ont été
nécessaires à l’élaboration de ce dernier : un simple fichier HTML composé d’un formulaire à
un champ dans lequel l’utilisateur pourra écrire sa requête, le servlet lui-même qui traite la
requête envoyée par l’utilisateur et envoie la réponse sur le navigateur client, et enfin un
fichier XML qui contient les valeurs par défaut des divers servlets déployés dans Tomcat.
4.5.2 Création du formulaire
Tout d’abord, il faut créer un fichier HTML contenant le formulaire, et avec comme action
pour ce formulaire, le nom du servlet qui va traiter la requête envoyée (le servlet s’appelle
req). Le seul champ du formulaire (nommé donnee) va contenir une requête SQL faite par
l’utilisateur, ce qui veut dire que ce dernier doit préalablement connaître les différentes tables
présentes dans la base de données, ainsi que leurs attributs.
<form action="req" method=GET>
Requete SQL:
<input type=text size=80 name=donnee>
26
<br>
<input type=submit>
</form>
J’avais choisi, dans un premier temps, un formulaire à un champ qui prenait juste comme
valeur le nom de la donnée multimédia à afficher, ce qui évitait à l’utilisateur de devoir
formuler une requête SQL. Cependant, j’ai abandonné cette solution car elle ne permettait
de faire des requêtes que sur une seule table de la base de données. J’ai donc opté pour la
solution permettant de faire des requêtes sur toutes les tables présentes dans la base de
données, mais nécessitant de formuler une requête SQL. Je vais expliquer quelles sont les
requêtes possibles dans la partie suivante concernant l’élaboration du servlet (cf. point
4.5.3).
L’inclusion de ce formulaire dans un fichier HTML nous donnera un document ressemblant à
ceci :
4.5.3 Elaboration du servlet
Une fois le formulaire fini, il m’a fallu concevoir le servlet permettant de traiter les données
envoyées par la requête. Pour ce faire, il faut dans un premier temps importer les différents
packages utiles à l’élaboration du servlet, ainsi que ceux nécessaires à la connexion à la
base de données, et à la manipulation de ces données :
27
import
import
import
import
import
javax.servlet.*;
javax.servlet.http.*;
java.sql.*;
oracle.sql.*;
oracle.jdbc.driver.*;
Une fois de plus, pour que le compilateur java trouve ces différents packages, il est
nécessaire de les définir dans le classpath :
SET CLASSPATH= k:\memoire\tomcat\lib\servlet.jar;k:\memoire\oracle817\classes12.zip
Ensuite, on déclare notre classe, et on construit la méthode init() qui va initialiser le servlet ;
cette méthode contient le code relatif à la connexion JDBC à la base de données. Ainsi, la
connexion à la base de donnée se fera au démarrage du serveur ou lors de la première
requête du client, et non à chaque requête d’un utilisateur.
public class req extends HttpServlet {
<declaration des variables necessaires a la connexion>
ServletContext scontext;
public void init(ServletConfig config) throws ServletException {
scontext = config.getServletContext();
<connexion a la base de donnee>
}
Comme le formulaire utilise la méthode d’envoi GET, une méthode doGet doit être définie
dans le servlet afin de traiter les données envoyées. Cette méthode possède deux
paramètres : request qui est la requête de l'utilisateur sous forme d'objet HttpServletRequest,
et res qui est la réponse à fournir à l'utilisateur sous forme d'objet HttpServletResponse.
Dans un premier temps, on ouvre un stream de sortie sur la réponse que l’on va afficher
dans le navigateur du client, et on récupère les paramètres du champs du formulaire au
moyen de la méthode getParameterNames(). Ensuite, pour chaque paramètre, on récupère
son nom, puis sa valeur (c’est à dire le contenu du champ, qui est la requête SQL de
l’utilisateur). Enfin, la méthodes recuperer est appelée avec pour attributs la requête SQL, le
stream de sortie sur lequel écrire les données, et la réponse à fournir à l’utilisateur.
public void doGet(HttpServletRequest request, HttpServletResponse res)
throws IOException, ServletException {
Enumeration e = request.getParameterNames();
OutputStream out = res.getOutputStream();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = request.getParameter(name);
recuperer(value,out,res);
}
}
La méthode recuperer va, dans un premier temps, exécuter la requête SQL sur la base de
données.
private void recuperer(String name, OutputStream out,
HttpServletResponse res){
try{
Statement stmt=conn.createStatement();
ResultSet results=stmt.executeQuery(name);
Ensuite, elle regarde quelle est la requête entrée par l’utilisateur afin de pouvoir traiter
comme il se doit les données récupérées de la base. En effet, deux requêtes « standards »
peuvent être formulées par un utilisateur:
28
1. SELECT donnee, type FROM … WHERE …
2. SELECT autre FROM … WHERE …
A l’aide de ces deux types de requêtes, on peut normalement récupérer n’importe quelle
donnée stockée dans la base, que ce soit une image, un son, une photo, une vidéo, des
caractères, des chiffres… En effet, la première requête permet de récupérer une donnée
multimédia quelconque, et la deuxième requête permet quant à elle de récupérer n’importe
quelle autre donnée, sachant que toute donnée qui n’est pas multimédia (son, image, photo,
vidéo) est forcément de type caractère ou numérique. Cependant, pour que cette manière de
procéder fonctionne, j’ai dû nommer toutes les attributs de type BLOB des différentes tables
de la base de données : donnee, et tous les attributs permettant de spécifier le type MIME de
ces données BLOBs : type [13]. Si l’utilisateur veut effectuer une requête lui retournant une
donnée de type multimédia, il devra donc faire un SELECT donnee, type et si il souhaite faire
une requête sur tout autre(s) attribut(s) d’une table, il lui suffit de préciser les attributs désirés
dans sa requête.
Pour savoir quelle est le type de la requête envoyée par l’utilisateur, on regarde les
caractères situés en neuvième et dixième positions de la requête : si le caractère située en
neuvième position est un ‘o’ et celui situé en dixième position est un ‘n’, on est dans le cas
d’un SELECT donnee, type FROM … WHERE … On doit donc récupérer un BLOB (la
donnée multimédia) et un string (le type MIME de la donnée) ; puis on définit que le type
MIME de la réponse HTTP envoyée au navigateur client correspond au type MIME de la
donnée multimédia, ceci grâce à la méthode setContentType(). Finalement, on lit la donnée
BLOB, et on l’écrit sur le stream de sortie.
if(((name.charAt(8))=='o')&&((name.charAt(9))=='n')){
//on prend le locator du blob
if(results.next()){
BLOB blobloc=((OracleResultSet)results).getBLOB(1);
String n=results.getString(2);
try{
res.setContentType(n);
InputStream entree=blobloc.getBinaryStream();
int chunk=blobloc.getChunkSize() ;
byte[] buffer=new byte[chunk];
int nbread=0 ; //nombres de bytes lus
while ((nbread=entree.read(buffer)) != -1)
out.write(buffer,0,nbread); //ecriture
out.flush();
out.close();
entree.close();
}
}
}
Si on est dans le cas d’un SELECT autre FROM … WHERE … on doit récupérer un ou
plusieurs strings car on a affaire à des données de type caractère ou de type numérique (il
est possible d’effectuer un getString() d’un attribut d’une table qui est de type number). On
regarde tout d’abord combien de strings on doit récupérer, au moyen d’une boucle for et d’un
compteur a. Ainsi, chaque fois que l’on trouve une virgule, avant d’avoir atteint la clause
FROM, on rajoute une unité au compteur (la variable c permet de savoir si la clause FROM
a déjà été atteinte). Par exemple, si l’utilisateur écrit une requête du type : SELECT nom,
description from equipe where noequipe=’1’, la valeur de a sera deux.
else{
int a=1,c=0;
for(int i=0;i<name.length();i++){
29
if((name.charAt(i)=='f')&&(name.charAt(i+1)=='r')&&(name.charAt
(i+2)=='o'))
c=1;
if((name.charAt(i)==',')&&(c==0))
a++;
}
Puis on récupère le(s) résultat(s) de la requête, et on définit le type MIME de la réponse
HTTP comme étant du texte. Finalement, on écrit la (les) donnée(s) sur le stream de sortie.
if(results.next()){
String first=results.getString(1);
if(a>=2)
second=results.getString(2);
if(a>=3)
third=results.getString(3);
…
try{
res.setContentType("text/vnd.rn-realtext");
out.write(first.getBytes());
if(a>=2){
out.write(second.getBytes());
}
if(a>=3){
out.write(third.getBytes());
}
…
4.5.4 Modification du fichier web.xml
La dernière étape a été la modification du fichier web.xml avec le rajout de ces quelques
lignes dans ce fichier qui contient les valeurs des diverses applications déployées dans
Tomcat, et qui permet de spécifier le nom et la classe du servlet.
<servlet>
<servlet-name>
req
</servlet-name>
<servlet-class>
req
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>
req
</servlet-name>
<url-pattern>
/req
</url-pattern>
</servlet-mapping>
30
4.5.5 Vue d’ensemble
Voici à quoi ressemble l’arborescence de mes fichiers, une fois ceux-ci créés et modifiés :
+ - tomcat
+- webapps
+- examples
*- req.html
+- WEB-INF
*- web.xml
+- classes
*- req.java
Pour tester le servlet, il suffit d’aller à l’URL : http://localhost:8080/examples/req.html
4.5.6 Exemple de requête
Une fois arrivé sur la page contenant le formulaire, il ne nous reste plus qu’à tester le servlet
en rentrant une requête SQL dans le champ du formulaire, du type :
SELECT donnee,type FROM image WHERE nom='img1.gif'
Si tout se passe bien, la photo correspondant à la requête apparaît dans le navigateur, avec
pour URL :
http://localhost:8080/examples/req?donnee=SELECT+donnee%2Ctype+FROM+multimedia+
WHERE+nom%3D%27img1.gif%27
Le fait d’utiliser la méthode d’envoi GET permet de connaître l’URL correspondant à une
requête, au moyen du servlet, sur la base de données. On va donc pouvoir concevoir des
présentations SMIL où les différentes données multimédias seront référencées au moyen de
cet URL.
4.6 Choix d’un player
Par la suite, j’en suis venu à concevoir un document SMIL simple à l’aide d’un éditeur de
texte afin de tester le bon fonctionnement du servlet, mais surtout des différents players
SMIL (cf. point 3.1.4). J’ai donc créé un document SMIL [11] qui joue différentes images en
séquence, accompagnées d’une chanson et d’un texte descriptif pour chacune d’entre elle,
et suivi d’une séquence vidéo. Cet exemple permet de tester tous les types de médias dans
les différents players.
Une fois la présentation créée, j’ai décidé de la tester dans les différents players afin de
choisir lequel j’allais utiliser par la suite. Mais là, j’ai eu la mauvaise surprise de voir qu’aucun
31
player n’était capable de jouer mon exemple en intégralité ! ! ! Tout d’abord, RealPlayer8 qui
supporte la version SMIL 1.0, ne permet pas de jouer des images de type jpeg en séquence.
Ensuite, QuickTime, qui supporte également la version SMIL 1.0, mettait du temps à charger
des images ne dépassant pas la taille de 10 Ko, et les images qui devaient s’afficher
pendant cinq secondes ne s’affichaient donc même pas ! ! ! Enfin, GriNS jouait les images,
mais pas le son ni la vidéo … Il semble que les développeurs de players sortent leur produit
le plus vite possible sur le marché, sans se soucier des bugs résiduels, avec pour seul souci
d’être le premier sur le marché dans un domaine qui bouge très rapidement. J’ai donc passé
énormément de temps à essayer de contourner les problèmes de ces différents players, en
vain …
Ensuite, je me suis tourné vers la solution Internet Explorer qui « supporte SMIL 2.0 à partir
de sa version 5.5» dit-on sur le site de Microsoft. J’ai donc voulu ouvrir mon document SMIL
dans le navigateur, mais ce dernier l’ouvrait dans RealPlayer8 et non pas dans le navigateur
lui-même ! J’ai alors effectué quelques recherches sur le web afin de comprendre comment
utiliser SMIL avec Internet Explorer ; c’est là que j’ai trouvé que le produit de Microsoft ne
supporte pas SMIL mais un langage dérivé (basé sur les spécifications de SMIL) nommé
HTML+TIME ! ! ! Vu que c’était la dernière solution qu’il me restait, j’ai décidé de concevoir
mon exemple en HTML+TIME afin de voir si tout marchait correctement.
4.6.1 HTML+TIME
J’ai commencé par apprendre ce langage (approuvé par le W3C) qui permet d’étendre les
fonctionnalités de SMIL aux navigateurs webs. En fait, HTML+TIME (nommé XHTML+SMIL
à partir de la version 6 d’Explorer) définit un certain nombre d’améliorations apportées à
HTML permettant d’ajouter une ligne temporelle, de l’interaction, ainsi qu’une
synchronisation entre les divers médias présents dans une page web afin de créer des
présentations dynamiques et interactives, toutes ces différentes caractéristiques étant
basées sur les spécifications et la terminologie de SMIL. En fait, HTML+TIME poursuit les
mêmes buts que SMIL, mais en voulant intégrer les différents balises SMIL dans un
document HTML pour pouvoir visualiser la présentation dans un navigateur et non pas dans
un player. Avec le développement de ce langage, Microsoft essaie de contrer l’invasion de
l’industrie des players dans le domaine des navigateurs webs, en essayant de s’implanter
sur leur marché ; cependant, ce langage n’a pas encore le succès escompté.
4.6.1.1 Structure d’un document HTML+TIME
Trois composants de base se trouvent dans l’entête d’un document HTML+TIME.
Premièrement, il faut déclarer le namespace du temps dans le tag <html>.
<html xmlns:t ="urn:schemas-microsoft-com:time" >
Ensuite, il faut spécifier un style pour le comportement du time2 et importer son
comportement. Ce code doit figurer dans chaque entête de document HTML+TIME :
<head>
<style>
.time { behavior: url(#default#TIME2); }
</style>
<?import namespace="t" implementation="#default#time2">
</head>
32
Maintenant, dans le corps du document, il est possible d’introduire des balises <par> et
<seq>, ainsi que toutes sortes d’attributs (begin, dur, …) ressemblants fortement à ceux
présents dans des documents SMIL.
<body>
<t:seq>
<t:par>
<img class="time" begin="0" dur="3" src="img1.jpg"/>
<div class="time" begin="0" dur="3">Pakistan-Allemagne</div>
</t:par>
</t:seq>
</body>
Ainsi, l’équivalent d’un document SMIL [12] est le fichier HTML+TIME [13]. On peut
remarquer que ces deux exemples possèdent un certain nombre de ressemblances sans
toutefois être complètement similaires. Cette solution d’utiliser HTML+TIME ne m’a pas
vraiment convaincu car ce langage possède un certain nombre de défauts : il n’est, par
exemple, reconnu que par les versions récentes d’Internet Explorer, les balises sont un peu
plus complexes à utiliser que celles présentes en SMIL, et il est, à mon avis, loin de devenir
un standard au même titre que son homologue. Le seul point positif réside dans le fait que
des pages HTML existantes peuvent être améliorées (du point de vue de la présentation et
de l’interactivité) en peu de temps au moyen de ce langage.
Cette solution ne m’a donc pas entièrement satisfait, et je suis reparti à la recherche d’un
player qui puisse jouer mon exemple de présentation SMIL sans aucun bug …Je me suis
donc redirigé dans un premier temps vers QuickTime, en essayant de comprendre d’où
provenait le problème du chargement extrêmement lent des données multimédias, sans
toutefois trouver de réponse. Mais au moment où je commençais à baisser les bras,
RealONE m’a tendu les siens ! ! !
4.6.2 RealONE
En surfant par hasard sur le web, j’ai découvert que RealNetworks sortait un nouveau player
en septembre 2001 (faisant également navigateur web) nommé RealONE. Je l’ai donc
téléchargé dès sa sortie, et j’ai testé mon exemple [11]. Là, ô miracle des technologies
modernes, ma présentation se jouait sans aucun problème, ou presque. En effet, RealONE,
comme RealPlayer, ne supporte pas très bien les images de type jpeg qui sont jouées en
séquence. J’ai donc décidé de convertir toutes les photos présentent dans la base de
données au format gif, puis j’ai testé à nouveau mon exemple : tout marchait à merveille ! ! !
De plus, contrairement aux autres players SMIL, RealONE supporte les spécifications de
SMIL 2.0, et il est donc possible d’utiliser, entre autre, le module d’animation définit dans
SMIL 2.0 permettant principalement d’animer les images et autres données multimédias
présentes dans une présentation.
4.7 Installation de Lazy
Une fois le player SMIL choisi, l’étape suivante a été d’installer Lazy (téléchargeable sur le
site http://cui.unige.ch/isi/lazy) afin de pouvoir créer des documents SMIL dynamiquement,
sur la base de nœuds. Tomcat étant déjà installé, il suffit d’installer le compilateur
(Compiler.class et lc.class) et le serveur de nœud (ns.class), sans oublier de modifier le
33
fichier web.xml (comme dans le cas du point 4.5.4). Les trois classes ci-dessus doivent être
insérées dans le même répertoire que le servlet créé précédemment (cf. point 4.5.5). De
plus, il faut insérer dans la base de données les tables nodes (qui va contenir les valeurs des
nœuds compilés) et naturals (qui contient les entiers de 0 à 9, et qui va servir pour les
nœuds prenant des paramètres). Il faut également définir un fichier Lazy.properties dans le
répertoire où seront créés les différents nœuds : il contient les ressources nécessaires pour
le compilateur et le serveur de nœuds Lazy, à savoir l’URL de la base de donnée, le nom
d’utilisateur, le mot de passe, le driver utilisé, et le nom du serveur de nœuds.
4.8 Conception de nœuds SMIL en Lazy
4.8.1 Modification du serveur de nœuds
Pour pouvoir créer des présentations SMIL en Lazy, il faut tout d’abord modifier le serveur de
nœud (ns.java). En effet, le serveur de nœuds produit par défaut une en-tête HTML, et
définit le type MIME du nœud compilé comme étant de type HTML. J’ai dû modifier quelque
peu le serveur de nœuds afin que ce dernier définisse le type MIME correctement, selon le
nom que l’on donne à notre nœud. De ce fait, si le nom du nœud commence par SMIL_, le
type MIME sera défini comme étant celui d’une application SMIL, sinon ce sera celui d’un
document HTML.
String a = request.getParameterValues("a")[0];
if(a.startsWith("SMIL_"))
response.setContentType("application/smil");
else
response.setContentType("text/html");
De plus, dans le cas d’un nœud SMIL, aucune en-tête ne doit être insérée dans le nœud
compilé ; toutes les balises SMIL seront définies au niveau de la création du nœud.
if(!a.startsWith("SMIL_")&&!a.startsWith("HTML_")){
out.println("<html>");
out.println("<head>");
out.println("<title>Node: " + a +"[" + ul + "]" + "</title>");
out.println("</head>");
out.println("<body>");
}
J’ai également modifié le serveur de nœuds afin qu’il permette la création de documents
HTML+TIME. De la même manière, tous les nœuds dont le nom commence par HTML_,
auront une en-tête qui leur est propre (cf. point 4.6.1.1).
if(a.startsWith("HTML_")){
out.println("<html xmlns:t =\"urn:schemas-microsoft-com:time\">");
out.println("<head>");
out.println("<style> .time { behavior: url(#default#TIME2); }");
out.println("</style>");
out.println("<title>Node: " + a +"[" + ul + "]" + "</title>");
out.println("<?import namespace=\"t\"
implementation=\"#default#time2\">");
out.println("</head>");
out.println("<body>");
}
34
De même, des balises de fin de document sont insérées dans le cas de nœuds « normaux »,
balises qui ne sont pas insérées si le nom du nœud commence par SMIL_.
4.8.2 Conception de nœuds SMIL
Une fois le serveur de nœud modifié, j’ai pu concevoir quelques nœuds SMIL en Lazy, afin
de vérifier le bon fonctionnement du tout, et avant de m’attaquer à la présentation finale. J’ai,
par exemple, créé un nœud [15] qui joue une série d’images les unes à la suite des autres
(une sorte de diaporama). Une fois le nœud conçu, il suffit de le compiler, puis d’aller sur la
page où se trouve l’ensemble de mes nœuds (http://localhost :8080/examples/ns?a=meta),
et enfin de cliquer sur le nom du nœud (le nœud doit avoir un nom commençant par SMIL_
cf. point 4.8.1) ; si tout se passe bien, RealONE va s’ouvrir et jouer ma présentation. De la
même manière, j’ai défini quelques autres nœuds afin de voir si les différents médias – que
se soient des images, du son, du texte, ou encore des vidéos – se jouaient correctement.
Les médias sont référencés dans un nœud Lazy au moyen de l’URL utilisé par la méthode
d’envoi GET correspondant à une requête à l’aide du servlet sur la base de donnée (cf. point
4.5.6). Toute référence à un média se fera de la manière suivante : on définit, dans un
premier temps, la balise correspondant au type du média que l’on souhaite afficher ainsi que
la region dans laquelle il s’affichera, puis on donne comme source pour ce média l’URL
produit par la méthode GET. Dans l’exemple suivant, tous les tuples de la table choisie, et
correspondants aux critères de sélection, seront affichés sous la forme d’image.
{<img region="image"
src="http://localhost:8080/examples/req?donnee=SELECT+donnee%2Ctype+FROM+mu
ltimedia+WHERE+nom%3D%27",nom,"%27" dur="5s">()}
4.9 Présentation finale
Finalement, je suis arrivé à l’ultime étape de mon travail, avec la création d’un exemple de
présentation dynamique sur le hockey sur gazon. J’ai conçu un exemple assez simple, mais
permettant de montrer les possibilités offertes par une base de données multimédia utilisée à
l’aide des langages SMIL et Lazy. L’utilisateur va pouvoir naviguer dans l’information,
interagir avec cette dernière en cliquant sur les liens qui l’intéresse car les différents nœuds
possèdent des références les uns aux autres ; il y a donc plusieurs moyens de voir
l’information.
Je n’ai produit que cinq nœuds en me basant sur une partie de la modélisation du domaine
(cf. point 4.2.1) ; nœuds qui me paraissaient les plus pertinents d’après le modèle, et surtout
d’après les données trouvées sur le web.
4.9.1 Détails des nœuds créés
Le premier nœud [16] permet d’afficher en musique toutes les photos concernant l’équipe
choisie par l’utilisateur : il doit rentrer comme paramètre le nom de l’équipe. Ce nœud
possède un lien vers celui contenant les règle du hockey sur gazon [19] , un autre vers la
35
liste des équipes [17], et enfin un dernier vers le détail des matchs que l’équipe doit jouer
[18]. De plus, un nœud affichant les matchs à jouer [20] est inclus dans ce nœud. Le second
nœud [19] permet d’afficher les règles du hockey sur gazon, et chacune des règles possède
un lien vers une vidéo explicative ; ce nœud possède également un lien vers la liste des
équipes. Le troisième nœud [17], quant à lui, permet d’afficher la liste des équipes et de
choisir celle qui nous intéresse ; il possède un lien vers le site de la fédération internationale
de hockey. Enfin, le dernier nœud [18] permet d’obtenir le détail des matchs concernant une
équipe.
4.9.2 Problèmes rencontrés
J’ai rencontré un certain nombre de problèmes lors de l’élaboration de ma présentation :
•
Premièrement, il m’a fallu augmenter la taille de certains attributs de la tables nodes. En
effet, les attributs pre et items sont définis à la base comme étant de type
Varchar2(2000). Or, cette taille n’est pas suffisante pour produire des documents SMIL
complexes, j’ai donc dû l’augmenter (Varchar2(4000)).
•
Ensuite, SMIL étant basé sur XML, et XML ne supportant pas le caractère &, il m’a donc
fallu remplacer tous les caractères & présents dans les différents nœuds Lazy par
&amp ; (Le caractère & est essentiellement présent lorsque l’on référence un nœud dans
un autre nœud.)
•
De plus, il n’est pas possible d’introduire du texte « en dur » dans une présentation
SMIL ; le texte s’affichant dans la présentation doit se trouver dans la base de données
(ou dans un fichier). J’ai donc dû créer une table legende contenant certains textes
apparaissant dans la présentation.
5. Conclusion
Le multimédia est un domaine qui bouge énormément, et très rapidement ; j’en veux pour
preuve la « découverte » de RealONE, un jour après sa sortie. Ainsi, beaucoup de
nouveautés apparaissent sans cesse que ce soit dans le domaine des players ou même
dans le domaine des langages de présentation de données multimédias. En me basant sur
les dernières spécifications, j’ai dû effectuer beaucoup de recherche car, du fait de cette
nouveauté, j’ai touché à des domaines qui étaient encore très peu explorés et, où peu
d’informations et d’exemples les concernants étaient disponibles.
Ce travail a permis de mettre en pratique et d'approfondir mes connaissances dans trois
domaines de l'informatique les plus dynamiques actuellement :
- les bases de données
- le web
- le multimédia
Grâce aux nouveaux types définis dans Oracle (LOBS) et à des langages bien adaptés pour
ce genre d'applications (java, SMIL et Lazy), il a été possible de concevoir rapidement des
documents multimédias. Mais la plus grosse difficulté est venue des players : sans la
découverte tardive de RealONE, le seul capable d'afficher correctement tout type de
36
documents SMIL, il aurait été impossible de démontrer le bon fonctionnement de mon
application.
Je garde le mot de la fin pour remercier ceux qui m’ont aidé et/ou supporté lors de
l’élaboration de ce travail : à savoir ma famille et ma copine. Je tiens tout particulièrement à
remercier le professeur Gilles Falquet pour son aide et ses conseils avisés.
6. Bibliographie
[1]
A. Michard, « XML, langage et applications », Eyrolles, 1999.
[2]
R. Plew et K. Stephens, « SQL », CampusPress, 2000.
[3]
V.S. Subrahmanian, « Principles of Multimedia Database Systems », Morgan
Kaufmann, 1998.
[4]
M. Vazirgiannis, « Interactive Multimedia Documents », Springer, 1999.
[5]
S.J. Gibbs et D.C. Tsichritzis, « Multimedia Programming », Addison-Wesley, 1995.
[6]
S. Khoshafian et A.B. Baker, « Multimedia and Imaging Databases, Morgan
Kaufmann, 1996.
les LOBs et autres types de données:
Oracle8 Server Application Developer’s Guide,
http://hojohn.photo.net/ora8doc/DOC/server803/A54642_01/ch_lob.htm
Oracle/SQL Tutorial, Michael Oertz,
http://sirius.cs.ucdavis.edu/teaching/sqltutorial
Oracle Data Type,
http://www.idera.com/support/documentation
Forum de DBA,
http://www.dbasupport.com/forums
JDBC :
Connexion JDBC à la base de données,
http://www.commentcamarche.net/jdbc/jdbcconnect.php3
Exécution de requêtes SQL sur la base de données,
http:// www.commentcamarche.net/jdbc/jdbcexec.php3
JDBC, Roger Whitney,
http://www.eli.sdsu.edu/courses/fall00/cs580/notes/jdbc/jdbc.html
TOMCAT :
Tomcat User’s Guide,
http://jakarta.apache.org/tomcat/tomcat-3.2-doc/uguide/tomcat_ug.html
37
SMIL et HTML+TIME:
Synchronized Multimedia Integration Language (SMIL 2.0), August 2001,
http://www.w3.org/TR/smil20/
Timed Interactive Multimedia Extensions for HTML,
http://www.w3.org/TR/NOTE-HTMLplusTIME
SMIL – présentation intéractive, N. Mérat et S. Nastasi, mai 2000,
http://cui.unige.ch/~nastasi7/smil/index.html
Quicktime and SMIL,
http://www.apple.com/quicktime/authoring/qtsmil2.html
SMIL tutorials,
http://streamingmediaworld.com/smil/tutor
Is HTML+TIME Out-of-Sync With SMIL ?, Lisa Rein, 1998,
http://www.xml.com/pub/a/98/10/htmltime.html
LAZY :
Lazy Home Page,
http://cui.unige.ch/isi/lazy
7. Annexes
[7]
ConJDBC.java
[8]
req.html
[9]
req.java
[10]
web.xml
[11]
player.smil
[12]
hockey.smil
[13]
hockey.html
[14]
create_tables.sql
[15]
SMIL_image.lz
[16]
SMIL_equipe.lz
[17]
SMIL_liste.lz
[18]
SMIL_match.lz
[19]
SMIL_regle.lz
[20]
SMIL_mixmatch.lz
38