/*
* This file is part of the RELAX NG schemas far (X)HTML5.
* Please see the file named LICENSE in the relaxng directory for
* license details.
*/
package org.whattf.syntax;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import nu.validator.gnu.xml.aelfred2.SAXDriver;
import nu.validator.htmlparser.sax.HtmlParser;
import nu.validator.xml.IdFilter;
import nu.validator.xml.SystemErrErrorHandler;
import org.whattf.checker.NormalizationChecker;
import org.whattf.checker.TextContentChecker;
import org.whattf.checker.jing.CheckerSchema;
import org.whattf.checker.jing.CheckerValidator;
import org.whattf.checker.table.TableChecker;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import com.thaiopensource.relaxng.impl.CombineValidator;
import com.thaiopensource.util.PropertyMap;
import com.thaiopensource.util.PropertyMapBuilder;
import com.thaiopensource.validate.Schema;
import com.thaiopensource.validate.SchemaReader;
import com.thaiopensource.validate.ValidateProperty;
import com.thaiopensource.validate.Validator;
import com.thaiopensource.validate.auto.AutoSchemaReader;
import com.thaiopensource.validate.prop.rng.RngProperty;
import com.thaiopensource.validate.rng.CompactSchemaReader;
import com.thaiopensource.xml.sax.CountingErrorHandler;
import com.thaiopensource.xml.sax.Jaxp11XMLReaderCreator;
/**
*
* @version $Id$
* @author hsivonen
*/
public class Driver {
private static final String PATH = "syntax/relaxng/tests/";
private PrintWriter err;
private PrintWriter out;
private Schema mainSchema;
private Schema assertionSchema;
private Validator validator;
private SystemErrErrorHandler errorHandler = new SystemErrErrorHandler();
private CountingErrorHandler countingErrorHandler = new CountingErrorHandler();
private HtmlParser htmlParser = new HtmlParser();
private XMLReader xmlParser;
private boolean failed = false;
private boolean verbose;
/**
* @param basePath
*/
public Driver(boolean verbose) {
this.verbose = verbose;
try {
this.err = new PrintWriter(new OutputStreamWriter(System.err,
"UTF-8"));
this.out = new PrintWriter(new OutputStreamWriter(System.out,
"UTF-8"));
/*
* SAXParserFactory factory = SAXParserFactory.newInstance();
* factory.setNamespaceAware(true); factory.setValidating(false);
* XMLReader parser = factory.newSAXParser().getXMLReader();
*/
this.xmlParser = new IdFilter(new SAXDriver());
} catch (Exception e) {
// If this happens, the JDK is too broken anyway
throw new RuntimeException(e);
}
}
private Schema schemaByFilename(File name) throws Exception {
PropertyMapBuilder pmb = new PropertyMapBuilder();
pmb.put(ValidateProperty.ERROR_HANDLER, errorHandler);
pmb.put(ValidateProperty.XML_READER_CREATOR,
new Jaxp11XMLReaderCreator());
RngProperty.CHECK_ID_IDREF.add(pmb);
PropertyMap jingPropertyMap = pmb.toPropertyMap();
InputSource schemaInput;
try {
schemaInput = new InputSource(name.toURL().toString());
} catch (MalformedURLException e1) {
System.err.println();
e1.printStackTrace(err);
failed = true;
return null;
}
SchemaReader sr;
if (name.getName().endsWith(".rnc")) {
sr = CompactSchemaReader.getInstance();
} else {
sr = new AutoSchemaReader();
}
return sr.createSchema(schemaInput, jingPropertyMap);
}
private void checkFile(File file) throws IOException, SAXException {
validator.reset();
InputSource is = new InputSource(new FileInputStream(file));
is.setSystemId(file.toURL().toString());
String name = file.getName();
if (name.endsWith(".html") || name.endsWith(".htm")) {
is.setEncoding("UTF-8");
if (verbose) {
out.println(file);
out.flush();
}
htmlParser.parse(is);
} else if (name.endsWith(".xhtml") || name.endsWith(".xht")) {
if (verbose) {
out.println(file);
out.flush();
}
xmlParser.parse(is);
}
}
private boolean isCheckableFile(File file) {
String name = file.getName();
return file.isFile()
&& (name.endsWith(".html") || name.endsWith(".htm")
|| name.endsWith(".xhtml") || name.endsWith(".xht"));
}
private void checkValidFiles(File directory) {
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (isCheckableFile(file)) {
errorHandler.reset();
try {
checkFile(file);
} catch (IOException e) {
} catch (SAXException e) {
}
if (errorHandler.isInError()) {
failed = true;
}
} else if (file.isDirectory()) {
checkValidFiles(file);
}
}
}
private void checkInvalidFiles(File directory) {
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (isCheckableFile(file)) {
countingErrorHandler.reset();
try {
checkFile(file);
} catch (IOException e) {
} catch (SAXException e) {
}
if (!countingErrorHandler.getHadErrorOrFatalError()) {
failed = true;
try {
err.println(file.toURL().toString()
+ " was supposed to be invalid but was not.");
err.flush();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
} else if (file.isDirectory()) {
checkInvalidFiles(file);
}
}
}
private void checkDirectory(File directory, File schema) throws SAXException {
try {
mainSchema = schemaByFilename(schema);
} catch (Exception e) {
err.println("Reading schema failed. Skipping test directory.");
e.printStackTrace();
err.flush();
return;
}
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if ("valid".equals(file.getName())) {
setup(errorHandler);
checkValidFiles(file);
} else if ("invalid".equals(file.getName())) {
setup(countingErrorHandler);
checkInvalidFiles(file);
}
}
}
/**
* @throws SAXNotSupportedException
* @throws SAXdException
*
*/
private void setup(ErrorHandler eh) throws SAXException {
PropertyMapBuilder pmb = new PropertyMapBuilder();
pmb.put(ValidateProperty.ERROR_HANDLER, eh);
pmb.put(ValidateProperty.XML_READER_CREATOR,
new Jaxp11XMLReaderCreator());
RngProperty.CHECK_ID_IDREF.add(pmb);
PropertyMap jingPropertyMap = pmb.toPropertyMap();
validator = mainSchema.createValidator(jingPropertyMap);
Validator assertionValidator = assertionSchema.createValidator(jingPropertyMap);
validator = new CombineValidator(validator, assertionValidator);
validator = new CombineValidator(validator, new CheckerValidator(
new TableChecker(), jingPropertyMap));
validator = new CombineValidator(validator, new CheckerValidator(
new NormalizationChecker(), jingPropertyMap));
validator = new CombineValidator(validator, new CheckerValidator(
new TextContentChecker(), jingPropertyMap));
htmlParser.setContentHandler(validator.getContentHandler());
htmlParser.setErrorHandler(eh);
htmlParser.setFeature("http://xml.org/sax/features/unicode-normalization-checking", true);
xmlParser.setContentHandler(validator.getContentHandler());
xmlParser.setErrorHandler(eh);
xmlParser.setFeature("http://xml.org/sax/features/unicode-normalization-checking", true);
htmlParser.setMappingLangToXmlLang(true);
}
public boolean check() throws SAXException {
try {
assertionSchema = CheckerSchema.ASSERTION_SCH;
} catch (Exception e) {
err.println("Reading schema failed. Terminating.");
e.printStackTrace();
err.flush();
return false;
}
checkDirectory(new File(PATH + "html5core/"), new File(PATH + "../xhtml5core.rnc"));
checkDirectory(new File(PATH + "html5core-plus-web-forms2/"), new File(
PATH + "../xhtml5core-plus-web-forms2.rnc"));
checkDirectory(new File(PATH + "html5full-html/"), new File(
PATH + "../html5full.rnc"));
checkDirectory(new File(PATH + "html5full-xhtml/"), new File(
PATH + "../xhtml5full-xhtml.rnc"));
checkDirectory(new File(PATH + "assertions/"), new File(
PATH + "../xhtml5full-xhtml.rnc"));
checkDirectory(new File(PATH + "tables/"), new File(PATH + "../xhtml5full-xhtml.rnc"));
checkDirectory(new File(PATH + "media-queries/"), new File(PATH + "../html5full.rnc"));
checkDirectory(new File(PATH + "mime-types/"), new File(PATH + "../html5full.rnc"));
if (verbose) {
if (failed) {
out.println("Failure!");
} else {
out.println("Success!");
}
}
err.flush();
out.flush();
return !failed;
}
/**
* @param args
* @throws SAXException
*/
public static void main(String[] args) throws SAXException {
boolean verbose = ((args.length == 1) && "-v".equals(args[0]));
Driver d = new Driver(verbose);
if (d.check()) {
System.exit(0);
} else {
System.exit(-1);
}
}
}