1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.xml.validation;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.List;
24 import javax.xml.parsers.ParserConfigurationException;
25 import javax.xml.parsers.SAXParser;
26 import javax.xml.parsers.SAXParserFactory;
27 import javax.xml.transform.Source;
28 import javax.xml.transform.Transformer;
29 import javax.xml.transform.TransformerException;
30 import javax.xml.transform.TransformerFactory;
31 import javax.xml.transform.dom.DOMSource;
32 import javax.xml.transform.sax.SAXSource;
33 import javax.xml.transform.stream.StreamResult;
34 import javax.xml.transform.stream.StreamSource;
35
36 import org.springframework.core.io.Resource;
37 import org.springframework.xml.sax.SaxUtils;
38 import org.xml.sax.InputSource;
39 import org.xml.sax.SAXException;
40 import org.xml.sax.SAXParseException;
41 import org.xml.sax.helpers.DefaultHandler;
42
43
44
45
46
47
48
49 abstract class Jaxp10ValidatorFactory {
50
51 private static final String SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
52
53 private static final String SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
54
55 static XmlValidator createValidator(Resource[] schemaResources, String schemaLanguage) throws IOException {
56 InputSource[] inputSources = new InputSource[schemaResources.length];
57 for (int i = 0; i < schemaResources.length; i++) {
58 inputSources[i] = SaxUtils.createInputSource(schemaResources[i]);
59 }
60 return new Jaxp10Validator(inputSources, schemaLanguage);
61 }
62
63 private static class Jaxp10Validator implements XmlValidator {
64
65 private SAXParserFactory parserFactory;
66
67 private TransformerFactory transformerFactory;
68
69 private InputSource[] schemaInputSources;
70
71 private String schemaLanguage;
72
73 private Jaxp10Validator(InputSource[] schemaInputSources, String schemaLanguage) {
74 this.schemaInputSources = schemaInputSources;
75 this.schemaLanguage = schemaLanguage;
76 transformerFactory = TransformerFactory.newInstance();
77 parserFactory = SAXParserFactory.newInstance();
78 parserFactory.setNamespaceAware(true);
79 parserFactory.setValidating(true);
80 }
81
82 public SAXParseException[] validate(Source source) throws IOException {
83 SAXParser parser = createSAXParser();
84 ValidationErrorHandler errorHandler = new ValidationErrorHandler();
85 try {
86 if (source instanceof SAXSource) {
87 validateSAXSource((SAXSource) source, parser, errorHandler);
88 }
89 else if (source instanceof StreamSource) {
90 validateStreamSource((StreamSource) source, parser, errorHandler);
91 }
92 else if (source instanceof DOMSource) {
93 validateDOMSource((DOMSource) source, parser, errorHandler);
94 }
95 else {
96 throw new IllegalArgumentException("Source [" + source.getClass().getName() +
97 "] is neither SAXSource, DOMSource, nor StreamSource");
98 }
99 return errorHandler.getErrors();
100 }
101 catch (SAXException ex) {
102 throw new XmlValidationException("Could not validate source: " + ex.getMessage(), ex);
103 }
104 }
105
106 private void validateDOMSource(DOMSource domSource, SAXParser parser, ValidationErrorHandler errorHandler)
107 throws IOException, SAXException {
108 try {
109
110
111 Transformer transformer = transformerFactory.newTransformer();
112 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
113 transformer.transform(domSource, new StreamResult(outputStream));
114 ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
115 validateStreamSource(new StreamSource(inputStream), parser, errorHandler);
116 }
117 catch (TransformerException ex) {
118 throw new XmlValidationException("Could not validate DOM source: " + ex.getMessage(), ex);
119 }
120
121 }
122
123 private void validateStreamSource(StreamSource streamSource,
124 SAXParser parser,
125 ValidationErrorHandler errorHandler) throws SAXException, IOException {
126 if (streamSource.getInputStream() != null) {
127 parser.parse(streamSource.getInputStream(), errorHandler);
128 }
129 else if (streamSource.getReader() != null) {
130 parser.parse(new InputSource(streamSource.getReader()), errorHandler);
131 }
132 else {
133 throw new IllegalArgumentException("StreamSource contains neither InputStream nor Reader");
134 }
135 }
136
137 private void validateSAXSource(SAXSource source, SAXParser parser, ValidationErrorHandler errorHandler)
138 throws SAXException, IOException {
139 parser.parse(source.getInputSource(), errorHandler);
140 }
141
142 private SAXParser createSAXParser() {
143 try {
144 SAXParser parser = parserFactory.newSAXParser();
145 parser.setProperty(SCHEMA_LANGUAGE, schemaLanguage);
146 parser.setProperty(SCHEMA_SOURCE, schemaInputSources);
147 return parser;
148 }
149 catch (ParserConfigurationException ex) {
150 throw new XmlValidationException("Could not create SAXParser: " + ex.getMessage(), ex);
151 }
152 catch (SAXException ex) {
153 throw new XmlValidationException("Could not create SAXParser: " + ex.getMessage(), ex);
154 }
155 }
156 }
157
158
159 private static class ValidationErrorHandler extends DefaultHandler {
160
161 private List errors = new ArrayList();
162
163 private SAXParseException[] getErrors() {
164 return (SAXParseException[]) errors.toArray(new SAXParseException[errors.size()]);
165 }
166
167 public void warning(SAXParseException ex) throws SAXException {
168 }
169
170 public void error(SAXParseException ex) throws SAXException {
171 errors.add(ex);
172 }
173
174 public void fatalError(SAXParseException ex) throws SAXException {
175 errors.add(ex);
176 }
177 }
178 }