com.moadbus.banking.iso.core.protocol.ConfigParser.java Source code

Java tutorial

Introduction

Here is the source code for com.moadbus.banking.iso.core.protocol.ConfigParser.java

Source

/*
j8583 A Java implementation of the ISO8583 protocol
Copyright (C) 2007 Enrique Zamudio Lopez
    
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
    
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */
package com.moadbus.banking.iso.core.protocol;

import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.net.URL;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.moadbus.banking.util.Config;

/**
 * Class to Parse the config xml
 *
 * @author Venu Sathu
 */
public class ConfigParser {

    private static final Log log = LogFactory.getLog(ConfigParser.class);
    private static MessageFactory msgFactory = null;

    /**
     * Creates a message factory configured from the default file, which is
     * mbs8583.xml located in the root of the classpath.
     */
    public static MessageFactory createDefault() throws IOException {
        if (msgFactory == null) {
            if (MessageFactory.class.getClassLoader().getResource("mbs8583.xml") == null) {
                log.error("createDefault: mbs8583.xml not found, returning empty message factory");
                return new MessageFactory();
            } else {
                msgFactory = createFromClasspathConfig("mbs8583.xml");
            }
        }
        return msgFactory;
    }

    /** Creates a message factory from the specified path inside the classpath. */
    public static MessageFactory createFromClasspathConfig(String path) throws IOException {
        if (msgFactory == null) {
            InputStream ins = MessageFactory.class.getClassLoader().getResourceAsStream(path);
            msgFactory = new MessageFactory();
            if (ins == null) {
                try {
                    System.err.println("TRYING:" + Config.getInstance().get("ISO_XML_PATH") + path);
                    ins = new FileInputStream(Config.getInstance().get("ISO_XML_PATH") + path);
                } catch (Exception e) {
                    ins = null;
                }
                if (ins == null) {
                    log.error("createFromClasspathConfig: File not found in classpath: " + path);
                    return msgFactory;
                }
            }
            if (log.isDebugEnabled()) {
                log.debug("Parsing config from classpath file " + path);
            }
            try {
                parse(msgFactory, ins);
            } finally {
                ins.close();
            }
        }
        return msgFactory;
    }

    /** Creates a message factory from the file located at the specified URL. */
    public static MessageFactory createFromUrl(URL url) throws IOException {
        if (msgFactory == null) {
            msgFactory = new MessageFactory();
            InputStream stream = url.openStream();
            try {
                parse(msgFactory, stream);
            } finally {
                stream.close();
            }
        }
        return msgFactory;
    }

    /**
     * Reads the XML from the stream and configures the message factory with its
     * values.
     *
     * @param mfact
     *            The message factory to be configured with the values read from
     *            the XML.
     * @param stream
     *            The InputStream containing the XML configuration.
     */
    protected static void parse(MessageFactory mfact, InputStream stream) throws IOException {
        final DocumentBuilderFactory docfact = DocumentBuilderFactory.newInstance();
        DocumentBuilder docb = null;
        Document doc = null;
        try {
            docb = docfact.newDocumentBuilder();
            doc = docb.parse(stream);
        } catch (ParserConfigurationException ex) {
            log.error("parse: Cannot parse XML configuration", ex);
            return;
        } catch (SAXException ex) {
            log.error("parse: Parsing XML configuration", ex);
            return;
        }
        final Element root = doc.getDocumentElement();

        // Read the ISO headers
        NodeList nodes = root.getElementsByTagName("header");
        Element elem = null;
        for (int i = 0; i < nodes.getLength(); i++) {
            elem = (Element) nodes.item(i);
            int type = parseType(elem.getAttribute("type"));
            if (type == -1) {
                throw new IOException("Invalid type for header: " + elem.getAttribute("type"));
            }
            if (elem.getChildNodes() == null || elem.getChildNodes().getLength() == 0) {
                throw new IOException("Invalid header element");
            }
            String header = elem.getChildNodes().item(0).getNodeValue();
            if (log.isTraceEnabled()) {
                log.trace("Adding ISO header for type " + elem.getAttribute("type") + ": " + header);
            }
            mfact.setIsoHeader(type, header);
        }

        // Read the message templates
        nodes = root.getElementsByTagName("template");
        for (int i = 0; i < nodes.getLength(); i++) {
            elem = (Element) nodes.item(i);
            int type = parseType(elem.getAttribute("type"));
            if (type == -1) {
                throw new IOException("Invalid type for template: " + elem.getAttribute("type"));
            }
            NodeList fields = elem.getElementsByTagName("field");
            IsoMessage m = new IsoMessage();
            m.setType(type);
            for (int j = 0; j < fields.getLength(); j++) {
                Element f = (Element) fields.item(j);
                int num = Integer.parseInt(f.getAttribute("num"));
                IsoType itype = IsoType.valueOf(f.getAttribute("type"));
                int length = 0;
                if (f.getAttribute("length").length() > 0) {
                    length = Integer.parseInt(f.getAttribute("length"));
                }
                String v = f.getChildNodes().item(0).getNodeValue();
                m.setValue(num, v, itype, length);
            }
            mfact.addMessageTemplate(m);
        }

        // Read the parsing guides
        nodes = root.getElementsByTagName("parse");
        for (int i = 0; i < nodes.getLength(); i++) {
            elem = (Element) nodes.item(i);
            int type = parseType(elem.getAttribute("type"));
            if (type == -1) {
                throw new IOException("Invalid type for parse guide: " + elem.getAttribute("type"));
            }
            NodeList fields = elem.getElementsByTagName("field");
            HashMap<Integer, FieldParseInfo> parseMap = new HashMap<Integer, FieldParseInfo>();
            for (int j = 0; j < fields.getLength(); j++) {
                Element f = (Element) fields.item(j);
                int num = Integer.parseInt(f.getAttribute("num"));
                IsoType itype = IsoType.valueOf(f.getAttribute("type"));
                int length = 0;
                if (f.getAttribute("length").length() > 0) {
                    length = Integer.parseInt(f.getAttribute("length"));
                }
                parseMap.put(num, new FieldParseInfo(itype, length));
            }
            mfact.setParseMap(type, parseMap);
        }

    }

    /**
     * Parses a message type expressed as a hex string and returns the integer
     * number. For example, "0200" or "200" return the number 512 (0x200)
     */
    private static int parseType(String type) throws IOException {
        if (type.length() % 2 == 1) {
            type = "0" + type;
        }
        if (type.length() != 4) {
            return -1;
        }
        return ((type.charAt(0) - 48) << 12) | ((type.charAt(1) - 48) << 8) | ((type.charAt(2) - 48) << 4)
                | (type.charAt(3) - 48);
    }

}