Correction TD CORBA no2

Transcription

Correction TD CORBA no2
Correction TD CORBA no2
Master 2 Ingénierie Informatique
—2005-2006—
Le langage IDL
L’objectif de ce td est de développer une application de forum interrogeable à
distance, permettant de poster ou de récupérer des messages.
x Exercice
1. Une application de forum simple
Pour développer l’application forum, nous vous proposons de respecter une
spécification IDL prédéfinie afin d’assurer l’interopérabilité entre vos différentes implantations de fora.
Les messages échangés ne sont pas des objets CORBA. Ils sont représentés par la
structure IDL suivante :
struct Message {
string title ;
string author ;
string date ;
string body ;
};
Le forum est un objet CORBA dédié à la gestion des messages d’un thème
particulier (attribut theme) et sous la responsabilité d’un administrateur (attribut
moderator). Il est représenté par l’interface IDL suivante :
i n t e r f a c e Forum {
readonly a t t r i b u t e string theme ;
readonly a t t r i b u t e string m o d e r a t o r;
boolean p o s t M e s s a g e( in Message m ) ;
Message g e t M e s s a g e( in string title ) ;
boolean r e m o v e M e s s a g e ( in string title ) ;
};
En respectant les étapes vues dans le td précédent, développez l’application forum,
c’est-à-dire l’interface IDL, le servant, le serveur et le client. Nous vous proposons de
placer vos définition IDL dans le module td2 et de placer les classes correspondantes
dans le paquetage fr.umlv.cri.corba.td2. Pour stocker les messages on pourra utiliser une table hachage ConcurrentHashMap qui associe chaque message à son titre.
1
✁
forum.idl
module t d 2 _ b a s i c {
struct Message {
string title ;
string author ;
string date ;
string body ;
};
i n t e r f a c e Forum {
readonly a t t r i b u t e string theme ;
readonly a t t r i b u t e string m o d e r a t o r;
boolean p o s t M e s s a g e( in Message m ) ;
Message g e t M e s s a g e( in string title ) ;
boolean r e m o v e M e s s a g e ( in string title ) ;
};
};
ForumImpl.java
package fr . umlv . cri . corba . t d 2 _ b a s i c;
import java . util . c o n c u r r e n t. C o n c u r r e n t H a s h M a p ;
public class F o r u m I m p l extends ForumPOA {
/* *
* Table de hachage c o n t e n a n t l ’ a s s o c i c a t i o n entre un nom et
* un message .
* L ’ accès c o n c u r r e n t à la table est permis .
*/
private C o n c u r r e n tHa shMa p < String , Message > messages =
new C o n c u r r e n tHa shMa p < String , Message >();
/* * Thème du forum */
private String theme ;
/* * Nom de l ’ a d m i n i s t r a t e u r */
private String m o d e r a t o r;
/* *
* C o n s t r u c t e u r d ’ un forum appelé par la fabrique .
*
* @param name nom du forum créé .
* @param theme thème du forum .
* @param m o d e r a t o r nom de l ’ a d m i n i s t r a t e u r du forum .
*/
2
F o r u m I m p l( String theme , String m o d e r a t o r) {
this . theme = theme ;
this . m o d e r a t o r = m o d e r a t o r;
}
/* *
* Retourne le thème du forum .
*/
public String theme () {
return theme ;
}
/* *
* Retourne le nom du m o d é r a t e u r du forum .
*/
public String m o d e r a t o r () {
return m o d e r a t o r;
}
/* *
* Poste un message dans le forum .
*
* @param m le message à poster .
* @return false s ’ il y a déjà un message avec le m^
e me titre .
*/
public boolean p o s t M e s s a g e ( Message m ) {
Message mInMap = messages . p u t I f A b s e n t( m . title , m );
return mInMap != null ;
}
/* *
* Récupère le message dont le titre est passé en argument .
*
* @param title le titre du message à r é c u p é r e r.
* @return le message ou null s ’ il n ’ existe pas de message
*
ayant ce titre .
*/
public Message g e t M e s s a g e( String title ) {
Message m = messages . get ( title );
return m ;
}
/* *
* Retire un message du forum .
*
* @param title le titre du message à retirer du forum .
* @return false si le message n ’ est pas présent dans le forum .
*/
public boolean r e m o v e M e s s a g e( String title ) {
3
return messages . remove ( title ) == null ;
}
}
ForumServer.java
package fr . umlv . cri . corba . t d 2 _ b a s i c;
import
import
import
import
import
import
import
org . omg . CORBA .*;
org . omg . CORBA . O R B P a c k a g e .*;
org . omg . P o r t a b l e S e r v e r .*;
org . omg . P o r t a b l e S e r v e r . POA ;
org . omg . P o r t a b l e S e r v e r . P O A M a n a g e r P a c k a g e . A d a p t e r I n a c t i v e ;
org . omg . P o r t a b l e S e r v e r . P O A P a c k a g e .*;
java . io .*;
public class F o r u m S e r v e r {
public static void main ( String args []) throws
S e r v a n t A l r ea dy Act iv e , InvalidName , ObjectNotActive ,
WrongPolicy , F i l e N o t F o u n d Ex ce pti on , A d a p t e r I n a c t i v e {
// I n i t i a l i s a t i o n de l ’ ORB
ORB orb = ORB . init ( args , null );
// R é c u p é r a t i o n de r é f é r e n c e de l ’ a d a p t a t e u r d ’ objets racine
POA rootPOA =
P O A H e l p e r. narrow ( orb . r e s o l v e _ i n i t i a l _ r e f e r e n c e s ( " RootPOA " ));
// I n i t i a l i s a t i o n de l ’ objet servant
F o r u m I m p l forum = new F o r u m I m p l( " java " ," forax " );
// E n r e g i s t r e m e n t du servant
byte [] s e r v a n t I d = rootPOA . a c t i v a t e _ o b j e c t( forum );
// R é c u p é r a t i o n de la r é f é r e n c e du servant et écriture
// dans un fichier
String r e f e r e n c e =
orb . o b j e c t _ t o _ s t r i n g ( rootPOA . i d _ t o _ r e f e r e n c e ( s e r v a n t I d ));
P r i n t W r i t e r file = new P r i n t W r i t e r( " O b j e c t R e f" );
file . println ( r e f e r e n c e );
file . close ();
// A c t i v a t i o n des servants
rootPOA . t h e _ P O A M a n a g e r (). activate ();
System . out . println ( " Server is ready " );
4
// Mise en attente des requètes
orb . run ();
}
}
ForumClient.java
package fr . umlv . cri . corba . t d 2 _ b a s i c;
import java . io .*;
import java . util .*;
import org . omg . CORBA .*;
public class F o r u m C l i e n t {
public static void main ( String [] args ) throws I O E x c e p t i o n {
// I n i t i a l i s a t i o n de l ’ ORB
ORB orb = ORB . init ( args , null );
// R é c u p é r a t i o n de la r é f é r e n c e du servant
BufferedReader fileReader =
new B u f f e r e d R e a d e r( new F i l e R e a d e r( " O b j e c t R e f" ));
String s t r i n g I O R = f i l e R e a d e r. readLine ();
f i l e R e a d e r. close ();
// Création , à partir de la r é f é r e n c e du servant ,
// d ’ un proxy local
Forum f o r u m P r o x y = F o r u m H e l p e r
. narrow ( orb . s t r i n g _ t o _ o b j e c t ( s t r i n g I O R ));
// I n v o c a t i o n de méthodes d i s t a n t e s
Message m =
new Message ( " CORBA " ," moi " ,( new Date ()). toString () ,
" Corba c ’ est bien ! " );
f o r u m P r o x y. p o s t M e s s a g e( m );
Message tmp = f o r u m P r o x y. g e t M e s s a g e( " CORBA " );
System . out . println ( " Titre : " + m . title );
System . out . println ( " Auteur : " + m . author );
System . out . println ( " Message : " + m . body );
}
}
✁
5
x Exercice
2. Les séquences
Modifier les fichiers de votre application de forum afin d’intégrer un type
séquence de messages (MessageSet), puis ajouter dans l’interface Forum l’opération
getMessages() qui renvoie la liste des messages du forum.
Rappelons qu’en IDL, une séquence correspond à un tableau de taille variable et
qu’un type séquence de nom TSet contenant des objets de type T est déclaré par :
typedef sequence <T > TSet
✁
forum.idl
typedef sequence < Message > M e s s a g e S e t;
ForumImpl.java
/* *
* Retourne la liste des messages du forum .
* @return la liste des messages
*/
public Message [] m e s s a g e L i s t () {
return messages . values (). toArray ( new Message [ messages . size ()]);
}
✁
x Exercice
3. Les exceptions
On souhaite maintenant améliorer l’interface de notre forum en lui faisant lever des
exceptions en cas d’erreur. Pour cela, il faut d’abord définir en IDL les exceptions avec
la syntaxe suivante :
e x c e p t i o n E x c e p t i o n N a m e { string message ; };
Ensuite il faut indiquer dans l’interface du forum les méthodes qui lèvent une exception. Rappelons qu’une méthode suivie du mot clef raises et du nom d’une exception
entre parenthèses, indique que la méthode est susceptible de lever ce type d’exception
au niveau du client au retour de l’appel.
Mettre en œuvre l’exception Reject qui sera levée par la méthode postMessage()
lorsque un message de même titre existe déjà et par les méthodes getMessage() et
removeMessage() s’il n’existe pas de message avec ce nom.
6
✁
forum.idl
e x c e p t i o n Reject { string message ; };
i n t e r f a c e Forum {
readonly a t t r i b u t e string theme ;
readonly a t t r i b u t e string m o d e r a t o r;
void p o s t M e s s a g e( in Message m ) raises ( Reject ) ;
Message g e t M e s s a g e( in string title ) raises ( Reject ) ;
void r e m o v e M e s s a g e ( in string title ) raises ( Reject ) ;
};
ForumImpl.java
/* *
* Poste un message dans le forum .
* @param m le message à poster .
* @return false s ’ il y a déjà un message avec le m^
e me titre .
*/
public void p o s t M e s s a g e( Message m ) throws Reject {
Message mInMap = messages . p u t I f A b s e n t( m . title , m );
if ( mInMap != null ) {
throw new Reject ( " P o s t M e s s a g e : message with title " +
m . title + " already exists ! " );
}
}
/* *
* Récupère le message dont le titre est passé en argument .
* @param title le titre du message à r é c u p é r e r.
* @return le message ou null s ’ il n ’ existe pas de message
* ayant ce titre .
*/
public Message g e t M e s s a g e( String title ) throws Reject {
Message m = messages . get ( title );
if ( m == null ) {
throw new Reject ( " G e t M e s s a g e : message with title " + title +
" does not exist ! " );
}
return m ;
}
/* *
* Supprime un message du forum .
* @param title le titre du message à retirer du forum .
7
* @return false si le message n ’ est pas présent dans le forum .
*/
public void r e m o v e M e s s a g e( String title ) throws Reject {
if ( messages . remove ( title ) == null ) {
throw new Reject ( " R e m o v e M e s s a g e : message " + title +
" does not exist ! " );
}
}
ForumClient.java
package fr . umlv . cri . corba . td2 ;
import java . io .*;
import java . util . Date ;
import org . omg . CORBA .*;
public class F o r u m C l i e n t {
public static void main ( String [] args ) throws I O E x c e p t i o n {
try {
// I n i t i a l i s a t i o n de l ’ ORB
ORB orb = ORB . init ( args , null );
// R é c u p é r a t i o n de la r é f é r e n c e du servant
B u f f e r e d R e a d e r f i l e R e a d e r = new B u f f e r e d R e a d e r (
new F i l e R e a d e r( " O b j e c t R e f" ));
String s t r i n g I O R = f i l e R e a d e r. readLine ();
f i l e R e a d e r. close ();
// Création , à partir de la r é f é r e n c e du servant ,
// d ’ un proxy local
Forum f o r u m P r o x y =
F o r u m H e l p e r. narrow ( orb . s t r i n g _ t o _ o b j e c t ( s t r i n g I O R ));
// I n v o c a t i o n de méthodes d i s t a n t e s
Message m = new Message ( " CORBA " , " moi " ,
( new Date ()). toString () ,
" Corba c ’ est bien ! " );
f o r u m P r o x y. p o s t M e s s a g e ( m );
Message tmp = f o r u m P r o x y. g e t M e s s a g e( " CORBA " );
System . out . println ( " Titre : " + m . title );
System . out . println ( " Auteur : " + m . author );
System . out . println ( " Message : " + m . body );
8
} catch ( Reject r ) {
System . err . println ( r . message );
}
}
}
✁
x Exercice
4. Les paramètres out
Dans cet exercice nous souhaitons ajouter à l’interface Forum la méthode getInfo()
suivante, qui retourne les différentes informations sur le forum :
i n t e r f a c e Forum {
void getInfo ( out string theme , out string moderator ,
out long size );
};
Nous rappelons que les classes IntHolder et StringHolder, entre autres, permettent de transmettre des paramètres par référence ; ce qui permet de récupérer la
valeur si elle a été modifiée par le serveur.
✁
ForumImpl.java
/* *
* Retourne dans les a r g u m e n t s les i n f o r m a t i o n s sur le forum .
*/
public void getInfo ( S t r i n g H o l d e r theme , S t r i n g H o l d e r moderator ,
I n t H o l d e r size ) {
theme . value = this . theme ;
m o d e r a t o r. value = this . m o d e r a t o r;
size . value = messages . size ();
}
ForumClient.java
S t r i n g H o l d e r t h e m e H o l d e r = new S t r i n g H o l d e r ();
S t r i n g H o l d e r m o d e r a t o r H o l d e r = new S t r i n g H o l d e r ();
I n t H o l d e r s i z e H o l d e r = new I n t H o l d e r ();
f o r u m P r o x y. getInfo ( themeHolder , moderatorHolder , s i z e H o l d e r );
System . out . println ( " Theme : " + t h e m e H o l d e r. value );
System . out . println ( " M o d é r a t e u r : " + m o d e r a t o r H o l d e r . value );
System . out . println ( " Nombre de messages : " + s i z e H o l d e r. value );
✁
9
10