/** * 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.StringReader; import java.util.List; import java.util.Vector; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.openmrs.util.OpenmrsConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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; /** * This class will parse an xml update.rdf file * * @version 1.0 */ public class UpdateFileParser { private static Logger log = LoggerFactory.getLogger(UpdateFileParser.class); private String content; // these properties store the 'best fit' (most recent update that will fit with the current code version) private String moduleId = null; private String currentVersion = null; private String downloadURL = null; /** * Default constructor * * @param s String to parse (Contents of update.rdf file) */ public UpdateFileParser(String s) { this.content = s; } /** * Parse the contents of the update.rdf file. * * @throws ModuleException * @should set properties from xml file * @should set properties using the newest update * @should not set properties using updates ahead of current openmrs version */ public void parse() throws ModuleException { StringReader stringReader = null; try { Document updateDoc = null; try { stringReader = new StringReader(content); InputSource inputSource = new InputSource(stringReader); inputSource.setSystemId("./"); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); // Disable resolution of external entities. See TRUNK-3942 db.setEntityResolver(new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) { return new InputSource(new StringReader("")); } }); updateDoc = db.parse(inputSource); } catch (Exception e) { log.warn("Unable to parse content"); throw new ModuleException("Error parsing update.rdf file: " + content, e); } Element rootNode = updateDoc.getDocumentElement(); String configVersion = rootNode.getAttribute("configVersion"); if (!validConfigVersions().contains(configVersion)) { throw new ModuleException("Invalid configVersion: '" + configVersion + "' found In content: " + content); } if ("1.0".equals(configVersion)) { // the only update in the xml file is the 'best fit' this.moduleId = getElement(rootNode, configVersion, "moduleId"); this.currentVersion = getElement(rootNode, configVersion, "currentVersion"); this.downloadURL = getElement(rootNode, configVersion, "downloadURL"); } else if ("1.1".equals(configVersion)) { this.moduleId = rootNode.getAttribute("moduleId"); NodeList nodes = rootNode.getElementsByTagName("update"); this.currentVersion = ""; // default to the lowest version possible // loop over all 'update' tags for (Integer i = 0; i < nodes.getLength(); i++) { Element currentNode = (Element) nodes.item(i); String currentVersion = getElement(currentNode, configVersion, "currentVersion"); // if the currently saved version is less than the current tag if (ModuleUtil.compareVersion(this.currentVersion, currentVersion) < 0) { String requireOpenMRSVersion = getElement(currentNode, configVersion, "requireOpenMRSVersion"); // if the openmrs code version is compatible, this node is a winner if (requireOpenMRSVersion == null || ModuleUtil.matchRequiredVersions(OpenmrsConstants.OPENMRS_VERSION_SHORT, requireOpenMRSVersion)) { this.currentVersion = currentVersion; this.downloadURL = getElement(currentNode, configVersion, "downloadURL"); } } } } } catch (ModuleException e) { // rethrow the moduleException throw e; } finally { if (stringReader != null) { stringReader.close(); } } } /** * 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"); versions.add("1.1"); return versions; } /** * @return the downloadURL */ public String getDownloadURL() { return downloadURL; } /** * @return the moduleId */ public String getModuleId() { return moduleId; } /** * @return the version */ public String getCurrentVersion() { return currentVersion; } }