stevel      2005/02/22 07:58:36

  Modified:    src/etc/testcases/taskdefs/optional xmlvalidate.xml
               src/etc/testcases/taskdefs/optional/xml endpiece.xml
               src/main/org/apache/tools/ant/taskdefs/optional
                        XMLValidateTask.java
               src/main/org/apache/tools/ant/taskdefs defaults.properties
               docs/manual optionaltasklist.html
  Added:       docs/manual/OptionalTasks schemavalidate.html
               src/etc/testcases/taskdefs/optional schemavalidate.xml
               src/etc/testcases/taskdefs/optional/xml doc-in-ns.xsd
                        endpiece-ns-no-location.xml
               src/main/org/apache/tools/ant/taskdefs/optional
                        SchemaValidate.java
               src/main/org/apache/tools/ant/util XmlConstants.java
               src/testcases/org/apache/tools/ant/taskdefs/optional
                        SchemaValidateTest.java
  Log:
  <schemavalidate>. Because I can never get the settings right.
  
  Revision  Changes    Path
  1.1                  ant/docs/manual/OptionalTasks/schemavalidate.html
  
  Index: schemavalidate.html
  ===================================================================
  <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>&lt;xmlcatalog&gt;</tt></a> 
elements</li>
    <li> <tt>&lt;schema&gt;</tt> elements, that bind a namespace URI to a URL 
or a
    local filename.
    <li><tt>&lt;dtd&gt;</tt> elements which are used to resolve DTDs and 
entities.</li>
    <li><tt>&lt;attribute&gt;</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>&lt;property&gt;</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>&lt;classpath&gt;</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>&lt;dtd&gt;</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>&lt;xmlcatalog&gt;</tt></a>
  element is used to perform entity resolution.</p>
  <h4>attribute</h4>
  <p>The <tt>&lt;attribute&gt;</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>&lt;property&gt;</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>
  &lt;xmlvalidate file="toto.xml"/&gt;
  </pre>
  Validate toto.xml
  <pre>
  &lt;xmlvalidate failonerror="no" lenient="yes" warn="yes"
               classname="org.apache.xerces.parsers.SAXParser"&gt;
               classpath="lib/xerces.jar"&gt;
    &lt;fileset dir="src" includes="style/*.xsl"/&gt;
  &lt;/xmlvalidate&gt;
  </pre>
  Validate all .xsl files in src/style, but only warn if there is an error, 
rather than
  halt the build.
  <pre>
  
  &lt;xmlvalidate file="struts-config.xml" warn="false"&gt;
    &lt;dtd publicId="-//Apache Software Foundation//DTD Struts Configuration 
1.0//EN"
         location="struts-config_1_0.dtd"/&gt;
  &lt;/xmlvalidate&gt;
  </pre>
  
  Validate a struts configuration, using a local copy of the DTD. 
  <pre> 
  &lt;xmlvalidate failonerror="no"&gt;
    &lt;fileset dir="${project.dir}" includes="**/*.xml"/&gt;
    &lt;xmlcatalog refid="mycatalog"/&gt;
  &lt;/xmlvalidate&gt;
  </pre>
  
  Scan all XML files in the project, using a predefined catalog to map URIs to 
local files.
  <pre>
  &lt;xmlvalidate failonerror="no"&gt;
    &lt;fileset dir="${project.dir}" includes="**/*.xml"/&gt;
    &lt;xmlcatalog&gt;
         &lt;dtd
           publicId=&quot;-//ArielPartners//DTD XML Article V1.0//EN&quot;
           
location=&quot;com/arielpartners/knowledgebase/dtd/article.dtd&quot;/&gt;
    &lt;/xmlcatalog&gt;
  &lt;/xmlvalidate&gt;
  </pre>
  Scan all XML files in the project, using the catalog defined inline.
  
  <pre>
  &lt;xmlvalidate failonerror="yes" lenient="no" warn="yes"&gt;
    &lt;fileset dir="xml" includes="**/*.xml"/&gt;
    &lt;attribute name="http://xml.org/sax/features/validation"; 
value="true"/&gt;
    &lt;attribute name="http://apache.org/xml/features/validation/schema";  
value="true"/&gt;
    &lt;attribute name="http://xml.org/sax/features/namespaces"; 
value="true"/&gt;
  &lt;/xmlvalidate&gt;
  </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 -->
  &lt;pathconvert dirsep="/" property="xsd.file"&gt;
  &lt;path&gt;
     &lt;pathelement location="xml/doc.xsd"/&gt;
  &lt;/path&gt;
  &lt;/pathconvert&gt;
  
  &lt;xmlvalidate file="xml/endpiece-noSchema.xml" lenient="false"
    failonerror="true" warn="true"&gt;
    &lt;attribute name="http://apache.org/xml/features/validation/schema";
    value="true"/&gt;
    &lt;attribute name="http://xml.org/sax/features/namespaces"; 
