Cette annexe montre l'application CrnpClient.java dans son ensemble. Celle-ci est abordée en détails dans le Chapitre 12.
/* * CrnpClient.java * ================ * * Remarque concernant l'analyse XML : * * Ce programme utilise l'API Sun Java Architecture for XML Processing (JAXP). * Reportez-vous à http://java.sun.com/xml/jaxp/index.html pour obtenir de la documentation * sur les API ainsi que des informations relatives à leur disponibilité * des informations relatives à leur disponibilité. * * Ce programme a été rédigé pour Java 1.3.1 ou supérieur. * * Présentation du programme : * * Le thread principal du programme crée un objet CrnpClient, attend que * l'utilisateur mette un terme à la démonstration, puis appelle la fermeture de * l'objet CrnpClient et quitte le programme. * * Le constructeur de CrnpClient crée un objet EventReceptionThread, * ouvre une connexion au serveur CRNP (à l'aide de l'hôte et du port spécifiés * dans la ligne de commande), construit un message d'enregistrement (sur la base * des spécifications de la ligne de commande), envoie un message d'enregistrement, * puis lit et analyse la réponse. * * L'objet EventReceptionThread crée un socket d'écoute lié au * nom d'hôte de la machine sur laquelle tourne le programme et au port * spécifié sur la ligne de commande. Il attend un rappel d'événement entrant, * moment auquel il construit un document XML sur la base du flux de socket entrant, * qu'il transmet à l'objet CrnpClient pour traitement. * * La méthode de fermeture de l'objet CrnpClient envoie simplement un message de * désenregistrement (REMOVE_CLIENT) SC_CALLBACK_REG au serveur crnp. * * Remarque concernant la gestion des erreurs : pour être bref, ce programme * se ferme purement et simplement dans la plupart des cas. Il est évident qu'une * véritable application tenterait de gérer les erreurs de diverses manières, par exemple * en lançant de nouvelles tentatives, le cas échéant. */ // Packages JAXP import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import org.xml.sax.*; import org.xml.sax.helpers.*; import org.w3c.dom.*; // Packages standard import java.net.*; import java.io.*; import java.util.*; /* * class CrnpClient * ----------------- * Voir les commentaires présentés ci-dessus dans l'en-tête du fichier. */ class CrnpClient { /* * main * ---- * Point d'entrée de l'exécution, main vérifie surtout * le nombre d'arguments de ligne de commande et construit une instance * d'un CrnpClient chargé d'effectuer toutes les tâches. */ public static void main(String []args) { InetAddress regIp = null; int regPort = 0, localPort = 0; /* Vérifie le nombre d'arguments de ligne de commande */ if (args.length < 4) { System.out.println( "Usage: java CrnpClient Hôte_crnp Port_crnp " + "Port_local (-ac | -ae | -re) " + "[(M | A | RG=nom | R=nom) [...]]"); System.exit(1); } /* * Nous nous attendons à ce que la ligne de commande contienne l'adresse IP/le * port du serveur crnp, le port local d'écoute ainsi que des arguments * indiquant le type d'enregistrement. */ try { regIp = InetAddress.getByName(args[0]); regPort = (new Integer(args[1])).intValue(); localPort = (new Integer(args[2])).intValue(); } catch (UnknownHostException e) { System.out.println(e); System.exit(1); } // Créez le CrnpClient CrnpClient client = new CrnpClient(regIp, regPort, localPort, args); // Attendez maintenant que l'utilisateur souhaite terminer le programme System.out.println("Hit return to terminate demo..."); // la lecture sera bloquée jusqu'à ce que l'utilisateur entre quelque chose try { System.in.read(); } catch (IOException e) { System.out.println(e.toString()); } // fermez le client client.shutdown(); System.exit(0); } /* * ====================== * Méthodes publiques * ====================== */ /* * Constructeur de l'objet CrnpClient * ----------------------- * Ce constructeur analyse les arguments de ligne de commande, ce qui nous permet * de savoir comment contacter le serveur crnp, crée le thread de réception des * événements et le démarre, crée l'objet XML DocumentBuilderFactory et enfin, * s'enregistre auprès du serveur crnp pour les rappels. */ public CrnpClient(InetAddress regIpIn, int regPortIn, int localPortIn, String []clArgs) { try { regIp = regIpIn; regPort = regPortIn; localPort = localPortIn; regs = clArgs; /* * Configuration de l'usine du générateur de documents pour * le traitement du format xml. */ setupXmlProcessing(); /* * Création de l'objet EventReceptionThread, qui crée un * ServerSocket et le lie à une adresse IP et à un port locaux. */ createEvtRecepThr(); /* * Enregistrement auprès du serveur crnp. */ registerCallbacks(); } catch (Exception e) { System.out.println(e.toString()); System.exit(1); } } /* * processEvent * --------------- * Rappel de l'objet CrnpClient, utilisé par EventReceptionThread * quand il reçoit des rappels d'événements. */ public void processEvent(Event event) { /* * Pour les besoins de la démonstration, il vous suffit d'imprimer l'événement * sur System.out. Une véritable application utiliserait * l'événement d'une manière ou d'une autre. */ event.print(System.out); } /* * shutdown * ------------- * Désenregistrement du serveur CRNP. */ public void shutdown() { try { /* envoi d'un message de désenregistrement au serveur */ unregister(); } catch (Exception e) { System.out.println(e); System.exit(1); } } /* * ====================== * Méthodes des assistants privés * ====================== */ /* * setupXmlProcessing * -------------------- * Il crée l'usine du générateur de documents permettant * l'analyse des événements et réponses xml. */ private void setupXmlProcessing() throws Exception { dbf = DocumentBuilderFactory.newInstance(); // Il n'est pas nécessaire de valider dbf.setValidating(false); dbf.setExpandEntityReferences(false); // Nous souhaitons ignorer les commentaires et les blancs dbf.setIgnoringComments(true); dbf.setIgnoringElementContentWhitespace(true); // Combinez les sections CDATA et les noeuds TEXT. dbf.setCoalescing(true); } /* * createEvtRecepThr * ------------------- * Il crée un nouvel objet EventReceptionThread, enregistre l'adresse IP * et le port auxquels est lié le socket d'écoute et * démarre le thread. */ private void createEvtRecepThr() throws Exception { /* Création de l'objet du thread */ evtThr = new EventReceptionThread(this); /* * Démarrage du thread pour lancer l'écoute * des rappels d'envoi d'événements. */ evtThr.start(); } /* * registerCallbacks * ------------------ * Il établit une connexion de socket au serveur crnp et envoie * un message d'enregistrement d'événement. */ private void registerCallbacks() throws Exception { System.out.println("About to register"); /* * Création d'un socket connecté à l'adresse IP/au port d'enregistrement * du serveur crnp et envoi des informations d'enregistrement. */ Socket sock = new Socket(regIp, regPort); String xmlStr = createRegistrationString(); PrintStream ps = new PrintStream(sock.getOutputStream()); ps.print(xmlStr); /* * Lecture de la réponse */ readRegistrationReply(sock.getInputStream()); /* * Fermeture de la connexion de socket */ sock.close(); } /* * unregister * ---------- * Comme dans le cas de registerCallbacks, une connexion de socket est établie avec * le serveur crnp, le message de désenregistrement est envoyé et le système * attend la réponse du serveur, puis ferme le socket. */ private void unregister() throws Exception { System.out.println("About to unregister"); /* * Création d'un socket connecté à l'adresse IP/au port d'enregistrement * du serveur crnp et envoi des informations de désenregistrement. */ Socket sock = new Socket(regIp, regPort); String xmlStr = createUnregistrationString(); PrintStream ps = new PrintStream(sock.getOutputStream()); ps.print(xmlStr); /* * Lecture de la réponse */ readRegistrationReply(sock.getInputStream()); /* * Fermeture de la connexion de socket */ sock.close(); } /* * createRegistrationString * ------------------ * Il construit un objet CallbackReg basé sur les arguments de ligne de commande * de ce programme, puis récupère la chaîne XML depuis l'objet * CallbackReg. */ private String createRegistrationString() throws Exception { /* * Création de la classe CallbackReg à proprement parler et définition du port. */ CallbackReg cbReg = new CallbackReg(); cbReg.setPort("" + localPort); // définissez le type d'enregistrement if (regs[3].equals("-ac")) { cbReg.setRegType(CallbackReg.ADD_CLIENT); } else if (regs[3].equals("-ae")) { cbReg.setRegType(CallbackReg.ADD_EVENTS); } else if (regs[3].equals("-re")) { cbReg.setRegType(CallbackReg.REMOVE_EVENTS); } else { System.out.println("Invalid reg type: " + regs[3]); System.exit(1); } // ajoutez les événements for (int i = 4; i < regs.length; i++) { if (regs[i].equals("M")) { cbReg.addRegEvent( createMembershipEvent()); } else if (regs[i].equals("A")) { cbReg.addRegEvent( createAllEvent()); } else if (regs[i].substring(0,2).equals("RG")) { cbReg.addRegEvent(createRgEvent( regs[i].substring(3))); } else if (regs[i].substring(0,1).equals("R")) { cbReg.addRegEvent(createREvent( regs[i].substring(2))); } } String xmlStr = cbReg.convertToXml(); System.out.println(xmlStr); return (xmlStr); } /* * createAllEvent * ---------------- * Il crée un événement d'enregistrement XML avec une classe EC_Cluster et aucune * sous-classe. */ private Event createAllEvent() { Event allEvent = new Event(); allEvent.setClass("EC_Cluster"); return (allEvent); } /* * createMembershipEvent * ---------------------- * Il crée un événement d'enregistrement XML avec la classe EC_Cluster, sous-classe * ESC_cluster_memberhip. */ private Event createMembershipEvent() { Event membershipEvent = new Event(); membershipEvent.setClass("EC_Cluster"); membershipEvent.setSubclass("ESC_cluster_membership"); return (membershipEvent); } /* * createRgEvent * ---------------- * Il crée un événement d'enregistrement XML avec la classe EC_Cluster, * sous-classe ESC_cluster_rg_state, et aucun "nom_rg" nvpair (sur la base * du paramètre d'entrée). */ private Event createRgEvent(String rgname) { /* * Création d'un événement de changement d'état pour le * groupe de ressources nom_rg. Remarquez que nous fournissons * un couple nom/valeur (nvpair) pour ce type d'événement, pour * spécifier le groupe de ressources qui nous intéresse. */ /* * Construction de l'objet d'événement et paramétrage des classes et sous-classes. */ Event rgStateEvent = new Event(); rgStateEvent.setClass("EC_Cluster"); rgStateEvent.setSubclass("ESC_cluster_rg_state"); /* * Création de l'objet nvpair et ajout de celui-ci à l'événement */ NVPair rgNvpair = new NVPair(); rgNvpair.setName("rg_name"); rgNvpair.setValue(rgname); rgStateEvent.addNvpair(rgNvpair); return (rgStateEvent); } /* * createREvent * ---------------- * Il crée un événement d'enregistrement XML avec la classe EC_Cluster, * sous-classe ESC_cluster_r_state, et un nvpair "nom-r" (sur la base * du paramètre d'entrée). */ private Event createREvent(String rname) { /* * Création d'un événement de changement d'état pour * la ressource nom_rg. Remarquez que nous fournissons * un couple nom/valeur (nvpair) pour ce type d'événement afin * de spécifier le groupe de ressources qui nous intéresse. */ Event rStateEvent = new Event(); rStateEvent.setClass("EC_Cluster"); rStateEvent.setSubclass("ESC_cluster_r_state"); NVPair rNvpair = new NVPair(); rNvpair.setName("r_name"); rNvpair.setValue(rname); rStateEvent.addNvpair(rNvpair); return (rStateEvent); } /* * createUnregistrationString * ------------------ * Il construit un objet REMOVE_CLIENT CallbackReg, puis récupère * la chaîne XML de l'objet CallbackReg. */ private String createUnregistrationString() throws Exception { /* * Création de l'objet CallbackReg. */ CallbackReg cbReg = new CallbackReg(); cbReg.setPort("" + localPort); cbReg.setRegType(CallbackReg.REMOVE_CLIENT); /* * Classement de l'enregistrement dans l'OutputStream */ String xmlStr = cbReg.convertToXml(); // Imprimez la chaîne dans un but de débogage System.out.println(xmlStr); return (xmlStr); } /* * readRegistrationReply * ------------------------ * Il analyse le langage xml dans un document, construit un objet RegReply * à partir du document et imprime l'objet RegReply. Remarquez * qu'une véritable application agirait sur la base du status_code * de l'objet RegReply. */ private void readRegistrationReply(InputStream stream) throws Exception { // Créez le constructeur de document DocumentBuilder db = dbf.newDocumentBuilder(); // // Définissez un Gestionnaire d'erreur avant l'analyse // Utilisez le gestionnaire par défaut. // db.setErrorHandler(new DefaultHandler()); // analysez le fichier d'entrée Document doc = db.parse(stream); RegReply reply = new RegReply(doc); reply.print(System.out); } /* variables des membres privés */ private InetAddress regIp; private int regPort; private EventReceptionThread evtThr; private String regs[]; /* variables des membres publics */ public int localPort; public DocumentBuilderFactory dbf; } /* * class EventReceptionThread * ---------------------------- * Reportez-vous aux commentaires ci-dessus dans l'en-tête du fichier. */ class EventReceptionThread extends Thread { /* * Constructeur d'EventReceptionThread * ---------------------------------- * Il crée un nouveau ServerSocket, associé au nom d'hôte local et à * un port générique. */ public EventReceptionThread(CrnpClient clientIn) throws IOException { /* * Conservation d'une référence au client permettant de le rappeler * à la réception d'un événement. */ client = clientIn; /* * Spécification de l'adresse IP à laquelle s'associer. * Il s'agit simplement de l'IP de l'hôte local. S'il existe plus * d'une interface publique configurée sur cette * machine, nous suivons celle proposée par * InetAddress.getLocalHost. * */ listeningSock = new ServerSocket(client.localPort, 50, InetAddress.getLocalHost()); System.out.println(listeningSock); } /* * run * --- * Appelé par la méthode Thread.Start. * * Boucle infinie, attendant des connexions entrantes sur le ServerSocket. * * Toutes les connexions entrantes étant acceptées, un objet Event * est créé depuis le flux xml. Il est ensuite transmis à * l'objet CrnpClient pour traitement. */ public void run() { /* * Boucle infinie. */ try { // // Créez le constructeur de document à l'aide de l'usine // du constructeur dans le CrnpClient. // DocumentBuilder db = client.dbf.newDocumentBuilder(); // // Définissez un Gestionnaire d'erreur avant l'analyse // Utilisez le gestionnaire par défaut. // db.setErrorHandler(new DefaultHandler()); while(true) { /* Attente d'un rappel du serveur */ Socket sock = listeningSock.accept(); // analysez le fichier d'entrée Document doc = db.parse(sock.getInputStream()); Event event = new Event(doc); client.processEvent(event); /* Fermeture du socket */ sock.close(); } // IMPOSSIBLE À ATTEINDRE } catch (Exception e) { System.out.println(e); System.exit(1); } } /* Variables des membres privés */ private ServerSocket listeningSock; private CrnpClient client; } /* * classe NVPair * ----------- * Cette classe enregistre une paire nom/valeur (deux chaînes). Elle sait comment * construire un message NVPAIR XML depuis ses membres et comment décomposer * un élément NVPAIR XML en ses membres. * * Remarquez que la spécification formelle d'un couple NVPAIR autorise plusieurs valeurs. * Pour simplifier, nous nous basons ici sur une seule valeur. */ class NVPair { /* * Deux constructeurs : le premier crée un couple NVPair vide, le second * un couple NVPair depuis un élément NVPAIR XML. */ public NVPair() { name = value = null; } public NVPair(Element elem) { retrieveValues(elem); } /* * Réglages publics. */ public void setName(String nameIn) { name = nameIn; } public void setValue(String valueIn) { value = valueIn; } /* * Impression du nom et de la valeur sur une seule ligne. */ public void print(PrintStream out) { out.println("NAME=" + name + " VALUE=" + value); } /* * createXmlElement * ------------------ * Il construit un élément NVPAIR XML à partir des variables des membres. * Il considère le document comme un paramètre, de manière à pouvoir créer * l'élément. */ public Element createXmlElement(Document doc) { // Créez l'élément. Element nvpair = (Element) doc.createElement("NVPAIR"); // // Ajoutez le nom. Remarquez que le nom actuel est // une section CDATA séparée. // Element eName = doc.createElement("NAME"); Node nameData = doc.createCDATASection(name); eName.appendChild(nameData); nvpair.appendChild(eName); // // Ajoutez la valeur. Remarquez que la valeur actuelle est // une section CDATA séparée. // Element eValue = doc.createElement("VALUE"); Node valueData = doc.createCDATASection(value); eValue.appendChild(valueData); nvpair.appendChild(eValue); return (nvpair); } /* * retrieveValues * ---------------- * Il analyse l'élément XML pour récupérer le nom et la valeur. */ private void retrieveValues(Element elem) { Node n; NodeList nl; // // Trouvez l'élément NOM // nl = elem.getElementsByTagName("NAME"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "NAME node."); return; } // // Obtenez la section TEXT // n = nl.item(0).getFirstChild(); if (n == null || n.getNodeType() != Node.TEXT_NODE) { System.out.println("Error in parsing: can't find " + "TEXT section."); return; } // Récupérez la valeur name = n.getNodeValue(); // // Définissez maintenant l'élément de valeur // nl = elem.getElementsByTagName("VALUE"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "VALUE node."); return; } // // Définissez la section TEXT // n = nl.item(0).getFirstChild(); if (n == null || n.getNodeType() != Node.TEXT_NODE) { System.out.println("Error in parsing: can't find " + "TEXT section."); return; } // Récupérez la valeur value = n.getNodeValue(); } /* * Accès public */ public String getName() { return (name); } public String getValue() { return (value); } // Var membre privé private String name, value; } /* * class Event * ----------- * Cette classe enregistre un événement se composant d'une classe, d'une sous-classe, * d'un fournisseur, d'un éditeur et d'une liste de couples nom/valeur. Elle sait * comment construire un élément SC_EVENT_REG XML à partir de ses membres et comment * décomposer un élément SC_EVENT XML en ses membres. Remarquez qu'il existe une * asymétrie ici : nous analysons des éléments SC_EVENT, mais construisons des * éléments SC_EVENT_REG. Ceci est dû au fait que les éléments SC_EVENT_REG sont * (que nous devons construire), alors que les éléments SC_EVENT sont utilisés dans * utilisés dans des messages d'enregistrement les envois d'événements (que nous * devons analyser). La seule différence réside dans le fait que les éléments SC_EVENT_REG * n'ont pas de fournisseurs ou d'éditeurs. */ class Event { /* * Deux constructeurs : le premier crée un événement vide. Le second * crée un événement à partir d'un document SC_EVENT XML. */ public Event() { regClass = regSubclass = null; nvpairs = new Vector(); } public Event(Document doc) { nvpairs = new Vector(); // // Convertissez le document en une chaîne à imprimer dans un but de // débogage. // DOMSource domSource = new DOMSource(doc); StringWriter strWrite = new StringWriter(); StreamResult streamResult = new StreamResult(strWrite); TransformerFactory tf = TransformerFactory.newInstance(); try { Transformer transformer = tf.newTransformer(); transformer.transform(domSource, streamResult); } catch (TransformerException e) { System.out.println(e.toString()); return; } System.out.println(strWrite.toString()); // Procédez à l'analyse actuelle. retrieveValues(doc); } /* * Réglages publics. */ public void setClass(String classIn) { regClass = classIn; } public void setSubclass(String subclassIn) { regSubclass = subclassIn; } public void addNvpair(NVPair nvpair) { nvpairs.add(nvpair); } /* * createXmlElement * ------------------ * Il construit un élément SC_EVENT_REG XML à partir des variables des membres. * Il considère le document comme un paramètre afin de pouvoir créer * l'élément. Il se fonde sur la capacité NVPair createXmlElement. */ public Element createXmlElement(Document doc) { Element event = (Element) doc.createElement("SC_EVENT_REG"); event.setAttribute("CLASS", regClass); if (regSubclass != null) { event.setAttribute("SUBCLASS", regSubclass); } for (int i = 0; i < nvpairs.size(); i++) { NVPair tempNv = (NVPair) (nvpairs.elementAt(i)); event.appendChild(tempNv.createXmlElement( doc)); } return (event); } /* * Impression des variables des membres sur plusieurs lignes. */ public void print(PrintStream out) { out.println("\tCLASS=" + regClass); out.println("\tSUBCLASS=" + regSubclass); out.println("\tVENDOR=" + vendor); out.println("\tPUBLISHER=" + publisher); for (int i = 0; i < nvpairs.size(); i++) { NVPair tempNv = (NVPair) (nvpairs.elementAt(i)); out.print("\t\t"); tempNv.print(out); } } /* * retrieveValues * ---------------- * Analyse du document XML pour récupérer la classe, la sous-classe, le fournisseur, * l'éditeur et les couples nvpair. */ private void retrieveValues(Document doc) { Node n; NodeList nl; // // Trouvez l'élément SC_EVENT. // nl = doc.getElementsByTagName("SC_EVENT"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "SC_EVENT node."); return; } n = nl.item(0); // // Récupérez les valeurs des attributs de CLASS, SUBCLASS, // VENDOR et PUBLISHER. // regClass = ((Element)n).getAttribute("CLASS"); regSubclass = ((Element)n).getAttribute("SUBCLASS"); publisher = ((Element)n).getAttribute("PUBLISHER"); vendor = ((Element)n).getAttribute("VENDOR"); // // Récupérez toutes les paires nv // for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) { nvpairs.add(new NVPair((Element)child)); } } /* * Méthodes d'accès public. */ public String getRegClass() { return (regClass); } public String getSubclass() { return (regSubclass); } public String getVendor() { return (vendor); } public String getPublisher() { return (publisher); } public Vector getNvpairs() { return (nvpairs); } // Var membre privé. private String regClass, regSubclass; private Vector nvpairs; private String vendor, publisher; } /* * classe CallbackReg * ----------- * Cette classe enregistre un port et un regType (deux chaînes) ainsi qu'une liste . * des événements. Elle sait comment construire un message SC_CALLBACK_REG XML à partir * de ses membres. * * Remarquez que cette classe ne doit pas être en mesure d'analyser les messages * SC_CALLBACK_REG parce que seul le serveur CRNP doit * le faire. */ class CallbackReg { // Définition utile pour la méthode setRegType public static final int ADD_CLIENT = 0; public static final int ADD_EVENTS = 1; public static final int REMOVE_EVENTS = 2; public static final int REMOVE_CLIENT = 3; public CallbackReg() { port = null; regType = null; regEvents = new Vector(); } /* * Réglages publics. */ public void setPort(String portIn) { port = portIn; } public void setRegType(int regTypeIn) { switch (regTypeIn) { case ADD_CLIENT: regType = "ADD_CLIENT"; break; case ADD_EVENTS: regType = "ADD_EVENTS"; break; case REMOVE_CLIENT: regType = "REMOVE_CLIENT"; break; case REMOVE_EVENTS: regType = "REMOVE_EVENTS"; break; default: System.out.println("Error, invalid regType " + regTypeIn); regType = "ADD_CLIENT"; break; } } public void addRegEvent(Event regEvent) { regEvents.add(regEvent); } /* * convertToXml * ------------------ * Il construit un document SC_CALLBACK_REG XML à partir des variables * des membres. Il se fonde sur la capacité Event createXmlElement. */ public String convertToXml() { Document document = null; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.newDocument(); } catch (ParserConfigurationException pce) { // L'analyseur avec des options spécifiques ne peut être créé pce.printStackTrace(); System.exit(1); } Element root = (Element) document.createElement( "SC_CALLBACK_REG"); root.setAttribute("VERSION", "1.0"); root.setAttribute("PORT", port); root.setAttribute("REG_TYPE", regType); for (int i = 0; i < regEvents.size(); i++) { Event tempEvent = (Event) (regEvents.elementAt(i)); root.appendChild(tempEvent.createXmlElement( document)); } document.appendChild(root); // // Convertissez maintenant le document en chaîne. // DOMSource domSource = new DOMSource(document); StringWriter strWrite = new StringWriter(); StreamResult streamResult = new StreamResult(strWrite); TransformerFactory tf = TransformerFactory.newInstance(); try { Transformer transformer = tf.newTransformer(); transformer.transform(domSource, streamResult); } catch (TransformerException e) { System.out.println(e.toString()); return (""); } return (strWrite.toString()); } // var membre privé private String port; private String regType; private Vector regEvents; } /* * class RegReply * ----------- * Cette classe enregistre un code_état et un msg_état (deux chaînes). * Elle sait comment décomposer un élément SC_REPLY XML en ses membres. */ class RegReply { /* * L'unique constructeur prend un document XML et l'analyse. */ public RegReply(Document doc) { // // Convertissez maintenant le document en chaîne. // DOMSource domSource = new DOMSource(doc); StringWriter strWrite = new StringWriter(); StreamResult streamResult = new StreamResult(strWrite); TransformerFactory tf = TransformerFactory.newInstance(); try { Transformer transformer = tf.newTransformer(); transformer.transform(domSource, streamResult); } catch (TransformerException e) { System.out.println(e.toString()); return; } System.out.println(strWrite.toString()); retrieveValues(doc); } /* * Accès public */ public String getStatusCode() { return (statusCode); } public String getStatusMsg() { return (statusMsg); } /* * Impression des informations sur une seule ligne. */ public void print(PrintStream out) { out.println(statusCode + ": " + (statusMsg != null ? statusMsg : "")); } /* * retrieveValues * ---------------- * Analyse des documents XML pour récupérer le Code_état et le Msg_état. */ private void retrieveValues(Document doc) { Node n; NodeList nl; // // Trouvez l'élément SC_REPLY. // nl = doc.getElementsByTagName("SC_REPLY"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "SC_REPLY node."); return; } n = nl.item(0); // Récupérez la valeur du STATUS_CODE attribute statusCode = ((Element)n).getAttribute("STATUS_CODE"); // // Trouvez l'élément SC_STATUS_MSG // nl = ((Element)n).getElementsByTagName("SC_STATUS_MSG"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "SC_STATUS_MSG node."); return; } // // Obtenez la section TEXT, le cas échéant. // n = nl.item(0).getFirstChild(); if (n == null || n.getNodeType() != Node.TEXT_NODE) { // Aucune erreur s'il n'y en a pas, par conséquent nous // revenons simplement sans message. return; } // Récupérez la valeur statusMsg = n.getNodeValue(); } // var membre privé private String statusCode; private String statusMsg; }