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"); | |||
} | |||
} |