Sun Cluster Entwicklerhandbuch Datendienste für Solaris OS

Beispiel zum Erstellen einer Java-Anwendung, die das CRNP verwendet

Das folgende Beispiel zeigt, wie eine einfache Java-Anwendung namens CrnpClient entwickelt wird, die das CRNP verwendet. Die Anwendung wird für Ereignisrückrufe mit dem CRNP-Server im Cluster registriert, hört die Ereignisrückrufe ab und verarbeitet die Ereignisse durch Drucken ihres Inhalts. Vor der Beendigung deregistriert die Anwendung ihre Anforderung von Ereignisrückmeldungen.

Beachten Sie folgende Punkte beim Prüfen dieses Beispiels:

ProcedureSo konfigurieren Sie Ihre Umgebung

Schritte
  1. Laden Sie JAXP und die richtige Version des Java-Compilers und der Virtual Machine herunter, und installieren Sie sie.

    Anweisungen hierzu finden Sie unter http://java.sun.com/xml/jaxp/index.html.


    Hinweis –

    Für dieses Beispiel ist mindestens Java 1.3.1 erforderlich.


  2. Geben Sie in dem Verzeichnis, in dem sich Ihre Quelldatei befindet, Folgendes ein:


    % javac -classpath jaxp-root/dom.jar:jaxp-rootjaxp-api. \
    jar:jaxp-rootsax.jar:jaxp-rootxalan.jar:jaxp-root/xercesImpl \
    .jar:jaxp-root/xsltc.jar -sourcepath . Quelldateiname.java
    

    wobei jaxp-root den absoluten oder relativen Pfad des Verzeichnisses darstellt, in dem sich die JAXP-jar-Dateien befinden und Quelldateiname den Namen der Java-Quelldatei bezeichnet.

    Ein classpath in Ihrer Kompilierungsbefehlszeile stellt sicher, dass der Compiler die JAXP-Klassen finden kann.

  3. Geben Sie beim Ausführen der Anwendung den classpath so an, dass die Anwendung die richtigen JAXP-Klassendateien laden kann (Beachten Sie, dass es sich bei dem ersten Pfad im classpath um das aktuelle Verzeichnis handelt):


    % java -cp .:jaxp-root/dom.jar:jaxp-rootjaxp-api. \
    jar:jaxp-rootsax.jar:jaxp-rootxalan.jar:jaxp-root/xercesImpl \
    .jar:jaxp-root/xsltc.jar Quelldateiname Argumente
    

    Damit ist die Umgebung konfiguriert, und Sie können die Anwendung entwickeln.

ProcedureEntwickeln Ihrer Anwendung

In diesem Teil des Beispiels können Sie eine Basisklasse namens CrnpClient erstellen, zusammen mit einer Hauptmethode, mit der die Befehlszeilenargumente geparst werden und ein CrnpClient-Objekt erstellt wird. Dieses Objekt übergibt die Befehlszeilenargumente an die Klasse, wartet, bis der Benutzer die Anwendung beendet, ruft shutdown für CrnpClient auf und wird dann beendet.

Der Konstruktor der CrnpClient-Klasse muss folgende Aufgaben ausführen:

Schritt

    Erstellen Sie den Java-Code, der die vorstehende Logik implementiert.

    Das folgende Beispiel zeigt den Hauptcode für die CrnpClient-Klasse. Die Implementierung der vier Helper-Methoden, auf die im Konstruktor verwiesen wird, sowie die Shutdown-Methoden werden weiter unten in diesem Kapitel beschrieben. Beachten Sie, dass der Code, mit dem alle erforderlichen Pakete importiert werden, dargestellt wird.

    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.*;
    import java.net.*;
    import java.io.*;
    import java.util.*;
    
    class CrnpClient
    {
            public static void main(String []args)
            {
                    InetAddress regIp = null;
                    int regPort = 0, localPort = 0;
                    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);
                    }
                    CrnpClient client = new CrnpClient(regIp, regPort, 
                        localPort, args);
                    System.out.println("Hit return to terminate demo...");
                    try {
                            System.in.read();
                    } catch (IOException e) {
                            System.out.println(e.toString());
                    }
                    client.shutdown();
                    System.exit(0);
            }
    
            public CrnpClient(InetAddress regIpIn, int regPortIn, 
                int localPortIn, String []clArgs)
            {
                    try {
                            regIp = regIpIn;
                            regPort = regPortIn;
                            localPort = localPortIn;
                            regs = clArgs;
                            setupXmlProcessing();
                            createEvtRecepThr();
                            registerCallbacks();
                    } catch (Exception e) {
                            System.out.println(e.toString());
                            System.exit(1);
                    }
            }
    
            public void shutdown()
            {
                    try {
                            unregister();
                    } catch (Exception e) {
                            System.out.println(e);
                            System.exit(1);
                    }
            }
    
            private InetAddress regIp;
            private int regPort;
            private EventReceptionThread evtThr;
            private String regs[];
            public int localPort;
            public DocumentBuilderFactory dbf;
    }

    Die Mitgliedsvariablen werden weiter unten in diesem Kapitel detailliert erläutert.

