package io.vertx.ext.web.api.validation.impl;
import io.vertx.ext.web.api.RequestParameter;
import io.vertx.ext.web.api.validation.ParameterTypeValidator;
import io.vertx.ext.web.api.validation.ValidationException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.StringReader;
public class XMLTypeValidator implements ParameterTypeValidator {
private Validator schemaValidator;
private XMLTypeValidator(Validator schemaValidator) throws SAXNotRecognizedException, SAXNotSupportedException {
this.schemaValidator = schemaValidator;
this.schemaValidator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
this.schemaValidator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
}
@Override
public RequestParameter isValid(String value) throws ValidationException {
try {
DocumentBuilder parser = createDocumentBuilderFactoryInstance().newDocumentBuilder();
Document document = parser.parse(value);
this.schemaValidator.validate(new DOMSource(document));
return RequestParameter.create(document);
} catch (Exception e) {
throw ValidationException.ValidationExceptionFactory.generateInvalidXMLBodyException(e.getMessage());
}
}
public static class XMLTypeValidatorFactory {
public static XMLTypeValidator createXMLTypeValidator(String xmlSchema) {
try {
SchemaFactory factory = createSchemaFactoryInstance();
Source xmlSchemaSource = new StreamSource(new StringReader(xmlSchema));
return new XMLTypeValidator(factory.newSchema(xmlSchemaSource).newValidator());
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
}
private static DocumentBuilderFactory createDocumentBuilderFactoryInstance() throws ParserConfigurationException {
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
String FEATURE;
FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
dbf.setFeature(FEATURE, true);
FEATURE = "http://xml.org/sax/features/external-general-entities";
dbf.setFeature(FEATURE, false);
FEATURE = "http://xml.org/sax/features/external-parameter-entities";
dbf.setFeature(FEATURE, false);
FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
dbf.setFeature(FEATURE, false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
return dbf;
}
private static SchemaFactory createSchemaFactoryInstance() throws SAXNotRecognizedException, SAXNotSupportedException {
final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
return factory;
}
}