Browse Source

Added ability to resolve entitys to local files.

Submitted by: Holger Engels <hengels@mercatis.de>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269760 13f79535-47bb-0310-9956-ffa450edef68
master
Peter Donald 24 years ago
parent
commit
1c87db68f3
1 changed files with 159 additions and 41 deletions
  1. +159
    -41
      src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java

+ 159
- 41
src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java View File

@@ -53,14 +53,10 @@
*/ */
package org.apache.tools.ant.taskdefs.optional; 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.MalformedURLException;
import java.net.URL; 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.AntClassLoader;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner; 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.FileSet;
import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference; 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; import org.xml.sax.helpers.ParserAdapter;


/**
/**
* The <code>XMLValidateTask</code> checks that an XML document is valid, * The <code>XMLValidateTask</code> checks that an XML document is valid,
* with a SAX validating parser. * with a SAX validating parser.
* @author Raphael Pierquin <a href="mailto:raphael.pierquin@agisphere.com">raphael.pierquin@agisphere.com</a> * @author Raphael Pierquin <a href="mailto:raphael.pierquin@agisphere.com">raphael.pierquin@agisphere.com</a>
@@ -101,7 +90,7 @@ public class XMLValidateTask extends Task {
protected boolean warn = true; protected boolean warn = true;
protected boolean lenient = false; protected boolean lenient = false;
protected String readerClassName = DEFAULT_XML_READER_CLASSNAME; protected String readerClassName = DEFAULT_XML_READER_CLASSNAME;
protected File file = null; // file to be validated protected File file = null; // file to be validated
protected Vector filesets = new Vector(); // sets of file to be validated protected Vector filesets = new Vector(); // sets of file to be validated
protected Path classpath; protected Path classpath;
@@ -118,6 +107,10 @@ public class XMLValidateTask extends Task {
= new ValidatorErrorHandler(); // to report sax parsing errors = new ValidatorErrorHandler(); // to report sax parsing errors
protected Hashtable features = new Hashtable(); protected Hashtable features = new Hashtable();


/**
* The list of configured DTD locations
*/
public ArrayList dtdLocations = new ArrayList();


/** /**
* Specify how parser error are to be handled. * Specify how parser error are to be handled.
@@ -125,7 +118,7 @@ public class XMLValidateTask extends Task {
* If set to <code>true</code> (default), throw a buildException if the parser yields an error. * If set to <code>true</code> (default), throw a buildException if the parser yields an error.
*/ */
public void setFailOnError(boolean fail) { public void setFailOnError(boolean fail) {
failOnError = fail; failOnError = fail;
} }


@@ -135,7 +128,7 @@ public class XMLValidateTask extends Task {
* If set to <code>true</true> (default), log a warn message for each SAX warn event. * If set to <code>true</true> (default), log a warn message for each SAX warn event.
*/ */
public void setWarn(boolean bool) { public void setWarn(boolean bool) {
warn = bool; warn = bool;
} }


@@ -151,7 +144,7 @@ public class XMLValidateTask extends Task {


lenient = bool; lenient = bool;
} }
/** /**
* Specify the class name of the SAX parser to be used. (optional) * Specify the class name of the SAX parser to be used. (optional)
* @param className should be an implementation of SAX2 <code>org.xml.sax.XMLReader</code> * @param className should be an implementation of SAX2 <code>org.xml.sax.XMLReader</code>
@@ -163,7 +156,7 @@ public class XMLValidateTask extends Task {
* @see org.xml.sax.Parser; * @see org.xml.sax.Parser;
*/ */
public void setClassName(String className) { public void setClassName(String className) {
readerClassName = className; readerClassName = className;
} }