ProcedureSo parsen Sie die Befehlszeilenargumente

Schritt

    Wie Sie die Befehlszeilenargumente parsen, erfahren Sie im Code in Anhang G, CrnpClient.java-Anwendung .

ProcedureSo definieren Sie den Ereignis-Empfangs-Thread

Im Code müssen Sie sicherstellen, dass der Ereignisempfang über einen eigenen Thread ausgeführt wird, so dass die Anwendung anderweitig weiterarbeiten kann, wenn der Thread blockiert ist und auf Ereignisrückmeldungen wartet.


Hinweis –

Die XML-Konfiguration wird weiter unten in diesem Kapitel erläutert.


Schritte
  1. Definieren Sie in Ihrem Code eine Thread-Unterklasse namens EventReceptionThread, die eine ServerSocket erstellt und darauf wartet, dass die Ereignisse am Socket ankommen.

    In diesem Teil des Beispielcodes werden Ereignisse weder gelesen noch verarbeitet. Lesen und Verarbeiten von Ereignissen, die weiter unten in diesem Kapitel erläutert werden. EventReceptionThread erstellt einen ServerSocket an einer Platzhalter-Netzwerkprotokolladresse. EventReceptionThread behält auch einen Verweis auf das CrnpClient -Objekt, sodass EventReceptionThread Ereignisse zur Verarbeitung an das CrnpClient-Objekt senden kann.

    class EventReceptionThread extends Thread
    {
            public EventReceptionThread(CrnpClient clientIn) throws IOException
            {
                    client = clientIn;
                    listeningSock = new ServerSocket(client.localPort, 50,
                        InetAddress.getLocalHost());
            }
    
            public void run()
            {
                    try {
                            DocumentBuilder db = client.dbf.newDocumentBuilder();
                            db.setErrorHandler(new DefaultHandler());
    
                            while(true) {
                                    Socket sock = listeningSock.accept();
                                    // Construct event from the sock stream and process it
                                    sock.close();
                            }
                            // UNREACHABLE
    
                    } catch (Exception e) {
                            System.out.println(e);
                            System.exit(1);
                    }
            }
    
            /* private member variables */
            private ServerSocket listeningSock;
            private CrnpClient client;
    }
  2. Erstellen Sie ein createEvtRecepThr-Objekt.

    private void createEvtRecepThr() throws Exception
    {
            evtThr = new EventReceptionThread(this);
            evtThr.start();
    }

ProcedureSo registrieren und deregistrieren Sie Rückrufe

Für die Registrierungsaufgabe sind folgende Aktionen erforderlich:

