/* * Lokomo OneCMDB - An Open Source Software for Configuration * Management of Datacenter Resources * * Copyright (C) 2006 Lokomo Systems AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. * * Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via * paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33 * Danderyd, Sweden. * */ package org.onecmdb.core.utils.xml; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.onecmdb.core.internal.model.ItemId; import org.onecmdb.core.utils.IBeanProvider; import org.onecmdb.core.utils.IBeanProviderSource; import org.onecmdb.core.utils.bean.AttributeBean; import org.onecmdb.core.utils.bean.CiBean; import org.onecmdb.core.utils.bean.ValueBean; import org.onecmdb.core.utils.xml.dtd.DtdAttribute; import org.onecmdb.core.utils.xml.dtd.DtdElement; public class XmlParser implements IBeanProvider, IBeanProviderSource { // Known Template Elements. public static final DtdElement ROOT_ELEMENT = new DtdElement("onecmdb"); public static final DtdElement TEMPLATES_ELEMENT = new DtdElement( "templates"); public static final DtdElement TEMPLATE_ELEMENT = new DtdElement("template"); public static final DtdElement INSTANCES_ELEMENT = new DtdElement( "instances"); public static final DtdElement ATTRIBUTE_ELEMENT = new DtdElement( "attribute"); public static final DtdElement COMPLEX_TYPE_ELEMENT = new DtdElement( "complexType"); public static final DtdElement SIMPLE_TYPE_ELEMENT = new DtdElement( "simpleType"); public static final DtdElement DERIVED_FROM_ELEMENT = new DtdElement( "derivedFrom"); public static final DtdElement SET_COMPLEX_VALUE_ELEMENT = new DtdElement( "setComplexValue"); public static final DtdElement SET_SIMPLE_VALUE_ELEMENT = new DtdElement( "setSimpleValue"); public static final DtdElement REF_ELEMENT = new DtdElement("ref"); public static final DtdElement REF_TYPE_ELEMENT = new DtdElement("refType"); public static final DtdElement POLICY_ELEMENT = new DtdElement("policy"); public static final DtdElement MAX_OCCURS_ELEMENT = new DtdElement( "maxOccurs"); public static final DtdElement MIN_OCCURS_ELEMENT = new DtdElement( "minOccurs"); public static final DtdElement DESCRIPTION_ELEMENT = new DtdElement( "description"); // Known Template Attributes. // Template Attribute public static final DtdAttribute ALIAS_ATTR = new DtdAttribute("alias", DtdAttribute.DEFAULT_OPTIONAL); public static final DtdAttribute GROUP_ATTR = new DtdAttribute("group", DtdAttribute.DEFAULT_OPTIONAL); public static final DtdAttribute CREATE_DATE_ATTR = new DtdAttribute("created", DtdAttribute.DEFAULT_OPTIONAL); public static final DtdAttribute LAST_MODIFIED_ATTR = new DtdAttribute("lastModified", DtdAttribute.DEFAULT_OPTIONAL); public static final DtdAttribute INSTANCE_NAME_EXPRESSION_ATTR = new DtdAttribute( "displayName", DtdAttribute.DEFAULT_OPTIONAL); // Attribute Attributes public static final DtdAttribute ATT_ALIAS_ATTR = new DtdAttribute( "attAlias", DtdAttribute.DEFAULT_REQUIRED); public static final DtdAttribute NAME_ATTR = new DtdAttribute("displayName", DtdAttribute.DEFAULT_OPTIONAL); public static final DtdAttribute ATTR_DERIVED = new DtdAttribute("derived", DtdAttribute.DEFAULT_OPTIONAL); public static final DtdAttribute ID_ATTR = new DtdAttribute("id", DtdAttribute.DEFAULT_OPTIONAL); private List<String> urls; private ArrayList<CiBean> beans; private boolean beansLoaded = false; private HashMap<String, CiBean> beanMap; //private Log log = LogFactory.getLog(this.getClass()); private IBeanProviderConfig beanConfig = null; public static String getTab(int level) { StringBuffer tab = new StringBuffer(); for (int i = 0; i < level; i++) { tab.append("\t"); } return (tab.toString()); } public static void main(String argv[]) { String path = argv[0]; XmlParser p = new XmlParser(); p.setURL(path); List<CiBean> beans = p.getBeans(); System.out.println("FOUND: " + beans.size()); XmlGenerator gen = new XmlGenerator(); gen.setBeans(beans); gen.setOutput("outOnecmdb.xml"); try { gen.process(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void setBeanProviderConfig(IBeanProviderConfig config) { this.beanConfig = config; } public void setURL(String url) { addURL(url); } public void addURL(String url) { if (this.urls == null) { this.urls = new ArrayList<String>(); } this.urls.add(url); beansLoaded = false; } public void setURLs(List<String> urls) { this.urls = urls; beansLoaded = false; } public CiBean getBean(String alias) { if (!beansLoaded) { loadBeans(); } CiBean bean = beanMap.get(alias); return (bean); } public List<CiBean> getBeans() { if (!beansLoaded) { loadBeans(); } return (beans); } private void loadBeans() { beans = new ArrayList<CiBean>(); for (String url : urls) { //log.info("Load provider url '" + url + "'"); if (this.beanConfig != null) { if (this.beanConfig.isImported(url)) { continue; } this.beanConfig.importURL(url); } // Need to locate this url. InputStream input = null; URL u = null; if (url.startsWith("res:") || url.startsWith("classpath:")) { int index = url.indexOf(':'); String resName = url.substring(index+1); u = this.getClass().getClassLoader().getResource(resName); if (u == null) { //log.error("Resource '" + resName + "' not found"); throw new IllegalArgumentException("No resource with name " + resName + " found"); } } else { try { u = new URL(url); } catch (MalformedURLException e) { //log.error("Url '" + url + "' malformed"); e.printStackTrace(); throw new IllegalArgumentException("Not a corect url:" + e.toString(), e); } } //log.debug("load url <" + u.getPath() + ">"); try { input = u.openStream(); } catch (IOException e) { e.printStackTrace(); //log.error("Can't open url '" + u.toExternalForm() + "'"); throw new IllegalArgumentException( "Can't open inputStream for url " + url + " :" + e.toString(), e); } try { beans.addAll(parseInputStream(input)); } catch (DocumentException e) { //log.error("Parsing url '" + u.toExternalForm() + "'", e); //e.printStackTrace(); System.out.println("ERROR in URL " + url); throw new IllegalAccessError("Can't parse XML URL[" + url + "]:" + e.toString()); } finally { // Close it or ? if (input != null) { try { input.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } // Build bean map. beanMap = new HashMap<String, CiBean>(); for (CiBean bean : beans) { beanMap.put(bean.getAlias(), bean); } this.beansLoaded = true; } public List<CiBean> parseInputStream(InputStream input) throws DocumentException { SAXReader reader = new SAXReader(); Document document = reader.read(input); List<CiBean> beans = new ArrayList<CiBean>(); Element el = document.getRootElement(); if (el.getName().equals(ROOT_ELEMENT.getName())) { for (Element childEl : (List<Element>) el.elements()) { if (childEl.getName().equals( TEMPLATES_ELEMENT.getName())) { beans.addAll(parseBlueprints(childEl)); continue; } if (childEl.getName().equals( INSTANCES_ELEMENT.getName())) { beans.addAll(parseInstances(childEl)); continue; } throw new IllegalAccessError("Unkown element <" + childEl.getName() + "> must be " + TEMPLATES_ELEMENT + "|" + INSTANCES_ELEMENT); } } else { throw new IllegalAccessError("Unkown root element <" + el.getName() + "> must be <" + ROOT_ELEMENT.getName() + ">"); } return(beans); } public List<CiBean> parseBlueprints(Element rootElement) { List els = rootElement.elements(); List<CiBean> ciBeans = new ArrayList<CiBean>(); for (int i = 0; i < els.size(); i++) { CiBean bean = parseBlueprint((Element) els.get(i)); ciBeans.add(bean); } return (ciBeans); } public List<CiBean> parseInstances(Element rootElement) { List els = rootElement.elements(); List<CiBean> ciBeans = new ArrayList<CiBean>(); for (int i = 0; i < els.size(); i++) { CiBean bean = parseInstance((Element) els.get(i)); ciBeans.add(bean); } return (ciBeans); } public CiBean parseInstance(Element ci) { String derivedFrom = ci.getName(); String alias = getAttributeValue(ci, ALIAS_ATTR, generateAlias(derivedFrom)); String id = getAttributeValue(ci, ID_ATTR, null); String displayNameExpr = getAttributeValue(ci, INSTANCE_NAME_EXPRESSION_ATTR, null); //log.debug("found instance " + alias); CiBean ciBean = new CiBean(); ciBean.setTemplate(false); ciBean.setAlias(alias); ciBean.setDerivedFrom(derivedFrom); if (id != null) { ciBean.setId(Long.parseLong(id)); } ciBean.setDisplayNameExpression(displayNameExpr); if (ci.getText() != null) { ciBean.setDisplayName(ci.getText().trim()); } String group = getAttributeValue(ci, GROUP_ATTR, null); ciBean.setGroup(group); List<Element> attributes = ci.elements(); List<ValueBean> vBeans = new ArrayList<ValueBean>(); for (Element attribute : attributes) { String attAlias = attribute.getName(); String valueId = getAttributeValue(attribute, ID_ATTR, null); if (attAlias.equals(DESCRIPTION_ELEMENT.getName())) { ciBean.setDescription(getValue(attribute)); continue; } ValueBean vBean = new ValueBean(); vBean.setAlias(attAlias); if (valueId != null) { vBean.setId(Long.parseLong(valueId)); } Element ref = attribute.element(REF_ELEMENT.getName()); if (ref != null) { if (ref.elements().size() == 1) { Element compositeElement = (Element)ref.elements().get(0); CiBean refBean = parseInstance(compositeElement); beans.add(refBean); vBean.setValue(refBean.getAlias()); vBean.setComplexValue(true); } else { String aliasValue = getAttributeValue(ref, ALIAS_ATTR, null); if (aliasValue != null) { vBean.setValue(aliasValue); vBean.setComplexValue(true); } } } else { vBean.setValue(getValue(attribute)); vBean.setComplexValue(false); } vBeans.add(vBean); } ciBean.setAttributeValues(vBeans); return (ciBean); } private String generateAlias(String prefix) { ItemId id = new ItemId(); return(prefix + "-" + id.toString()); } public CiBean parseBlueprint(Element ci) { if (!ci.getName().equals(TEMPLATE_ELEMENT.getName())) { throw new IllegalAccessError("Unknown element <" + ci.getName() + "> must be <" + TEMPLATE_ELEMENT.getName() + ">"); } String alias = getAttributeValue(ci, ALIAS_ATTR, null); if (alias == null) { throw new IllegalAccessError("Alias must be specified on element <" + ci.getName() + ">"); } String instanceNameExpression = getAttributeValue(ci, INSTANCE_NAME_EXPRESSION_ATTR, null); //log.debug("found template " + alias); String id = getAttributeValue(ci, ID_ATTR, null); CiBean ciBean = new CiBean(); ciBean.setAlias(alias); ciBean.setDisplayNameExpression(instanceNameExpression); ciBean.setTemplate(true); String group = getAttributeValue(ci, GROUP_ATTR, null); ciBean.setGroup(group); if (id != null) { ciBean.setId(Long.parseLong(id)); } List<Element> attributes = ci.elements(); List<AttributeBean> aBeans = new ArrayList<AttributeBean>(); for (Element el : attributes) { if (el.getName().equals(ATTRIBUTE_ELEMENT.getName())) { String attrAlias = getAttributeValue(el, ATT_ALIAS_ATTR, null); String name = getAttributeValue(el, NAME_ATTR, null); String derived = getAttributeValue(el, ATTR_DERIVED, "false"); String attrId = getAttributeValue(el, ID_ATTR, null); AttributeBean aBean = new AttributeBean(); aBean.setDisplayName(name); aBean.setAlias(attrAlias); aBean.setDerived(Boolean.parseBoolean(derived)); if (attrId != null) { aBean.setId(Long.parseLong(attrId)); } for (Element aEl : (List<Element>) el.elements()) { if (aEl.getName().equals(SIMPLE_TYPE_ELEMENT.getName())) { aBean.setType(aEl.getTextTrim()); aBean.setComplexType(false); } if (aEl.getName().equals(POLICY_ELEMENT.getName())) { Element max = aEl.element(MAX_OCCURS_ELEMENT.getName()); if (max != null) { aBean.setMaxOccurs(max.getTextTrim()); } Element min = aEl.element(MIN_OCCURS_ELEMENT.getName()); if (min != null) { aBean.setMinOccurs(min.getTextTrim()); } } if (aEl.getName().equals(COMPLEX_TYPE_ELEMENT.getName())) { Element ref = aEl.element(REF_ELEMENT.getName()); if (ref == null) { throw new IllegalAccessError("Missing element <" + REF_ELEMENT.getName() + "> in element <" + aEl.getName() + "> template=" + alias + ", attribute=" + attrAlias); } Element refType = aEl.element(REF_TYPE_ELEMENT .getName()); // It's ok, atleast for references. String refTypeAlias = null; if (refType != null) { /* throw new IllegalAccessError("Missing element <" + REF_TYPE_ELEMENT.getName() + "> in element <" + aEl.getName() + "> template=" + alias + ", attribute=" + attrAlias); */ Element refTypeRef = refType.element(REF_ELEMENT .getName()); if (refTypeRef == null) { throw new IllegalAccessError("Missing element <" + REF_ELEMENT.getName() + "> in element <" + refType.getName() + "> template=" + alias + ", attribute=" + attrAlias); } refTypeAlias = getAttributeValue(refTypeRef, ALIAS_ATTR, null); } String refAlias = getAttributeValue(ref, ALIAS_ATTR, null); aBean.setRefType(refTypeAlias); aBean.setType(refAlias); aBean.setComplexType(true); } if (aEl.getName().equals(DESCRIPTION_ELEMENT.getName())) { aBean.setDescription(aEl.getTextTrim()); } if (aEl.getName().equals(SET_SIMPLE_VALUE_ELEMENT.getName())) { ValueBean vBean = new ValueBean(); String vId = getAttributeValue(aEl, ID_ATTR, null); if (vId != null) { vBean.setId(Long.parseLong(vId)); } vBean.setValue(getValue(aEl)); vBean.setAlias(attrAlias); vBean.setComplexValue(false); ciBean.addAttributeValue(vBean); } if (el.getName().equals(SET_COMPLEX_VALUE_ELEMENT.getName())) { ValueBean vBean = new ValueBean(); String vId = getAttributeValue(aEl, ID_ATTR, null); if (vId != null) { vBean.setId(Long.parseLong(vId)); } Element ref = aEl.element(REF_ELEMENT.getName()); if (ref == null) { throw new IllegalAccessError("Missing element <" + REF_ELEMENT.getName() + "> in element <" + el.getName() + "> template=" + alias + ", attribute=" + attrAlias); } String aliasValue = getAttributeValue(ref, ALIAS_ATTR, null); vBean.setValue(aliasValue); vBean.setComplexValue(true); vBean.setAlias(attrAlias); ciBean.addAttributeValue(vBean); } } ciBean.addAttribute(aBean); } else if (el.getName().equals(SET_SIMPLE_VALUE_ELEMENT.getName())) { String attrAlias = getAttributeValue(el, ATT_ALIAS_ATTR, null); ValueBean vBean = new ValueBean(); String vId = getAttributeValue(el, ID_ATTR, null); if (vId != null) { vBean.setId(Long.parseLong(vId)); } vBean.setValue(getValue(el)); vBean.setAlias(attrAlias); vBean.setComplexValue(false); ciBean.addAttributeValue(vBean); } else if (el.getName().equals(SET_COMPLEX_VALUE_ELEMENT.getName())) { String attrAlias = getAttributeValue(el, ATT_ALIAS_ATTR, null); ValueBean vBean = new ValueBean(); String vId = getAttributeValue(el, ID_ATTR, null); if (vId != null) { vBean.setId(Long.parseLong(vId)); } Element ref = el.element(REF_ELEMENT.getName()); if (ref == null) { throw new IllegalAccessError("Missing element <" + REF_ELEMENT.getName() + "> in element <" + el.getName() + "> template=" + alias + ", attribute=" + attrAlias); } String aliasValue = getAttributeValue(ref, ALIAS_ATTR, null); vBean.setValue(aliasValue); vBean.setComplexValue(true); vBean.setAlias(attrAlias); ciBean.addAttributeValue(vBean); } else if (el.getName().equals(DERIVED_FROM_ELEMENT.getName())) { Element ref = el.element(REF_ELEMENT.getName()); if (ref == null) { throw new IllegalAccessError("Missing element <" + REF_ELEMENT.getName() + "> in element <" + el.getName() + "> template=" + alias); } String aliasValue = getAttributeValue(ref, ALIAS_ATTR, null); ciBean.setDerivedFrom(aliasValue); } else if (el.getName().equals(DESCRIPTION_ELEMENT.getName())) { ciBean.setDescription(el.getTextTrim()); } else { throw new IllegalAccessError("Unkown element <" + el.getName() + "> in element <" + ci.getName() + "> template=" + alias); } } // Validate alias and derivedFrom if (ciBean.getAlias() == null) { throw new IllegalArgumentException("No alias specified on element '" + ci.getName() + "'"); } if (ciBean.getDerivedFrom() == null) { //log.warn("No derivedFrom specified on element '" + ciBean.getAlias() + "'"); //throw new IllegalArgumentException("No derivedFrom specified on element '" + ciBean.getAlias() + "'"); } return (ciBean); } private String getValue(Element el) { String trimmedValue = el.getTextTrim(); if (trimmedValue == null) { return(null); } if (trimmedValue.equals("")) { return(null); } return(trimmedValue); } private String getAttributeValue(Element e, DtdAttribute a, String defaultValue) { Attribute attr = e.attribute(a.getName()); if (attr == null) { if (a.isRequiered()) { throw new IllegalArgumentException("Missing attribute " + a.getName() + " in element " + e.getName()); } return (defaultValue); } String value = attr.getText(); return (value); } private String getAttribute(Element e, String name, String defaultValue, boolean requiered, String error) { // Must be there. Attribute a = e.attribute(name); if (a == null) { if (!requiered) { return (defaultValue); } //log.error(error + " Missing attribute " + name); throw new IllegalArgumentException(error + " Missing attribute " + name); } String value = a.getText(); if (value == null) { if (!requiered) { return (defaultValue); } //log.error(error + " Missing attribute " + name); throw new IllegalArgumentException(error + " Missing attribute " + name); } return (value); } public void dumpElement(Element el, int level) { System.out.println(tab(level) + el.getName() + ":" + el.getData() + " {"); List attributes = el.attributes(); for (int i = 0; i < attributes.size(); i++) { Attribute a = (Attribute) attributes.get(i); System.out.println(tab(level) + " " + a.getName() + "=" + a.getData()); } List els = el.elements(); for (int i = 0; i < els.size(); i++) { dumpElement((Element) els.get(i), level + 1); } System.out.println(tab(level) + "}"); } private String tab(int level) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < level; i++) { buffer.append(" "); } return (buffer.toString()); } }