org.psikeds.knowledgebase.xml.impl.XSDValidator.java Source code

Java tutorial

Introduction

Here is the source code for org.psikeds.knowledgebase.xml.impl.XSDValidator.java

Source

/*******************************************************************************
 * psiKeds :- ps induced knowledge entity delivery system
 *
 * Copyright (c) 2013, 2014 Karsten Reincke, Marco Juliano, Deutsche Telekom AG
 *
 * This file is free software: you can redistribute
 * it and/or modify it under the terms of the
 * [x] GNU Affero General Public License
 * [ ] GNU General Public License
 * [ ] GNU Lesser General Public License
 * [ ] Creatice Commons ShareAlike License
 *
 * For details see file LICENSING in the top project directory
 *******************************************************************************/
package org.psikeds.knowledgebase.xml.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.xml.sax.SAXException;

import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;

import org.psikeds.knowledgebase.xml.KBValidator;

/**
 * Validate whether an XML is correct against a given XSD, i.e. check whether
 * the Knowledge Base meets the Specification.<br>
 *
 * Note:
 * XML and XSD can be both Files or both Inputstreams or both Spring-Resources
 * but not a combination of different Types.<br>
 *
 * @author marco@juliano.de
 *
 */
public class XSDValidator implements KBValidator {

    private static final String DEFAULT_ENCODING = "UTF-8";

    private String xsdFilename;
    private String xmlFilename;
    private String encoding;
    private InputStream xsdStream;
    private InputStream xmlStream;
    private Resource xsdResource;
    private Resource xmlResource;

    /**
     * Default constructor
     */
    public XSDValidator() {
        this.xsdFilename = null;
        this.xmlFilename = null;
        this.encoding = DEFAULT_ENCODING;
        this.xsdStream = null;
        this.xmlStream = null;
        this.xsdResource = null;
        this.xmlResource = null;
    }

    /**
     * Constructor using filenames and encoding type
     * 
     * @param xsdFilename
     *          Name of the XSD schema file
     * @param xmlFilename
     *          Name of the XML file
     * @param encoding
     *          Encoding type, e.g. ISO-8859-1 or UTF-8
     */
    public XSDValidator(final String xsdFilename, final String xmlFilename, final String encoding) {
        this.xsdFilename = xsdFilename;
        this.xmlFilename = xmlFilename;
        this.encoding = encoding;
        this.xsdStream = null;
        this.xmlStream = null;
        this.xsdResource = null;
        this.xmlResource = null;
    }

    /**
     * Constructor using filenames and UTF-8 encoding
     * 
     * @param xsdFilename
     *          Name of the XSD schema file
     * @param xmlFilename
     *          Name of the XML file
     */
    public XSDValidator(final String xsdFilename, final String xmlFilename) {
        this(xsdFilename, xmlFilename, DEFAULT_ENCODING);
    }

    /**
     * Constructor using input streams for xsd and xml
     * 
     * @param xsdStream
     *          Stream to the XSD schema
     * @param xmlStream
     *          Stream to the XML data
     */
    public XSDValidator(final InputStream xsdStream, final InputStream xmlStream) {
        this.xsdFilename = null;
        this.xmlFilename = null;
        this.encoding = null;
        this.xsdStream = xsdStream;
        this.xmlStream = xmlStream;
        this.xsdResource = null;
        this.xmlResource = null;
    }

    /**
     * Constructor using Spring-Resources for XSD and XML
     * 
     * @param xsdResource
     *          Spring-Resource for the XSD schema
     * @param xmlResource
     *          Spring-Resource for the XML data
     */
    public XSDValidator(final Resource xsdResource, final Resource xmlResource) {
        this.xsdFilename = null;
        this.xmlFilename = null;
        this.encoding = null;
        this.xsdStream = null;
        this.xmlStream = null;
        this.xsdResource = xsdResource;
        this.xmlResource = xmlResource;
    }

    /**
     * @return the xsdFilename
     */
    public String getXsdFilename() {
        return this.xsdFilename;
    }

    /**
     * @param xsdFilename
     *          the xsdFilename to set
     */
    public void setXsdFilename(final String xsdFilename) {
        this.xsdFilename = xsdFilename;
    }

    /**
     * @return the xmlFilename
     */
    public String getXmlFilename() {
        return this.xmlFilename;
    }

    /**
     * @param xmlFilename
     *          the xmlFilename to set
     */
    public void setXmlFilename(final String xmlFilename) {
        this.xmlFilename = xmlFilename;
    }

    /**
     * @return the encoding
     */
    public String getEncoding() {
        return this.encoding;
    }

    /**
     * @param encoding
     *          the encoding to set
     */
    public void setEncoding(final String encoding) {
        this.encoding = encoding;
    }

    /**
     * @return the xsdStream
     */
    public InputStream getXsdStream() {
        return this.xsdStream;
    }

    /**
     * @param xsdStream
     *          the xsdStream to set
     */
    public void setXsdStream(final InputStream xsdStream) {
        this.xsdStream = xsdStream;
    }

    /**
     * @return the xmlStream
     */
    public InputStream getXmlStream() {
        return this.xmlStream;
    }

