• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

xmlunit / xmlunit / 673

pending completion
673

push

travis-ci-com

bodewig
next batch of fixed javadoc warnings, just a few hundred left

8 of 8 new or added lines in 4 files covered. (100.0%)

5329 of 5806 relevant lines covered (91.78%)

4.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.86
/xmlunit-legacy/src/main/java/org/custommonkey/xmlunit/Validator.java
1
/*
2
******************************************************************
3
Copyright (c) 2001-2007,2015-2016,2022 Jeff Martin, Tim Bacon
4
All rights reserved.
5

6
Redistribution and use in source and binary forms, with or without
7
modification, are permitted provided that the following conditions
8
are met:
9

10
    * Redistributions of source code must retain the above copyright
11
      notice, this list of conditions and the following disclaimer.
12
    * Redistributions in binary form must reproduce the above
13
      copyright notice, this list of conditions and the following
14
      disclaimer in the documentation and/or other materials provided
15
      with the distribution.
16
    * Neither the name of the XMLUnit nor the names
17
      of its contributors may be used to endorse or promote products
18
      derived from this software without specific prior written
19
      permission.
20

21
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
POSSIBILITY OF SUCH DAMAGE.
33

34
******************************************************************
35
*/
36

37
package org.custommonkey.xmlunit;
38

39
import org.xmlunit.validation.Languages;
40
import org.xmlunit.validation.ParsingValidator;
41
import org.xmlunit.validation.ValidationProblem;
42
import org.xmlunit.validation.ValidationResult;
43

44
import org.custommonkey.xmlunit.exceptions.ConfigurationException;
45
import org.custommonkey.xmlunit.exceptions.XMLUnitRuntimeException;
46

47
import java.io.File;
48
import java.io.IOException;
49
import java.io.InputStream;
50
import java.io.InputStreamReader;
51
import java.io.Reader;
52
import java.io.StringReader;
53
import java.util.ArrayList;
54
import java.util.List;
55

56
import org.w3c.dom.Document;
57
import org.xml.sax.InputSource;
58
import org.xml.sax.helpers.DefaultHandler;
59

60
import javax.xml.transform.Source;
61
import javax.xml.transform.sax.SAXSource;
62
import javax.xml.transform.stream.StreamSource;
63

64
/**
65
 * Validates XML against its internal or external DOCTYPE, or a completely
66
 *  different DOCTYPE.
67
 * Usage:
68
 * <ul>
69
 * <li><code>new Validator(readerForXML);</code> <br>
70
 *   to validate some XML that contains or references an accessible DTD or
71
 *   schema
72
 * </li>
73
 * <li><code>new Validator(readerForXML, systemIdForValidation);</code> <br>
74
 *   to validate some XML that references a DTD but using a local systemId
75
 *   to perform the validation
76
 * </li>
77
 * <li><code>new Validator(readerForXML, systemIdForValidation, doctypeName);</code> <br>
78
 *   to validate some XML against a completely different DTD
79
 * </li>
80
 * </ul>
81
 */
