• Aucun résultat trouvé

Les resolvers définissent la politique de séquencement au niveau des greffons et non pas au niveau des aspects. De plus, le compilateur d’AIRIA signale une erreur pour chaque interaction entre greffon non résolu ce qui répond à notre besoin d’appliquer une résolution explicite et systématique des interférences potentielles. Pour la mise en œuvre de la détection d’interfé- rences à base d’assertion, il n’existe pas d’extension ASPECTJ spécifique.

La contribution principale de cette thèse est de démontrer que l’extensionAIRIA- ciblant les

questions de séquencement - est également suffisante pour rendre la détection d’interférences possible. Cela est dû au fait que la construction de resolver ajoute davantage d’observabilité à ASPECTJ. Les points d’observation manquants deviennent disponibles, ce qui nous permet de

mettre en œuvre la détection des interférences à l’aide d’assertions.

Un resolver est une sorte de greffon around utilisé pour contrôler la composition des gref- fons à des points de jonction partagés, c’est-à-dire un greffon pour composer des greffons. Un exemple est donné dans le listing4.1. Les caractéristiques du resolver sont les suivantes. Un re- solver est défini par un mot-clé suivi d’un nom de resolver et d’une liste de paramètres (sender et une liste vide dans le listing4.1, ligne 2). De plus, le resolver précise quand il contrôle la com- position (par l’intermédiaire de la clause and / or) et comment le séquencement des greffons est réalisé (par le biais de la clause proceed). La clause and / or du resolver fonctionne comme une expression de coupe, sauf qu’elle spécifie une liste de greffons potentiellement en conflit (listing4.1, ligne 3). Lorsque les greffons spécifiés dans la clause and / or sont tissés à un point de jonction partagé, le resolver est tissé en premier à ce point de jonction, afin de gérer le sé- quencement des greffons. En d’autres termes, un resolver est un greffon possédant une priorité plus élevée que les greffons qu’il gère.

Un resolver ayant également le statut de greffon, il peut être manipulé par un autre resol- ver, ce qui donne des hiérarchies de resolvers. Il est important de noter que tous les greffons dansAIRIAsont des greffons de type "autour". Ainsi, pour mettre en œuvre un greffon de type

"avant", nous utilisons simplement un greffon de type "autour" muni d’une partie "après" vide. De même, nous mettons en œuvre un greffon "après" par un greffon de type "autour" muni

qu’ils possèdent un nom unique. Par exemple, dans le listing4.1, la ligne 3 se réfère à un gref- fon nommé logMsg appartenant à l’aspect Alog.

Un resolver spécifie une précédence à grain fin entre les greffons. Dans le listing4.1, le resol- ver sender est appliqué à chaque point de jonction où les greffons ALog.logMsg, ACrypt.encrypt, AAuth.auth sont tissés (comme spécifié dans la clause and). La liste entre crochets détermine l’ordre d’exécution de la clause proceed (Listing4.1, ligne 4). Dans notre exemple, AAuth.auth est appliqué en premier, puis Alog.logMsg est appliqué et enfin ACrypt.encrypt chiffre le mes- sage avant de l’envoyer.

1 aspect LogEncryptAuth {

2 void resolver sender () :

3 and( ALog . logMsg , ACrypt . encrypt , AAuth . auth ){

4 [ AAuth . auth , ALog . logMsg , ACrypt . encrypt ]. proceed () ;}}

Listing 4.1 – Utilisation de resolver dans notre exemple

La liste entre crochets peut être considérée comme représentant la chaîne d’exécution des greffons sur la figure4.1. Cette représentation s’avère pratique pour la détection d’interférences, parce que toutes les transitions dans le cycle de vie sont désormais rendues explicites. Nous pouvons insérer des greffons supplémentaires dans le séquencement pour la capture des va- riables d’état, l’observation des modifications de leur valeur, la capture des événements, lever ou abaisser des drapeaux, etc. Notez cependant que le listing4.1représente un cas simple où tous les greffons sont gérés par un seul resolver. Dans le cas général, le séquencement peut être défini en utilisant des resolvers de resolvers, comme l’illustrent les listings4.2et4.3. Dans cet exemple, nous avons un resolver pour la journalisation et le chiffrement (Listing4.3). Il est in- voqué par un resolver racine (Listing4.2) qui gère aussi le chiffrement. L’ordre qui en résulte pour les trois greffons est le même que dans le listing4.1, même si cela n’est pas intuitif.

En effet le listing4.2indique que pour les greffons gérés par le resolver LogEncryptAuth.sender l’ordre de précédence est celui figurant dans la clause proceed de ce dernier, c’est-à-dire Log- Crypt. logCrypt< AAuth.auth < ALog.logMsg comme l’indique la partie supérieure de l’arbre de resolvers décrit dans la figure4.2.

L’ordre de précédence défini par le greffon LogCrypt.logCrypt est ALog.logMsg < ACrypt.encrypt ce qui correspond à la partie inférieure de l’arbre décrit dans la figure figure4.2. Finalement l’ordre de précédence définie par l’arbre figure dans la partie droite de la figure 4.2et cor- respond à l’ordre total suivant LogEncryptAuth.sender < LogCrypt. logCrypt < AAuth.auth < ALog.logMsg < ACrypt.encrypt.

1 aspect LogEncryptAuth {

2 void resolver sender () :

3 and( LogCrypt . logCrypt , AAuth . auth , ALog . logMsg ){

4 [ LogCrypt . logCrypt , AAuth . auth , ALog . logMsg ]. proceed () ;}}

Listing 4.2 – Utilisation de resolver de resolvers (partie 1 : resolver racine)

Le compilateur d’AIRIAvérifie que, quel que soit le point de jonction partagé, un resolver de

racine unique gère les conflits à ce point de jonction. Un ordre d’exécution total doit être obtenu à partir de l’arbre de resolvers à partir de la racine (voir [74] pour plus de détails). On peut ainsi contrôler précisément l’ordre des greffons. L’insertion des greffons d’instrumentation doit être adaptée à de telles structures arborescentes.

LogEncryptAuth.sender

LogCrypt. logCrypt AAuth.auth ALog.logMsg ALog.logMsg ACrypt.encrypt

LogEncryptAuth.sender <LogCrypt. logCrypt < AAuth.auth <ALog.logMsg < ACrypt.encrypt

Gère

Est invoqué avant

FIGURE4.2 – Ordre total induit par les listing4.2et4.3

1 aspect LogCrypt {

2 void resolver logCrypt () :

3 and( ALog . logMsg , ACrypt . encrypt ){

4 [ ALog . logMsg , ACrypt . encrypt ]. proceed () ;}}

Listing 4.3 – Utilisation de resolver de resolvers (partie 2 : resolver auxiliaire)