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 }