aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java764
1 files changed, 764 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
new file mode 100644
index 00000000..05c043df
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
@@ -0,0 +1,764 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tools.ant.taskdefs.optional;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Vector;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.DTDLocation;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.XMLCatalog;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.JAXPUtils;
+import org.apache.tools.ant.util.XmlConstants;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.ParserAdapter;
+
+/**
+ * Checks XML files are valid (or only well formed). The
+ * task uses the SAX2 parser implementation provided by JAXP by default
+ * (probably the one that is used by Ant itself), but one can specify any
+ * SAX1/2 parser if needed.
+ *
+ */
+public class XMLValidateTask extends Task {
+
+ /**
+ * helper for path -> URI and URI -> path conversions.
+ */
+ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
+ protected static final String INIT_FAILED_MSG =
+ "Could not start xml validation: ";
+
+ // ant task properties
+ // defaults
+ // CheckStyle:VisibilityModifier OFF - bc
+ protected boolean failOnError = true;
+ protected boolean warn = true;
+ protected boolean lenient = false;
+ protected String readerClassName = null;
+
+ /** file to be validated */
+ protected File file = null;
+ /** sets of file to be validated */
+ protected Vector filesets = new Vector();
+ protected Path classpath;
+
+ /**
+ * the parser is viewed as a SAX2 XMLReader. If a SAX1 parser is specified,
+ * it's wrapped in an adapter that make it behave as a XMLReader.
+ * a more 'standard' way of doing this would be to use the JAXP1.1 SAXParser
+ * interface.
+ */
+ protected XMLReader xmlReader = null;
+ // XMLReader used to validation process
+ protected ValidatorErrorHandler errorHandler = new ValidatorErrorHandler();
+ // to report sax parsing errors
+ // CheckStyle:VisibilityModifier ON
+
+ /** The vector to store all attributes (features) to be set on the parser. **/
+ private Vector attributeList = new Vector();
+
+ /**
+ * List of properties.
+ */
+ private final Vector propertyList = new Vector();
+
+ private XMLCatalog xmlCatalog = new XMLCatalog();
+ /** Message for successful validation */
+ public static final String MESSAGE_FILES_VALIDATED
+ = " file(s) have been successfully validated.";
+
+ private AntClassLoader readerLoader = null;
+
+ /**
+ * Specify how parser error are to be handled.
+ * Optional, default is <code>true</code>.
+ * <p>
+ * If set to <code>true</code> (default), throw a buildException if the
+ * parser yields an error.
+ * @param fail if set to <code>false</code> do not fail on error
+ */
+ public void setFailOnError(boolean fail) {
+ failOnError = fail;
+ }
+
+ /**
+ * Specify how parser error are to be handled.
+ * <p>
+ * If set to <code>true</code> (default), log a warn message for each SAX warn event.
+ * @param bool if set to <code>false</code> do not send warnings
+ */
+ public void setWarn(boolean bool) {
+ warn = bool;
+ }
+
+ /**
+ * Specify whether the parser should be validating. Default
+ * is <code>true</code>.
+ * <p>
+ * If set to false, the validation will fail only if the parsed document
+ * is not well formed XML.
+ * <p>
+ * this option is ignored if the specified class
+ * with {@link #setClassName(String)} is not a SAX2 XMLReader.
+ * @param bool if set to <code>false</code> only fail on malformed XML
+ */
+ public void setLenient(boolean bool) {
+ lenient = bool;
+ }
+
+ /**
+ * Specify the class name of the SAX parser to be used. (optional)
+ * @param className should be an implementation of SAX2
+ * <code>org.xml.sax.XMLReader</code> or SAX2 <code>org.xml.sax.Parser</code>.
+ * <p> if className is an implementation of
+ * <code>org.xml.sax.Parser</code>, {@link #setLenient(boolean)},
+ * will be ignored.
+ * <p> if not set, the default will be used.
+ * @see org.xml.sax.XMLReader
+ * @see org.xml.sax.Parser
+ */
+ public void setClassName(String className) {
+ readerClassName = className;
+ }
+
+ /**
+ * Specify the classpath to be searched to load the parser (optional)
+ * @param classpath the classpath to load the parser
+ */
+ public void setClasspath(Path classpath) {
+ if (this.classpath == null) {
+ this.classpath = classpath;
+ } else {
+ this.classpath.append(classpath);
+ }
+ }
+
+ /**
+ * @see #setClasspath
+ * @return the classpath created
+ */
+ public Path createClasspath() {
+ if (this.classpath == null) {
+ this.classpath = new Path(getProject());
+ }
+ return this.classpath.createPath();
+ }
+
+ /**
+ * Where to find the parser class; optional.
+ * @see #setClasspath
+ * @param r reference to a classpath defined elsewhere
+ */
+ public void setClasspathRef(Reference r) {
+ createClasspath().setRefid(r);
+ }
+
+ /**
+ * specify the file to be checked; optional.
+ * @param file the file to be checked
+ */
+ public void setFile(File file) {
+ this.file = file;
+ }
+
+ /**
+ * add an XMLCatalog as a nested element; optional.
+ * @param catalog XMLCatalog to use
+ */
+ public void addConfiguredXMLCatalog(XMLCatalog catalog) {
+ xmlCatalog.addConfiguredXMLCatalog(catalog);
+ }
+
+ /**
+ * specify a set of file to be checked
+ * @param set the fileset to check
+ */
+ public void addFileset(FileSet set) {
+ filesets.addElement(set);
+ }
+
+ /**
+ * Add an attribute nested element. This is used for setting arbitrary
+ * features of the SAX parser.
+ * Valid attributes
+ * <a href=
+ * "http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"
+ * >include</a>
+ * @return attribute created
+ * @since ant1.6
+ */
+ public Attribute createAttribute() {
+ final Attribute feature = new Attribute();
+ attributeList.addElement(feature);
+ return feature;
+ }
+
+ /**
+ * Creates a property.
+ *
+ * @return a property.
+ * @since ant 1.6.2
+ */
+ public Property createProperty() {
+ final Property prop = new Property();
+ propertyList.addElement(prop);
+ return prop;
+ }
+
+ /**
+ * Called by the project to let the task initialize properly.
+ *
+ * @exception BuildException if something goes wrong with the build
+ */
+ public void init() throws BuildException {
+ super.init();
+ xmlCatalog.setProject(getProject());
+ }
+
+ /**
+ * Create a DTD location record; optional.
+ * This stores the location of a DTD. The DTD is identified
+ * by its public Id.
+ * @return created DTD location
+ */
+ public DTDLocation createDTD() {
+ DTDLocation dtdLocation = new DTDLocation();
+ xmlCatalog.addDTD(dtdLocation);
+ return dtdLocation;
+ }
+ /**
+ * accessor to the xmlCatalog used in the task
+ * @return xmlCatalog reference
+ */
+ protected EntityResolver getEntityResolver() {
+ return xmlCatalog;
+ }
+
+ /**
+ * get the XML reader. Non-null only after {@link #initValidator()}.
+ * If the reader is an instance of {@link ParserAdapter} then
+ * the parser is a SAX1 parser, and you cannot call
+ * {@link #setFeature(String, boolean)} or {@link #setProperty(String, String)}
+ * on it.
+ * @return the XML reader or null.
+ */
+ protected XMLReader getXmlReader() {
+ return xmlReader;
+ }
+
+ /**
+ * execute the task
+ * @throws BuildException if <code>failonerror</code> is true and an error happens
+ */
+ public void execute() throws BuildException {
+ try {
+ int fileProcessed = 0;
+ if (file == null && (filesets.size() == 0)) {
+ throw new BuildException(
+ "Specify at least one source - " + "a file or a fileset.");
+ }
+
+
+
+ if (file != null) {
+ if (file.exists() && file.canRead() && file.isFile()) {
+ doValidate(file);
+ fileProcessed++;
+ } else {
+ String errorMsg = "File " + file + " cannot be read";
+ if (failOnError) {
+ throw new BuildException(errorMsg);
+ } else {
+ log(errorMsg, Project.MSG_ERR);
+ }
+ }
+ }
+
+ final int size = filesets.size();
+ for (int i = 0; i < size; i++) {
+
+ FileSet fs = (FileSet) filesets.elementAt(i);
+ DirectoryScanner ds = fs.getDirectoryScanner(getProject());
+ String[] files = ds.getIncludedFiles();
+
+ for (int j = 0; j < files.length; j++) {
+ File srcFile = new File(fs.getDir(getProject()), files[j]);
+ doValidate(srcFile);
+ fileProcessed++;
+ }
+ }
+ onSuccessfulValidation(fileProcessed);
+ } finally {
+ cleanup();
+ }
+ }
+
+ /**
+ * handler called on successful file validation.
+ * @param fileProcessed number of files processed.
+ */
+ protected void onSuccessfulValidation(int fileProcessed) {
+ log(fileProcessed + MESSAGE_FILES_VALIDATED);
+ }
+
+ /**
+ * init the parser :
+ * load the parser class, and set features if necessary
+ * It is only after this that the reader is valid
+ * @throws BuildException if something went wrong
+ */
+ protected void initValidator() {
+
+ xmlReader = createXmlReader();
+
+ xmlReader.setEntityResolver(getEntityResolver());
+ xmlReader.setErrorHandler(errorHandler);
+
+ if (!isSax1Parser()) {
+ // turn validation on
+ if (!lenient) {
+ setFeature(XmlConstants.FEATURE_VALIDATION, true);
+ }
+ // set the feature from the attribute list
+ final int attSize = attributeList.size();
+ for (int i = 0; i < attSize; i++) {
+ Attribute feature = (Attribute) attributeList.elementAt(i);
+ setFeature(feature.getName(), feature.getValue());
+
+ }
+ // Sets properties
+ final int propSize = propertyList.size();
+ for (int i = 0; i < propSize; i++) {
+ final Property prop = (Property) propertyList.elementAt(i);
+ setProperty(prop.getName(), prop.getValue());
+ }
+ }
+ }
+
+ /**
+ * test that returns true if we are using a SAX1 parser.
+ * @return true when a SAX1 parser is in use
+ */
+ protected boolean isSax1Parser() {
+ return (xmlReader instanceof ParserAdapter);
+ }
+
+ /**
+ * create the XML reader.
+ * This is one by instantiating anything specified by {@link #readerClassName},
+ * falling back to a default reader if not.
+ * If the returned reader is an instance of {@link ParserAdapter} then
+ * we have created and wrapped a SAX1 parser.
+ * @return the new XMLReader.
+ */
+ protected XMLReader createXmlReader() {
+ Object reader = null;
+ if (readerClassName == null) {
+ reader = createDefaultReaderOrParser();
+ } else {
+
+ Class readerClass = null;
+ try {
+ // load the parser class
+ if (classpath != null) {
+ readerLoader = getProject().createClassLoader(classpath);
+ readerClass = Class.forName(readerClassName, true,
+ readerLoader);
+ } else {
+ readerClass = Class.forName(readerClassName);
+ }
+
+ reader = readerClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new BuildException(INIT_FAILED_MSG + readerClassName, e);
+ } catch (InstantiationException e) {
+ throw new BuildException(INIT_FAILED_MSG + readerClassName, e);
+ } catch (IllegalAccessException e) {
+ throw new BuildException(INIT_FAILED_MSG + readerClassName, e);
+ }
+ }
+
+ // then check it implements XMLReader
+ XMLReader newReader;
+ if (reader instanceof XMLReader) {
+ newReader = (XMLReader) reader;
+ log(
+ "Using SAX2 reader " + reader.getClass().getName(),
+ Project.MSG_VERBOSE);
+ } else {
+
+ // see if it is a SAX1 Parser
+ if (reader instanceof Parser) {
+ newReader = new ParserAdapter((Parser) reader);
+ log(
+ "Using SAX1 parser " + reader.getClass().getName(),
+ Project.MSG_VERBOSE);
+ } else {
+ throw new BuildException(
+ INIT_FAILED_MSG
+ + reader.getClass().getName()
+ + " implements nor SAX1 Parser nor SAX2 XMLReader.");
+ }
+ }
+ return newReader;
+ }
+
+ /**
+ * Cleans up resources.
+ *
+ * @since Ant 1.8.0
+ */
+ protected void cleanup() {
+ if (readerLoader != null) {
+ readerLoader.cleanup();
+ readerLoader = null;
+ }
+ }
+
+ /**
+ * Returns a SAX-based XMLReader or a SAX-based Parser.
+ * @return reader or parser
+ */
+ private Object createDefaultReaderOrParser() {
+ Object reader;
+ try {
+ reader = createDefaultReader();
+ } catch (BuildException exc) {
+ reader = JAXPUtils.getParser();
+ }
+ return reader;
+ }
+
+ /**
+ * Create a reader if the use of the class did not specify another one.
+ * If a BuildException is thrown, the caller may revert to an alternate
+ * reader.
+ * @return a new reader.
+ * @throws BuildException if something went wrong
+ */
+ protected XMLReader createDefaultReader() {
+ return JAXPUtils.getXMLReader();
+ }
+
+ /**
+ * Set a feature on the parser.
+ * @param feature the name of the feature to set
+ * @param value the value of the feature
+ * @throws BuildException if the feature was not supported
+ */
+ protected void setFeature(String feature, boolean value)
+ throws BuildException {
+ log("Setting feature " + feature + "=" + value, Project.MSG_DEBUG);
+ try {
+ xmlReader.setFeature(feature, value);
+ } catch (SAXNotRecognizedException e) {
+ throw new BuildException(
+ "Parser "
+ + xmlReader.getClass().getName()
+ + " doesn't recognize feature "
+ + feature,
+ e,
+ getLocation());
+ } catch (SAXNotSupportedException e) {
+ throw new BuildException(
+ "Parser "
+ + xmlReader.getClass().getName()
+ + " doesn't support feature "
+ + feature,
+ e,
+ getLocation());
+ }
+ }
+
+ /**
+ * Sets a property.
+ *
+ * @param name a property name
+ * @param value a property value.
+ * @throws BuildException if an error occurs.
+ * @throws BuildException if the property was not supported
+ */
+ protected void setProperty(String name, String value) throws BuildException {
+ // Validates property
+ if (name == null || value == null) {
+ throw new BuildException("Property name and value must be specified.");
+ }
+
+ try {
+ xmlReader.setProperty(name, value);
+ } catch (SAXNotRecognizedException e) {
+ throw new BuildException(
+ "Parser "
+ + xmlReader.getClass().getName()
+ + " doesn't recognize property "
+ + name,
+ e,
+ getLocation());
+ } catch (SAXNotSupportedException e) {
+ throw new BuildException(
+ "Parser "
+ + xmlReader.getClass().getName()
+ + " doesn't support property "
+ + name,
+ e,
+ getLocation());
+ }
+ }
+
+ /**
+ * parse the file
+ * @param afile the file to validate.
+ * @return true if the file validates.
+ */
+ protected boolean doValidate(File afile) {
+ //for every file, we have a new instance of the validator
+ initValidator();
+ boolean result = true;
+ try {
+ log("Validating " + afile.getName() + "... ", Project.MSG_VERBOSE);
+ errorHandler.init(afile);
+ InputSource is = new InputSource(new FileInputStream(afile));
+ String uri = FILE_UTILS.toURI(afile.getAbsolutePath());
+ is.setSystemId(uri);
+ xmlReader.parse(is);
+ } catch (SAXException ex) {
+ log("Caught when validating: " + ex.toString(), Project.MSG_DEBUG);
+ if (failOnError) {
+ throw new BuildException(
+ "Could not validate document " + afile);
+ }
+ log("Could not validate document " + afile + ": " + ex.toString());
+ result = false;
+ } catch (IOException ex) {
+ throw new BuildException(
+ "Could not validate document " + afile,
+ ex);
+ }
+ if (errorHandler.getFailure()) {
+ if (failOnError) {
+ throw new BuildException(
+ afile + " is not a valid XML document.");
+ }
+ result = false;
+ log(afile + " is not a valid XML document", Project.MSG_ERR);
+ }
+ return result;
+ }
+
+ /**
+ * ValidatorErrorHandler role :
+ * <ul>
+ * <li> log SAX parse exceptions,
+ * <li> remember if an error occurred
+ * </ul>
+ */
+ protected class ValidatorErrorHandler implements ErrorHandler {
+
+ // CheckStyle:VisibilityModifier OFF - bc
+ protected File currentFile = null;
+ protected String lastErrorMessage = null;
+ protected boolean failed = false;
+ // CheckStyle:VisibilityModifier ON
+ /**
+ * initialises the class
+ * @param file file used
+ */
+ public void init(File file) {
+ currentFile = file;
+ failed = false;
+ }
+ /**
+ * did an error happen during last parsing ?
+ * @return did an error happen during last parsing ?
+ */
+ public boolean getFailure() {
+ return failed;
+ }
+
+ /**
+ * record a fatal error
+ * @param exception the fatal error
+ */
+ public void fatalError(SAXParseException exception) {
+ failed = true;
+ doLog(exception, Project.MSG_ERR);
+ }
+ /**
+ * receive notification of a recoverable error
+ * @param exception the error
+ */
+ public void error(SAXParseException exception) {
+ failed = true;
+ doLog(exception, Project.MSG_ERR);
+ }
+ /**
+ * receive notification of a warning
+ * @param exception the warning
+ */
+ public void warning(SAXParseException exception) {
+ // depending on implementation, XMLReader can yield hips of warning,
+ // only output then if user explicitly asked for it
+ if (warn) {
+ doLog(exception, Project.MSG_WARN);
+ }
+ }
+
+ private void doLog(SAXParseException e, int logLevel) {
+
+ log(getMessage(e), logLevel);
+ }
+
+ private String getMessage(SAXParseException e) {
+ String sysID = e.getSystemId();
+ if (sysID != null) {
+ String name = sysID;
+ if (sysID.startsWith("file:")) {
+ try {
+ name = FILE_UTILS.fromURI(sysID);
+ } catch (Exception ex) {
+ // if this is not a valid file: just use the uri
+ }
+ }
+ int line = e.getLineNumber();
+ int col = e.getColumnNumber();
+ return name
+ + (line == -1
+ ? ""
+ : (":" + line + (col == -1 ? "" : (":" + col))))
+ + ": "
+ + e.getMessage();
+ }
+ return e.getMessage();
+ }
+ }
+
+ /**
+ * The class to create to set a feature of the parser.
+ * @since ant1.6
+ */
+ public static class Attribute {
+ /** The name of the attribute to set.
+ *
+ * Valid attributes <a href=
+ * "http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"
+ * >include.</a>
+ */
+ private String attributeName = null;
+
+ /**
+ * The value of the feature.
+ **/
+ private boolean attributeValue;
+
+ /**
+ * Set the feature name.
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ attributeName = name;
+ }
+ /**
+ * Set the feature value to true or false.
+ * @param value feature value
+ */
+ public void setValue(boolean value) {
+ attributeValue = value;
+ }
+
+ /**
+ * Gets the attribute name.
+ * @return the feature name
+ */
+ public String getName() {
+ return attributeName;
+ }
+
+ /**
+ * Gets the attribute value.
+ * @return the feature value
+ */
+ public boolean getValue() {
+ return attributeValue;
+ }
+ }
+
+ /**
+ * A Parser property.
+ * See <a href="http://xml.apache.org/xerces-j/properties.html">
+ * XML parser properties</a> for usable properties
+ * @since ant 1.6.2
+ */
+ public static final class Property {
+
+ private String name;
+ private String value;
+ /**
+ * accessor to the name of the property
+ * @return name of the property
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * setter for the name of the property
+ * @param name name of the property
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * getter for the value of the property
+ * @return value of the property
+ */
+ public String getValue() {
+ return value;
+ }
+ /**
+ * sets the value of the property
+ * @param value value of the property
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ } // Property
+
+
+
+}