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