org.openmrs.module.SqlDiffFileParser.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.SqlDiffFileParser.java

Source

/**
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
 *
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
 * graphic logo is a trademark of OpenMRS Inc.
 */
package org.openmrs.module;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Vector;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

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

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.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * This class will parse an xml sql diff file
 *
 * @version 1.0
 */
public class SqlDiffFileParser {

    private static Log log = LogFactory.getLog(SqlDiffFileParser.class);

    private static final String SQLDIFF_CHANGELOG_FILENAME = "sqldiff.xml";

    /**
     * Get the diff map. Return a sorted map<version, sql statements>
     *
     * @return SortedMap<String, String>
     * @throws ModuleException
     */
    public static SortedMap<String, String> getSqlDiffs(Module module) throws ModuleException {
        if (module == null) {
            throw new ModuleException("Module cannot be null");
        }

        SortedMap<String, String> map = new TreeMap<String, String>(new VersionComparator());

        InputStream diffStream = null;

        // get the diff stream
        JarFile jarfile = null;
        try {
            try {
                jarfile = new JarFile(module.getFile());
            } catch (IOException e) {
                throw new ModuleException("Unable to get jar file", module.getName(), e);
            }

            diffStream = ModuleUtil.getResourceFromApi(jarfile, module.getModuleId(), module.getVersion(),
                    SQLDIFF_CHANGELOG_FILENAME);
            if (diffStream == null) {
                // Try the old way. Loading from the root of the omod
                ZipEntry diffEntry = jarfile.getEntry(SQLDIFF_CHANGELOG_FILENAME);
                if (diffEntry == null) {
                    log.debug("No sqldiff.xml found for module: " + module.getName());
                    return map;
                } else {
                    try {
                        diffStream = jarfile.getInputStream(diffEntry);
                    } catch (IOException e) {
                        throw new ModuleException("Unable to get sql diff file stream", module.getName(), e);
                    }
                }
            }

            try {
                // turn the diff stream into an xml document
                Document diffDoc = null;
                try {
                    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                    DocumentBuilder db = dbf.newDocumentBuilder();
                    db.setEntityResolver(new EntityResolver() {

                        @Override
                        public InputSource resolveEntity(String publicId, String systemId)
                                throws SAXException, IOException {
                            // When asked to resolve external entities (such as a DTD) we return an InputSource
                            // with no data at the end, causing the parser to ignore the DTD.
                            return new InputSource(new StringReader(""));
                        }
                    });
                    diffDoc = db.parse(diffStream);
                } catch (Exception e) {
                    throw new ModuleException("Error parsing diff sqldiff.xml file", module.getName(), e);
                }

                Element rootNode = diffDoc.getDocumentElement();

                String diffVersion = rootNode.getAttribute("version");

                if (!validConfigVersions().contains(diffVersion)) {
                    throw new ModuleException("Invalid config version: " + diffVersion, module.getModuleId());
                }

                NodeList diffNodes = getDiffNodes(rootNode, diffVersion);

                if (diffNodes != null && diffNodes.getLength() > 0) {
                    int i = 0;
                    while (i < diffNodes.getLength()) {
                        Element el = (Element) diffNodes.item(i++);
                        String version = getElement(el, diffVersion, "version");
                        String sql = getElement(el, diffVersion, "sql");
                        map.put(version, sql);
                    }
                }
            } catch (ModuleException e) {
                if (diffStream != null) {
                    try {
                        diffStream.close();
                    } catch (IOException io) {
                        log.error("Error while closing config stream for module: " + module.getModuleId(), io);
                    }
                }

                // rethrow the moduleException
                throw e;
            }

        } finally {
            try {
                if (jarfile != null) {
                    jarfile.close();
                }
            } catch (IOException e) {
                log.warn("Unable to close jarfile: " + jarfile.getName());
            }
        }
        return map;
    }

    /**
     * Generic method to get a module tag
     *
     * @param element
     * @param version
     * @param tag
     * @return
     */
    private static String getElement(Element element, String version, String tag) {
        if (element.getElementsByTagName(tag).getLength() > 0) {
            return element.getElementsByTagName(tag).item(0).getTextContent();
        }
        return "";
    }

    /**
     * List of the valid sqldiff versions
     *
     * @return
     */
    private static List<String> validConfigVersions() {
        List<String> versions = new Vector<String>();
        versions.add("1.0");
        return versions;
    }

    /**
     * Finds the nodes that contain diff information
     *
     * @param element
     * @param version
     * @return
     */
    private static NodeList getDiffNodes(Element element, String version) {
        NodeList diffNodes = null;

        if ("1.0".equals(version)) {
            diffNodes = element.getElementsByTagName("diff");
        }

        return diffNodes;
    }

}