Solaris OS용 Sun Cluster 데이터 서비스 개발 안내서

CRNP를 사용하는 Java 응용 프로그램 생성 예

다음 예에서는 CRNP를 사용하는 CrnpClient라는 간단한 Java 응용 프로그램을 개발하는 방법을 보여줍니다. 이 응용 프로그램은 클러스터의 CRNP 서버에 이벤트 콜백을 등록하고 이러한 이벤트 콜백을 수신하며 해당 내용을 인쇄하여 이벤트를 처리합니다. 종료하기 전에 이 응용 프로그램은 이벤트 콜백에 대한 요청을 등록 취소합니다.

다음 사항에 주의하면서 이 예를 검토합니다.

Procedure환경 설정 방법

단계
  1. JAXP와 올바른 버전의 Java 컴파일러 및 가상 머신을 다운로드하여 설치합니다.

    http://java.sun.com/xml/jaxp/index.html에서 지침을 확인할 수 있습니다.


    주 –

    이 예를 사용하려면 Java 1.3.1 이상이 필요합니다.


  2. 소스 파일이 있는 디렉토리에서 다음을 입력합니다.


    % 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 . source-filename.java
    

    여기서 jaxp-root는 JAXP jar 파일이 있는 디렉토리의 절대 또는 상대 경로 이며 source-filename은 Java 소스 파일의 이름입니다.

    컴파일러가 JAXP 클래스를 찾을 수 있도록 컴파일 명령줄에 classpath 를 지정해야 합니다.

  3. 응용 프로그램을 실행할 때 응용 프로그램이 적절한 JAXP 클래스 파일을 로드할 수 있도록 다음과 같이 classpath를 지정합니다. classpath의 첫 번째 경로는 현재 디렉토리입니다.


    % java -cp .:jaxp-root/dom.jar:jaxp-rootjaxp-api. \
    jar:jaxp-rootsax.jar:jaxp-rootxalan.jar:jaxp-root/xercesImpl \
    .jar:jaxp-root/xsltc.jar source-filename arguments
    

    이제 환경이 구성되었으므로 응용 프로그램을 개발할 수 있습니다.

Procedure응용 프로그램 개발 시작 방법

이 부분의 예에서는 명령줄 인자를 구문 분석하고 CrnpClient 객체를 생성하는 주 메소드를 가진 CrnpClient라는 기본 클래스를 만듭니다. 이 객체는 클래스에 명령줄 인자를 전달하고 사용자가 응용 프로그램을 종료하기를 기다렸다가 CrnpClient에서 shutdown을 호출한 다음 종료합니다.

CrnpClient 클래스의 구성자는 다음 작업을 실행해야 합니다.

단계

    앞의 논리를 구현하는 Java 코드를 만듭니다.

    다음 예에서는 CrnpClient 클래스의 스켈레톤 코드를 보여줍니다. 구성자 및 종료 메소드에서 참조되는 4개의 도우미 메소드에 대한 구현은 나중에 표시됩니다. 필요한 모든 패키지를 가져오는 코드가 표시됩니다.

    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;
    }

    구성원 변수에 대해서는 나중에 자세히 설명됩니다.

Procedure명령줄 인자 구문 분석 방법

단계

    명령줄 인자를 구문 분석하려면 부록 G, CrnpClient.java 응용 프로그램의 코드를 참조하십시오.

Procedure이벤트 수신 스레드 정의 방법

이벤트 스레드가 차단되어 이벤트 콜백을 대기하는 동안 응용 프로그램에서 다른 작업을 계속할 수 있으려면 코드에서 이벤트 수신이 별도의 스레드에서 수행되도록 지정해야 합니다.


주 –

XML 설정에 대해서는 나중에 자세히 설명됩니다.


단계
  1. ServerSocket을 만들고 이 소켓에서 이벤트가 도착하기를 기다리는 EventReceptionThread라는 Thread 하위 클래스를 코드에 정의합니다.

    이 코드 예 부분에서는 이벤트를 읽거나 처리하지 않습니다. 이벤트 읽기 및 처리에 대해서는 나중에 자세히 설명됩니다. EventReceptionThread는 와일드카드 인터네트워킹 프로토콜 주소에서 ServerSocket을 만듭니다. EventReceptionThreadCrnpClient 객체에 대한 참조를 유지하므로 EventReceptionThread에서 처리할 CrnpClient 객체에 이벤트를 보낼 수 있습니다.

    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. createEvtRecepThr 객체를 생성합니다.

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

