You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by co...@apache.org on 2002/03/05 14:49:47 UTC
cvs commit: jakarta-ant/src/main/org/apache/tools/ant/types DTDLocation.java XCatalog.java defaults.properties
conor 02/03/05 05:49:47
Modified: src/main/org/apache/tools/ant/taskdefs XSLTProcess.java
src/main/org/apache/tools/ant/taskdefs/optional
TraXLiaison.java
src/main/org/apache/tools/ant/types defaults.properties
Added: src/main/org/apache/tools/ant/types DTDLocation.java
XCatalog.java
Log:
New datatype - xcatalog - used to store information about locally available
XML DTDs. This allows such info to be shared among a number of different
tasks such as XMLValidate, ejbjar, style, etc.
Also checkstyle cleanup of the affected files.
Submitted by: dIon Gillard <di...@multitask.com.au>
Revision Changes Path
1.38 +254 -100 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.37
retrieving revision 1.38
diff -u -w -u -r1.37 -r1.38
--- XSLTProcess.java 3 Mar 2002 01:46:20 -0000 1.37
+++ XSLTProcess.java 5 Mar 2002 13:49:46 -0000 1.38
@@ -54,11 +54,9 @@
package org.apache.tools.ant.taskdefs;
-
+import java.lang.reflect.Method;
import java.io.File;
import java.util.Enumeration;
-
-
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
@@ -67,7 +65,8 @@
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.FileUtils;
-
+import org.apache.tools.ant.types.XCatalog;
+import org.xml.sax.EntityResolver;
/**
* A Task to process via XSLT a set of XML documents. This is
@@ -87,7 +86,7 @@
* such as images, or html files in the source directory will be
* copied into the destination directory.
*
- * @version $Revision: 1.37 $
+ * @version $Revision: 1.38 $
*
* @author <a href="mailto:kvisco@exoffice.com">Keith Visco</a>
* @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a>
@@ -98,31 +97,65 @@
*/
public class XSLTProcess extends MatchingTask implements XSLTLogger {
-
+ /** destination directory */
private File destDir = null;
+ /** where to find the source XML file, default is the project's basedir */
private File baseDir = null;
+ /** XSL stylesheet */
private String xslFile = null;
+ /** extension of the files produced by XSL processing */
private String targetExtension = ".html";
+
+ /** additional parameters to be passed to the stylesheets */
private Vector params = new Vector();
+ /** Input XML document to be used */
private File inFile = null;
+ /** Output file */
private File outFile = null;
+ /** The name of the XSL processor to use */
private String processor;
+
+ /** Classpath to use when trying to load the XSL processor */
private Path classpath = null;
+
+ /** The Liason implementation to use to communicate with the XSL
+ * processor */
private XSLTLiaison liaison;
+
+ /** Flag which indicates if the stylesheet has been loaded into
+ * the processor */
private boolean stylesheetLoaded = false;
+ /** force output of target files even if they already exist */
private boolean force = false;
+ /** Utilities used for file operations */
private FileUtils fileUtils;
+ /** XSL output method to be used */
private String outputtype = null;
+ /** for resolving entities such as dtds */
+ private XCatalog xcatalog;
+
+ /** Name of the TRAX Liason class */
+ private static final String TRAX_LIAISON_CLASS =
+ "org.apache.tools.ant.taskdefs.optional.TraXLiaison";
+
+ /** Name of the now-deprecated XSLP Liason class */
+ private static final String XSLP_LIASON_CLASS =
+ "org.apache.tools.ant.taskdefs.optional.XslpLiaison";
+
+ /** Name of the Xalan liason class */
+ private static final String XALAN_LIASON_CLASS =
+ "org.apache.tools.ant.taskdefs.optional.XalanLiaison";
+
/**
* Whether to style all files in the included directories as well.
*
@@ -140,6 +173,7 @@
/**
* Whether to style all files in the included directories as well.
*
+ * @param b true if files in included directories are processed.
* @since 1.35, Ant 1.5
*/
public void setScanIncludedDirectories(boolean b) {
@@ -148,6 +182,8 @@
/**
* Executes the task.
+ *
+ * @exception BuildException if there is an execution problem.
*/
public void execute() throws BuildException {
DirectoryScanner scanner;
@@ -179,7 +215,8 @@
* the wrong version has been used.
*/
if (stylesheet.exists()) {
- log("DEPRECATED - the style attribute should be relative to the project\'s");
+ log("DEPRECATED - the style attribute should be relative "
+ + "to the project\'s");
log(" basedir, not the tasks\'s basedir.");
}
}
@@ -208,7 +245,6 @@
for (int i = 0;i < list.length; ++i) {
process( baseDir, list[i], destDir, stylesheet );
}
-
if (performDirectoryScan) {
// Process all the directories marked for styling
dirs = scanner.getIncludedDirectories();
@@ -223,6 +259,8 @@
/**
* Set whether to check dependencies, or always generate.
+ *
+ * @param force true if always generate.
**/
public void setForce(boolean force) {
this.force = force;
@@ -230,6 +268,8 @@
/**
* Set the base directory.
+ *
+ * @param dir the base directory
**/
public void setBasedir(File dir) {
baseDir = dir;
@@ -255,6 +295,8 @@
/**
* Sets the file to use for styling relative to the base directory
* of this task.
+ *
+ * @param xslFile the stylesheet to use
*/
public void setStyle(String xslFile) {
this.xslFile = xslFile;
@@ -262,6 +304,8 @@
/**
* Set the classpath to load the Processor through (attribute).
+ *
+ * @param classpath the classpath to use when loading the XSL processor
*/
public void setClasspath(Path classpath) {
createClasspath().append(classpath);
@@ -269,6 +313,8 @@
/**
* Set the classpath to load the Processor through (nested element).
+ *
+ * @return a path instance to be configured by the Ant core.
*/
public Path createClasspath() {
if (classpath == null) {
@@ -280,34 +326,54 @@
/**
* Set the classpath to load the Processor through via reference
* (attribute).
+ *
+ * @param r the id of the Ant path instance to act as the classpath
+ * for loading the XSL processor
*/
public void setClasspathRef(Reference r) {
createClasspath().setRefid(r);
}
-
+ /**
+ * Set the name of the XSL processor to use
+ *
+ * @param processor the name of the XSL processor
+ */
public void setProcessor(String processor) {
this.processor = processor;
}
/**
+ * store the xcatalog for resolving entities
+ *
+ * @param xcatalog the xcatalog instance to use to look up DTDs
+ */
+ public void addXcatalog(XCatalog xcatalog) {
+ this.xcatalog = xcatalog;
+ }
+
+ /**
* Load processor here instead of in setProcessor - this will be
* called from within execute, so we have access to the latest
* classpath.
+ *
+ * @param proc the name of the processor to load.
+ * @exception Exception if the processor cannot be loaded.
*/
private void resolveProcessor(String proc) throws Exception {
if (proc.equals("trax")) {
final Class clazz =
- loadClass("org.apache.tools.ant.taskdefs.optional.TraXLiaison");
+ loadClass(TRAX_LIAISON_CLASS);
liaison = (XSLTLiaison)clazz.newInstance();
} else if (proc.equals("xslp")) {
- log("DEPRECATED - xslp processor is deprecated. Use trax or xalan instead.");
+ log("DEPRECATED - xslp processor is deprecated. Use trax or "
+ + "xalan instead.");
final Class clazz =
- loadClass("org.apache.tools.ant.taskdefs.optional.XslpLiaison");
+ loadClass(XSLP_LIASON_CLASS);
liaison = (XSLTLiaison) clazz.newInstance();
} else if (proc.equals("xalan")) {
final Class clazz =
- loadClass("org.apache.tools.ant.taskdefs.optional.XalanLiaison");
+ loadClass(XALAN_LIASON_CLASS);
liaison = (XSLTLiaison)clazz.newInstance();
} else {
liaison = (XSLTLiaison) loadClass(proc).newInstance();
@@ -317,6 +383,10 @@
/**
* Load named class either via the system classloader or a given
* custom classloader.
+ *
+ * @param classname the name of the class to load.
+ * @return the requested class.
+ * @exception Exception if the class could not be loaded.
*/
private Class loadClass(String classname) throws Exception {
if (classpath == null) {
@@ -331,6 +401,8 @@
/**
* Sets an out file
+ *
+ * @param outFile the output File instance.
*/
public void setOut(File outFile){
this.outFile = outFile;
@@ -338,6 +410,8 @@
/**
* Sets an input xml file to be styled
+ *
+ * @param inFile the input file
*/
public void setIn(File inFile){
this.inFile = inFile;
@@ -346,6 +420,12 @@
/**
* Processes the given input XML file and stores the result
* in the given resultFile.
+ *
+ * @param baseDir the base directory for resolving files.
+ * @param xmlFile the input file
+ * @param destDir the destination directory
+ * @param stylesheet the stylesheet to use.
+ * @exception BuildException if the processing fails.
*/
private void process(File baseDir, String xmlFile, File destDir,
File stylesheet)
@@ -367,7 +447,8 @@
int dotPos = xmlFile.lastIndexOf('.');
if(dotPos>0){
- outFile = new File(destDir,xmlFile.substring(0,xmlFile.lastIndexOf('.'))+fileExt);
+ outFile = new File(destDir,
+ xmlFile.substring(0, xmlFile.lastIndexOf('.')) + fileExt);
}else{
outFile = new File(destDir,xmlFile+fileExt);
}
@@ -394,17 +475,30 @@
} //-- processXML
- private void process(File inFile, File outFile, File stylesheet) throws BuildException {
+ /**
+ * Process the input file to the output file with the given stylesheet.
+ *
+ * @param inFile the input file to process.
+ * @param outFile the detination file.
+ * @param stylesheet the stylesheet to use.
+ * @exception BuildException if the processing fails.
+ */
+ private void process(File inFile, File outFile, File stylesheet)
+ throws BuildException {
try{
long styleSheetLastModified = stylesheet.lastModified();
- log("In file "+inFile+" time: " + inFile.lastModified() , Project.MSG_DEBUG);
- log("Out file "+outFile+" time: " + outFile.lastModified() , Project.MSG_DEBUG);
- log("Style file "+xslFile+" time: " + styleSheetLastModified , Project.MSG_DEBUG);
+ log("In file " + inFile + " time: " + inFile.lastModified(),
+ Project.MSG_DEBUG);
+ log("Out file " + outFile + " time: " + outFile.lastModified(),
+ Project.MSG_DEBUG);
+ log("Style file " + xslFile + " time: " + styleSheetLastModified,
+ Project.MSG_DEBUG);
if (force ||
inFile.lastModified() > outFile.lastModified() ||
styleSheetLastModified > outFile.lastModified()) {
ensureDirectoryFor( outFile );
- log("Processing " + inFile + " to " + outFile, Project.MSG_INFO);
+ log("Processing " + inFile + " to " + outFile,
+ Project.MSG_INFO);
configureLiaison(stylesheet);
liaison.transform(inFile, outFile);
}
@@ -417,7 +511,14 @@
}
}
- private void ensureDirectoryFor( File targetFile ) throws BuildException {
+ /**
+ * Ensure the directory exists for a given file
+ *
+ * @param targetFile the file for which the directories are required.
+ * @exception BuildException if the directories cannot be created.
+ */
+ private void ensureDirectoryFor(File targetFile)
+ throws BuildException {
File directory = new File( targetFile.getParent() );
if (!directory.exists()) {
if (!directory.mkdirs()) {
@@ -427,6 +528,11 @@
}
}
+ /**
+ * Get the Liason implementation to use in processing.
+ *
+ * @return an instance of the XSLTLiason interface.
+ */
protected XSLTLiaison getLiaison() {
// if processor wasn't specified, see if TraX is available. If not,
// default it to xslp or xalan, depending on which is in the classpath
@@ -458,24 +564,52 @@
return liaison;
}
+ /**
+ * Create an instance of an XSL parameter for configuration by Ant.
+ *
+ * @return an instance of the Param class to be configured.
+ */
public Param createParam() {
Param p = new Param();
params.addElement(p);
return p;
}
+ /**
+ * The Param inner class used to store XSL parameters
+ */
public class Param {
+ /** The parameter name */
private String name=null;
+
+ /** The parameter's XSL expression */
private String expression=null;
+ /**
+ * Set the parameter name.
+ *
+ * @param name the name of the parameter.
+ */
public void setName(String name){
this.name = name;
}
+ /**
+ * The XSL expression for the parameter value
+ *
+ * @param expression the XSL expression representing the
+ * parameter's value.
+ */
public void setExpression(String expression){
this.expression = expression;
}
+ /**
+ * Get the parameter name
+ *
+ * @return the parameter name
+ * @exception BuildException if the name is not set.
+ */
public String getName() throws BuildException{
if(name==null) {
throw new BuildException("Name attribute is missing.");
@@ -483,6 +617,12 @@
return name;
}
+ /**
+ * Get the parameter expression
+ *
+ * @return the parameter expression
+ * @exception BuildException if the expression is not set.
+ */
public String getExpression() throws BuildException{
if(expression==null) {
throw new BuildException("Expression attribute is missing.");
@@ -503,6 +643,9 @@
/**
* Loads the stylesheet and set xsl:param parameters.
+ *
+ * @param stylesheet the file form which to load the stylesheet.
+ * @exception BuildException if the stylesheet cannot be loaded.
*/
protected void configureLiaison(File stylesheet) throws BuildException {
if (stylesheetLoaded) {
@@ -517,6 +660,17 @@
Param p = (Param)e.nextElement();
liaison.addParam( p.getName(), p.getExpression() );
}
+ // if liaison is a TraxLiason, use XCatalog as the entity
+ // resolver
+ if (liaison.getClass().getName().equals(TRAX_LIAISON_CLASS) &&
+ xcatalog != null) {
+ log("Configuring TraxLiaison and calling entity resolver",
+ Project.MSG_DEBUG);
+ Method resolver = liaison.getClass()
+ .getDeclaredMethod("setEntityResolver",
+ new Class[] {EntityResolver.class});
+ resolver.invoke(liaison, new Object[] {xcatalog});
+ }
} catch (Exception ex) {
log("Failed to read stylesheet " + stylesheet, Project.MSG_INFO);
throw new BuildException(ex);
1.13 +35 -1 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java
Index: TraXLiaison.java
===================================================================
RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -w -u -r1.12 -r1.13
--- TraXLiaison.java 7 Feb 2002 22:01:57 -0000 1.12
+++ TraXLiaison.java 5 Mar 2002 13:49:46 -0000 1.13
@@ -63,6 +63,12 @@
import org.apache.tools.ant.taskdefs.XSLTLoggerAware;
import org.apache.tools.ant.taskdefs.XSLTLogger;
+import org.xml.sax.InputSource;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.XMLReader;
+
+import javax.xml.parsers.SAXParserFactory;
+
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
@@ -72,6 +78,9 @@
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+
+import javax.xml.transform.sax.SAXSource;
/**
* Concrete liaison for XSLT processor implementing TraX. (ie JAXP 1.1)
@@ -96,6 +105,9 @@
private XSLTLogger logger;
+ /** possible resolver for publicIds */
+ private EntityResolver resolver;
+
public TraXLiaison() throws Exception {
tfactory = TransformerFactory.newInstance();
tfactory.setErrorListener(this);
@@ -128,7 +140,23 @@
try {
fis = new FileInputStream(infile);
fos = new FileOutputStream(outfile);
- StreamSource src = new StreamSource(fis);
+ // FIXME: need to use a SAXSource as the source for the transform
+ // so we can plug in our own entity resolver
+ Source src = null;
+ if (resolver != null) {
+ if (tfactory.getFeature(SAXSource.FEATURE)) {
+ SAXParserFactory spFactory = SAXParserFactory.newInstance();
+ spFactory.setNamespaceAware( true );
+ XMLReader reader = spFactory.newSAXParser().getXMLReader();
+ reader.setEntityResolver(resolver);
+ src = new SAXSource(reader, new InputSource(fis));
+ } else {
+ throw new IllegalStateException("xcatalog specified, but "+
+ "parser doesn't support SAX");
+ }
+ } else {
+ src = new StreamSource(fis);
+ }
src.setSystemId(getSystemId(infile));
StreamResult res = new StreamResult(fos);
// not sure what could be the need of this...
@@ -225,4 +253,10 @@
logger.log(msg.toString());
}
+ /** Set the class to resolve entities during the transformation
+ */
+ public void setEntityResolver(EntityResolver aResolver) throws Exception {
+ resolver = aResolver;
+ }
+
} //-- TraXLiaison
1.9 +2 -0 jakarta-ant/src/main/org/apache/tools/ant/types/defaults.properties
Index: defaults.properties
===================================================================
RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/types/defaults.properties,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -w -u -r1.8 -r1.9
--- defaults.properties 19 Feb 2002 16:48:47 -0000 1.8
+++ defaults.properties 5 Mar 2002 13:49:47 -0000 1.9
@@ -8,3 +8,5 @@
classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet
substitution=org.apache.tools.ant.types.Substitution
regexp=org.apache.tools.ant.types.RegularExpression
+xcatalog=org.apache.tools.ant.types.XCatalog
+
1.1 jakarta-ant/src/main/org/apache/tools/ant/types/DTDLocation.java
Index: DTDLocation.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 DTD and Entity nested elements.
*
* @author <a href="mailto:conor@cortexebusiness.com.au">Conor MacNeill</a>
* @author dIon Gillard
*/
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;
}
/**
* @param location the location of the resource associated with the
* publicId
*/
public void setLocation(String location) {
this.location = location;
}
/**
* @return the publicId
*/
public String getPublicId() {
return publicId;
}
/**
* @return the location of the resource identified by the publicId
*/
public String getLocation() {
return location;
}
}
1.1 jakarta-ant/src/main/org/apache/tools/ant/types/XCatalog.java
Index: XCatalog.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.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* This data type provides a catalog of DTD locations
* <p>
* <code>
* <catalog><br>
* <dtd publicId="" location="/path/to/file.jar" /><br>
* <dtd publicId location="/path/to/file2.jar" /gt;<br>
* <entity publicId="" location="/path/to/file3.jar" /><br>
* <entity publicId="" location="/path/to/file4.jar" /><br>
* </catalog><br>
* </code>
* <p>
* The object implemention <code>sometask</code> must provide a method called
* <code>createCatalog</code> which returns an instance of <code>XCatalog</code>.
* Nested dtd and entity definitions are handled by the XCatalog object and
* must be labeled <code>dtd</code> and <code>entity</code> respectively.</p>
*
* <p>Possible future extension could allow a catalog file instead of nested
* elements, or use Norman Walsh's entity resolver from xml-commons</p>
*
* @author dIon Gillard
* @version $Id: XCatalog.java,v 1.1 2002/03/05 13:49:47 conor Exp $
*/
public class XCatalog extends DataType implements Cloneable, EntityResolver {
//-- Fields ----------------------------------------------------------------
/** holds dtd/entity objects until needed */
private Vector elements = new Vector();
//-- Methods ---------------------------------------------------------------
/**
* @return the elements of the catalog - DTDLocation objects
*/
private Vector getElements() {
return elements;
}
/**
* Set the list of DTDLocation object sin the catalog
*
* @param aVector the new list of DTD Locations to use in the catalog.
*/
private void setElements(Vector aVector) {
elements = aVector;
}
/**
* Add a DTD Location to the catalog
*
* @param aDTD the DTDLocation instance to be aded to the catalog
*/
private void addElement(DTDLocation aDTD) {
getElements().add(aDTD);
}
/**
* Creates the nested <code><dtd></code> element.
*
* @param dtd the infromation about the DTD to be added to the catalog
* @exception BuildException if this is a reference and no nested
* elements are allowed.
*/
public void addDTD(DTDLocation dtd) throws BuildException {
if (isReference()) {
throw noChildrenAllowed();
}
getElements().add(dtd);
}
/**
* Creates the nested <code><entity></code> element
*
* @param dtd the infromation about the DTD 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);
}
/**
* Makes this instance in effect a reference to another XCatalog instance.
*
* <p>You must not set another attribute or nest elements inside
* this element if you make it a reference.</p>
*
* @param r the reference to which this catalogi instance is associated
* @exception BuildException if this instance already has been configured.
*/
public void setRefid(Reference r) throws BuildException {
if (!elements.isEmpty()) {
throw tooManyAttributes();
}
// change this to get the objects from the other reference
Object o = r.getReferencedObject(getProject());
// we only support references to other XCatalogs
if (o instanceof XCatalog) {
// set all elements from referenced catalog to this one
XCatalog catalog = (XCatalog) o;
setElements(catalog.getElements());
} else {
String msg = r.getRefId() + " doesn\'t refer to an XCatalog";
throw new BuildException(msg);
}
super.setRefid(r);
}
/**
* @see org.xml.sax.EntityResolver#resolveEntity
*/
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
InputSource source = null;
DTDLocation matchingDTD = findMatchingDTD(publicId);
if (matchingDTD != null) {
// check if publicId is mapped to a file
log("Matching DTD found for publicId: '" + publicId +
"' location: '" + matchingDTD.getLocation() + "'",
Project.MSG_DEBUG);
File dtdFile = new File(matchingDTD.getLocation());
if (dtdFile.exists() && dtdFile.canRead()) {
source = new InputSource( new FileInputStream(dtdFile) );
source.setSystemId(dtdFile.toURL().toExternalForm());
log("matched a readable file", Project.MSG_DEBUG);
} else {
// check if publicId is a resource
// FIXME: ClassLoader: should this be context?
ClassLoader loader
= Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream(
matchingDTD.getLocation() );
if (is != null) {
source = new InputSource(is);
source.setSystemId(loader.getResource(
matchingDTD.getLocation()).toExternalForm());
log("matched a resource", Project.MSG_DEBUG);
} else {
// check if it's a URL
try {
URL dtdUrl = new URL(matchingDTD.getLocation());
InputStream dtdIs = dtdUrl.openStream();
if (dtdIs != null) {
source = new InputSource(dtdIs);
source.setSystemId(dtdUrl.toExternalForm());
log("matched as a URL", Project.MSG_DEBUG);
} else {
log("No match, parser will use: '" + systemId + "'",
Project.MSG_DEBUG);
}
} catch ( IOException ioe) {
//ignore
}
}
}
} else {
log("No match, parser will use: '" + systemId + "'",
Project.MSG_DEBUG);
}
// else let the parser handle it as a URI as we don't know what to
// do with it
return source;
}
/**
* Find a DTDLocation instance for the given publicId.
*
* @param publicId the publicId of the DTD for which local information is
* required
* @return a DTDLocation instance with information on the local location
* of the DTD or null if no such information is available
*/
private DTDLocation findMatchingDTD(String publicId) {
Iterator elements = getElements().iterator();
DTDLocation element = null;
while (elements.hasNext()) {
element = (DTDLocation)elements.next();
if (element.getPublicId().equals(publicId)) {
return element;
}
}
return null;
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>