From 1c87db68f361c1881999570f0e2b470b40f815bd Mon Sep 17 00:00:00 2001 From: Peter Donald Date: Sat, 6 Oct 2001 07:00:14 +0000 Subject: [PATCH] Added ability to resolve entitys to local files. Submitted by: Holger Engels git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269760 13f79535-47bb-0310-9956-ffa450edef68 --- .../taskdefs/optional/XMLValidateTask.java | 200 ++++++++++++++---- 1 file changed, 159 insertions(+), 41 deletions(-) diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java index cd7503484..0cea84632 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java @@ -53,14 +53,10 @@ */ package org.apache.tools.ant.taskdefs.optional; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; +import java.io.*; import java.net.MalformedURLException; import java.net.URL; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; +import java.util.*; import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; @@ -69,17 +65,10 @@ import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Reference; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.Parser; -import org.xml.sax.SAXException; -import org.xml.sax.SAXNotRecognizedException; -import org.xml.sax.SAXNotSupportedException; -import org.xml.sax.SAXParseException; -import org.xml.sax.XMLReader; +import org.xml.sax.*; import org.xml.sax.helpers.ParserAdapter; -/** +/** * The XMLValidateTask checks that an XML document is valid, * with a SAX validating parser. * @author Raphael Pierquin raphael.pierquin@agisphere.com @@ -101,7 +90,7 @@ public class XMLValidateTask extends Task { protected boolean warn = true; protected boolean lenient = false; protected String readerClassName = DEFAULT_XML_READER_CLASSNAME; - + protected File file = null; // file to be validated protected Vector filesets = new Vector(); // sets of file to be validated protected Path classpath; @@ -118,6 +107,10 @@ public class XMLValidateTask extends Task { = new ValidatorErrorHandler(); // to report sax parsing errors protected Hashtable features = new Hashtable(); + /** + * The list of configured DTD locations + */ + public ArrayList dtdLocations = new ArrayList(); /** * Specify how parser error are to be handled. @@ -125,7 +118,7 @@ public class XMLValidateTask extends Task { * If set to true (default), throw a buildException if the parser yields an error. */ public void setFailOnError(boolean fail) { - + failOnError = fail; } @@ -135,7 +128,7 @@ public class XMLValidateTask extends Task { * If set to true (default), log a warn message for each SAX warn event. */ public void setWarn(boolean bool) { - + warn = bool; } @@ -151,7 +144,7 @@ public class XMLValidateTask extends Task { lenient = bool; } - + /** * Specify the class name of the SAX parser to be used. (optional) * @param className should be an implementation of SAX2 org.xml.sax.XMLReader @@ -163,7 +156,7 @@ public class XMLValidateTask extends Task { * @see org.xml.sax.Parser; */ public void setClassName(String className) { - + readerClassName = className; } @@ -211,6 +204,27 @@ public class XMLValidateTask extends Task { filesets.addElement(set); } + /** + * Create a DTD location record. This stores the location of a DTD. The DTD is identified + * by its public Id. The location may either be a file location or a resource location. + */ + public DTDLocation createDTD() { + DTDLocation dtdLocation = new DTDLocation(); + dtdLocations.add(dtdLocation); + + return dtdLocation; + } + + protected EntityResolver getEntityResolver() { + LocalResolver resolver = new LocalResolver(); + + for (Iterator i = dtdLocations.iterator(); i.hasNext();) { + DTDLocation location = (DTDLocation)i.next(); + resolver.registerDTD(location); + } + return resolver; + } + public void execute() throws BuildException { int fileProcessed = 0; @@ -233,13 +247,13 @@ public class XMLValidateTask extends Task { log(errorMsg, Project.MSG_ERR); } } - + for (int i=0; i *
  • log SAX parse exceptions, *
  • remember if an error occured * */ protected class ValidatorErrorHandler implements ErrorHandler { - + protected File currentFile = null; protected String lastErrorMessage = null; protected boolean failed = false; - + public void init(File file) { currentFile = file; failed = false; } - + // did an error happen during last parsing ? public boolean getFailure() { - + return failed; } public void fatalError(SAXParseException exception) { - failed = true; doLog(exception,Project.MSG_ERR); } public void error(SAXParseException exception) { - failed = true; doLog(exception,Project.MSG_ERR); } - + public void warning(SAXParseException exception) { - // depending on implementation, XMLReader can yield hips of warning, + // depending on implementation, XMLReader can yield hips of warning, // only output then if user explicitely asked for it if (warn) doLog(exception,Project.MSG_WARN); } - + private void doLog(SAXParseException e, int logLevel) { - + log(getMessage(e), logLevel); } @@ -435,4 +448,109 @@ public class XMLValidateTask extends Task { return e.getMessage(); } } + + public static class DTDLocation { + private String publicId = null; + private String location = null; + + public void setPublicId(String publicId) { + this.publicId = publicId; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getPublicId() { + return publicId; + } + + public String getLocation() { + return location; + } + } + + private class LocalResolver + implements EntityResolver + { + private Hashtable fileDTDs = new Hashtable(); + private Hashtable resourceDTDs = new Hashtable(); + private Hashtable urlDTDs = new Hashtable(); + + public LocalResolver() {} + + public void registerDTD(String publicId, String location) { + if (location == null) { + return; + } + + File fileDTD = new File(location); + if (fileDTD.exists()) { + if (publicId != null) { + fileDTDs.put(publicId, fileDTD); + log("Mapped publicId " + publicId + " to file " + fileDTD, Project.MSG_VERBOSE); + } + return; + } + + if (LocalResolver.this.getClass().getResource(location) != null) { + if (publicId != null) { + resourceDTDs.put(publicId, location); + log("Mapped publicId " + publicId + " to resource " + location, Project.MSG_VERBOSE); + } + } + + try { + if (publicId != null) { + URL urldtd = new URL(location); + urlDTDs.put(publicId, urldtd); + } + } catch ( java.net.MalformedURLException e) { + //ignored + } + } + + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException + { + File dtdFile = (File) fileDTDs.get(publicId); + if (dtdFile != null) { + try { + log("Resolved " + publicId + " to local file " + dtdFile, Project.MSG_VERBOSE); + return new InputSource(new FileInputStream(dtdFile)); + } catch( FileNotFoundException ex ) { + // ignore + } + } + + String dtdResourceName = (String)resourceDTDs.get(publicId); + if (dtdResourceName != null) { + InputStream is = this.getClass().getResourceAsStream(dtdResourceName); + if (is != null) { + log("Resolved " + publicId + " to local resource " + dtdResourceName, Project.MSG_VERBOSE); + return new InputSource(is); + } + } + + URL dtdUrl = (URL) urlDTDs.get(publicId); + if ( dtdUrl != null ) { + try { + InputStream is = dtdUrl.openStream(); + log("Resolved " + publicId + " to url " + dtdUrl, Project.MSG_VERBOSE); + return new InputSource(is); + } catch ( IOException ioe) { + //ignore + } + } + + log("Could not resolve ( publicId: " + publicId + ", systemId: " + systemId + ") to a local entity", + Project.MSG_INFO); + + return null; + } + + public void registerDTD(DTDLocation location) { + registerDTD(location.getPublicId(), location.getLocation()); + } + } }