    /**
     * @param xmlStream
     *          the xmlStream to set
     */
    public void setXmlStream(final InputStream xmlStream) {
        this.xmlStream = xmlStream;
    }

    /**
     * @return the xsdResource
     */
    public Resource getXsdResource() {
        return this.xsdResource;
    }

    /**
     * @param xsdResource
     *          the xsdResource to set
     */
    public void setXsdResource(final Resource xsdResource) {
        this.xsdResource = xsdResource;
    }

    /**
     * @return the xmlResource
     */
    public Resource getXmlResource() {
        return this.xmlResource;
    }

    /**
     * @param xmlResource
     *          the xmlResource to set
     */
    public void setXmlResource(final Resource xmlResource) {
        this.xmlResource = xmlResource;
    }

    // -------------------------------------------------------------
    // ---- Method for validation of XML against XSD
    // -------------------------------------------------------------

    /**
     * Validate XML against specified XSD schmema file.<br>
     * 
     * @throws SAXException
     *           if XML is not valid against XSD
     * @throws IOException
     */
    @Override
    public void validate() throws SAXException, IOException {
        if (this.xsdStream != null && this.xmlStream != null) {
            validate(this.xsdStream, this.xmlStream);
            // Note: We do not close the streams here.
            // It's the responsibility of the caller
            return;
        }
        if (this.xsdResource != null && this.xmlResource != null) {
            validate(this.xsdResource, this.xmlResource);
            return;
        }
        if (!StringUtils.isEmpty(this.xsdFilename) && !StringUtils.isEmpty(this.xmlFilename)
                && !StringUtils.isEmpty(this.encoding)) {
            Reader xml = null;
            try {
                xml = new InputStreamReader(new FileInputStream(this.xmlFilename), this.encoding);
                validate(this.xsdFilename, xml);
                return;
            } finally {
                // We opened the file, therefore we also
                // must close the Reader/Stream again!
                if (xml != null) {
                    try {
                        xml.close();
                    } catch (final IOException ex) {
                        // ignore
                    } finally {
                        xml = null;
                    }
                }
            }
        }
        throw new IllegalArgumentException("Unsupported configuration settings!");
    }

    // -------------------------------------------------------------
    // ---- Static helpers for validation of XML against XSD
    // -------------------------------------------------------------

    /**
     * Validate XML reader against specified XSD schmema file.<br>
     * <b>Note:</b> The XML reader will not be closed. This must be invoked by
     * the caller afterwards!<br>
     * 
     * @param xsd
     *          Filename of XSD-schema that will be used to validate the
     *          XML-file
     * @param xml
     *          Reader for XML file
     * @throws SAXException
     *           if XML is not valid against XSD
     * @throws IOException
     */
    public static void validate(final String xsd, final Reader xml) throws SAXException, IOException {
        validate(new StreamSource(new File(xsd)), new StreamSource(xml));
    }

    /**
     * Validate XML against specified XSD schmema.<br>
     * <b>Note:</b> The XML source/stream will not be closed. This must be
     * invoked by the caller afterwards!<br>
     * 
     * @param xsd
     *          Input stream for XSD-schema that will be used to validate the
     *          XML
     * @param xml
     *          Input stream for XML
     * @throws SAXException
     *           if XML is not valid against XSD
     * @throws IOException
     */
    public static void validate(final InputStream xsd, final InputStream xml) throws SAXException, IOException {
        validate(new StreamSource(xsd), new StreamSource(xml));
    }

    /**
     * Validate XML against specified XSD schmema.
     * 
     * @param xsd
     *          Spring-Resource for the XSD-schema that will be used to validate the
     *          XML
     * @param xml
     *          Spring-Resource for the XML
     * @throws SAXException
     *           if XML is not valid against XSD
     * @throws IOException
     */
    public static void validate(final Resource xsd, final Resource xml) throws SAXException, IOException {
        InputStream xsdStream = null;
        InputStream xmlStream = null;
        try {
            xsdStream = xsd.getInputStream();
            xmlStream = xml.getInputStream();
            validate(xsdStream, xmlStream);
        } finally {
            // we opened the streams, we close them
            if (xsdStream != null) {
                try {
                    xsdStream.close();
                } catch (final Exception ex) {
                    // ignore
                } finally {
                    xsdStream = null;
                }
            }
            if (xmlStream != null) {
                try {
                    xmlStream.close();
                } catch (final Exception ex) {
                    // ignore
                } finally {
                    xmlStream = null;
                }
            }
        }
    }

    /**
     * Validate XML against specified XSD schmema.<br>
     * <b>Note:</b> The XML source/stream will not be closed. This must be
     * invoked by the caller afterwards!<br>
     * 
     * @param xsd
     *          Source for XSD-schema that will be used to validate the XML
     * @param xml
     *          Source for XML
     * @throws SAXException
     *           if XML is not valid against XSD
     * @throws IOException
     */
    public static void validate(final Source xsd, final Source xml) throws SAXException, IOException {
        final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final Schema schema = factory.newSchema(xsd);
        final Validator validator = schema.newValidator();
        validator.validate(xml);
    }
}