ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bode...@apache.org
Subject cvs commit: jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/optional XmlValidateTest.java
Date Tue, 05 Nov 2002 16:33:29 GMT
bodewig     2002/11/05 08:33:29

  Modified:    .        WHATSNEW build.xml
               docs/manual install.html
               docs/manual/CoreTypes xmlcatalog.html
               src/etc/testcases/taskdefs/optional xmlvalidate.xml
               src/main/org/apache/tools/ant/taskdefs XSLTProcess.java
               src/main/org/apache/tools/ant/types DTDLocation.java
                        XMLCatalog.java
               src/testcases/org/apache/tools/ant/taskdefs/optional
                        XmlValidateTest.java
  Added:       src/main/org/apache/tools/ant/types EntityLocation.java
                        ResourceLocation.java
               src/main/org/apache/tools/ant/types/resolver
                        ApacheCatalog.java ApacheCatalogResolver.java
                        package.html
  Log:
  Make <xmlcatalog> support the OASIS "Open Catalog" standard with
  Norman Walsh resolver code from xml-commons.
  
  Submitted by:	Craeg K Strong <cstrong at arielpartners.com>
  
  Revision  Changes    Path
  1.305     +4 -0      jakarta-ant/WHATSNEW
  
  Index: WHATSNEW
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/WHATSNEW,v
  retrieving revision 1.304
  retrieving revision 1.305
  diff -u -r1.304 -r1.305
  --- WHATSNEW	5 Nov 2002 14:51:51 -0000	1.304
  +++ WHATSNEW	5 Nov 2002 16:33:27 -0000	1.305
  @@ -67,6 +67,10 @@
     define ids or paths and use Ant's location magic for filename resolutions
     in the XML file.
   
  +* <xmlcatalog> will now support external catalogs according to the
  +  OASIS "Open Catalog" standard - if resolver.jar from Apache's
  +  xml-commons is in your CLASSPATH.
  +
   Changes from Ant 1.5.1Beta1 to 1.5.1
   ====================================
   
  
  
  
  1.331     +15 -0     jakarta-ant/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/build.xml,v
  retrieving revision 1.330
  retrieving revision 1.331
  diff -u -r1.330 -r1.331
  --- build.xml	24 Oct 2002 19:15:47 -0000	1.330
  +++ build.xml	5 Nov 2002 16:33:28 -0000	1.331
  @@ -51,6 +51,7 @@
     <property name="ant.package" value="org/apache/tools/ant"/>
     <property name="optional.package" value="${ant.package}/taskdefs/optional"/>
     <property name="optional.type.package" value="${ant.package}/types/optional"/>
  +  <property name="apache.resolver.type.package" value="${ant.package}/types/resolver"/>
     <property name="util.package" value="${ant.package}/util"/>
     <property name="regexp.package" value="${util.package}/regexp"/>
   
  @@ -195,6 +196,9 @@
     <selector id="needs.xslp">
       <filename name="${optional.package}/XslpLiaison*"/>
     </selector>
  +  <selector id="needs.apache.resolver">
  +    <filename name="${apache.resolver.type.package}/**"/>
  +  </selector>
     <selector id="needs.junit">
       <filename name="${optional.package}/junit/**"/>
     </selector>
  @@ -341,6 +345,9 @@
       <available property="xslp.present"
                  classname="com.kvisco.xsl.XSLProcessor"
                  classpathref="classpath"/>
  +   <available property="apache.resolver.present"
  +              classname="org.apache.xml.resolver.tools.CatalogResolver"
  +              classpathref="classpath" />
       <available property="xalan.present"
                  classname="org.apache.xalan.xslt.XSLTProcessorFactory"
                  classpathref="classpath"/>
  @@ -570,6 +577,7 @@
               <selector refid="needs.xalan1" unless="xalan.present"/>
               <selector refid="needs.xalan2" unless="xalan2.present"/>
               <selector refid="needs.xslp" unless="xslp.present"/>
  +            <selector refid="needs.apache.resolver" unless="apache.resolver.present"/>
               <selector refid="needs.junit" unless="junit.present"/>
               <selector refid="needs.jakarta.regexp" 
                         unless="jakarta.regexp.present"/>
  @@ -739,6 +747,7 @@
               <selector refid="needs.xalan1"/>
               <selector refid="needs.xalan2"/>
               <selector refid="needs.xslp"/>
  +            <selector refid="needs.apache.resolver"/>
               <selector refid="needs.junit"/>
               <selector refid="needs.jakarta.regexp"/>
               <selector refid="needs.jakarta.oro"/>
  @@ -790,6 +799,12 @@
            basedir="${build.classes}"
            manifest="${manifest.tmp}">
         <selector refid="needs.xslp"/>
  +    </jar>
  +
  +    <jar destfile="${build.lib}/${optional.jars.prefix}-apache-resolver.jar"
  +         basedir="${build.classes}"
  +         manifest="${manifest.tmp}">
  +      <selector refid="needs.apache.resolver"/>
       </jar>
   
       <jar destfile="${build.lib}/${optional.jars.prefix}-junit.jar"
  
  
  
  1.34      +6 -0      jakarta-ant/docs/manual/install.html
  
  Index: install.html
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/docs/manual/install.html,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- install.html	22 Jul 2002 11:12:16 -0000	1.33
  +++ install.html	5 Nov 2002 16:33:28 -0000	1.34
  @@ -381,6 +381,12 @@
       <td><a href="http://www.clarkware.com/software/JDepend.html"
           target="_top">http://www.clarkware.com/software/JDepend.html</a></td>
     </tr>
  +  <tr>
  +    <td>resolver.jar</td>
  +    <td>xmlcatalog datatype <em>only if support for external catalog files is desired</em></td>
  +    <td><a href="http://xml.apache.org/dist/commons"
  +        target="_top">http://xml.apache.org/dist/commons</a></td>
  +  </tr>
   </table>
   <br>
   <hr>
  
  
  
  1.3       +60 -4     jakarta-ant/docs/manual/CoreTypes/xmlcatalog.html
  
  Index: xmlcatalog.html
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/docs/manual/CoreTypes/xmlcatalog.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- xmlcatalog.html	1 Jun 2002 12:26:35 -0000	1.2
  +++ xmlcatalog.html	5 Nov 2002 16:33:28 -0000	1.3
  @@ -19,6 +19,10 @@
   to efficiently allow a local substitution for a resource available on the 
   web.
   </p>
  +<p><b>Note:</b> This task <em>uses, but does not depend on</em> external
  +libraries not included in the Ant distribution.  See <a
  +  href="../install.html#librarydependencies">Library Dependencies</a> for more
  +information.</p>
   <p>This data type provides a catalog of resource locations based
   on the <a
   href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
  @@ -59,17 +63,34 @@
   <p>XMLCatalogs are specified as either a reference to another XMLCatalog, 
   defined
   previously in a build file, or as a list of <code>dtd</code> or
  -<code>entity</code> locations.  A separate classpath for entity resolution 
  +<code>entity</code> locations.  In addition, external catalog files
  +may be specified in <code>catalogfiles</code> filesets, but they will
  +be ignored unless the resolver library from xml-commons is available
  +in the system classpath.  A separate classpath for entity resolution 
   may be specified inline via nested <code>classpath</code> elements; 
   otherwise the system classpath is used for this as well.</p>
   <p>XMLCatalogs can also be nested inside other XMLCatalogs.  For
   example, a "superset" XMLCatalog could be made by including several
   nested XMLCatalogs that referred to other, previously defined
   XMLCatalogs.</p>
  +<p>Resource locations can be specified either in-line or in
  +external catalog file(s), or both.  In order to use an external
  +catalog file, the xml-commons resolver library ("resolver.jar")
  +must be in your path.  External catalog files may be either <a
  +href="http://oasis-open.org/committees/entity/background/9401.html">
  +plain text format</a> or <a
  +href="http://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
  +XML format</a>.  If the xml-commons resolver library is not found in the
  +classpath, external catalog files, specified in <code>catalogfiles</code>
  +filesets, will be ignored and a warning will be logged.  In this case, however,
  +processing of inline entries will proceed normally.</p>
   <p>Currently, only <code>&lt;dtd&gt;</code> and
   <code>&lt;entity&gt;</code> elements may be specified inline; these
   roughly correspond to OASIS catalog entry types <code>PUBLIC</code> and
  -<code>URI</code> respectively.</p>  
  +<code>URI</code> respectively.  By contrast, external catalog files
  +may use any of the entry types defined in the 
  +<a href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
  ++OASIS specification</a>.</p>
   <h3><a name="ResolverAlgorithm">Entity/DTD/URI Resolution Algorithm</a></h3>
   
   When an entity, DTD, or URI is looked up by the XML processor, the
  @@ -101,6 +122,18 @@
   <code>blat.dtd</code>.
   
   
  +<h4>3a. Apache xml-commons resolver lookup</h4>
  +
  +<p>What happens next depends on whether the resolver library from
  +xml-commons is available on the classpath.  If so, we defer all
  +further attempts at resolving to it.  The resolver library supports
  +extremely sophisticated functionality like URL rewriting and so on,
  +which can be accessed by making the appropriate entries in external
  +catalog files (XMLCatalog does not yet provide inline support for all
  +of the entries defined in the <a
  +href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">OASIS
  +standard</a>).</p>
  +
   <h4>3. URL-space lookup</h4>
   
   <p>Finally, we attempt to make a URL out of the <code>location</code>.
  @@ -171,6 +204,22 @@
   <p>The classpath to use for <a href="#ResolverAlgorithm">entity
   resolution</a>.  The nested <code>&lt;classpath&gt;</code> is a
   <a href="../using.html#path">path</a>-like structure.</p>
  +<h4>catalogfiles</h4>
  +<p>
  +The nested <code>catalogfiles</code> element specifies a <a
  +href="../CoreTypes/fileset.html">FileSet</a>.  All files included in
  +this fileset are assumed to be OASIS catalog files, in either
  +<a href="http://oasis-open.org/committees/entity/background/9401.html">
  +plain text format</a> or <a
  +href="http://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
  +XML format</a>.  Multiple <code>catalogfiles</code> filesets may be
  +specified.  Of course, if you use wildcards in your fileset, you will
  +want to use some sort of naming convention to ensure that you don't
  +accidentally match non-catalog files.  If the resolver library from
  +xml-commons is not available in the classpath, all
  +<code>catalogfiles</code> will be ignored and a warning will be
  +logged.
  +</p>
   <h3>Examples</h3>
   <p>Set up an XMLCatalog with a single dtd referenced locally in a user's 
   home 
  @@ -197,7 +246,8 @@
   </pre></blockquote>
   
   <p>Set up an XMLCatalog with a combination of DTDs and entities as
  -well as a nested XMLCatalog:</p>
  +well as a nested XMLCatalog and external catalog files in both
  +formats:</p>
   
   <blockquote><pre>
       &lt;xmlcatalog id=&quot;allcatalogs&quot;&gt;
  @@ -207,7 +257,13 @@
           &lt;entity 
               publicId=&quot;LargeLogo&quot;
               location=&quot;com/arielpartners/images/ariel-logo-large.gif&quot;/&gt;
  -	&lt;xmlcatalog refid="commonDTDs"/&gt;
  +    &lt;xmlcatalog refid="commonDTDs"/&gt;
  +        &lt;catalogfiles 
  +            dir=&quot;/anetwork/drive&quot;
  +            includes=&quot;**/catalog&quot;/&gt;
  +        &lt;catalogfiles 
  +            dir=&quot;/my/catalogs&quot;
  +            includes=&quot;**/catalog.xml&quot;/&gt;
       &lt;/xmlcatalog&gt;
   </pre></blockquote>
   <p>To reference the above XMLCatalog in an <code>xslt</code> task:<p>
  
  
  
  1.7       +11 -1     jakarta-ant/src/etc/testcases/taskdefs/optional/xmlvalidate.xml
  
  Index: xmlvalidate.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/etc/testcases/taskdefs/optional/xmlvalidate.xml,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- xmlvalidate.xml	23 Sep 2002 14:59:42 -0000	1.6
  +++ xmlvalidate.xml	5 Nov 2002 16:33:28 -0000	1.7
  @@ -38,8 +38,18 @@
         </xmlcatalog>
       </xmlvalidate>
     </target>
  + 
  +  <target name="xmlcatalogfiles">
  +    <xmlvalidate warn="false">
  +      <fileset dir="xml" includes="**/about.xml"/>
  +      <xmlcatalog classpath="xml">
  +        <catalogfiles dir="xml" includes="catalog"/>
  +        <dtd publicID="-//stevo//DTD doc 1.0//EN"
  +             location="doc.dtd"/>
  +      </xmlcatalog>
  +    </xmlvalidate>
  +  </target>
   
  -  
     <target name="testSchemaGood">
       <xmlvalidate warn="false" lenient="no" >
         <fileset dir="xml" includes="endpiece.xml"/>
  
  
  
  1.53      +2 -1      jakarta-ant/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
  
  Index: XSLTProcess.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -u -r1.52 -r1.53
  --- XSLTProcess.java	25 Jul 2002 15:21:05 -0000	1.52
  +++ XSLTProcess.java	5 Nov 2002 16:33:28 -0000	1.53
  @@ -67,6 +67,7 @@
   import org.apache.tools.ant.types.Reference;
   import org.apache.tools.ant.types.XMLCatalog;
   import org.apache.tools.ant.util.FileUtils;
  +import javax.xml.transform.URIResolver;
   
   /**
    * Processes a set of XML documents via XSLT. This is
  
  
  
  1.3       +14 -33    jakarta-ant/src/main/org/apache/tools/ant/types/DTDLocation.java
  
  Index: DTDLocation.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/types/DTDLocation.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DTDLocation.java	18 Mar 2002 02:44:30 -0000	1.2
  +++ DTDLocation.java	5 Nov 2002 16:33:28 -0000	1.3
  @@ -54,44 +54,25 @@
   package org.apache.tools.ant.types;
   
   /**
  - * Helper class to handle the DTD and Entity nested elements.
  + * <p>Helper class to handle the DTD nested element.  Instances of
  + * this class correspond to the <code>PUBLIC</code> catalog entry type
  + * of the <a
  + * href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
  + * OASIS "Open Catalog" standard</a>.</p>
    *
  + * <p>Possible Future Enhancement: Bring the Ant element name into
  + * conformance with the OASIS standard.</p>
  + *
  + * @see org.apache.xml.resolver.Catalog
    * @author Conor MacNeill
    * @author dIon Gillard
  + * @author <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a>
  + * @version $Id$
    */
  -public class DTDLocation {
  -    /** publicId of the dtd/entity */
  -    private String publicId = null;
  -    /** location of the dtd/entity - a file/resource/URL */
  -    private String location = null;
  -
  -    /**
  -     * @param publicId uniquely identifies the resource
  -     */
  -    public void setPublicId(String publicId) {
  -        this.publicId = publicId;
  -    }
  +public class DTDLocation extends ResourceLocation {
   
  -    /**
  -     * @param location the location of the resource associated with the
  -     *      publicId
  -     */
  -    public void setLocation(String location) {
  -        this.location = location;
  +    public DTDLocation() {
  +        super("PUBLIC");
       }
   
  -    /**
  -     * @return the publicId
  -     */
  -    public String getPublicId() {
  -        return publicId;
  -    }
  -
  -    /**
  -     * @return the location of the resource identified by the publicId
  -     */
  -    public String getLocation() {
  -        return location;
  -    }
   }
  -
  
  
  
  1.16      +502 -68   jakarta-ant/src/main/org/apache/tools/ant/types/XMLCatalog.java
  
  Index: XMLCatalog.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/types/XMLCatalog.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- XMLCatalog.java	25 Jul 2002 15:21:21 -0000	1.15
  +++ XMLCatalog.java	5 Nov 2002 16:33:28 -0000	1.16
  @@ -54,6 +54,8 @@
   
   package org.apache.tools.ant.types;
   
  +import java.lang.reflect.Method;
  +
   import java.io.File;
   import java.io.FileInputStream;
   import java.io.FileNotFoundException;
  @@ -72,6 +74,7 @@
   import javax.xml.transform.sax.SAXSource;
   import org.apache.tools.ant.AntClassLoader;
   import org.apache.tools.ant.BuildException;
  +import org.apache.tools.ant.DirectoryScanner;
   import org.apache.tools.ant.Project;
   import org.apache.tools.ant.util.FileUtils;
   import org.xml.sax.EntityResolver;
  @@ -138,13 +141,14 @@
    * @author <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a>
    * @version $Id$
    */
  -public class XMLCatalog extends DataType implements Cloneable, EntityResolver, URIResolver {
  +public class XMLCatalog extends DataType 
  +    implements Cloneable, EntityResolver, URIResolver {
       /** File utilities instance */
       private FileUtils fileUtils = FileUtils.newFileUtils();
   
       //-- Fields ----------------------------------------------------------------
   
  -    /** holds dtd/entity objects until needed */
  +    /** Holds dtd/entity objects and catalog filesets until needed. */
       private Vector elements = new Vector();
   
       /**
  @@ -152,6 +156,14 @@
        */
       private Path classpath;
   
  +    /**
  +     * The name of the bridge to the Apache xml-commons resolver
  +     * class, used to determine whether resolver.jar is present in the
  +     * classpath.
  +     */
  +    public static final String APACHE_RESOLVER
  +        = "org.apache.tools.ant.types.resolver.ApacheCatalogResolver";
  +
       //-- Methods ---------------------------------------------------------------
   
       public XMLCatalog() {
  @@ -159,9 +171,11 @@
       }
   
       /**
  -     * Returns the elements of the catalog - DTDLocation objects.
  +     * Returns the elements of the catalog - ResolverLocation and FileSet
  +     * objects.
        *
  -     * @return the elements of the catalog - DTDLocation objects
  +     * @return the elements of the catalog - ResolverLocation and FileSet
  +     * objects
        */
       private Vector getElements() {
           return elements;
  @@ -177,14 +191,18 @@
       }
   
       /**
  -     * Set the list of DTDLocation objects in the catalog.  Not
  -     * allowed if this catalog is itself a reference to another
  -     * catalog -- that is, a catalog cannot both refer to another
  -     * <em>and</em> contain elements or other attributes.
  +     * Set the list of ResourceLocation objects and FileSets in the catalog.
  +     * Not allowed if this catalog is itself a reference to another catalog --
  +     * that is, a catalog cannot both refer to another <em>and</em> contain
  +     * elements or other attributes.
        *
  -     * @param aVector the new list of DTD Locations to use in the catalog.
  +     * @param aVector the new list of ResourceLocations and FileSets
  +     * to use in the catalog.
        */
       private void setElements(Vector aVector) {
  +        if (isReference()) {
  +            throw noChildrenAllowed();
  +        }
           elements = aVector;
       }
   
  @@ -237,6 +255,22 @@
           setChecked( false );
       }
   
  +    /** Creates the nested <code>&lt;catalogfiles&gt;</code> element.  Not
  +     * allowed if this catalog is itself a reference to another catalog -- that
  +     * is, a catalog cannot both refer to another <em>and</em> contain elements
  +     * or other attributes.
  +     *
  +     * @param fs the fileset of external catalogs.
  +     * @exception BuildException
  +     * if this is a reference and no nested elements are allowed.
  +     */
  +    public void addCatalogfiles(FileSet fs) throws BuildException {
  +        if (isReference()) {
  +            throw noChildrenAllowed();
  +        }
  +        getElements().addElement(fs);
  +    }
  +
       /**
        * Creates the nested <code>&lt;dtd&gt;</code> element.  Not
        * allowed if this catalog is itself a reference to another
  @@ -248,7 +282,7 @@
        * @exception BuildException if this is a reference and no nested
        *       elements are allowed.
        */
  -    public void addDTD(DTDLocation dtd) throws BuildException {
  +    public void addDTD(ResourceLocation dtd) throws BuildException {
           if (isReference()) {
               throw noChildrenAllowed();
           }
  @@ -256,6 +290,9 @@
           getElements().addElement(dtd);
           setChecked( false );
       }
  +    public void addDTD(DTDLocation dtd) throws BuildException {
  +        addDTD((ResourceLocation)dtd);
  +    }
   
       /**
        * Creates the nested <code>&lt;entity&gt;</code> element.    Not
  @@ -263,13 +300,34 @@
        * catalog -- that is, a catalog cannot both refer to another
        * <em>and</em> contain elements or other attributes.
        *
  -     * @param dtd the information about the URI resource mapping to be
  -     *       added to the catalog
  +     * @param entity the information about the URI resource mapping to
  +     * be added to the catalog.
        * @exception BuildException if this is a reference and no nested
        *       elements are allowed.
        */
  -    public void addEntity(DTDLocation dtd) throws BuildException {
  -        addDTD(dtd);
  +    public void addEntity(EntityLocation entity) throws BuildException {
  +        if (isReference()) {
  +            throw noChildrenAllowed();
  +        }
  +        getElements().addElement(entity);
  +    }
  +
  +    /**
  +     * Creates the nested <code>&lt;entity&gt;</code> element.    Not
  +     * allowed if this catalog is itself a reference to another
  +     * catalog -- that is, a catalog cannot both refer to another
  +     * <em>and</em> contain elements or other attributes.
  +     *
  +     * @param entity the information about the URI resource mapping to
  +     * be added to the catalog.
  +     * @exception BuildException if this is a reference and no nested
  +     *       elements are allowed.
  +     */
  +    public void addEntity(DTDLocation entity) throws BuildException {
  +        if (isReference()) {
  +            throw noChildrenAllowed();
  +        }
  +        getElements().addElement(entity);
       }
   
       /**
  @@ -337,17 +395,18 @@
       public InputSource resolveEntity(String publicId, String systemId)
           throws SAXException, IOException {
   
  -       if (!isChecked()) {
  -          // make sure we don't have a circular reference here
  -          Stack stk = new Stack();
  -          stk.push(this);
  -          dieOnCircularReference(stk, getProject());
  -       }
  +        if (!isChecked()) {
  +            // make sure we don't have a circular reference here
  +            Stack stk = new Stack();
  +            stk.push(this);
  +            dieOnCircularReference(stk, getProject());
  +        }
   
           log("resolveEntity: '" + publicId + "': '" + systemId + "'",
               Project.MSG_DEBUG);
   
  -        InputSource inputSource = resolveEntityImpl(publicId );
  +        InputSource inputSource = 
  +            getCatalogResolver().resolveEntity(publicId, systemId);
   
           if (inputSource == null) {
               log("No matching catalog entry found, parser will use: '" +
  @@ -365,12 +424,12 @@
       public Source resolve(String href, String base)
           throws TransformerException {
   
  -       if (!isChecked()) {
  -          // make sure we don't have a circular reference here
  -          Stack stk = new Stack();
  -          stk.push(this);
  -          dieOnCircularReference(stk, getProject());
  -       }
  +        if (!isChecked()) {
  +            // make sure we don't have a circular reference here
  +            Stack stk = new Stack();
  +            stk.push(this);
  +            dieOnCircularReference(stk, getProject());
  +        }
   
           SAXSource source = null;
   
  @@ -389,11 +448,11 @@
               //
               source = new SAXSource();
               try
  -            {
  -                URL baseURL = new URL(base);
  -                URL url = (uri.length() == 0 ? baseURL : new URL(baseURL, uri));
  -                source.setInputSource(new InputSource(url.toString()));
  -            }
  +                {
  +                    URL baseURL = new URL(base);
  +                    URL url = (uri.length() == 0 ? baseURL : new URL(baseURL, uri));
  +                    source.setInputSource(new InputSource(url.toString()));
  +                }
               catch (MalformedURLException ex) {
                   // At this point we are probably in failure mode, but
                   // try to use the bare URI as a last gasp
  @@ -406,25 +465,67 @@
       }
   
       /**
  -     * Find a DTDLocation instance for the given publicId.
  +     * The instance of the CatalogResolver strategy to use.
  +     */
  +    private static CatalogResolver catalogResolver = null;
  +
  +    /**
  +     * Factory method for creating the appropriate CatalogResolver
  +     * strategy implementation.  
  +     * <p> Until we query the classpath, we don't know whether the Apache
  +     * resolver (Norm Walsh's library from xml-commons) is available or not.
  +     * This method determines whether the library is available and creates the
  +     * appropriate implementation of CatalogResolver based on the answer.</p>
  +     * <p>This is an application of the Gang of Four Strategy Pattern
  +     * combined with Template Method.</p>
        *
        * @param publicId the publicId of the Resource for which local information
        *        is required
  -     * @return a DTDLocation instance with information on the local location
  +     * @return a ResourceLocation instance with information on the local location
        *         of the Resource or null if no such information is available
        */
  -    private DTDLocation findMatchingEntry(String publicId) {
  -        Enumeration elements = getElements().elements();
  -        DTDLocation element = null;
  -        while (elements.hasMoreElements()) {
  -            element = (DTDLocation) elements.nextElement();
  -            if (element.getPublicId().equals(publicId)) {
  -                return element;
  +    private CatalogResolver getCatalogResolver() {
  +
  +        if (catalogResolver == null) {
  +
  +            AntClassLoader loader = null;
  +
  +            loader = new AntClassLoader(project, Path.systemClasspath);
  +
  +            try {
  +                Class clazz = loader.forceLoadSystemClass(APACHE_RESOLVER);
  +                Object obj  = clazz.newInstance();
  +                //
  +                // Success!  The xml-commons resolver library is
  +                // available, so use it.
  +                //
  +                catalogResolver = new ApacheResolver(clazz, obj);
  +            } 
  +            catch (Throwable ex) {
  +                //
  +                // The xml-commons resolver library is not 
  +                // available, so we can't use it.
  +                //
  +                catalogResolver = new InternalResolver();
  +                //
  +                // If any <catalogfiles> are specified, warn that they
  +                // will be ignored.
  +                //
  +                Enumeration enum = getElements().elements();
  +                while (enum.hasMoreElements()) {
  +                    Object o = enum.nextElement();
  +                    if (o instanceof FileSet) {
  +                        log("Warning: External catalogfiles will be ignored",
  +                            Project.MSG_WARN);
  +                        break;
  +                    }
  +                }
               }
           }
  -        return null;
  +        return catalogResolver;
       }
   
  +
       /**
        * <p>This is called from the URIResolver to set an EntityResolver
        * on the SAX parser to be used for new XML documents that are
  @@ -465,6 +566,29 @@
       }
   
       /**
  +     * Find a ResourceLocation instance for the given publicId.
  +     *
  +     * @param publicId the publicId of the Resource for which local information is 
  +     *        required.
  +     * @return a ResourceLocation instance with information on the local location 
  +     *         of the Resource or null if no such information is available.
  +     */
  +    private ResourceLocation findMatchingEntry(String publicId) {
  +        Enumeration enum = getElements().elements();
  +        ResourceLocation element = null;
  +        while (enum.hasMoreElements()) {
  +            Object o = enum.nextElement();
  +            if (o instanceof ResourceLocation) {
  +                element = (ResourceLocation)o;
  +                if (element.getPublicId().equals(publicId)) {
  +                    return element;
  +                }
  +            }
  +        }
  +        return null;
  +    }
  +
  +    /**
        * Utility method to remove trailing fragment from a URI.
        * For example,
        * <code>http://java.sun.com/index.html#chapter1</code>
  @@ -484,17 +608,17 @@
       }
   
       /**
  -     * Utility method to lookup a DTDLocation in the filesystem.
  +     * Utility method to lookup a ResourceLocation in the filesystem.
        *
        * @return An InputSource for reading the file, or <code>null</code>
        *     if the file does not exist or is not readable.
        */
  -    private InputSource filesystemLookup(DTDLocation matchingEntry) {
  +    private InputSource filesystemLookup(ResourceLocation matchingEntry) {
   
           String uri = matchingEntry.getLocation();
   
           //
  -        // The DTDLocation may specify a relative path for its
  +        // The ResourceLocation may specify a relative path for its
           // location attribute.  This is resolved using the appropriate
           // base.
           //
  @@ -522,12 +646,12 @@
       }
   
       /**
  -     * Utility method to lookup a DTDLocation in the classpath.
  +     * Utility method to lookup a ResourceLocation in the classpath.
        *
        * @return An InputSource for reading the resource, or <code>null</code>
        *    if the resource does not exist in the classpath or is not readable.
        */
  -    private InputSource classpathLookup(DTDLocation matchingEntry) {
  +    private InputSource classpathLookup(ResourceLocation matchingEntry) {
   
           InputSource source = null;
   
  @@ -557,7 +681,7 @@
       }
   
       /**
  -     * Utility method to lookup a DTDLocation in URL-space.
  +     * Utility method to lookup a ResourceLocation in URL-space.
        *
        * @return An InputSource for reading the resource, or <code>null</code>
        *    if the resource does not identify a valid URL or is not readable.
  @@ -602,31 +726,33 @@
       /**
        * Implements the guts of the resolveEntity() lookup strategy.
        */
  -    private InputSource resolveEntityImpl(String publicId) {
  +    /*
  +      private InputSource resolveEntityImpl(String publicId) {
   
  -        InputSource result = null;
  +      InputSource result = null;
   
  -        DTDLocation matchingEntry = findMatchingEntry(publicId);
  +      ResourceLocation matchingEntry = findMatchingEntry(publicId);
   
  -        if (matchingEntry != null) {
  +      if (matchingEntry != null) {
   
  -            log("Matching catalog entry found for publicId: '" +
  -                matchingEntry.getPublicId() + "' location: '" +
  -                matchingEntry.getLocation() + "'",
  -                Project.MSG_DEBUG);
  +      log("Matching catalog entry found for publicId: '" +
  +      matchingEntry.getPublicId() + "' location: '" +
  +      matchingEntry.getLocation() + "'",
  +      Project.MSG_DEBUG);
   
  -            result = filesystemLookup(matchingEntry);
  +      result = filesystemLookup(matchingEntry);
   
  -            if (result == null) {
  -                result = classpathLookup(matchingEntry);
  -            }
  +      if (result == null) {
  +      result = classpathLookup(matchingEntry);
  +      }
   
  -            if (result == null) {
  -                result = urlLookup(matchingEntry.getLocation(), null);
  -            }
  -        }
  -        return result;
  -    }
  +      if (result == null) {
  +      result = urlLookup(matchingEntry.getLocation(), null);
  +      }
  +      }
  +      return result;
  +      }
  +    */
   
       /**
        * Implements the guts of the resolve() lookup strategy.
  @@ -636,7 +762,7 @@
           SAXSource result = null;
           InputSource source = null;
   
  -        DTDLocation matchingEntry = findMatchingEntry(href);
  +        ResourceLocation matchingEntry = findMatchingEntry(href);
   
           if (matchingEntry != null) {
   
  @@ -660,5 +786,313 @@
               }
           }
           return result;
  +    }
  +
  +    /**
  +     * Interface implemented by both the InternalResolver strategy and
  +     * the ApacheResolver strategy.
  +     */
  +    private interface CatalogResolver extends URIResolver, EntityResolver {
  +
  +        InputSource resolveEntity(String publicId, String systemId);
  +
  +        Source resolve(String href, String base) throws TransformerException;
  +    }
  +
  +    /**
  +     * The InternalResolver strategy is used if the Apache resolver
  +     * library (Norm Walsh's library from xml-commons) is not
  +     * available.  In this case, external catalog files will be
  +     * ignored.
  +     * 
  +     */
  +    private class InternalResolver implements CatalogResolver {
  +
  +        public InternalResolver() {
  +            log("Apache resolver library not found, internal resolver will be used",
  +                Project.MSG_INFO);
  +        }
  +
  +        public InputSource resolveEntity(String publicId,
  +                                         String systemId) {
  +
  +            InputSource result = null;
  +
  +            ResourceLocation matchingEntry = findMatchingEntry(publicId);
  +
  +            if (matchingEntry != null) {
  +
  +                log("Matching catalog entry found for publicId: '" + 
  +                    matchingEntry.getPublicId() + "' location: '" + 
  +                    matchingEntry.getLocation() + "'",
  +                    Project.MSG_DEBUG);
  +
  +                result = filesystemLookup(matchingEntry);
  +
  +                if (result == null) {
  +                    result = classpathLookup(matchingEntry);
  +                }
  +
  +                if (result == null) {
  +                    result = urlLookup(matchingEntry.getLocation(), null);
  +                }
  +            }
  +            return result;
  +        }
  +
  +
  +
  +        public Source resolve(String href, String base)
  +            throws TransformerException {
  +
  +            SAXSource result = null;
  +            InputSource source = null;
  +
  +            ResourceLocation matchingEntry = findMatchingEntry(href);
  +
  +            if (matchingEntry != null) {
  +
  +                log("Matching catalog entry found for uri: '" + 
  +                    matchingEntry.getPublicId() + "' location: '" + 
  +                    matchingEntry.getLocation() + "'",
  +                    Project.MSG_DEBUG);
  +
  +                source = filesystemLookup(matchingEntry);
  +
  +                if (source == null) {
  +                    source = classpathLookup(matchingEntry);
  +                }
  +
  +                if (source == null) {
  +                    source = urlLookup(matchingEntry.getLocation(), base);
  +                }
  +
  +                if (source != null) {
  +                    result = new SAXSource(source);
  +                }
  +            }
  +            return result;
  +        }
  +    }
  +
  +    /**
  +     * The ApacheResolver strategy is used if the Apache resolver
  +     * library (Norm Walsh's library from xml-commons) is available in
  +     * the classpath.  The ApacheResolver is a essentially a superset
  +     * of the InternalResolver.
  +     * 
  +     */
  +    private class ApacheResolver implements CatalogResolver {
  +
  +        private Method setXMLCatalog = null;
  +        private Method parseCatalog = null;
  +        private Method resolveEntity = null;
  +        private Method resolve = null;
  +
  +        /** The instance of the ApacheCatalogResolver bridge class */
  +        private Object resolverImpl = null;
  +
  +        private boolean externalCatalogsProcessed = false;
  +
  +        public ApacheResolver(Class resolverImplClass, 
  +                              Object resolverImpl) {
  +
  +            this.resolverImpl = resolverImpl;
  +
  +            //
  +            // Get Method instances for each of the methods we need to
  +            // call on the resolverImpl using reflection.  We can't
  +            // call them directly, because they require on the
  +            // xml-commons resolver library which may not be available
  +            // in the classpath.
  +            //
  +            try {
  +                setXMLCatalog =
  +                    resolverImplClass.getMethod("setXMLCatalog",
  +                                                new Class[] 
  +                        { XMLCatalog.class });
  +
  +                parseCatalog =
  +                    resolverImplClass.getMethod("parseCatalog",
  +                                                new Class[] 
  +                        { String.class });
  +
  +                resolveEntity =
  +                    resolverImplClass.getMethod("resolveEntity",
  +                                                new Class[] 
  +                        { String.class, String.class });
  +
  +                resolve =
  +                    resolverImplClass.getMethod("resolve",
  +                                                new Class[] 
  +                        { String.class, String.class });
  +            }
  +            catch (NoSuchMethodException ex) {
  +                throw new BuildException(ex);
  +            }
  +
  +            log("Apache resolver library found, xml-commons resolver will be used",
  +                Project.MSG_INFO);
  +        }
  +
  +        public InputSource resolveEntity(String publicId,
  +                                         String systemId) {
  +            InputSource result = null;
  +
  +            processExternalCatalogs();
  +
  +            ResourceLocation matchingEntry = findMatchingEntry(publicId);
  +
  +            if (matchingEntry != null) {
  +
  +                log("Matching catalog entry found for publicId: '" + 
  +                    matchingEntry.getPublicId() + "' location: '" + 
  +                    matchingEntry.getLocation() + "'",
  +                    Project.MSG_DEBUG);
  +
  +                result = filesystemLookup(matchingEntry);
  +
  +                if (result == null) {
  +                    result = classpathLookup(matchingEntry);
  +                }
  +
  +                if (result == null) {
  +                    try {
  +                        result = 
  +                            (InputSource)resolveEntity.invoke(resolverImpl,
  +                                                              new Object[]
  +                                { publicId, systemId });
  +                    }
  +                    catch (Exception ex) {
  +                        throw new BuildException(ex);
  +                    }
  +                }
  +            }
  +            else {
  +                //
  +                // We didn't match a ResourceLocation, but since we
  +                // only support PUBLIC and URI entry types, it is
  +                // still possible that there is another entry in an
  +                // external catalog that will match.  We call Apache
  +                // resolver's resolveEntity method to cover this
  +                // possibility.
  +                //
  +                try {
  +                    result = 
  +                        (InputSource)resolveEntity.invoke(resolverImpl,
  +                                                          new Object[]
  +                            { publicId, systemId });
  +                }
  +                catch (Exception ex) {
  +                    throw new BuildException(ex);
  +                }
  +            }
  +
  +            return result;
  +        }
  +
  +        public Source resolve(String href, String base)
  +            throws TransformerException {
  +
  +            SAXSource result = null;
  +            InputSource source = null;
  +
  +            processExternalCatalogs();
  +
  +            ResourceLocation matchingEntry = findMatchingEntry(href);
  +
  +            if (matchingEntry != null) {
  +
  +                log("Matching catalog entry found for uri: '" + 
  +                    matchingEntry.getPublicId() + "' location: '" + 
  +                    matchingEntry.getLocation() + "'",
  +                    Project.MSG_DEBUG);
  +
  +                source = filesystemLookup(matchingEntry);
  +
  +                if (source == null) {
  +                    source = classpathLookup(matchingEntry);
  +                }
  +
  +                if (source != null) {
  +                    result = new SAXSource(source);
  +                } else {
  +                    try {
  +                        result = 
  +                            (SAXSource)resolve.invoke(resolverImpl,
  +                                                      new Object[]
  +                                { href, base });
  +                    }
  +                    catch (Exception ex) {
  +                        throw new BuildException(ex);
  +                    }
  +                }
  +            }
  +            else {
  +                //
  +                // We didn't match a ResourceLocation, but since we
  +                // only support PUBLIC and URI entry types, it is
  +                // still possible that there is another entry in an
  +                // external catalog that will match.  We call Apache
  +                // resolver's resolveEntity method to cover this
  +                // possibility.
  +                //
  +                try {
  +                    result = 
  +                        (SAXSource)resolve.invoke(resolverImpl,
  +                                                  new Object[]
  +                            { href, base });
  +                }
  +                catch (Exception ex) {
  +                    throw new BuildException(ex);
  +                }
  +            }
  +            return result;
  +        }
  +
  +        /**
  +         * Process each external catalog file specified in a
  +         * <code>&lt;catalogfiles&gt;</code> FileSet.  It will be
  +         * parsed by the resolver library, and the individual elements
  +         * will be added back to us (that is, the controlling
  +         * XMLCatalog instance) via a callback mechanism.
  +         */
  +        private void processExternalCatalogs() {
  +
  +            if (externalCatalogsProcessed == false) {
  +
  +                try {
  +                    setXMLCatalog.invoke(resolverImpl, 
  +                                         new Object[] 
  +                    { XMLCatalog.this });
  +                }
  +                catch (Exception ex) {
  +                    throw new BuildException(ex);
  +                }
  +
  +                Enumeration enum = getElements().elements();
  +                while (enum.hasMoreElements()) {
  +                    Object o = enum.nextElement();
  +                    if (o instanceof FileSet) {
  +                        FileSet fs = (FileSet)o;
  +                        DirectoryScanner ds = 
  +                            fs.getDirectoryScanner(getProject());
  +                        String[] files = ds.getIncludedFiles();
  +                        for (int i = 0; i < files.length; i++) {
  +                            File catFile = new File(ds.getBasedir(), files[i]); 
  +                            try {
  +                                parseCatalog.invoke(resolverImpl, 
  +                                                    new Object[] 
  +                                { catFile.getPath() });
  +                            }
  +                            catch (Exception ex) {
  +                                throw new BuildException(ex);
  +                            }
  +                        }
  +                    }
  +                }
  +            }
  +            externalCatalogsProcessed = true;
  +        }
       }
   }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/EntityLocation.java
  
  Index: EntityLocation.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.tools.ant.types;
  
  /**
   * Helper class to handle the Entity nested element.  Instances of
   * this class correspond to the <code>URI</code> catalog entry type of
   * the <a
   * href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
   * OASIS "Open Catalog" standard</a>.</p>
   *
   * <p>Possible Future Enhancement: Bring the Ant element name into
   * conformance with the OASIS standard.</p>
   *
   * @see org.apache.xml.resolver.Catalog
   * @author Conor MacNeill
   * @author dIon Gillard
   * @author <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a>
   */
  public class EntityLocation extends ResourceLocation {
  
      public EntityLocation() {
          super("URI");
      }
  
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/ResourceLocation.java
  
  Index: ResourceLocation.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.tools.ant.types;
  
  import java.net.URL;
  
  /**
   * <p>Helper class to handle the <code>&lt;dtd&gt;</code> and
   * <code>&lt;entity&gt;</code> nested elements.  These correspond to
   * the <code>PUBLIC</code> and <code>URI</code> catalog entry types,
   * respectively, as defined in the <a
   * href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
   * OASIS "Open Catalog" standard</a>.</p>
   *
   * <p>Possible Future Enhancements:
   * <ul>
   * <li>Bring the Ant element names into conformance with the OASIS standard</li>
   * <li>Add support for additional OASIS catalog entry types</li>
   * </ul>
   * </p>
   *
   * @see org.apache.xml.resolver.Catalog
   * @author Conor MacNeill
   * @author dIon Gillard
   * @author <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a>
   * @version $Id: ResourceLocation.java,v 1.1 2002/11/05 16:33:28 bodewig Exp $
   */
  public class ResourceLocation {
  
      //-- Fields ----------------------------------------------------------------
  
      /** 
       * name of the catalog entry type, as per OASIS spec.
       */
      protected String name = null;
  
      /** publicId of the dtd/entity. */
      private String publicId = null;
  
      /** location of the dtd/entity - a file/resource/URL. */
      private String location = null;
  
      /** 
       * base URL of the dtd/entity, or null. If null, the Ant project
       * basedir is assumed.  If the location specifies a relative
       * URL/pathname, it is resolved using the base.  The default base
       * for an external catalog file is the directory in which it is
       * located.
       */
      private String base = null;
  
      //-- Methods ---------------------------------------------------------------
  
      protected ResourceLocation(String name) {
          this.name = name;
      }
     
      /**
       * @param publicId uniquely identifies the resource.
       */
      public void setPublicId(String publicId) {
          this.publicId = publicId;
      }
  
      /**
       * @param location the location of the resource associated with the
       *      publicId.
       */
      public void setLocation(String location) {
          this.location = location;
      }
  
      /**
       * @param base the base URL of the resource associated with the
       * publicId.  If the location specifies a relative URL/pathname,
       * it is resolved using the base.  The default base for an
       * external catalog file is the directory in which it is located.
       */
      public void setBase(String base) {
          this.base = base;
      }
  
      /**
       * @return the publicId of the resource.
       */
      public String getPublicId() {
          return publicId;
      }
  
      /**
       * @return the location of the resource identified by the publicId.
       */
      public String getLocation() {
          return location;
      }
  
      /**
       * @return the base of the resource identified by the publicId.
       */
      public String getBase() {
          return base;
      }
  
      /**
       * @return the name of the catalog entry type.  Currently this is
       * one of <code>PUBLIC</code> or <code>URI</code>.
       * 
       * @see org.apache.xml.resolver.Catalog
       */
      public String getName() {
          return name;
      }
  
  } //-- ResourceLocation
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/resolver/ApacheCatalog.java
  
  Index: ApacheCatalog.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.resolver;
  
  import org.apache.xml.resolver.Catalog;
  import org.apache.xml.resolver.CatalogEntry;
  
  import org.apache.xml.resolver.helpers.Debug;
  import org.apache.xml.resolver.helpers.PublicId;
  
  /**
   * This class extends the Catalog class provided by Norman Walsh's
   * resolver library in xml-commons in order to add classpath entity
   * and URI resolution.  Since XMLCatalog already does classpath
   * resolution, we simply add all CatalogEntry instances back to the
   * controlling XMLCatalog instance.  This is done via a callback
   * mechanism.  ApacheCatalog is <em>only</em> used for external
   * catalog files.  Inline entries (currently <code>&lt;dtd&gt;</code>
   * and <code>&lt;entity&gt;</code>) are not added to ApacheCatalog.
   * See XMLCatalog.java for the details of the entity and URI
   * resolution algorithms.
   *
   * @see org.apache.tools.ant.types.XMLCatalog.CatalogResolver
   * @author <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a>
   * @version $Id: ApacheCatalog.java,v 1.1 2002/11/05 16:33:29 bodewig Exp $
   */
  public class ApacheCatalog extends Catalog {
  
      /** The resolver object to callback. */
      private ApacheCatalogResolver resolver = null;
  
      /**
       * <p>Create a new ApacheCatalog instance.</p>
       *
       * <p>This method overrides the superclass method of the same name
       *  in order to set the resolver object for callbacks.  The reason
       *  we have to do this is that internally Catalog creates a new
       *  instance of itself for each external catalog file processed.
       *  That is, if two external catalog files are processed, there
       *  will be a total of two ApacheCatalog instances, and so on.</p>
       */
      protected Catalog newCatalog() {
          ApacheCatalog cat = (ApacheCatalog)super.newCatalog();
          cat.setResolver(resolver);
          return cat;
      }
      
      /** Set the resolver object to callback. */
      public void setResolver(ApacheCatalogResolver resolver) {
          this.resolver = resolver;
      }
      
      /**
       * <p>This method overrides the superclass method of the same name
       * in order to add catalog entries back to the controlling
       * XMLCatalog instance.  In this way, we can add classpath lookup
       * for these entries.</p>
       *
       * <p>When we add an external catalog file, the entries inside it
       * get parsed by this method.  Therefore, we override it to add
       * each of them back to the controlling XMLCatalog instance.  This
       * is done by performing a callback to the ApacheCatalogResolver,
       * which in turn calls the XMLCatalog.</p>
       *
       * <p>XMLCatalog currently only understands <code>PUBLIC</code>
       * and <code>URI</code> entry types, so we ignore the other types.</p>
       *
       * @param entry The CatalogEntry to process.
       */
      public void addEntry(CatalogEntry entry) {
  
          int type = entry.getEntryType();
  
          if (type == PUBLIC) {
  
              String publicid = PublicId.normalize(entry.getEntryArg(0));
              String systemid = normalizeURI(entry.getEntryArg(1));
  
              if (resolver == null) {
                  Debug.message(1, "Internal Error: null ApacheCatalogResolver");
              }
              else {
                  resolver.addPublicEntry(publicid, systemid, base.toExternalForm());
              }
  
          } else if (type == URI) {
              
              String uri = normalizeURI(entry.getEntryArg(0));
              String altURI = normalizeURI(entry.getEntryArg(1));
  
              if (resolver == null) {
                  Debug.message(1, "Internal Error: null ApacheCatalogResolver");
              }
              else {
                  resolver.addURIEntry(uri, altURI, base.toExternalForm());
              }
  
          }
          
          super.addEntry(entry);
      }
  
  } //- ApacheCatalog
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/resolver/ApacheCatalogResolver.java
  
  Index: ApacheCatalogResolver.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.resolver;
  
  import java.io.IOException;
  
  import java.net.MalformedURLException;
  
  import org.apache.tools.ant.BuildException;
  
  import org.apache.tools.ant.types.XMLCatalog;
  import org.apache.tools.ant.types.DTDLocation;
  import org.apache.tools.ant.types.EntityLocation;
  
  import org.apache.xml.resolver.Catalog;
  import org.apache.xml.resolver.CatalogManager;
  
  import org.apache.xml.resolver.tools.CatalogResolver;
  
  /**
   * <p>This class extends the CatalogResolver class provided by Norman
   * Walsh's resolver library in xml-commons.  It provides the bridge
   * between the Ant XMLCatalog datatype and the xml-commons Catalog
   * class.  XMLCatalog calls methods in this class using Reflection in
   * order to avoid requiring the xml-commons resolver library in the
   * path.</p>
   * 
   * <p>The {@link org.apache.tools.ant.types.resolver.ApacheCatalog
   * ApacheCatalog} class is used to parse external catalog files, which
   * can be in either <a
   * href="http://oasis-open.org/committees/entity/background/9401.html">
   * plain text format</a> or <a
   * href="http://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
   * XML format</a>.</p>
   * 
   * <p>For each entry found in an external catalog file, if any, an
   * instance of {@link org.apache.tools.ant.types.ResourceLocation
   * ResourceLocation} is created and added to the controlling
   * XMLCatalog datatype.  In this way, these entries will be included
   * in XMLCatalog's lookup algorithm.  See XMLCatalog.java for more
   * details.</p>
   *
   * @see org.apache.tools.ant.types.XMLCatalog.CatalogResolver
   * @see org.apache.xml.resolver.CatalogManager
   * @author <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a>
   * @version $Id: ApacheCatalogResolver.java,v 1.1 2002/11/05 16:33:29 bodewig Exp $
   */
  
  public class ApacheCatalogResolver extends CatalogResolver {
  
      /** The XMLCatalog object to callback. */
      private XMLCatalog xmlCatalog = null;
      
      static
      {
          //
          // If you don't do this, you get all sorts of annoying
          // warnings about a missing properties file.  However, it
          // seems to work just fine with default values.  Ultimately,
          // we should probably include a "CatalogManager.properties"
          // file in the ant jarfile with some default property
          // settings.  See CatalogManager.java for more details.
          //
          CatalogManager.ignoreMissingProperties(true);
  
          //
          // Make sure CatalogResolver instantiates ApacheCatalog,
          // rather than a plain Catalog
          //
          System.setProperty("xml.catalog.className",
                             ApacheCatalog.class.getName());
  
          // debug
          // System.setProperty("xml.catalog.verbosity", "4");
      }
  
      /** Set the XMLCatalog object to callback. */
      public void setXMLCatalog(XMLCatalog xmlCatalog) {
          this.xmlCatalog = xmlCatalog;
      }
  
      /** 
       * XMLCatalog calls this to add an external catalog file for each
       * file within a <code>&lt;catalogfiles&gt;</code> fileset.
       */
      public void parseCatalog(String file) {
  
          ApacheCatalog catalog = (ApacheCatalog)getCatalog();
  
          // Pass in reference to ourselves so we can be called back.
          catalog.setResolver(this);
  
          try {
              catalog.parseCatalog(file);
          }
          catch(MalformedURLException ex) {
              throw new BuildException(ex);
          }
          catch(IOException ex) {
              throw new BuildException(ex);
          }
      }
  
      /**
       * <p>Add a PUBLIC catalog entry to the controlling XMLCatalog instance.
       * ApacheCatalog calls this for each PUBLIC entry found in an external
       * catalog file.</p>
       *
       * @param publicid The public ID of the resource
       * @param systemid The system ID (aka location) of the resource
       * @param base The base URL of the resource.  If the systemid
       * specifies a relative URL/pathname, it is resolved using the
       * base.  The default base for an external catalog file is the
       * directory in which the catalog is located.
       * 
       */
      public void addPublicEntry(String publicid, 
                                 String systemid,
                                 String base) {
  
          DTDLocation dtd = new DTDLocation();
          dtd.setBase(base);
          dtd.setPublicId(publicid);
          dtd.setLocation(systemid);
          
          xmlCatalog.addDTD(dtd);
      }
  
      /**
       * <p>Add a URI catalog entry to the controlling XMLCatalog instance.
       * ApacheCatalog calls this for each URI entry found in an external
       * catalog file.</p>
       *
       * @param URI The URI of the resource
       * @param altURI The URI to which the resource should be mapped
       * (aka the location)
       * @param base The base URL of the resource.  If the altURI
       * specifies a relative URL/pathname, it is resolved using the
       * base.  The default base for an external catalog file is the
       * directory in which the catalog is located.
       * 
       */
      public void addURIEntry(String uri, 
                              String altURI,
                              String base) {
  
          EntityLocation entity = new EntityLocation();
          entity.setBase(base);
          entity.setPublicId(uri);
          entity.setLocation(altURI);
          
          xmlCatalog.addEntity(entity);
      }
  
  } //-- ApacheCatalogResolver
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/resolver/package.html
  
  Index: package.html
  ===================================================================
  <body>
  Ant integration with xml-commons resolver.
  
  <p>These classes enhance the <code>&lt;xmlcatalog&gt;</code> datatype
  to support external catalog files using the xml-commons resolver, in
  accordance with the
  <a href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
  OASIS "Open Catalog" standard</a>.  They will be used if and only if
  the xml-commons resolver library is available on the classpath.</p>
  
  @see <A HREF="http://xml.apache.org/commons">Apache xml-commons Project</A>
  
  @see org.apache.tools.ant.types.XMLCatalog
  @see org.apache.tools.ant.types.resolver.ApacheCatalogResolver
  @see org.apache.tools.ant.types.resolver.ApacheCatalog
  
  @author <A HREF="mailto:cstrong@arielpartners.com">Craeg Strong</A>
  
  
  <hr>
  <p align="center">Copyright &copy; 2002 Apache Software Foundation. All rights
  Reserved.</p>
  </body>
  
  
  
  1.6       +11 -0     jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java
  
  Index: XmlValidateTest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- XmlValidateTest.java	30 Sep 2002 09:40:39 -0000	1.5
  +++ XmlValidateTest.java	5 Nov 2002 16:33:29 -0000	1.6
  @@ -122,6 +122,17 @@
       }
   
       /**
  +     * catalogfiles fileset should be ignored
  +     * if resolver.jar is not present, but will 
  +     * be used if it is.  either way, test should
  +     * work b/c we have a nested dtd with the same
  +     * entity
  +     */
  +    public void testXmlCatalogFiles() {
  +      executeTarget("xmlcatalogfiles");
  +    }
  +
  +    /**
        * Test nested xmlcatalog definitions
        */
       public void testXmlCatalogNested() {
  
  
  

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message