Schritte
  1. Erstellen Sie den Java-Code, der die vorstehende Logik implementiert.

    Folgender Beispielcode zeigt die Implementierung der registerCallbacks-Methode der CrnpClient-Klasse (die vom CrnpClient-Konstruktur aufgerufen wird). Die Aufrufe von createRegistrationString() und readRegistrationReply () werden weiter unten in diesem Kapitel detailliert beschrieben.

    regIp und regPort sind Objektmitglieder, die vom Konstruktur eingerichtet werden.

    private void registerCallbacks() throws Exception
    { 
            Socket sock = new Socket(regIp, regPort);
            String xmlStr = createRegistrationString();
            PrintStream ps = new 
                    PrintStream(sock.getOutputStream());
            ps.print(xmlStr);
            readRegistrationReply(sock.getInputStream();
            sock.close();
    }
  2. Implementieren Sie die unregister-Methode.

    Diese Methode wird von der shutdown-Methode von CrnpClient aufgerufen. Die Implementierung von createUnregistrationString wird weiter unten in diesem Kapitel detailliert beschrieben.

    private void unregister() throws Exception
    {
            Socket sock = new Socket(regIp, regPort);
            String xmlStr = createUnregistrationString();
            PrintStream ps = new PrintStream(sock.getOutputStream());
            ps.print(xmlStr);
            readRegistrationReply(sock.getInputStream());
            sock.close();
    }

ProcedureSo generieren Sie die XML

Nachdem Sie nun die Struktur der Anwendung eingerichtet und den gesamten Netzwerkcode geschrieben haben, müssen Sie den Code schreiben, der die XML generiert und parst. Beginnen Sie damit, den Code, mit dem die SC_CALLBACK_REG-XML-Registrierungsmeldung generiert wird, zu schreiben.

Eine SC_CALLBACK_REG-Meldung besteht aus einem Registrierungstyp (ADD_CLIENT, REMOVE_CLIENT, ADD_EVENTS oder REMOVE_EVENTS), einem Rückruf-Port und einer Liste mit wichtigen Ereignissen. Jedes Ereignis besteht aus einer Klasse und einer Unterklasse, gefolgt von einer Liste der Namens- und Wertepaare.

In diesem Teil des Beispiels schreiben Sie eine CallbackReg-Klasse, die den Registrierungstyp, den Rückmelde-Port und die Liste der Registrierungsereignisse speichert. Diese Klasse kann sich auch selbst in eine SC_CALLBACK_REG-XML-Meldung serialisieren.

Eine interessante Methode dieser Klasse ist die convertToXml-Methode, die eine SC_CALLBACK_REG-XML-Meldungszeichenkette aus den Klassenmitgliedern erstellt. In der JAXP-Dokumentation unter http://java.sun.com/xml/jaxp/index.html wird der Code dieser Methode detailliert beschrieben.

Die Implementierung der Event-Klasse wird im folgenden Beispielcode dargestellt. Beachten Sie, dass die CallbackReg-Klasse eine Event-Klasse verwendet, das ein Ereignis speichert und das dieses Ereignis in ein XML- Element konvertieren kann.

Schritte
  1. Erstellen Sie den Java-Code, der die vorstehende Logik implementiert.

    class CallbackReg
    {
            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();
            }
    
            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);
            } 
    
            public String convertToXml()
            {
                    Document document = null;
                    DocumentBuilderFactory factory =
                        DocumentBuilderFactory.newInstance();
                    try {
                            DocumentBuilder builder = factory.newDocumentBuilder();
                            document = builder.newDocument(); 
                    } catch (ParserConfigurationException pce) {
                            // Parser with specified options can't be built
                            pce.printStackTrace();
                            System.exit(1);
                    }
    
                    // Create the root element
                    Element root = (Element) document.createElement("SC_CALLBACK_REG");
    
                    // Add the attributes
                    root.setAttribute("VERSION", "1.0");
                    root.setAttribute("PORT", port);
                    root.setAttribute("regType", regType);
    
                    // Add the events
                    for (int i = 0; i < regEvents.size(); i++) {
                            Event tempEvent = (Event)
                                (regEvents.elementAt(i));
                            root.appendChild(tempEvent.createXmlElement(document));
                    }
                    document.appendChild(root);
    
                    // Convert the whole thing to a string
                    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());
            }
    
            private String port;
            private String regType;
            private Vector regEvents;
    }
  2. Implementieren Sie die Event- und NVPair-Klassen.

    Beachten Sie, dass die CallbackReg-Klasse eine Event-Klasse verwendet, die wiederum eine NVPair -Klasse verwendet.

    class Event
    {
    
            public Event()
            {
                    regClass = regSubclass = null;
                    nvpairs = new Vector();
            }
    
            public void setClass(String classIn)
            {
                    regClass = classIn;
            }
    
            public void setSubclass(String subclassIn)
            {
                    regSubclass = subclassIn;
            }
    
            public void addNvpair(NVPair nvpair)
            {
                    nvpairs.add(nvpair);
            }
    
            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);
            }
    
            private String regClass, regSubclass;
            private Vector nvpairs;
    }
    
    class NVPair
    {
            public NVPair()
            {
                    name = value = null;
            }
    
            public void setName(String nameIn)
            {
                    name = nameIn;
            }
    
            public void setValue(String valueIn)
            {
                    value = valueIn;
            }
    
            public Element createXmlElement(Document doc)
            {
                    Element nvpair = (Element)
                        doc.createElement("NVPAIR");
                    Element eName = doc.createElement("NAME");
                    Node nameData = doc.createCDATASection(name);
                    eName.appendChild(nameData);
                    nvpair.appendChild(eName);
                    Element eValue = doc.createElement("VALUE");
                    Node valueData = doc.createCDATASection(value);
                    eValue.appendChild(valueData);
                    nvpair.appendChild(eValue);
    
                    return (nvpair);
            }
    
            private String name, value;
    }

