Contenu de CrnpClient.java
/*
* 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;
}