1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.model.application.provider;
import com.thaiopensource.util.PropertyMap;
import com.thaiopensource.util.PropertyMapBuilder;
import com.thaiopensource.validate.ValidateProperty;
import com.thaiopensource.validate.ValidationDriver;
import com.thaiopensource.validate.rng.CompactSchemaReader;
import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.io.reader.NamedReader;
import com.yahoo.yolean.Exceptions;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.logging.Level;
/**
* Validates xml files against a schema.
*
* @author tonytv
*/
public class SchemaValidator {
private final CustomErrorHandler errorHandler = new CustomErrorHandler();
private final ValidationDriver driver;
private final DeployLogger deployLogger;
/**
* Initializes the validator by using the given file as schema file
*
* @param schemaFile schema file
* @throws IOException if it is not possible to read schema files
*/
SchemaValidator(File schemaFile, DeployLogger deployLogger) throws IOException, SAXException {
this.deployLogger = deployLogger;
this.driver = new ValidationDriver(PropertyMap.EMPTY, instanceProperties(), CompactSchemaReader.getInstance());
driver.loadSchema(ValidationDriver.fileInputSource(schemaFile));
}
public void validate(File file) throws IOException {
validate(file, file.getName());
}
public void validate(File file, String fileName) throws IOException {
validate(ValidationDriver.fileInputSource(file), fileName);
}
public void validate(Reader reader) throws IOException {
validate(new InputSource(reader), null);
}
public void validate(NamedReader reader) throws IOException {
validate(new InputSource(reader), reader.getName());
}
public void validate(InputSource inputSource, String fileName) throws IOException {
errorHandler.fileName = (fileName == null ? " input" : fileName);
try {
if ( ! driver.validate(inputSource)) {
// Shouldn't happen, error handler should have thrown
throw new RuntimeException("Aborting due to earlier XML errors.");
}
} catch (SAXException e) {
// This should never happen, as it is handled by the ErrorHandler
// installed for the driver.
throw new IllegalArgumentException(
"XML error in " + (fileName == null ? " input" : fileName) + ": " + Exceptions.toMessageString(e));
}
}
private PropertyMap instanceProperties() {
PropertyMapBuilder builder = new PropertyMapBuilder();
builder.put(ValidateProperty.ERROR_HANDLER, errorHandler);
return builder.toPropertyMap();
}
private class CustomErrorHandler implements ErrorHandler {
volatile String fileName;
public void warning(SAXParseException e) throws SAXException {
deployLogger.log(Level.WARNING, message(e));
}
public void error(SAXParseException e) throws SAXException {
throw new IllegalArgumentException(message(e));
}
public void fatalError(SAXParseException e) throws SAXException {
throw new IllegalArgumentException(message(e));
}
private String message(SAXParseException e) {
return "XML error in " + fileName + ": " +
Exceptions.toMessageString(e)
+ " [" + e.getLineNumber() + ":" + e.getColumnNumber() + "]";
}
}
}
|