ProcedureSo erstellen Sie die Registrierungs- und Deregistrierungsmeldungen

Nachdem Sie die Helper-Klassen, die die XML-Meldungen generieren, erstellt haben, können Sie die Implementierung der createRegistrationString-Methode schreiben. Diese Methode wird von der registerCallbacks-Methode aufgerufen, die unter So registrieren und deregistrieren Sie Rückrufe beschrieben wird.

createRegistrationString erstellt ein CallbackReg-Objekt und richtet dessen Registrierungstyp und Port ein. Anschließend konstruiert createRegistrationString unter Verwendung der createAllEvent-, createMembershipEvent-, createRgEvent- und createREvent-Helper-Methoden verschiedene Ereignisse. Jedes Ereignis wird diesem Objekt nach Erstellung des CallbackReg-Objekts hinzugefügt. Zuletzt ruft createRegistrationString die convertToXml-Methode des CallbackReg-Objekts auf, um die XML-Meldung im String-Format abzurufen.

Beachten Sie, dass die regs-Mitgliedsvariable die Befehlszeilenargumente speichert, die ein Benutzer der Anwendung liefert. Das fünfte und alle folgenden Argumente geben die Ereignisse an, für die eine Anwendung registriert werden soll. Das vierte Argument gibt den Registrierungstyp an; es wird in diesem Beispiel jedoch übergangen. Der vollständige Code in Anhang G, CrnpClient.java-Anwendung zeigt, wie dieses vierte Argument verwendet wird.

Schritte
  1. Erstellen Sie den Java-Code, der die vorstehende Logik implementiert.

    private String createRegistrationString() throws Exception
    {
            CallbackReg cbReg = new CallbackReg();
            cbReg.setPort("" + localPort);
    
            cbReg.setRegType(CallbackReg.ADD_CLIENT);
    
            // add the events
            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();
            return (xmlStr);
    }
    
    private Event createAllEvent()
    {
            Event allEvent = new Event();
            allEvent.setClass("EC_Cluster");
            return (allEvent);
    }
    
    private Event createMembershipEvent()
    {
            Event membershipEvent = new Event();
            membershipEvent.setClass("EC_Cluster");
            membershipEvent.setSubclass("ESC_cluster_membership");
            return (membershipEvent);
    }
    
    private Event createRgEvent(String rgname)
    {
            Event rgStateEvent = new Event();
            rgStateEvent.setClass("EC_Cluster");
            rgStateEvent.setSubclass("ESC_cluster_rg_state");
    
            NVPair rgNvpair = new NVPair();
            rgNvpair.setName("rg_name");
            rgNvpair.setValue(rgname);
            rgStateEvent.addNvpair(rgNvpair);
    
            return (rgStateEvent);
    }
    
    private Event createREvent(String rname)
    {
            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);
    }
  2. Erstellen Sie die Deregistrierungs-Zeichenkette.

    Das Erstellen der Deregistrierungszeichenkette ist einfacher als das Erstellen der Registrierungszeichenkette, da Sie keine Ereignisse zu berücksichtigen brauchen.

    private String createUnregistrationString() throws Exception
    {
            CallbackReg cbReg = new CallbackReg();
            cbReg.setPort("" + localPort);
            cbReg.setRegType(CallbackReg.REMOVE_CLIENT);
            String xmlStr = cbReg.convertToXml();
            return (xmlStr);
    }

