001 package com.thaiopensource.relaxng.util; 002 003 import com.thaiopensource.util.PropertyMapBuilder; 004 import com.thaiopensource.validate.Flag; 005 import com.thaiopensource.validate.SchemaReader; 006 import com.thaiopensource.validate.ValidationDriver; 007 import com.thaiopensource.validate.schematron.SchematronProperty; 008 import com.thaiopensource.validate.rng.CompactSchemaReader; 009 import com.thaiopensource.validate.rng.RngProperty; 010 import com.thaiopensource.xml.sax.ErrorHandlerImpl; 011 import org.apache.tools.ant.BuildException; 012 import org.apache.tools.ant.DirectoryScanner; 013 import org.apache.tools.ant.Project; 014 import org.apache.tools.ant.Task; 015 import org.apache.tools.ant.types.FileSet; 016 import org.xml.sax.SAXException; 017 import org.xml.sax.SAXParseException; 018 019 import java.io.File; 020 import java.io.IOException; 021 import java.util.Vector; 022 023 024 /** 025 * Ant task to validate XML files using RELAX NG or other schema languages. 026 */ 027 028 public class JingTask extends Task { 029 030 private File schemaFile; 031 private File src; 032 private final Vector filesets = new Vector(); 033 private PropertyMapBuilder properties = new PropertyMapBuilder(); 034 private boolean failOnError = true; 035 private SchemaReader schemaReader = null; 036 037 private class LogErrorHandler extends ErrorHandlerImpl { 038 int logLevel = Project.MSG_ERR; 039 040 public void warning(SAXParseException e) throws SAXParseException { 041 logLevel = Project.MSG_WARN; 042 super.warning(e); 043 } 044 045 public void error(SAXParseException e) { 046 logLevel = Project.MSG_ERR; 047 super.error(e); 048 } 049 050 public void printException(Throwable e) { 051 logLevel = Project.MSG_ERR; 052 super.printException(e); 053 } 054 055 public void print(String message) { 056 log(message, logLevel); 057 } 058 } 059 060 public JingTask() { 061 RngProperty.CHECK_ID_IDREF.add(properties); 062 } 063 064 public void execute() throws BuildException { 065 if (schemaFile == null) 066 throw new BuildException("There must be an rngFile or schemaFile attribute", 067 location); 068 if (src == null && filesets.size() == 0) 069 throw new BuildException("There must be a file attribute or a fileset child element", 070 location); 071 072 ErrorHandlerImpl eh = new LogErrorHandler(); 073 074 boolean hadError = false; 075 076 try { 077 ValidationDriver driver = new ValidationDriver(properties.toPropertyMap(), schemaReader); 078 if (!driver.loadSchema(ValidationDriver.fileInputSource(schemaFile))) 079 hadError = true; 080 else { 081 if (src != null) { 082 if (!driver.validate(ValidationDriver.fileInputSource(src))) 083 hadError = true; 084 } 085 for (int i = 0; i < filesets.size(); i++) { 086 FileSet fs = (FileSet)filesets.elementAt(i); 087 DirectoryScanner ds = fs.getDirectoryScanner(project); 088 File dir = fs.getDir(project); 089 String[] srcs = ds.getIncludedFiles(); 090 for (int j = 0; j < srcs.length; j++) { 091 if (!driver.validate(ValidationDriver.fileInputSource(new File(dir, srcs[j])))) 092 hadError = true; 093 } 094 } 095 } 096 } 097 catch (SAXException e) { 098 hadError = true; 099 eh.printException(e); 100 } 101 catch (IOException e) { 102 hadError = true; 103 eh.printException(e); 104 } 105 if (hadError && failOnError) 106 throw new BuildException("Validation failed, messages should have been provided.", location); 107 } 108 109 /** 110 * Handles the <code>rngfile</code> attribute. 111 * 112 * @param rngFilename the attribute value 113 */ 114 public void setRngfile(String rngFilename) { 115 schemaFile = project.resolveFile(rngFilename); 116 } 117 118 /** 119 * Handles the <code>schemafile</code> attribute. 120 * 121 * @param schemaFilename the attribute value 122 */ 123 public void setSchemafile(String schemaFilename) { 124 schemaFile = project.resolveFile(schemaFilename); 125 } 126 127 public void setFile(File file) { 128 this.src = file; 129 } 130 131 /** 132 * Handles the <code>checkid</code> attribute. 133 * 134 * @param checkid the attribute value converted to a boolean 135 */ 136 public void setCheckid(boolean checkid) { 137 properties.put(RngProperty.CHECK_ID_IDREF, 138 checkid ? Flag.PRESENT : null); 139 } 140 141 /** 142 * Handles the <code>compactsyntax</code> attribute. 143 * 144 * @param compactsyntax the attribute value converted to a boolean 145 */ 146 public void setCompactsyntax(boolean compactsyntax) { 147 schemaReader = compactsyntax ? CompactSchemaReader.getInstance() : null; 148 } 149 150 /** 151 * Handles the <code>feasible</code> attribute. 152 * 153 * @param feasible the attribute value converted to a boolean 154 */ 155 public void setFeasible(boolean feasible) { 156 properties.put(RngProperty.FEASIBLE, feasible ? Flag.PRESENT : null); 157 } 158 159 /** 160 * Handles the phase attribute. 161 * 162 * @param phase the attribute value 163 */ 164 public void setPhase(String phase) { 165 SchematronProperty.PHASE.put(properties, phase); 166 } 167 168 /** 169 * Handles the <code>failonerror</code> attribute. 170 * 171 * @param failOnError the attribute value converted to a boolean 172 */ 173 public void setFailonerror(boolean failOnError) { 174 this.failOnError = failOnError; 175 } 176 177 public void addFileset(FileSet set) { 178 filesets.addElement(set); 179 } 180 181 }