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><dtd></code> and
<code><entity></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><classpath></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>
<xmlcatalog id="allcatalogs">
@@ -207,7 +257,13 @@
<entity
publicId="LargeLogo"
location="com/arielpartners/images/ariel-logo-large.gif"/>
- <xmlcatalog refid="commonDTDs"/>
+ <xmlcatalog refid="commonDTDs"/>
+ <catalogfiles
+ dir="/anetwork/drive"
+ includes="**/catalog"/>
+ <catalogfiles
+ dir="/my/catalogs"
+ includes="**/catalog.xml"/>
</xmlcatalog>
</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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">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><catalogfiles></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><dtd></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><entity></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><entity></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><catalogfiles></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 [EMAIL PROTECTED]
*
* 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:[EMAIL PROTECTED]">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 [EMAIL PROTECTED]
*
* 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><dtd></code> and
* <code><entity></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:[EMAIL PROTECTED]">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 [EMAIL PROTECTED]
*
* 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><dtd></code>
* and <code><entity></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:[EMAIL PROTECTED]">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 [EMAIL PROTECTED]
*
* 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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:[EMAIL PROTECTED]">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><catalogfiles></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><xmlcatalog></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:[EMAIL PROTECTED]">Craeg Strong</A>
<hr>
<p align="center">Copyright © 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:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>