82
public class Validator extends DefaultHandler {
83
    private final InputSource validationInputSource;
84
    private final StringBuilder messages;
85
    private final boolean usingDoctypeReader;
86
    private final String systemId;
87

88
    private Object schemaSource;
89
    private boolean useSchema = false;
5✔
90

91
    private Boolean isValid;
92

93
    /**
94
     * Baseline constructor: called by all others
95
     *
96
     * @param inputSource document to validate
97
     * @param systemId system id of the DTD to use during validation
98
     * @param usingDoctypeReader whether to use {@link DoctypeReader}
99
     */
100
    protected Validator(InputSource inputSource,
101
                        String systemId,
102
                        boolean usingDoctypeReader) {
5✔
103
        isValid = null;
5✔
104
        messages = new StringBuilder();
5✔
105
        this.validationInputSource = inputSource;
5✔
106
        this.systemId = systemId;
5✔
107
        this.usingDoctypeReader = usingDoctypeReader;
5✔
108
    }
5✔
109

110
    /**
111
     * DOM-style constructor: allows Document validation post-manipulation
112
     * of the DOM tree's contents.
113
     * This takes a fairly tortuous route to validation as DOM level 2 does
114
     * not allow creation of Doctype nodes.
115
     * The supplied systemId and doctype name will replace any Doctype
116
     * settings in the Document.
117
     *
118
     * @param document document to validate
119
     * @param systemID system id of the DTD to use during validation
120
     * @param doctype overrides the document's doctype
121
     */
122
    public Validator(Document document, String systemID, String doctype) {
123
        this(new InputStreamReader(new NodeInputStream(document)),
5✔
124
             systemID, doctype);
125
    }
5✔
126

127
    /**
128
     * Basic constructor.
129
     * Validates the contents of the Reader using the DTD or schema referenced
130
     *  by those contents.
131
     *
132
     * @param readerForValidation document to validate
133
     */
134
    public Validator(Reader readerForValidation) {
135
        this(readerForValidation, null);
5✔
136
    }
5✔
137

138
    /**
139
     * Basic constructor.
140
     * Validates the contents of the String using the DTD or schema referenced
141
     *  by those contents.
142
     *
143
     * @param stringForValidation document to validate
144
     */
145
    public Validator(String stringForValidation) {
146
        this(new StringReader(stringForValidation));
5✔
147
    }
5✔
148

149
    /**
150
     * Basic constructor.
151
     * Validates the contents of the InputSource using the DTD or
152
     * schema referenced by those contents.
153
     *
154
     * @param sourceForValidation document to validate
155
     */
156
    public Validator(InputSource sourceForValidation) {
157
        this(sourceForValidation, null);
5✔
158
    }
5✔
159

160
    /**
161
     * Extended constructor.
162
     * Validates the contents of the Reader using the DTD specified with the
163
     *  systemID. There must be DOCTYPE instruction in the markup that
164
     *  references the DTD or else the markup will be considered invalid: if
165
     *  there is no DOCTYPE in the markup use the 3-argument constructor
166
     *
167
     * @param readerForValidation document to validate
168
     * @param systemID system id of the DTD to use during validation
169
     */
170
    public Validator(Reader readerForValidation, String systemID) {
171
        this(new InputSource(readerForValidation), systemID,
5✔
172
             readerForValidation instanceof DoctypeReader);
173
    }
5✔
174

175
    /**
176
     * Extended constructor.
177
     * Validates the contents of the String using the DTD specified with the
178
     *  systemID. There must be DOCTYPE instruction in the markup that
179
     *  references the DTD or else the markup will be considered invalid: if
180
     *  there is no DOCTYPE in the markup use the 3-argument constructor
181
     *
182
     * @param stringForValidation document to validate
183
     * @param systemID system id of the DTD to use during validation
184
     */
185
    public Validator(String stringForValidation, String systemID) {
186
        this(new StringReader(stringForValidation), systemID);
5✔
187
    }
5✔
188

189
    /**
190
     * Extended constructor.
191
     * Validates the contents of the InputSource using the DTD
192
     * specified with the systemID. There must be DOCTYPE instruction
193
     * in the markup that references the DTD or else the markup will
194
     * be considered invalid: if there is no DOCTYPE in the markup use
195
     * the 3-argument constructor
196
     *
197
     * @param sourceForValidation document to validate
198
     * @param systemID system id of the DTD to use during validation
199
     */
200
    public Validator(InputSource sourceForValidation, String systemID) {
201
        this(sourceForValidation, systemID, false);
5✔
202
    }
5✔
203

204
    /**
205
     * Full constructor.
206
     * Validates the contents of the InputSource using the DTD
207
     * specified with the systemID and named with the doctype name.
208
     *
209
     * @param sourceForValidation document to validate
210
     * @param systemID system id of the DTD to use during validation
211
     * @param doctype overrides the document's doctype
212
     */
213
    public Validator(InputSource sourceForValidation, String systemID,
214
                     String doctype) {
215
        this(sourceForValidation.getCharacterStream() != null
5✔
216
             ? new InputSource(new DoctypeReader(sourceForValidation
2✔
217
                                                 .getCharacterStream(),
4✔
218
                                                 doctype, systemID))
219
             : new InputSource(new DoctypeInputStream(sourceForValidation
2✔
220
                                                      .getByteStream(),
4✔
221
                                                      sourceForValidation
222
                                                      .getEncoding(),
4✔
223
                                                      doctype, systemID)),
224
             systemID, true);
225
    }
5✔
226

227
    /**
228
     * Full constructor.
229
     * Validates the contents of the Reader using the DTD specified with the
230
     *  systemID and named with the doctype name.
231
     *
232
     * @param readerForValidation document to validate
233
     * @param systemID system id of the DTD to use during validation
234
     * @param doctype overrides the document's doctype
235
     */
236
    public Validator(Reader readerForValidation, String systemID,
237
                     String doctype) {
238
        this(readerForValidation instanceof DoctypeReader
5✔
239
             ? readerForValidation
240
             : new DoctypeReader(readerForValidation, doctype, systemID),
2✔
241
             systemID);
242
    }
5✔
243

244
    /**
245
     * Turn on XML Schema validation.
246
     *
247
     * <p><b>This feature should work with any XML parser that is JAXP
248
     * 1.2 compliant and supports XML Schema validation.</b></p>
249
     *
250
     * <p>For a fully JAXP 1.2 compliant parser the property {@link
251
     * JAXPConstants.Properties#SCHEMA_LANGUAGE
252
     * http://java.sun.com/xml/jaxp/properties/schemaLanguage} is set,
253
     * if this fails the method falls back to the features
254
     * http://apache.org/xml/features/validation/schema &amp;
255
     * http://apache.org/xml/features/validation/dynamic which should
256
     * cover early versions of Xerces 2 as well.</p>
257
     *
258
     * @param use indicate that XML Schema should be used to validate
259
     * documents.
260
     * @see #setJAXP12SchemaSource(Object)
261
     */
262
    public void useXMLSchema(boolean use) {
263
        useSchema = use;
5✔
264
    }
5✔
265

266
    /**
267
     * Perform the validation of the source against DTD / Schema.
268
     *
269
     * @return true if the input supplied to the constructor passes validation,
270
     *  false otherwise
271
     */
272
    public boolean isValid() {
273
        validate();
5✔
274
        return isValid.booleanValue();
5✔
275
    }
276

277
    /**
278
     * Assert that a document is valid.
279
     */
280
    public void assertIsValid() {
281
        if (!isValid()){
5✔
282
            junit.framework.Assert.fail(messages.toString());
×
283
        }
284
    }
5✔
285

286
    /**
287
     * Append any validation message(s) to the specified StringBuffer.
288
     *
289
     * @param toAppendTo
290
     * @return specified StringBuffer with message(s) appended
291
     */
292
    private StringBuilder appendMessage(StringBuilder toAppendTo) {
293
        if (isValid()) {
5✔
294
            return toAppendTo.append("[valid]");
5✔
295
        }
296
        return toAppendTo.append(messages);
5✔
297
    }
298

299
    /**
300
     * @return class name appended with validation messages
301
     */
302
    @Override
303
    public String toString() {
304
        StringBuilder builder = new StringBuilder(super.toString()).append(':');
5✔
305
        return appendMessage(builder).toString();
5✔
306
    }
307

308
    /**
309
     * Actually perform validation.
310
     */
311
    private void validate() {
312
        if (isValid != null) {
5✔
313
            return;
5✔
314
        }
315

316
        ParsingValidator v =
5✔
317
            new ParsingValidator(useSchema ? Languages.W3C_XML_SCHEMA_NS_URI
2✔
318
                                 : Languages.XML_DTD_NS_URI);
2✔
319
        List<Source> schemaSourceList = new ArrayList<Source>();
5✔
320
        if (systemId != null) {
5✔
321
            schemaSourceList.add(new StreamSource(systemId));
5✔
322
        }
323
        addSchemaSources(schemaSource, schemaSourceList);
5✔
324
        v.setSchemaSources(schemaSourceList.toArray(new Source[0]));
5✔
325

326
        try {
327
            ValidationResult r =
5✔
328
                v.validateInstance(new SAXSource(validationInputSource));
4✔
329
            isValid = r.isValid() ? Boolean.TRUE : Boolean.FALSE;
5✔
330
            for (ValidationProblem p : r.getProblems()) {
5✔
331
                validationProblem(p);
5✔
332
            }
5✔
333
        } catch (org.xmlunit.ConfigurationException e) {
×
334
            throw new ConfigurationException(e.getCause());
×
335
        } catch (org.xmlunit.XMLUnitException e) {
×
336
            throw new XMLUnitRuntimeException(e.getMessage(), e.getCause());
×
337
        }
5✔
338

339
        if (usingDoctypeReader && isValid == Boolean.FALSE) {
5✔
340
            try {
341
                messages.append("\nContent was: ")
4✔
342
                    .append(getOriginalContent(validationInputSource));
343
            } catch (IOException e) {
5✔
344
                // silent but deadly?
345
            }
×
346
        }
347
    }
5✔
348

349
    private void validationProblem(ValidationProblem p) {
350
        String msg = "At line " + p.getLine() + ", column: "
5✔
351
            + p.getColumn() + " ==> " + p.getMessage();
4✔
352
        if (!msg.endsWith("\n")) {
5✔
353
            msg += "\n";
5✔
354
        }
355
        invalidate(msg);
5✔
356
    }
5✔
357

358
    /**
359
     * Set the validation status flag to false and capture the message for use
360
     * later.
361
     *
362
     * @param message
363
     */
364
    private void invalidate(String message) {
365
        isValid = Boolean.FALSE;
5✔
366
        messages.append(message).append(' ');
5✔
367
    }
5✔
368

369
    /**
370
     * As per JAXP 1.2 changes, which introduced a standard way for parsers to
371
     * support schema validation. Since only W3C Schema support was included in
372
     * JAXP 1.2, this is the only mechanism currently supported by this method.
373
     *
374
     * @param schemaSource
375
     *            This can be one of the following:
376
     * <ul>
377
     *   <li>String that points to the URI of the schema</li>
378
     *   <li>InputStream with the contents of the schema</li>
379
     *   <li>SAX InputSource</li>
380
     *   <li>File</li>
381
     *   <li>an array of Objects with the contents being one of the
382
     *       types defined above. An array of Objects can be used only when
383
     *       the schema language has the ability to assemble a schema at
384
     *       runtime. When an array of Objects is passed it is illegal to
385
     *       have two schemas that share the same namespace.</li>
386
     * </ul>
387
     * @see "http://java.sun.com/webservices/jaxp/change-requests-11.html"
388
     */
389
    public void setJAXP12SchemaSource(Object schemaSource) {
390
        this.schemaSource = schemaSource;
5✔
391
    }
5✔
392

393
    private static void addSchemaSources(Object schemaSources,
394
                                         List<Source> targetList) {
395
        if (schemaSources instanceof String) {
5✔
396
            targetList.add(new StreamSource((String) schemaSources));
5✔
397
        } else if (schemaSources instanceof File) {
5✔
398
            targetList.add(new StreamSource((File) schemaSources));
5✔
399
        } else if (schemaSources instanceof InputStream) {
5✔
400
            targetList.add(new StreamSource((InputStream) schemaSources));
5✔
401
        } else if (schemaSources instanceof InputSource) {
5✔
402
            targetList.add(new SAXSource((InputSource) schemaSources));
5✔
403
        } else if (schemaSources instanceof Object[]) {
5✔
404
            for (Object s : (Object[]) schemaSources) {
5✔
405
                addSchemaSources(s, targetList);
5✔
406
            }
407
        } else if (schemaSources != null) {
5✔
408
            throw new XMLUnitRuntimeException("Unknown schema source type: "
×
409
                                              + schemaSources.getClass());
410
        }
411
    }
5✔
412

413
    private static String getOriginalContent(InputSource s)
414
        throws IOException {
415
        return s.getCharacterStream() instanceof DoctypeReader
4✔
416
            ? ((DoctypeReader) s.getCharacterStream()).getContent()
2✔
417
            : ((DoctypeInputStream) s.getByteStream())
4✔
418
                  .getContent(s.getEncoding());
2✔
419
    }
420
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc