IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API standards et tierces Java Discussion :

Probleme avec la recherche directe de methodes sur une Class (API java.lang.reflect) [FAQ]


Sujet :

API standards et tierces Java

  1. #1
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Points : 4 314
    Points
    4 314
    Par défaut Probleme avec la recherche directe de methodes sur une Class (API java.lang.reflect)
    Bonjour. Voici mon probleme, avec un exemple simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    public class TestClass {
      public void afficheInt(int i) {
        System.out.println(i);
      }
      public void afficheInteger(Integer i) {
        afficheInt(i.intValue());
      }
    }
     
    public class TrouverMethodes {
      public static void main(String[] args) {
        Class maClasseDeTest = TestClass.class;
        Class[] arguments = { Integer.class };
        try {
          maClasseDeTest.getMethod("afficheInteger", arguments);
          System.out.println("methode trouvee");
        } catch (Exception e) {
          System.out.println("probleme!");
        }
        try {
          maClasseDeTest.getMethod("afficheInt", arguments);
          System.out.println("methode trouvee");
        } catch (Exception e) {
          System.out.println("probleme!");
        }
      }
    }
    Ma premiere recherche de methode se passe correctement, alors que la deuxieme lève une Exception "MethodNotFound". Ce n'est pas étonnant, cette méthode attend un paramètre de type "int" et non "Integer".

    Seulement voilà, je dois absolument réussir à obtenir la méthode afficheInt de ma TestClass via un "getMethod". Ma question est donc: comment faire, puisque getMethod attend comme 2e argument un tableau de Class et que l'argument "int" attendu par afficheInt est une primitive.

    (Note: pour ceux qui voudraient tester le code, il manque les "import", et mon tableau d'arguments n'est par typé car je travaille en java 1.4.2)

    Merci d'avance pour toutes vos idées.

  2. #2
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Class[] arguments2 = { Integer.TYPE };
    		
    try {
    	maClasseDeTest.getMethod("afficheInt", arguments2);
    	System.out.println("methode trouvee");
    } catch (Exception e) {
    	System.out.println("probleme!");
    }

  3. #3
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Je ne sais pas pourquoi (une intuition), mais j'ai l'impression que tu utilises l'introspection à mauvais escient...

    Dans quel but tu veux l'utiliser précisément?

  4. #4
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    A noter que l'on peut également utiliser int.class, mais je ne suis pas sûr que cela fonctionne avec le JDK 1.4.2 (ca marche sûr sur le 5.0).

    a++

  6. #6
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Points : 4 314
    Points
    4 314
    Par défaut
    Citation Envoyé par bulbo
    Je dirais meme plus:
    Effectivement... J'avais bien été voir la FAQ mais je n'avais pas trouvé le chapître sur la réflexivité. Toutes mes excuses!

    Citation Envoyé par ®om
    Je ne sais pas pourquoi (une intuition), mais j'ai l'impression que tu utilises l'introspection à mauvais escient...
    Dans quel but tu veux l'utiliser précisément?
    J'ai programmé cet exemple de façon à expliquer mon problème simplement. En réalité, je travaille sur une application dont le paramétrage est obtenu dynamiquement à partir d'un fichier de configuration XML.
    Or dans ce fichier de paramétrage, j'ai (entre autres) une liste de classes et de méthodes à invoquer dessus (avec leurs arguments). Comme je récupère toutes ces informations sous forme de texte, je suis (à mon grand regret d'ailleurs) obligé de travailler de la manière la plus générique possible et en utilisant la réflexivité.

    En tout cas, merci à tous pour vos réponses on ne peut plus rapides. Je peux passer ce post en résolu (même si je me retrouve maintenant avec un problème qui découle directement de la réponse... ;-) )

  7. #7
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par CyberChouan
    J'ai programmé cet exemple de façon à expliquer mon problème simplement. En réalité, je travaille sur une application dont le paramétrage est obtenu dynamiquement à partir d'un fichier de configuration XML.
    Or dans ce fichier de paramétrage, j'ai (entre autres) une liste de classes et de méthodes à invoquer dessus (avec leurs arguments). Comme je récupère toutes ces informations sous forme de texte, je suis (à mon grand regret d'ailleurs) obligé de travailler de la manière la plus générique possible et en utilisant la réflexivité.
    Oki

    C'est que ça arrive souvent que des gens utilisent la réflexivité pour appeler une méthode au lieu d'utiliser une interface

  8. #8
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par CyberChouan
    J'ai programmé cet exemple de façon à expliquer mon problème simplement. En réalité, je travaille sur une application dont le paramétrage est obtenu dynamiquement à partir d'un fichier de configuration XML.
    On dirait du Spring...

  9. #9
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2004
    Messages
    265
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2004
    Messages : 265
    Points : 342
    Points
    342
    Par défaut
    Citation Envoyé par pseudocode
    On dirait du Spring...
    On dirait meme plus généralement le pattern IOC non ?

  10. #10
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par gailuris
    On dirait meme plus généralement le pattern IOC non ?
    Pour etre plus precis, c'est le pattern "dependency injection"

  11. #11
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Points : 4 314
    Points
    4 314
    Par défaut
    Citation Envoyé par pseudocode
    On dirait du Spring...
    Effectivement, j'ai déjà travaillé avec Spring et je suis tout à fait conscient que je suis en train de "copier" son système de chargement de paramétrage (et en moins bien). Cependant, je n'ai pas le choix... c'est le projet qui veut ça.

    Du coup, je crée et j'utilise des classes qui ressemblent à des "Beans", dont les attributs qui ont besoin d'être manipulés par l'XML ont les accesseurs associés.

    Ensuite, quand je lis param="X" dans mon XML, je fais une recherche et une invocation de la méthode setParam(String) avec le paramètre "X" sur la classe concernée.

  12. #12
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par CyberChouan
    Effectivement, j'ai déjà travaillé avec Spring et je suis conscient que je suis en train de "copier" son système de chargement de paramétrage (et en moins bien). Cependant, je n'ai pas le choix... c'est le projet qui veut ça.
    Oui, je connais ca.

    Moi: "il faudrait tout recoder en utilisant Spring"
    Eux: "Non, on a pas le temps et c'est trop risqué de toucher au code."
    Moi: "C'est sur, y a moins de risque a recoder Spring nous meme !! "

  13. #13
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Points : 4 314
    Points
    4 314
    Par défaut
    Question subsidiaire par rapport à mon problème initial...

    Pour rechercher une méthode, j'ai donc: son nom, ainsi qu'un tableau de Class.
    Cependant, si la méthode attend un int, mon tableau de classes actuel contient un Integer. De même si ma méthode attend une List, mon tableau de classes peut contenir une LinkedList.

    Donc ce qu'il me faudrait, c'est un algorithme de recherche qui effectue la recherche de la méthode:
    - avec les classes demandées
    - avec les types de base des classes demandées
    - avec les superClass et les interfaces des classes demandées

    Je suppose que je ne suis pas le premier à avoir ce problème et je me demandais si vous connaissiez un Framework ou une classe résolvant ce problème.

  14. #14
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par CyberChouan
    Je suppose que je ne suis pas le premier à avoir ce problème et je me demandais si vous connaissiez un Framework ou une classe résolvant ce problème.
    org.apache.commons.beanutils.MethodUtils.invokeMethod()

  15. #15
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Points : 4 314
    Points
    4 314
    Par défaut
    Exactement ce qu'il me fallait! Merci.

    Entretemps, j'avais redéveloppé quelque chose de similaire pour mes besoins. Si jamais ça vous intéresse, vous pouvez librement copier, améliorer, compléter...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
     
    /*
     * Created on 25 janv. 07
     */
     
    import java.lang.reflect.Method;
    import java.util.LinkedList;
    import java.util.List;
     
    /**
     * @author CyberChouan
     * @version 2007.01.25
     */
    public class MethodUtils {
     
    	/**
             * Lors de l'invocation d'une {@link Method} via la methode 'invoke',
             * si le parametre attendu est une primitive, l'invocation avec en
             * parametre l'objet associe fonctionne
             * @param expected
             * @param given
             * @return
             */
    	public static boolean isInvocableFrom(Class expected, Class given) {
    		if(expected.isAssignableFrom(given)) {
    			return true;
    		} else if (hasWrapper(expected)) {
    			return given.equals(getWrapper(expected));
    		} else {
    			return false;
    		}
    	}
     
    	public static boolean hasPrimitive(Class javaClass) {
    		if(javaClass.equals(Integer.class)) { return true; }
    		if(javaClass.equals(Long.class)) { return true; }
    		if(javaClass.equals(Float.class)) { return true; }
    		if(javaClass.equals(Double.class)) { return true; }
    		if(javaClass.equals(Short.class)) { return true; }
    		if(javaClass.equals(Void.class)) { return true; }
    		if(javaClass.equals(Character.class)) { return true; }
    		if(javaClass.equals(Byte.class)) { return true; }
    		if(javaClass.equals(Boolean.class)) { return true; }
    		return false;
    	}
     
    	public static Class getPrimitive(Class javaClass) {
    		if(javaClass.equals(Integer.class)) { return Integer.TYPE; }
    		if(javaClass.equals(Long.class)) { return Long.TYPE; }
    		if(javaClass.equals(Float.class)) { return Float.TYPE; }
    		if(javaClass.equals(Double.class)) { return Double.TYPE; }
    		if(javaClass.equals(Short.class)) { return Short.TYPE; }
    		if(javaClass.equals(Void.class)) { return Void.TYPE; }
    		if(javaClass.equals(Character.class)) { return Character.TYPE; }
    		if(javaClass.equals(Byte.class)) { return Byte.TYPE; }
    		if(javaClass.equals(Boolean.class)) { return Boolean.TYPE; }
    		return null;
    	}
     
    	public static boolean hasWrapper(Class javaClass) {
    		if(javaClass.equals(Integer.TYPE)) { return true; }
    		if(javaClass.equals(Long.TYPE)) { return true; }
    		if(javaClass.equals(Float.TYPE)) { return true; }
    		if(javaClass.equals(Double.TYPE)) { return true; }
    		if(javaClass.equals(Short.TYPE)) { return true; }
    		if(javaClass.equals(Void.TYPE)) { return true; }
    		if(javaClass.equals(Character.TYPE)) { return true; }
    		if(javaClass.equals(Byte.TYPE)) { return true; }
    		if(javaClass.equals(Boolean.TYPE)) { return true; }
    		return false;
    	}
     
    	public static Class getWrapper(Class javaClass) {
    		if(javaClass.equals(Integer.TYPE)) { return Integer.class; }
    		if(javaClass.equals(Long.TYPE)) { return Long.class; }
    		if(javaClass.equals(Float.TYPE)) { return Float.class; }
    		if(javaClass.equals(Double.TYPE)) { return Double.class; }
    		if(javaClass.equals(Short.TYPE)) { return Short.class; }
    		if(javaClass.equals(Void.TYPE)) { return Void.class; }
    		if(javaClass.equals(Character.TYPE)) { return Character.class; }
    		if(javaClass.equals(Byte.TYPE)) { return Byte.class; }
    		if(javaClass.equals(Boolean.TYPE)) { return Boolean.class; }
    		return null;
    	}
     
    	/**
             * Recherche une methode nommee 'methodName', invocable a partir d'arguments
             * de types parameterTypes. Si plusieurs methodes correcpondantes sont trouvees,
             * on en renvoie une au hasard (la premiere de la liste) 
             * @param methodClass
             * @param methodName
             * @param parameterTypes
             * @return
             */
    	public static Method findMethod(Class methodClass, String methodName, Class[] parameterTypes) {
    		try { return findExactMethod(methodClass, methodName, parameterTypes);} 
    		catch (Exception e) {
    			List methods = getMethods(methodClass, methodName, parameterTypes.length);
    			List invocableMethods  = findInvocableMethods(methods, parameterTypes);
     
    			if(invocableMethods.size() > 0) {
    				return (Method) invocableMethods.get(0);
    			} else {
    				return null;
    			}
    		}
    	}
     
    	public static List findInvocableMethods(List methods, Class[] parameterTypes) {
    		Method method;
    		List invocableMethods = new LinkedList();
    		for(int i=0; i<methods.size(); i++) {
    			method = (Method) methods.get(i);
    			if(isInvocableFrom(method, parameterTypes)) {
    				invocableMethods.add(method);
    			}
    		}
    		return invocableMethods;
    	}
    	/**
             * Utilisation directe de la methode 'getMethod' de {@link Class} 
             * @param methodClass
             * @param methodName
             * @param parameterTypes
             * @return
             * @throws SecurityException
             * @throws NoSuchMethodException
             */
    	public static Method findExactMethod(Class methodClass, String methodName, Class[] parameterTypes) 
    		throws SecurityException, NoSuchMethodException {
    		return methodClass.getMethod(methodName, parameterTypes);
    	}
     
    	public static boolean isInvocableFrom(Method method, Class[] argsTypes) {
    		Class[] expectedArgsTypes = method.getParameterTypes();
     
    		// Si le nombre d'arguments n'est pas le meme, la methode n'est pas
    		// 'invocable' a partir des arguments proposes
    		if (argsTypes.length != expectedArgsTypes.length) {
    			return false;
    		}
     
    		// Si un des types est incompatible, la methode n'est pas
    		// 'invocable' a partir des arguments propos 
    		for(int i=0; i<argsTypes.length; i++) {
    			if(!isInvocableFrom(expectedArgsTypes[i], argsTypes[i])) {
    				return false;
    			}
    		}
    		return true;
    	}
     
    	/**
             * Renvoie la liste des methodes de la classe 'methodClass' qui portent le nom
             * 'name', et qui prennent 'nbArgs' arguments
             * @param methodsClass
             * @param name
             * @param nbArgs
             * @return
             */
    	public static List getMethods(Class methodsClass, String name, int nbArgs) {
    		Method[] classMethods = methodsClass.getMethods();
    		Method temp;
    		List result = new LinkedList();
     
    		for(int i=0; i<classMethods.length; i++) {
    			temp = classMethods[i];
    			if(temp.getName().equals(name) && temp.getParameterTypes().length == nbArgs) {
    				result.add(temp);
    			}
    		}
    		return result;
    	}
     
    	/**
             * Renvoie la liste des 'getters' d'une classe, c'est a dire les methodes
             * dont le nom commence par 'get' (ou 'is' si l'attribut de la classe est
             * booleen) et qui n'ont pas de parametres
             * @param javaClass
             * @return
             */
    	public static List getGetters(Class javaClass) {
    		Method[] classMethods = javaClass.getMethods();
    		Method temp;
    		List result = new LinkedList();
     
    		for(int i=0; i<classMethods.length; i++) {
    			temp = classMethods[i];
    			if((temp.getName().startsWith("get") || temp.getName().startsWith("is"))
    				&& temp.getParameterTypes().length == 0) {
    				result.add(temp);
    			}
    		}
    		return result;
    	}
     
     
    	public static void main(String[] args) {
    		System.out.println(isInvocableFrom(Integer.TYPE, Integer.class));
     
    	}
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 13/09/2007, 17h07
  2. problem avec la recherche d'une valeur dans les table
    Par anilane dans le forum Bases de données
    Réponses: 6
    Dernier message: 25/05/2007, 19h35
  3. Réponses: 3
    Dernier message: 09/04/2006, 13h04
  4. Réponses: 3
    Dernier message: 18/03/2006, 19h51
  5. Réponses: 2
    Dernier message: 10/10/2005, 02h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo