git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277707 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -0,0 +1,310 @@ | |||
| <html> | |||
| <head> | |||
| <title>SchemaValidate Task</title> | |||
| </head> | |||
| <body> | |||
| <h2><a name="schemavalidate">SchemaValidate</a></h2> | |||
| <h3>Description</h3> | |||
| <p>This task validates XML files described by an XML Schema. | |||
| The task extends the XmlValidate task with XSD-specific features.</p> | |||
| <ol> | |||
| <li>The parser is created validating and namespace aware | |||
| </li> | |||
| <li>Validation is turned on.</li> | |||
| <li>and Schema validation is turned on.</li> | |||
| <li>Any default schema supplied is used as the no-namespace schema | |||
| <li>All nested schema declarations are turned into the list of namespace-url | |||
| bindings for schema lookup. | |||
| </ol> | |||
| Note that nested catalogs are still used for lookup of the URLs given as the | |||
| sources of schema documents, so you can still delegate lookup to a catalog, you | |||
| just need to list all schema URIs and their URL equivalents. | |||
| <p>This task supports the use of nested | |||
| <li><a href="../CoreTypes/xmlcatalog.html"><tt><xmlcatalog></tt></a> elements</li> | |||
| <li> <tt><schema></tt> elements, that bind a namespace URI to a URL or a | |||
| local filename. | |||
| <li><tt><dtd></tt> elements which are used to resolve DTDs and entities.</li> | |||
| <li><tt><attribute></tt> elements which are used to set features on the parser. | |||
| These can be any number of | |||
| <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"><tt>http://xml.org/sax/features/</tt></a> | |||
| or other features that your parser may support.</li> | |||
| <li><tt><property></tt> elements, containing string properties | |||
| </p> | |||
| <p> | |||
| The task only supports SAX2 or later parsers: it is an error to specify a SAX1 | |||
| parser. | |||
| <h3>Parameters</h3> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">file</td> | |||
| <td valign="top">the file(s) you want to check. (optionally can use an embedded fileset)</td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">defaultSchemaFile</td> | |||
| <td valign="top"> | |||
| filename of a no-namespace XSD file to provide the | |||
| schema for no-namespace XML content. | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">noNamespaceURL</td> | |||
| <td valign="top"> | |||
| URL of a no-namespace XSD file to provide the | |||
| schema for no-namespace XML content. | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">noNamespaceFile</td> | |||
| <td valign="top"> | |||
| filename of a no-namespace XSD file to provide the | |||
| schema for no-namespace XML content. | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">fullchecking</td> | |||
| <td valign="top"> | |||
| enable full schema checking. Slow but strict. | |||
| </td> | |||
| <td valign="top" align="center">No - default true</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">lenient</td> | |||
| <td valign="top"> | |||
| if true, only check the XML document is well formed | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">classname</td> | |||
| <td valign="top">the parser to use.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">classpathref</td> | |||
| <td valign="top">where to find the parser class. | |||
| Optionally can use an embedded <tt><classpath></tt> element.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">failonerror</td> | |||
| <td valign="top">fails on a error if set to true (defaults to true).</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">warn</td> | |||
| <td valign="top">log parser warn events.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| </table> | |||
| <h3><a name="nested">Nested Elements</a></h3> | |||
| <h4>schema</h4> | |||
| <p> | |||
| Identify the name and location of a schema that may be used in validating | |||
| the document(s). | |||
| </p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td width="12%" valign="top"><b>Attribute</b></td> | |||
| <td width="78%" valign="top"><b>Description</b></td> | |||
| <td width="10%" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">namespace</td> | |||
| <td valign="top">URI of the schema namespace</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">url</td> | |||
| <td valign="top">URL of the schema</td> | |||
| <td align="center" valign="top">One of url or file is required</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">file</td> | |||
| <td valign="top">file of the schema</td> | |||
| <td align="center" valign="top">One of url or file is required</td> | |||
| </tr> | |||
| </table> | |||
| <h4>dtd</h4> | |||
| <p> | |||
| <tt><dtd></tt> is used to specify different locations for DTD resolution. | |||
| </p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td width="12%" valign="top"><b>Attribute</b></td> | |||
| <td width="78%" valign="top"><b>Description</b></td> | |||
| <td width="10%" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">publicId</td> | |||
| <td valign="top">Public ID of the DTD to resolve</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">location</td> | |||
| <td valign="top">Location of the DTD to use, which can be a file, | |||
| a resource, or a URL</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| </table> | |||
| <h4>xmlcatalog</h4> | |||
| <p>The <a href="../CoreTypes/xmlcatalog.html"><tt><xmlcatalog></tt></a> | |||
| element is used to perform entity resolution.</p> | |||
| <h4>attribute</h4> | |||
| <p>The <tt><attribute></tt> element is used to set parser features.<br> | |||
| Features usable with the xerces parser are defined here : | |||
| <a href="http://xml.apache.org/xerces-j/features.html">Setting features</a><br> | |||
| SAX features are defined here: | |||
| <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"><tt>http://xml.org/sax/features/</tt></a><br> | |||
| </p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td width="12%" valign="top"><b>Attribute</b></td> | |||
| <td width="78%" valign="top"><b>Description</b></td> | |||
| <td width="10%" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">name</td> | |||
| <td valign="top">The name of the feature</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">value</td> | |||
| <td valign="top">The boolean value of the feature</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| </table> | |||
| </p> | |||
| <h4>property</h4> | |||
| <p>The <tt><property></tt> element is used to set properties. | |||
| These properties are defined here for the xerces XML parser implementation : | |||
| <a href="http://xml.apache.org/xerces-j/properties.html">XML Parser properties</a> | |||
| Properties can be used to set the schema used to validate the XML file. | |||
| </p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td width="12%" valign="top"><b>Attribute</b></td> | |||
| <td width="78%" valign="top"><b>Description</b></td> | |||
| <td width="10%" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">name</td> | |||
| <td valign="top">The name of the feature</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">value</td> | |||
| <td valign="top">The string value of the property</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| </table> | |||
| </p> | |||
| <h3>Examples</h3> | |||
| <pre> | |||
| <xmlvalidate file="toto.xml"/> | |||
| </pre> | |||
| Validate toto.xml | |||
| <pre> | |||
| <xmlvalidate failonerror="no" lenient="yes" warn="yes" | |||
| classname="org.apache.xerces.parsers.SAXParser"> | |||
| classpath="lib/xerces.jar"> | |||
| <fileset dir="src" includes="style/*.xsl"/> | |||
| </xmlvalidate> | |||
| </pre> | |||
| Validate all .xsl files in src/style, but only warn if there is an error, rather than | |||
| halt the build. | |||
| <pre> | |||
| <xmlvalidate file="struts-config.xml" warn="false"> | |||
| <dtd publicId="-//Apache Software Foundation//DTD Struts Configuration 1.0//EN" | |||
| location="struts-config_1_0.dtd"/> | |||
| </xmlvalidate> | |||
| </pre> | |||
| Validate a struts configuration, using a local copy of the DTD. | |||
| <pre> | |||
| <xmlvalidate failonerror="no"> | |||
| <fileset dir="${project.dir}" includes="**/*.xml"/> | |||
| <xmlcatalog refid="mycatalog"/> | |||
| </xmlvalidate> | |||
| </pre> | |||
| Scan all XML files in the project, using a predefined catalog to map URIs to local files. | |||
| <pre> | |||
| <xmlvalidate failonerror="no"> | |||
| <fileset dir="${project.dir}" includes="**/*.xml"/> | |||
| <xmlcatalog> | |||
| <dtd | |||
| publicId="-//ArielPartners//DTD XML Article V1.0//EN" | |||
| location="com/arielpartners/knowledgebase/dtd/article.dtd"/> | |||
| </xmlcatalog> | |||
| </xmlvalidate> | |||
| </pre> | |||
| Scan all XML files in the project, using the catalog defined inline. | |||
| <pre> | |||
| <xmlvalidate failonerror="yes" lenient="no" warn="yes"> | |||
| <fileset dir="xml" includes="**/*.xml"/> | |||
| <attribute name="http://xml.org/sax/features/validation" value="true"/> | |||
| <attribute name="http://apache.org/xml/features/validation/schema" value="true"/> | |||
| <attribute name="http://xml.org/sax/features/namespaces" value="true"/> | |||
| </xmlvalidate> | |||
| </pre> | |||
| Validate all .xml files in xml directory with the parser configured to perform schema validation. Note: The parser must support the | |||
| <pre>http://apache.org/xml/features/validation/schema</pre> feature. | |||
| <br> | |||
| <pre> | |||
| <!-- Converts path to URL format --> | |||
| <pathconvert dirsep="/" property="xsd.file"> | |||
| <path> | |||
| <pathelement location="xml/doc.xsd"/> | |||
| </path> | |||
| </pathconvert> | |||
| <xmlvalidate file="xml/endpiece-noSchema.xml" lenient="false" | |||
| failonerror="true" warn="true"> | |||
| <attribute name="http://apache.org/xml/features/validation/schema" | |||
| value="true"/> | |||
| <attribute name="http://xml.org/sax/features/namespaces" value="true"/> | |||
| <property | |||
| name="http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation" | |||
| value="${xsd.file}"/> | |||
| </xmlvalidate> | |||
| </pre> | |||
| <br> | |||
| Validate the file xml/endpiece-noSchema.xml against the schema xml/doc.xsd. | |||
| <br> | |||
| <hr> | |||
| <p align="center">Copyright © 2001-2002,2004 The Apache Software Foundation. All rights | |||
| Reserved.</p> | |||
| </body> | |||
| </html> | |||
| @@ -56,11 +56,12 @@ | |||
| <a href="OptionalTasks/replaceregexp.html">ReplaceRegExp</a><br> | |||
| <a href="OptionalTasks/rexec.html">RExec</a><br> | |||
| <a href="OptionalTasks/rpm.html">Rpm</a><br> | |||
| <a href="OptionalTasks/serverdeploy.html">ServerDeploy</a><br> | |||
| <a href="OptionalTasks/setproxy.html">Setproxy</a><br> | |||
| <a href="OptionalTasks/schemavalidate.html">SchemaValidate</a><br> | |||
| <a href="OptionalTasks/scp.html">Scp</a><br> | |||
| <a href="OptionalTasks/script.html">Script</a><br> | |||
| <a href="OptionalTasks/scriptdef.html">Scriptdef</a><br> | |||
| <a href="OptionalTasks/serverdeploy.html">ServerDeploy</a><br> | |||
| <a href="OptionalTasks/setproxy.html">Setproxy</a><br> | |||
| <a href="OptionalTasks/sound.html">Sound</a><br> | |||
| <a href="OptionalTasks/sos.html">SourceOffSite</a><br> | |||
| <a href="OptionalTasks/splash.html">Splash</a><br> | |||
| @@ -0,0 +1,30 @@ | |||
| <project name="validate" default="default" basedir="."> | |||
| <property name="doc.xsd" location="xml/doc.xsd"/> | |||
| <property name="doc-in-ns.xsd" location="xml/doc-in-ns.xsd"/> | |||
| <property name="namespace" value="http://apache.org/ant/doc/" /> | |||
| <property name="endpiece-ns-no-location.xml" | |||
| location="xml/endpiece-ns-no-location.xml"/> | |||
| <target name="testNoNamespace"> | |||
| <schemavalidate | |||
| defaultSchemaFile="${doc.xsd}" | |||
| file="xml/endpiece-noSchema.xml"> | |||
| </schemavalidate> | |||
| </target> | |||
| <target name="testNSMapping"> | |||
| <schemavalidate | |||
| file="${endpiece-ns-no-location.xml}"> | |||
| <schema namespace="${namespace}" file="${doc-in-ns.xsd}" /> | |||
| <schema namespace="http://apache.org/ant/2" | |||
| url="http://ant.apache.org/" /> | |||
| </schemavalidate> | |||
| </target> | |||
| <target name="default" depends="testNoNamespace,testNSMapping" /> | |||
| </project> | |||
| @@ -0,0 +1,22 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" | |||
| targetNamespace="http://apache.org/ant/doc/" | |||
| xmlns:tns="http://apache.org/ant/doc/" | |||
| elementFormDefault="qualified"> | |||
| <xs:element name="doc"> | |||
| <xs:complexType> | |||
| <xs:sequence> | |||
| <xs:element ref="tns:section"/> | |||
| </xs:sequence> | |||
| </xs:complexType> | |||
| </xs:element> | |||
| <xs:element name="section"> | |||
| <xs:complexType> | |||
| <xs:simpleContent> | |||
| <xs:extension base="xs:string"> | |||
| <xs:attribute name="title" type="xs:string"/> | |||
| </xs:extension> | |||
| </xs:simpleContent> | |||
| </xs:complexType> | |||
| </xs:element> | |||
| </xs:schema> | |||
| @@ -0,0 +1,7 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <doc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="doc-in-ns.xsd" xmlns="http://apache.org/ant/doc/"> | |||
| <section title="endpiece"> | |||
| With a little luck, the network will pick me up. | |||
| This is Ripley - last survivor of The Nostromo - signing off. | |||
| </section> | |||
| </doc> | |||
| @@ -1,8 +1,6 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <doc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
| xsi:noNamespaceSchemaLocation="doc.xsd" | |||
| xmlns="http://Massive/Attack+Mezzanine"> | |||
| <section title="endpiece"> | |||
| <doc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="doc-in-ns.xsd" xmlns="http://apache.org/ant/doc/"> | |||
| <section title="endpiece"> | |||
| With a little luck, the network will pick me up. | |||
| This is Ripley - last survivor of The Nostromo - signing off. | |||
| </section> | |||
| @@ -175,5 +175,18 @@ | |||
| </xmlvalidate> | |||
| </target> | |||
| <target name="testSchemaWithXSD"> | |||
| <xmlvalidate warn="false" lenient="false" | |||
| file="xml/endpiece-noSchema.xml"> | |||
| <attribute name="http://apache.org/xml/features/validation/schema" | |||
| value="true"/> | |||
| <property | |||
| name="http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation" | |||
| value="${xsd.file}"/> | |||
| </xmlvalidate> | |||
| </target> | |||
| </project> | |||
| @@ -206,6 +206,7 @@ rexec=org.apache.tools.ant.taskdefs.optional.net.RExecTask | |||
| scriptdef=org.apache.tools.ant.taskdefs.optional.script.ScriptDef | |||
| ildasm=org.apache.tools.ant.taskdefs.optional.dotnet.Ildasm | |||
| apt=org.apache.tools.ant.taskdefs.Apt | |||
| schemavalidate=org.apache.tools.ant.taskdefs.optional.SchemaValidate | |||
| # deprecated ant tasks (kept for back compatibility) | |||
| starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut | |||
| @@ -0,0 +1,361 @@ | |||
| /* | |||
| * Copyright 2004 The Apache Software Foundation | |||
| * | |||
| * Licensed 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 org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.types.DTDLocation; | |||
| import org.apache.tools.ant.util.XmlConstants; | |||
| import org.apache.tools.ant.util.JAXPUtils; | |||
| import org.xml.sax.XMLReader; | |||
| import org.xml.sax.SAXNotRecognizedException; | |||
| import org.xml.sax.SAXNotSupportedException; | |||
| import org.xml.sax.SAXException; | |||
| import javax.xml.parsers.SAXParserFactory; | |||
| import javax.xml.parsers.SAXParser; | |||
| import javax.xml.parsers.ParserConfigurationException; | |||
| import java.util.List; | |||
| import java.util.ArrayList; | |||
| import java.util.Iterator; | |||
| import java.io.File; | |||
| import java.net.MalformedURLException; | |||
| /** | |||
| * Validate XML Schema documents. | |||
| * This task validates XML schema documents. It requires an XML parser | |||
| * that handles the relevant SAx, Xerces or JAXP options. | |||
| * | |||
| * To resolve remote referencies, Ant may need its proxy set up, using the | |||
| * setproxy task. | |||
| * | |||
| * Hands off most of the work to its parent, {@link XMLValidateTask} | |||
| * @since Ant1.7 | |||
| */ | |||
| public class SchemaValidate extends XMLValidateTask { | |||
| private List schemaLocations= new ArrayList(); | |||
| /** full checking of a schema */ | |||
| private boolean fullChecking=true; | |||
| /** | |||
| * default URL for nonamespace schemas | |||
| */ | |||
| private SchemaLocation anonymousSchema; | |||
| public static final String ERROR_SAX_1 = "SAX1 parsers are not supported"; | |||
| public static final String ERROR_NO_XSD_SUPPORT = | |||
| "Parser does not support Xerces or JAXP schema features"; | |||
| public static final String ERROR_TOO_MANY_DEFAULT_SCHEMAS = | |||
| "Only one of defaultSchemaFile and defaultSchemaURL allowed"; | |||
| public static final String ERROR_PARSER_CREATION_FAILURE = "Could not create parser"; | |||
| /** | |||
| * Called by the project to let the task initialize properly. The default | |||
| * implementation is a no-op. | |||
| * | |||
| * @throws BuildException if something goes wrong with the build | |||
| */ | |||
| public void init() throws BuildException { | |||
| super.init(); | |||
| //validating | |||
| setLenient(false); | |||
| } | |||
| public boolean enableXercesSchemaValidation() { | |||
| try { | |||
| setFeature(XmlConstants.FEATURE_XSD,true); | |||
| //set the schema source for the doc | |||
| setNoNamespaceSchemaProperty( | |||
| XmlConstants.PROPERTY_NO_NAMESPACE_SCHEMA_LOCATION); | |||
| } catch (BuildException e) { | |||
| log(e.toString(),Project.MSG_VERBOSE); | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| private void setNoNamespaceSchemaProperty(String property) { | |||
| String anonSchema = getNoNamespaceSchemaURL(); | |||
| if (anonSchema != null) { | |||
| setProperty(property, | |||
| anonSchema); | |||
| } | |||
| } | |||
| /** | |||
| * JAXP12 schema attributes | |||
| * @see <A href="http://java.sun.com/xml/jaxp/change-requests-11.html"> | |||
| * JAXP 1.2 Approved CHANGES</A> | |||
| * @return | |||
| */ | |||
| public boolean enableJAXP12SchemaValidation() { | |||
| try { | |||
| //enable XSD | |||
| setProperty(XmlConstants.FEATURE_JAXP12_SCHEMA_LANGUAGE, | |||
| XmlConstants.URI_XSD); | |||
| //set the schema source for the doc | |||
| setNoNamespaceSchemaProperty( | |||
| XmlConstants.FEATURE_JAXP12_SCHEMA_SOURCE); | |||
| } catch (BuildException e) { | |||
| log(e.toString(), Project.MSG_VERBOSE); | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| public void addSchema(SchemaLocation location) { | |||
| schemaLocations.add(location); | |||
| } | |||
| /** | |||
| * enable full schema checking. Slower but better. | |||
| * @param fullChecking | |||
| */ | |||
| public void setFullChecking(boolean fullChecking) { | |||
| this.fullChecking = fullChecking; | |||
| } | |||
| /** | |||
| * create a schema location to hold the anonymous | |||
| * schema | |||
| */ | |||
| protected void createAnonymousSchema() { | |||
| if(anonymousSchema==null) { | |||
| anonymousSchema=new SchemaLocation(); | |||
| } | |||
| anonymousSchema.setNamespace("(no namespace)"); | |||
| } | |||
| /** | |||
| * identify the URL of the default schema | |||
| * @param defaultSchemaURL | |||
| */ | |||
| public void setNoNamespaceURL(String defaultSchemaURL) { | |||
| createAnonymousSchema(); | |||
| this.anonymousSchema.setUrl(defaultSchemaURL); | |||
| } | |||
| /** | |||
| * identify a file containing the default schema | |||
| * @param defaultSchemaFile | |||
| */ | |||
| public void setNoNamespaceFile(File defaultSchemaFile) { | |||
| createAnonymousSchema(); | |||
| this.anonymousSchema.setFile(defaultSchemaFile); | |||
| } | |||
| /** | |||
| * 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() { | |||
| super.initValidator(); | |||
| XMLReader xmlReader = getXmlReader(); | |||
| //validate the parser type | |||
| if(isSax1Parser()) { | |||
| throw new BuildException(ERROR_SAX_1); | |||
| } | |||
| //enable schema | |||
| //setFeature(XmlConstants.FEATURE_VALIDATION,false); | |||
| setFeature(XmlConstants.FEATURE_NAMESPACES,true); | |||
| if(!enableXercesSchemaValidation() && | |||
| !enableJAXP12SchemaValidation()) { | |||
| //couldnt use the xerces or jaxp calls | |||
| throw new BuildException(ERROR_NO_XSD_SUPPORT); | |||
| } | |||
| //enable schema checking | |||
| setFeature(XmlConstants.FEATURE_XSD_FULL_VALIDATION,fullChecking); | |||
| //turn off DTDs | |||
| setFeatureIfSupported(XmlConstants.FEATURE_DISALLOW_DTD,true); | |||
| //schema declarations go in next | |||
| addSchemaLocations(); | |||
| } | |||
| /** | |||
| * Create a reader if the use of the class did not specify another one. | |||
| * The reason to not use {@link JAXPUtils#getXMLReader()} was to | |||
| * create our own factory with our own options. | |||
| * @return | |||
| */ | |||
| protected XMLReader createDefaultReader() { | |||
| SAXParserFactory factory = SAXParserFactory.newInstance(); | |||
| factory.setValidating(true); | |||
| factory.setNamespaceAware(true); | |||
| XMLReader reader = null; | |||
| try { | |||
| SAXParser saxParser = factory.newSAXParser(); | |||
| reader = saxParser.getXMLReader(); | |||
| } catch (ParserConfigurationException e) { | |||
| throw new BuildException(ERROR_PARSER_CREATION_FAILURE,e); | |||
| } catch (SAXException e) { | |||
| throw new BuildException(ERROR_PARSER_CREATION_FAILURE, e); | |||
| } | |||
| return reader; | |||
| } | |||
| /** | |||
| * build a string list of all schema locations, then set the relevant | |||
| * property. | |||
| */ | |||
| protected void addSchemaLocations() { | |||
| Iterator it = schemaLocations.iterator(); | |||
| StringBuffer buffer = new StringBuffer(); | |||
| int count = 0; | |||
| while (it.hasNext()) { | |||
| if (count > 0) { | |||
| buffer.append(' '); | |||
| } | |||
| SchemaLocation schemaLocation = (SchemaLocation) it.next(); | |||
| String tuple = schemaLocation.getURIandLocation(); | |||
| buffer.append(tuple); | |||
| count++; | |||
| } | |||
| if (count > 0) { | |||
| setProperty(XmlConstants.PROPERTY_SCHEMA_LOCATION, buffer.toString()); | |||
| } | |||
| } | |||
| /** | |||
| * get the URL of the no namespace schema | |||
| * @return | |||
| */ | |||
| protected String getNoNamespaceSchemaURL() { | |||
| if(anonymousSchema==null) { | |||
| return null; | |||
| } else { | |||
| return anonymousSchema.getSchemaLocationURL(); | |||
| } | |||
| } | |||
| /** | |||
| * set a feature if it is supported, log at verbose level if | |||
| * not | |||
| * @param feature | |||
| * @param value | |||
| */ | |||
| protected void setFeatureIfSupported(String feature,boolean value) { | |||
| try { | |||
| getXmlReader().setFeature(feature, value); | |||
| } catch (SAXNotRecognizedException e) { | |||
| log("Not recognizied: "+feature,Project.MSG_VERBOSE); | |||
| } catch (SAXNotSupportedException e) { | |||
| log("Not supported: " + feature, Project.MSG_VERBOSE); | |||
| } | |||
| } | |||
| /** | |||
| * representation of a schema location. This is a URI plus either a file or | |||
| * a url | |||
| */ | |||
| public static class SchemaLocation { | |||
| private String namespace; | |||
| private File file; | |||
| private String url; | |||
| public static final String ERROR_NO_URI = "No URI"; | |||
| private static final String ERROR_TWO_LOCATIONS = | |||
| "Both URL and File were given for schema "; | |||
| public static final String ERROR_NO_FILE = "File not found: "; | |||
| public static final String ERROR_NO_URL_REPRESENTATION = "Cannot make a URL of "; | |||
| public static final String ERROR_NO_LOCATION = "No file or URL supplied for the schema "; | |||
| public SchemaLocation() { | |||
| } | |||
| public String getNamespace() { | |||
| return namespace; | |||
| } | |||
| public void setNamespace(String namespace) { | |||
| this.namespace = namespace; | |||
| } | |||
| public File getFile() { | |||
| return file; | |||
| } | |||
| public void setFile(File file) { | |||
| this.file = file; | |||
| } | |||
| public String getUrl() { | |||
| return url; | |||
| } | |||
| public void setUrl(String url) { | |||
| this.url = url; | |||
| } | |||
| public String getSchemaLocationURL() { | |||
| boolean hasFile = file != null; | |||
| boolean hasURL = isSet(url); | |||
| //error if both are empty, or both are set | |||
| if(!hasFile && !hasURL) { | |||
| throw new BuildException( | |||
| ERROR_NO_LOCATION+namespace); | |||
| } | |||
| if (hasFile && hasURL) { | |||
| throw new BuildException(ERROR_TWO_LOCATIONS + namespace); | |||
| } | |||
| String schema = url; | |||
| if (hasFile) { | |||
| if (!file.exists()) { | |||
| throw new BuildException(ERROR_NO_FILE + file); | |||
| } | |||
| try { | |||
| schema = file.toURL().toString(); | |||
| } catch (MalformedURLException e) { | |||
| //this is almost implausible, but required handling | |||
| throw new BuildException(ERROR_NO_URL_REPRESENTATION + file,e); | |||
| } | |||
| } | |||
| return schema; | |||
| } | |||
| /** | |||
| * validate the fields then create a "uri location" string | |||
| * | |||
| * @return string of uri and location | |||
| * @throws BuildException | |||
| */ | |||
| public String getURIandLocation() throws BuildException { | |||
| if (!isSet(getNamespace())) { | |||
| throw new BuildException(ERROR_NO_URI); | |||
| } | |||
| StringBuffer buffer = new StringBuffer(); | |||
| buffer.append(namespace); | |||
| buffer.append(' '); | |||
| buffer.append(getSchemaLocationURL()); | |||
| return new String(buffer); | |||
| } | |||
| private boolean isSet(String property) { | |||
| return property != null && property.length() != 0; | |||
| } | |||
| } //SchemaLocation | |||
| } | |||
| @@ -33,6 +33,7 @@ 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; | |||
| @@ -258,6 +259,19 @@ public class XMLValidateTask extends Task { | |||
| 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 | |||
| @@ -304,16 +318,56 @@ public class XMLValidateTask extends Task { | |||
| /** | |||
| * 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 | |||
| for (int i = 0; i < attributeList.size(); i++) { | |||
| Attribute feature = (Attribute) attributeList.elementAt(i); | |||
| setFeature(feature.getName(), feature.getValue()); | |||
| } | |||
| // Sets properties | |||
| for (int i = 0; i < propertyList.size(); 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 | |||
| */ | |||
| private void initValidator() { | |||
| 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. | |||
| * @returns the new XMLReader. | |||
| */ | |||
| protected XMLReader createXmlReader() { | |||
| Object reader = null; | |||
| if (readerClassName == null) { | |||
| try { | |||
| reader = JAXPUtils.getXMLReader(); | |||
| } catch (BuildException exc) { | |||
| reader = JAXPUtils.getParser(); | |||
| } | |||
| reader = createDefaultReaderOrParser(); | |||
| } else { | |||
| Class readerClass = null; | |||
| @@ -338,8 +392,9 @@ public class XMLValidateTask extends Task { | |||
| } | |||
| // then check it implements XMLReader | |||
| XMLReader newReader; | |||
| if (reader instanceof XMLReader) { | |||
| xmlReader = (XMLReader) reader; | |||
| newReader = (XMLReader) reader; | |||
| log( | |||
| "Using SAX2 reader " + reader.getClass().getName(), | |||
| Project.MSG_VERBOSE); | |||
| @@ -347,7 +402,7 @@ public class XMLValidateTask extends Task { | |||
| // see if it is a SAX1 Parser | |||
| if (reader instanceof Parser) { | |||
| xmlReader = new ParserAdapter((Parser) reader); | |||
| newReader = new ParserAdapter((Parser) reader); | |||
| log( | |||
| "Using SAX1 parser " + reader.getClass().getName(), | |||
| Project.MSG_VERBOSE); | |||
| @@ -358,36 +413,41 @@ public class XMLValidateTask extends Task { | |||
| + " implements nor SAX1 Parser nor SAX2 XMLReader."); | |||
| } | |||
| } | |||
| return newReader; | |||
| } | |||
| xmlReader.setEntityResolver(getEntityResolver()); | |||
| xmlReader.setErrorHandler(errorHandler); | |||
| if (!(xmlReader instanceof ParserAdapter)) { | |||
| // turn validation on | |||
| if (!lenient) { | |||
| setFeature("http://xml.org/sax/features/validation", true); | |||
| } | |||
| // set the feature from the attribute list | |||
| for (int i = 0; i < attributeList.size(); i++) { | |||
| Attribute feature = (Attribute) attributeList.elementAt(i); | |||
| setFeature(feature.getName(), feature.getValue()); | |||
| } | |||
| // Sets properties | |||
| for (int i = 0; i < propertyList.size(); i++) { | |||
| final Property prop = (Property) propertyList.elementAt(i); | |||
| setProperty(prop.getName(), prop.getValue()); | |||
| } | |||
| /** | |||
| * | |||
| * @return | |||
| */ | |||
| 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 | |||
| */ | |||
| private void setFeature(String feature, boolean value) | |||
| protected void setFeature(String feature, boolean value) | |||
| throws BuildException { | |||
| log("Setting feature " + feature + "=" + value, Project.MSG_DEBUG); | |||
| try { | |||
| @@ -417,8 +477,9 @@ public class XMLValidateTask extends Task { | |||
| * @param name a property name | |||
| * @param value a property value. | |||
| * @throws BuildException if an error occurs. | |||
| * @throws BuildException if the property was not supported | |||
| */ | |||
| private void setProperty(String name, String value) throws BuildException { | |||
| 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."); | |||
| @@ -448,7 +509,7 @@ public class XMLValidateTask extends Task { | |||
| /** | |||
| * parse the file | |||
| */ | |||
| private void doValidate(File afile) { | |||
| protected void doValidate(File afile) { | |||
| try { | |||
| log("Validating " + afile.getName() + "... ", Project.MSG_VERBOSE); | |||
| errorHandler.init(afile); | |||
| @@ -655,4 +716,6 @@ public class XMLValidateTask extends Task { | |||
| } // Property | |||
| } | |||
| @@ -0,0 +1,47 @@ | |||
| /* | |||
| * Copyright 2004 The Apache Software Foundation | |||
| * | |||
| * Licensed 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.util; | |||
| /** | |||
| * XML Parser constants, all kept in one place for ease of reuse | |||
| * @see <a href="http://xml.apache.org/xerces-j/features.html">Xerces features</a> | |||
| * @see <a href="http://xml.apache.org/xerces-j/properties.html">Xerces properties</a> | |||
| * @see <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description">SAX.</a> | |||
| */ | |||
| public class XmlConstants { | |||
| public static final String PROPERTY_SCHEMA_LOCATION = | |||
| "http://apache.org/xml/properties/schema/external-schemaLocation"; | |||
| public static final String PROPERTY_NO_NAMESPACE_SCHEMA_LOCATION = | |||
| "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"; | |||
| public static final String FEATURE_XSD_FULL_VALIDATION = | |||
| "http://apache.org/xml/features/validation/schema-full-checking"; | |||
| public static final String FEATURE_XSD = "http://apache.org/xml/features/validation/schema"; | |||
| public static final String FEATURE_VALIDATION = "http://xml.org/sax/features/validation"; | |||
| public static final String FEATURE_NAMESPACES = "http://xml.org/sax/features/namespaces"; | |||
| public static final String FEATURE_JAXP12_SCHEMA_LANGUAGE = | |||
| "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; | |||
| public static final String FEATURE_JAXP12_SCHEMA_SOURCE = | |||
| "http://java.sun.com/xml/jaxp/properties/schemaSource"; | |||
| public static final String URI_XSD = | |||
| "http://www.w3.org/2001/XMLSchema"; | |||
| public static final String FEATURE_EXTERNAL_ENTITIES = | |||
| "http://xml.org/sax/features/external-general-entities"; | |||
| public static final String FEATURE_DISALLOW_DTD = | |||
| "http://apache.org/xml/features/disallow-doctype-decl"; | |||
| } | |||
| @@ -0,0 +1,63 @@ | |||
| /* | |||
| * Copyright 2004 The Apache Software Foundation | |||
| * | |||
| * Licensed 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 org.apache.tools.ant.BuildFileTest; | |||
| /** | |||
| * Test schema validation | |||
| */ | |||
| public class SchemaValidateTest extends BuildFileTest { | |||
| /** | |||
| * where tasks run | |||
| */ | |||
| private final static String TASKDEFS_DIR = | |||
| "src/etc/testcases/taskdefs/optional/"; | |||
| /** | |||
| * Constructor | |||
| * | |||
| * @param name testname | |||
| */ | |||
| public SchemaValidateTest(String name) { | |||
| super(name); | |||
| } | |||
| /** | |||
| * The JUnit setup method | |||
| */ | |||
| public void setUp() { | |||
| configureProject(TASKDEFS_DIR + "schemavalidate.xml"); | |||
| } | |||
| /** | |||
| * test with no namespace | |||
| */ | |||
| public void testNoNamespace() throws Exception { | |||
| executeTarget("testNoNamespace"); | |||
| } | |||
| /** | |||
| * add namespace awareness. | |||
| */ | |||
| public void testNSMapping() throws Exception { | |||
| executeTarget("testNSMapping"); | |||
| } | |||
| } | |||