Procedure콜백 등록 및 등록 취소 방법

등록 작업은 다음과 같이 구성됩니다.

단계
  1. 앞의 논리를 구현하는 Java 코드를 만듭니다.

    다음 예제 코드에서는 CrnpClient 구성자에 의해 호출되는 CrnpClient 클래스의 registerCallbacks 메소드에 대한 구현을 보여줍니다. createRegistrationString()readRegistrationReply() 호출에 대해서는 나중에 자세히 설명됩니다.

    regIpregPort는 구성자에 의해 설정되는 객체 구성원입니다.

    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. unregister 메소드를 구현합니다.

    이 메소드는 CrnpClientshutdown 메소드에 의해 호출됩니다. createUnregistrationString 구현에 대해서는 나중에 자세히 설명됩니다.

    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();
    }

ProcedureXML 생성 방법

이제 응용 프로그램의 구조를 설정하고 모든 네트워킹 코드를 작성했으므로 XML을 생성 및 구문 분석하는 코드를 작성합니다. 먼저 SC_CALLBACK_REG XML 등록 메시지를 생성하는 코드를 작성합니다.

SC_CALLBACK_REG 메시지는 등록 유형(ADD_CLIENT, REMOVE_CLIENT, ADD_EVENTS 또는 REMOVE_EVENTS), 콜백 포트 및 원하는 이벤트 목록으로 구성됩니다. 각 이벤트는 클래스 및 하위 클래스로 구성되며 이름 및 값 쌍 목록이 그 뒤에 옵니다.

이 예 부분에서는 등록 유형, 콜백 포트 및 등록 이벤트 목록을 저장하는 CallbackReg 클래스를 작성합니다. 이 클래스는 또한 SC_CALLBACK_REG XML 메시지에 대해 자신을 일련화할 수 있습니다.

이 클래스에서 흥미로운 메소드는 클래스 구성원에서 SC_CALLBACK_REG XML 메시지 문자열을 만드는 convertToXml 메소드입니다. http://java.sun.com/xml/jaxp/index.html의 JAXP 설명서에는 이 메소드의 코드가 자세히 설명되어 있습니다.

다음 예제 코드에는 Event 클래스의 구현이 나와 있습니다. CallbackReg 클래스는 하나의 이벤트를 저장하고 이 이벤트를 XML Element로 변환할 수 있는 Event 클래스를 사용합니다.

단계
  1. 앞의 논리를 구현하는 Java 코드를 만듭니다.

    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. EventNVPair 클래스를 구현합니다.

    CallbackReg 클래스는 NVPair 클래스를 직접 사용하는 Event 클래스를 사용합니다.

    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;
    }

Procedure등록 및 등록 취소 메시지 작성 방법

이제 XML 메시지를 생성하는 도우미 클래스를 만들었으므로 createRegistrationString 메소드의 구현을 작성할 수 있습니다. 이 메소드는 콜백 등록 및 등록 취소 방법에 설명된 registerCallbacks 메소드에 의해 호출됩니다.

createRegistrationStringCallbackReg 객체를 생성하고 해당 등록 유형 및 포트를 설정합니다. 그런 다음 createRegistrationStringcreateAllEvent, createMembershipEvent, createRgEventcreateREvent 도우미 메소드를 사용하여 다양한 이벤트를 생성합니다. CallbackReg 객체가 만들어진 후에 각 이벤트는 이 객체에 추가됩니다. 마지막으로 createRegistrationStringCallbackReg 객체에서 convertToXml 메소드를 호출하여 String 형태로 XML 메시지를 검색합니다.

regs 구성원 변수는 사용자가 응용 프로그램에 제공하는 명령줄 인자를 저장합니다. 다섯 번째 및 그 이후의 인자는 응용 프로그램이 등록해야 하는 이벤트를 지정합니다. 네 번째 인자는 등록 유형을 지정하지만 이 예에서는 무시됩니다. 부록 G, CrnpClient.java 응용 프로그램의 전체 코드에는 이 네 번째 인자를 사용하는 방법이 나와 있습니다.

