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/replaceregexp.html">ReplaceRegExp</a><br> | ||||
<a href="OptionalTasks/rexec.html">RExec</a><br> | <a href="OptionalTasks/rexec.html">RExec</a><br> | ||||
<a href="OptionalTasks/rpm.html">Rpm</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/scp.html">Scp</a><br> | ||||
<a href="OptionalTasks/script.html">Script</a><br> | <a href="OptionalTasks/script.html">Script</a><br> | ||||
<a href="OptionalTasks/scriptdef.html">Scriptdef</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/sound.html">Sound</a><br> | ||||
<a href="OptionalTasks/sos.html">SourceOffSite</a><br> | <a href="OptionalTasks/sos.html">SourceOffSite</a><br> | ||||
<a href="OptionalTasks/splash.html">Splash</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"?> | <?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. | With a little luck, the network will pick me up. | ||||
This is Ripley - last survivor of The Nostromo - signing off. | This is Ripley - last survivor of The Nostromo - signing off. | ||||
</section> | </section> | ||||
@@ -175,5 +175,18 @@ | |||||
</xmlvalidate> | </xmlvalidate> | ||||
</target> | </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> | </project> | ||||
@@ -206,6 +206,7 @@ rexec=org.apache.tools.ant.taskdefs.optional.net.RExecTask | |||||
scriptdef=org.apache.tools.ant.taskdefs.optional.script.ScriptDef | scriptdef=org.apache.tools.ant.taskdefs.optional.script.ScriptDef | ||||
ildasm=org.apache.tools.ant.taskdefs.optional.dotnet.Ildasm | ildasm=org.apache.tools.ant.taskdefs.optional.dotnet.Ildasm | ||||
apt=org.apache.tools.ant.taskdefs.Apt | apt=org.apache.tools.ant.taskdefs.Apt | ||||
schemavalidate=org.apache.tools.ant.taskdefs.optional.SchemaValidate | |||||
# deprecated ant tasks (kept for back compatibility) | # deprecated ant tasks (kept for back compatibility) | ||||
starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut | 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.types.XMLCatalog; | ||||
import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
import org.apache.tools.ant.util.JAXPUtils; | import org.apache.tools.ant.util.JAXPUtils; | ||||
import org.apache.tools.ant.util.XmlConstants; | |||||
import org.xml.sax.EntityResolver; | import org.xml.sax.EntityResolver; | ||||
import org.xml.sax.ErrorHandler; | import org.xml.sax.ErrorHandler; | ||||
@@ -258,6 +259,19 @@ public class XMLValidateTask extends Task { | |||||
protected EntityResolver getEntityResolver() { | protected EntityResolver getEntityResolver() { | ||||
return xmlCatalog; | 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 | * execute the task | ||||
* @throws BuildException if <code>failonerror</code> is true and an error happens | * @throws BuildException if <code>failonerror</code> is true and an error happens | ||||
@@ -304,16 +318,56 @@ public class XMLValidateTask extends Task { | |||||
/** | /** | ||||
* init the parser : | * init the parser : | ||||
* load the parser class, and set features if necessary | * 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; | Object reader = null; | ||||
if (readerClassName == null) { | if (readerClassName == null) { | ||||
try { | |||||
reader = JAXPUtils.getXMLReader(); | |||||
} catch (BuildException exc) { | |||||
reader = JAXPUtils.getParser(); | |||||
} | |||||
reader = createDefaultReaderOrParser(); | |||||
} else { | } else { | ||||
Class readerClass = null; | Class readerClass = null; | ||||
@@ -338,8 +392,9 @@ public class XMLValidateTask extends Task { | |||||
} | } | ||||
// then check it implements XMLReader | // then check it implements XMLReader | ||||
XMLReader newReader; | |||||
if (reader instanceof XMLReader) { | if (reader instanceof XMLReader) { | ||||
xmlReader = (XMLReader) reader; | |||||
newReader = (XMLReader) reader; | |||||
log( | log( | ||||
"Using SAX2 reader " + reader.getClass().getName(), | "Using SAX2 reader " + reader.getClass().getName(), | ||||
Project.MSG_VERBOSE); | Project.MSG_VERBOSE); | ||||
@@ -347,7 +402,7 @@ public class XMLValidateTask extends Task { | |||||
// see if it is a SAX1 Parser | // see if it is a SAX1 Parser | ||||
if (reader instanceof Parser) { | if (reader instanceof Parser) { | ||||
xmlReader = new ParserAdapter((Parser) reader); | |||||
newReader = new ParserAdapter((Parser) reader); | |||||
log( | log( | ||||
"Using SAX1 parser " + reader.getClass().getName(), | "Using SAX1 parser " + reader.getClass().getName(), | ||||
Project.MSG_VERBOSE); | Project.MSG_VERBOSE); | ||||
@@ -358,36 +413,41 @@ public class XMLValidateTask extends Task { | |||||
+ " implements nor SAX1 Parser nor SAX2 XMLReader."); | + " 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. | * Set a feature on the parser. | ||||
* @param feature the name of the feature to set | * @param feature the name of the feature to set | ||||
* @param value the value of the feature | * @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 { | throws BuildException { | ||||
log("Setting feature " + feature + "=" + value, Project.MSG_DEBUG); | log("Setting feature " + feature + "=" + value, Project.MSG_DEBUG); | ||||
try { | try { | ||||
@@ -417,8 +477,9 @@ public class XMLValidateTask extends Task { | |||||
* @param name a property name | * @param name a property name | ||||
* @param value a property value. | * @param value a property value. | ||||
* @throws BuildException if an error occurs. | * @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 | // Validates property | ||||
if (name == null || value == null) { | if (name == null || value == null) { | ||||
throw new BuildException("Property name and value must be specified."); | throw new BuildException("Property name and value must be specified."); | ||||
@@ -448,7 +509,7 @@ public class XMLValidateTask extends Task { | |||||
/** | /** | ||||
* parse the file | * parse the file | ||||
*/ | */ | ||||
private void doValidate(File afile) { | |||||
protected void doValidate(File afile) { | |||||
try { | try { | ||||
log("Validating " + afile.getName() + "... ", Project.MSG_VERBOSE); | log("Validating " + afile.getName() + "... ", Project.MSG_VERBOSE); | ||||
errorHandler.init(afile); | errorHandler.init(afile); | ||||
@@ -655,4 +716,6 @@ public class XMLValidateTask extends Task { | |||||
} // Property | } // 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"); | |||||
} | |||||
} |