@@ -211,6 +204,27 @@ public class XMLValidateTask extends Task {
filesets.addElement(set); 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 { public void execute() throws BuildException {


int fileProcessed = 0; int fileProcessed = 0;
@@ -233,13 +247,13 @@ public class XMLValidateTask extends Task {
log(errorMsg, Project.MSG_ERR); log(errorMsg, Project.MSG_ERR);
} }
} }
for (int i=0; i<filesets.size(); i++) { for (int i=0; i<filesets.size(); i++) {


FileSet fs = (FileSet) filesets.elementAt(i); FileSet fs = (FileSet) filesets.elementAt(i);
DirectoryScanner ds = fs.getDirectoryScanner(project); DirectoryScanner ds = fs.getDirectoryScanner(project);
String[] files = ds.getIncludedFiles(); String[] files = ds.getIncludedFiles();
for (int j=0; j < files.length ; j++) { for (int j=0; j < files.length ; j++) {
File srcFile = new File(fs.getDir(project), files[j]); File srcFile = new File(fs.getDir(project), files[j]);
doValidate(srcFile); doValidate(srcFile);
@@ -266,16 +280,16 @@ public class XMLValidateTask extends Task {
// loader.addSystemPackageRoot("org.xml"); // needed to avoid conflict // loader.addSystemPackageRoot("org.xml"); // needed to avoid conflict
readerClass = loader.loadClass(readerClassName); readerClass = loader.loadClass(readerClassName);
AntClassLoader.initializeClass(readerClass); AntClassLoader.initializeClass(readerClass);
} else
} else
readerClass = Class.forName(readerClassName); readerClass = Class.forName(readerClassName);
// then check it implements XMLReader // then check it implements XMLReader
if (XMLReader.class.isAssignableFrom(readerClass)) { if (XMLReader.class.isAssignableFrom(readerClass)) {


xmlReader = (XMLReader) readerClass.newInstance(); xmlReader = (XMLReader) readerClass.newInstance();
log("Using SAX2 reader " + readerClassName, Project.MSG_VERBOSE); log("Using SAX2 reader " + readerClassName, Project.MSG_VERBOSE);
} else { } else {
// see if it is a SAX1 Parser // see if it is a SAX1 Parser
if (Parser.class.isAssignableFrom(readerClass)) { if (Parser.class.isAssignableFrom(readerClass)) {
Parser parser = (Parser) readerClass.newInstance(); Parser parser = (Parser) readerClass.newInstance();
@@ -295,8 +309,9 @@ public class XMLValidateTask extends Task {
throw new BuildException(INIT_FAILED_MSG + readerClassName, e); throw new BuildException(INIT_FAILED_MSG + readerClassName, e);
} }


xmlReader.setEntityResolver(getEntityResolver());
xmlReader.setErrorHandler(errorHandler); xmlReader.setErrorHandler(errorHandler);
if (! (xmlReader instanceof ParserAdapter)) { if (! (xmlReader instanceof ParserAdapter)) {
// turn validation on // turn validation on
if (! lenient) { if (! lenient) {
@@ -330,12 +345,12 @@ public class XMLValidateTask extends Task {
if (warn) if (warn)
log("Could'nt set feature '" log("Could'nt set feature '"
+ feature + feature
+ "' because the parser doesn't recognize it",
+ "' because the parser doesn't recognize it",
Project.MSG_WARN); Project.MSG_WARN);
} catch (SAXNotSupportedException e) { } catch (SAXNotSupportedException e) {
if (warn) if (warn)
log("Could'nt set feature '" log("Could'nt set feature '"
+ feature
+ feature
+ "' because the parser doesn't support it", + "' because the parser doesn't support it",
Project.MSG_WARN); Project.MSG_WARN);
} }
@@ -362,60 +377,58 @@ public class XMLValidateTask extends Task {
} catch (IOException ex) { } catch (IOException ex) {
throw new BuildException("Could'nt validate document " + afile, ex); throw new BuildException("Could'nt validate document " + afile, ex);
} }
if (errorHandler.getFailure()) { if (errorHandler.getFailure()) {
if (failOnError) if (failOnError)
throw new BuildException(afile + " is not a valid XML document."); throw new BuildException(afile + " is not a valid XML document.");
else else
log(afile + " is not a valid XML document",Project.MSG_ERR); log(afile + " is not a valid XML document",Project.MSG_ERR);
}
}
} }


/* /*
* ValidatorErrorHandler role :
* ValidatorErrorHandler role :
* <ul> * <ul>
* <li> log SAX parse exceptions, * <li> log SAX parse exceptions,
* <li> remember if an error occured * <li> remember if an error occured
* </ul> * </ul>
*/ */
protected class ValidatorErrorHandler implements ErrorHandler { protected class ValidatorErrorHandler implements ErrorHandler {
protected File currentFile = null; protected File currentFile = null;
protected String lastErrorMessage = null; protected String lastErrorMessage = null;
protected boolean failed = false; protected boolean failed = false;
public void init(File file) { public void init(File file) {
currentFile = file; currentFile = file;
failed = false; failed = false;
} }
// did an error happen during last parsing ? // did an error happen during last parsing ?
public boolean getFailure() { public boolean getFailure() {
return failed; return failed;
} }


public void fatalError(SAXParseException exception) { public void fatalError(SAXParseException exception) {

failed = true; failed = true;
doLog(exception,Project.MSG_ERR); doLog(exception,Project.MSG_ERR);
} }


public void error(SAXParseException exception) { public void error(SAXParseException exception) {

failed = true; failed = true;
doLog(exception,Project.MSG_ERR); doLog(exception,Project.MSG_ERR);
} }
public void warning(SAXParseException exception) { 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 // only output then if user explicitely asked for it
if (warn) if (warn)
doLog(exception,Project.MSG_WARN); doLog(exception,Project.MSG_WARN);
} }
private void doLog(SAXParseException e, int logLevel) { private void doLog(SAXParseException e, int logLevel) {
log(getMessage(e), logLevel); log(getMessage(e), logLevel);
} }


@@ -435,4 +448,109 @@ public class XMLValidateTask extends Task {
return e.getMessage(); 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());
}
}
} }

Loading…
Cancel
Save