value="true"/&gt;
    &lt;property
    
name="http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation";
    value="${xsd.file}"/&gt;
  &lt;/xmlvalidate&gt;
  </pre>
  <br>
  Validate the file xml/endpiece-noSchema.xml against the schema xml/doc.xsd.
  <br>
  <hr>
  <p align="center">Copyright &copy; 2001-2002,2004 The Apache Software 
Foundation. All rights
  Reserved.</p>
  
  </body>
  </html>
  
  
  
  
  1.14      +13 -0     ant/src/etc/testcases/taskdefs/optional/xmlvalidate.xml
  
  Index: xmlvalidate.xml
  ===================================================================
  RCS file: /home/cvs/ant/src/etc/testcases/taskdefs/optional/xmlvalidate.xml,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- xmlvalidate.xml   2 Jun 2004 20:32:11 -0000       1.13
  +++ xmlvalidate.xml   22 Feb 2005 15:58:35 -0000      1.14
  @@ -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>
   
  
  
  
  1.1                  
ant/src/etc/testcases/taskdefs/optional/schemavalidate.xml
  
  Index: schemavalidate.xml
  ===================================================================
  <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>
  
  
  1.3       +2 -4      ant/src/etc/testcases/taskdefs/optional/xml/endpiece.xml
  
  Index: endpiece.xml
  ===================================================================
  RCS file: /home/cvs/ant/src/etc/testcases/taskdefs/optional/xml/endpiece.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- endpiece.xml      8 Nov 2002 09:06:20 -0000       1.2
  +++ endpiece.xml      22 Feb 2005 15:58:36 -0000      1.3
  @@ -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>
  
  
  
  1.1                  ant/src/etc/testcases/taskdefs/optional/xml/doc-in-ns.xsd
  
  Index: doc-in-ns.xsd
  ===================================================================
  <?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>
  
  
  
  1.1                  
ant/src/etc/testcases/taskdefs/optional/xml/endpiece-ns-no-location.xml
  
  Index: endpiece-ns-no-location.xml
  ===================================================================
  <?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.47      +94 -31    
ant/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
  
  Index: XMLValidateTask.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- XMLValidateTask.java      6 Jan 2005 12:05:08 -0000       1.46
  +++ XMLValidateTask.java      22 Feb 2005 15:58:36 -0000      1.47
  @@ -33,6 +33,7 @@
   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 @@
       protected EntityResolver getEntityResolver() {
           return xmlCatalog;
       }
  +
  +    /**
  +     * get the XML reader. Non-null only after [EMAIL PROTECTED] 
#initValidator()}.
  +     * If the reader is an instance of  [EMAIL PROTECTED] ParserAdapter} then
  +     * the parser is a SAX1 parser, and you cannot call
  +     * [EMAIL PROTECTED] #setFeature(String, boolean)} or [EMAIL PROTECTED] 
#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 @@
       /**
        * 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 [EMAIL PROTECTED] 
#readerClassName},
  +     * falling back to a default reader if not.
  +     * If the returned reader is an instance of [EMAIL PROTECTED] 
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 @@
           }
   
           // 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 @@
   
               // 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 @@
                           + " 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 @@
        * @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 @@
       /**
        * 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 @@
   
       } // Property
   
  +
  +
   }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/optional/SchemaValidate.java
  
  Index: SchemaValidate.java
  ===================================================================
  /*
   * 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, [EMAIL PROTECTED] 
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 [EMAIL PROTECTED] 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
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/util/XmlConstants.java
  
  Index: XmlConstants.java
  ===================================================================
  /*
   * 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";;
  }
  
  
  
  1.1                  
ant/src/testcases/org/apache/tools/ant/taskdefs/optional/SchemaValidateTest.java
  
  Index: SchemaValidateTest.java
  ===================================================================
  /*
   * 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");
      }
  
  }
  
  
  
  1.165     +1 -0      
ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties,v
  retrieving revision 1.164
  retrieving revision 1.165
  diff -u -r1.164 -r1.165
  --- defaults.properties       7 Jan 2005 21:56:59 -0000       1.164
  +++ defaults.properties       22 Feb 2005 15:58:36 -0000      1.165
  @@ -206,6 +206,7 @@
   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
  
  
  
  1.41      +3 -2      ant/docs/manual/optionaltasklist.html
  
  Index: optionaltasklist.html
  ===================================================================
  RCS file: /home/cvs/ant/docs/manual/optionaltasklist.html,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -u -r1.40 -r1.41
  --- optionaltasklist.html     2 Oct 2003 00:04:55 -0000       1.40
  +++ optionaltasklist.html     22 Feb 2005 15:58:36 -0000      1.41
  @@ -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>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to