package org.zstack.test.deployer; import org.zstack.header.exception.CloudRuntimeException; import org.zstack.test.deployer.schema.DeployerConfig; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; import java.lang.reflect.Field; import java.util.Collection; // xsd spec 1.0 has a flaw that there is no way to get an any order sequence, // which means you have to arrange xml elements as the same order as they present // in xsd schema file if using JAXB validator. So we have to write our validator here public class DeployerValidator { private static final CLogger logger = Utils.getLogger(DeployerValidator.class); private DeployerConfig config; DeployerValidator(DeployerConfig config) { this.config = config; } private void validateCollection(Field f, Object obj) throws IllegalArgumentException, IllegalAccessException { XmlType xtype = obj.getClass().getAnnotation(XmlType.class); if (xtype == null) { return; } String elementName = xtype.name(); logger.debug(String.format("validating %s->%s", elementName, f.getName())); Collection l = (Collection) f.get(obj); XmlElement eat = f.getAnnotation(XmlElement.class); if (eat != null && (eat.required() && (l == null || l.isEmpty()))) { throw new IllegalArgumentException(String.format("field[%s] of element[%s] is mandatory, cannot be missed", f.getName(), elementName)); } XmlAttribute aat = f.getAnnotation(XmlAttribute.class); if (aat != null && (aat.required() && (l == null || l.isEmpty()))) { throw new IllegalArgumentException(String.format("field[%s] of element[%s] is mandatory, cannot be missed", aat.name(), elementName)); } if (l != null) { Object val = l.iterator().next(); if (val != null) { validateObject(val); } } } private void validateField(Field f, Object obj) throws IllegalArgumentException, IllegalAccessException { XmlType xtype = obj.getClass().getAnnotation(XmlType.class); if (xtype == null) { return; } Object val = f.get(obj); String elementName = xtype.name(); logger.debug(String.format("validating %s->%s", elementName, f.getName())); XmlElement eat = f.getAnnotation(XmlElement.class); if (eat != null && eat.required() && val == null) { throw new IllegalArgumentException(String.format("field[%s] of element[%s] is mandatory, cannot be missed", f.getName(), elementName)); } XmlAttribute aat = f.getAnnotation(XmlAttribute.class); if (aat != null && aat.required() && val == null) { throw new IllegalArgumentException(String.format("field[%s] of element[%s] is mandatory, cannot be missed", aat.name(), elementName)); } if (val != null) { validateObject(val); } } private void validateObject(Object obj) throws IllegalArgumentException, IllegalAccessException { for (Field f : obj.getClass().getDeclaredFields()) { f.setAccessible(true); if (Collection.class.isAssignableFrom(f.getType())) { validateCollection(f, obj); } else { validateField(f, obj); } } } void vaildate() { try { validateObject(config); } catch (Exception e) { throw new CloudRuntimeException(e); } } }