ProcedureSo konfigurieren Sie den XML-Parser

Bisher wurden der Netzwerk- und der XML-Generierungscode für die Anwendung erstellt. Der CrnpClient-Konstruktur ruft eine setupXmlProcessing -Methode auf. Mit dieser Methode wird ein DocumentBuilderFactory-Objekt erstellt und es werden verschiedene Parsing-Eigenschaften für dieses Objekt eingerichtet. In der JAXP-Dokumentation wird diese Methode detailliert beschrieben. Weitere Informationen finden Sie unter http://java.sun.com/xml/jaxp/index.html.

Schritt

    Erstellen Sie den Java-Code, der die vorstehende Logik implementiert.

    private void setupXmlProcessing() throws Exception
    {
            dbf = DocumentBuilderFactory.newInstance();
    
            // We don't need to bother validating
            dbf.setValidating(false);
            dbf.setExpandEntityReferences(false);
    
            // We want to ignore comments and whitespace
            dbf.setIgnoringComments(true);
            dbf.setIgnoringElementContentWhitespace(true);
    
            // Coalesce CDATA sections into TEXT nodes.
            dbf.setCoalescing(true);
    }

ProcedureSo parsen Sie die Registrierungsantwort

Um die SC_REPLY-XML-Meldung zu parsen, die vom CRNP-Server als Antwort auf eine Registrierungs- oder Deregistrierungsmeldung gesendet wird, benötigen Sie eine RegReply -Helper-Klasse. Diese Klasse kann aufbauend auf einem XML-Dokument erstellt werden. Die Klasse ermöglicht den Zugang zum Statuscode und zur Statusmeldung. Um den XML-Stream vom Server zu parsen, müssen Sie ein neues XML-Dokument erstellen und die Parse-Methode dieses Dokuments verwenden. In der JAXP-Dokumentation unter http://java.sun.com/xml/jaxp/index.html wird diese Methode detailliert beschrieben.

Schritte
  1. Erstellen Sie den Java-Code, der die vorstehende Logik implementiert.

    Beachten Sie, dass die readRegistrationReply-Methode die neue RegReply-Klasse verwendet.

    private void readRegistrationReply(InputStream stream) throws Exception
    {
            // Create the document builder
            DocumentBuilder db = dbf.newDocumentBuilder();
            db.setErrorHandler(new DefaultHandler());
    
            //parse the input file
            Document doc = db.parse(stream);
    
            RegReply reply = new RegReply(doc);
            reply.print(System.out);
    }
  2. Implementieren Sie die RegReply-Klasse.

    Beachten Sie, dass die retrieveValues-Methode der DOM-Struktur im XML-Dokument folgt und den Statuscode und die Statusmeldung abruft. Die JAXP-Dokumentation unter http://java.sun.com/xml/jaxp/index.html enthält weitere Informationen.

    class RegReply
    {
            public RegReply(Document doc)
            {
                    retrieveValues(doc);
            }
    
            public String getStatusCode()
            {
                    return (statusCode);
            }
    
            public String getStatusMsg()
            {
                    return (statusMsg);
            }
            public void print(PrintStream out)
            {
                    out.println(statusCode + ": " +
                        (statusMsg != null ? statusMsg : ""));
            }
    
            private void retrieveValues(Document doc)
            {
                    Node n;
                    NodeList nl;
                    String nodeName;
    
                    // Find the SC_REPLY element.
                    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);
    
                    // Retrieve the value of the statusCode attribute
                    statusCode = ((Element)n).getAttribute("STATUS_CODE");
    
                    // Find the SC_STATUS_MSG element
                    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;
                    }
                    // Get the TEXT section, if there is one.
                    n = nl.item(0).getFirstChild();
                    if (n == null || n.getNodeType() != Node.TEXT_NODE) {
                    // Not an error if there isn't one, so we just silently return.
                            return;
                    }
    
                    // Retrieve the value
                    statusMsg = n.getNodeValue();
            }
    
            private String statusCode;
            private String statusMsg;
    }