단계
  1. 앞의 논리를 구현하는 Java 코드를 만듭니다.

    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. 등록 취소 문자열을 만듭니다.

    등록 취소 문자열을 만드는 것은 이벤트를 수용할 필요가 없기 때문에 등록 문자열을 만드는 것보다 쉽습니다.

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

ProcedureXML 구문 분석기 설정 방법

이제 응용 프로그램의 네트워킹 및 XML 생성 코드를 만들었습니다. CrnpClient 구성자는 setupXmlProcessing 메소드를 호출합니다. 이 메소드는 DocumentBuilderFactory 객체를 만들고 이 객체에 대한 다양한 구분 분석 등록 정보를 설정합니다. JAXP 설명서에 이 메소드가 자세히 설명되어 있습니다. http://java.sun.com/xml/jaxp/index.html을 참조하십시오.

단계

    앞의 논리를 구현하는 Java 코드를 만듭니다.

    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);
    }

Procedure등록 응답 구문 분석 방법

등록 또는 등록 취소 메시지에 응답하여 CRNP 서버가 보낸 SC_REPLY XML 메시지를 구분 분석하려면 RegReply 도우미 클래스가 필요합니다. 이 클래스는 XML 문서에서 생성할 수 있습니다. 이 클래스는 상태 코드와 상태 메시지에 대한 액세서를 제공합니다. 서버의 XML 스트림을 구문 분석하려면 새 XML 문서를 만들고 이 문서의 구문 분석 메소드를 사용해야 합니다. http://java.sun.com/xml/jaxp/index.html의 JAXP 설명서에 이 메소드가 자세히 설명되어 있습니다.

단계
  1. 앞의 논리를 구현하는 Java 코드를 만듭니다.

    readRegistrationReply 메소드는 새 RegReply 클래스를 사용한다는 점에 주의합니다.

    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. RegReply 클래스를 구현합니다.

    retrieveValues 메소드가 XML 문서의 DOM 트리를 통과하면서 상태 코드와 상태 메시지를 추출한다는 것에 주의합니다. http://java.sun.com/xml/jaxp/index.html의 JAXP 설명서에 자세한 내용 이 나와 있습니다.

    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;
    }

Procedure콜백 이벤트 구문 분석 방법

마지막 단계는 실제 콜백 이벤트를 구분 분석 및 처리하는 것입니다. 이 작업을 지원하기 위해 XML 생성 방법에서 만든 Event 클래스를 수정하여 이 클래스가 XML 문서에서 Event를 생성하고 XML Element를 만들 수 있게 합니다. 이러한 변경 작업에는 XML 문서를 사용하는 추가 구성자, retrieveValues 메소드, 두 개의 추가 구성원 변수(vendorpublisher), 모든 필드에 대한 액세서 메소드 및 마지막으로 인쇄 메소드가 필요합니다.

단계
  1. 앞의 논리를 구현하는 Java 코드를 만듭니다.

    이 코드는 등록 응답 구문 분석 방법에 설명된 RegReply 클래스의 코드와 비슷합니다.

    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. XML 구문 분석을 지원하는 NVPair 클래스에 대한 추가 구성자와 메소드를 구현합니다.

    단계 1에 표시된 것처럼 Event 클래스를 변경하려면 NVPair 클래스를 비슷하게 변경해야 합니다.

    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. 이벤트 콜백을 대기하는 EventReceptionThread에서 while 루프를 구현합니다.

    EventReceptionThread 이벤트 수신 스레드 정의 방법에 설명되어 있습니다.

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

Procedure응용 프로그램 실행 방법

단계
  1. 수퍼유저가 되거나 동등한 역할을 맡습니다.

  2. 응용 프로그램을 실행합니다.


    # java CrnpClient crnpHost crnpPort localPort ...
    

    CrnpClient 응용 프로그램의 전체 코드는 부록 G, CrnpClient.java 응용 프로그램에 나와 있습니다.