ProcedureSo parsen Sie die Rückrufereignisse

Der letzte Schritt besteht in der Analyse und Verarbeitung der Rückmeldeereignisse selbst. Ändern Sie dazu die Event-Klasse, die Sie unter So generieren Sie die XML erstellt haben, so, dass diese Klasse ein Event aus einem XML-Dokument konstruieren und ein XML- Element erstellen kann. Für diese Änderung sind ein zusätzlicher Konstruktor (der ein XML-Dokument verwendet), eine retrieveValues-Methode, das Hinzufügen von zwei Mitgliedsvariablen (vendor und publisher), Zugriffsmethoden für alle Felder und schließlich eine Druckmethode erforderlich.

Schritte
  1. Erstellen Sie den Java-Code, der die vorstehende Logik implementiert.

    Note that this code is similar to the code for the RegReply class that is described in So parsen Sie die Registrierungsantwort.

    public Event(Document doc)
            {
                    nvpairs = new Vector();
                    retrieveValues(doc);
            }
            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);
                    }
            }
    
            private void retrieveValues(Document doc)
            {
                    Node n;
                    NodeList nl;
                    String nodeName;
    
                    // Find the SC_EVENT element.
                    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);
    
                    //
                    // Retrieve the values of the CLASS, SUBCLASS,
                    // VENDOR and PUBLISHER attributes.
                    //
                    regClass = ((Element)n).getAttribute("CLASS");
                    regSubclass = ((Element)n).getAttribute("SUBCLASS");
                    publisher = ((Element)n).getAttribute("PUBLISHER");
                    vendor = ((Element)n).getAttribute("VENDOR");
    
                    // Retrieve all the nv pairs
                    for (Node child = n.getFirstChild(); child != null;
                        child = child.getNextSibling())
                    {
                           nvpairs.add(new NVPair((Element)child));
                    }
            }
    
            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);
            }
    
            private String vendor, publisher;
  2. Implementieren Sie die zusätzlichen Konstruktoren und Methoden für die NVPair-Klasse, die das XML-Parsen unterstützt.

    Die Änderungen an der Event-Klasse, die in Schritt 1 abgebildet sind, setzen ähnliche Änderungen an der NVPair-Klasse voraus.

    public NVPair(Element elem)
            {
                    retrieveValues(elem);
            }
            public void print(PrintStream out)
            {
                    out.println("NAME=" + name + " VALUE=" + value);
            }
            private void retrieveValues(Element elem)
            {
                    Node n;
                    NodeList nl;
                    String nodeName;
    
                    // Find the NAME element
                    nl = elem.getElementsByTagName("NAME");
                    if (nl.getLength() != 1) {
                       System.out.println("Error in parsing: can't find "
                           + "NAME node.");
                       return;
                    }
                    // Get the TEXT section
                    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;
                    }
    
                    // Retrieve the value
                    name = n.getNodeValue();
    
                    // Now get the value element
                    nl = elem.getElementsByTagName("VALUE");
                    if (nl.getLength() != 1) {
                       System.out.println("Error in parsing: can't find "
                           + "VALUE node.");
                       return;
                    }
                    // Get the TEXT section
                    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;
                    }
    
                    // Retrieve the value
                    value = n.getNodeValue();
                    }
    
            public String getName()
            {
                    return (name);
            }
    
            public String getValue()
            {
                    return (value);
            }
    }
  3. Implementieren Sie die while-Schleife in EventReceptionThread, die auf Ereignisrückrufe wartet.

    EventReceptionThread wird in So definieren Sie den Ereignis-Empfangs-Thread beschrieben.

    while(true) {
                    Socket sock = listeningSock.accept();
                    Document doc = db.parse(sock.getInputStream());
                    Event event = new Event(doc);
                    client.processEvent(event);
                    sock.close();
            }

ProcedureSo führen Sie die Anwendung aus

Schritte
  1. Nehmen Sie Superuser-Status oder eine entsprechende administrative Rolle an.

  2. Führen Sie die Anwendung aus.


    # java CrnpClient CRNPHost CMPPort LokalerPort ...
    

    Der vollständige Code für die CrnpClient-Anwendung befindet sich in Anhang G, CrnpClient.java-Anwendung .