1 /* 2 * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.xml.validation; 27 28 import java.io.IOException; 29 30 import javax.xml.transform.Result; 31 import javax.xml.transform.Source; 32 33 import org.w3c.dom.ls.LSResourceResolver; 34 import org.xml.sax.ErrorHandler; 35 import org.xml.sax.SAXException; 36 import org.xml.sax.SAXNotRecognizedException; 37 import org.xml.sax.SAXNotSupportedException; 38 39 /** 40 * A processor that checks an XML document against {@link Schema}. 41 * 42 * <p> 43 * A validator object is not thread-safe and not reentrant. 44 * In other words, it is the application's responsibility to make 45 * sure that one {@link Validator} object is not used from 46 * more than one thread at any given time, and while the {@code validate} 47 * method is invoked, applications may not recursively call 48 * the {@code validate} method. 49 * 50 * 51 * @author <a href="mailto:Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a> 52 * @since 1.5 53 */ 54 public abstract class Validator { 55 56 /** 57 * Constructor for derived classes. 58 * 59 * <p>The constructor does nothing. 60 * 61 * <p>Derived classes must create {@link Validator} objects that have 62 * {@code null} {@link ErrorHandler} and 63 * {@code null} {@link LSResourceResolver}. 64 */ 65 protected Validator() { 66 } 67 68 /** 69 * Reset this {@code Validator} to its original configuration. 70 * 71 * <p>{@code Validator} is reset to the same state as when it was created with 72 * {@link Schema#newValidator()}. 73 * {@code reset()} is designed to allow the reuse of existing {@code Validator}s 74 * thus saving resources associated with the creation of new {@code Validator}s. 75 * 76 * <p>The reset {@code Validator} is not guaranteed to have 77 * the same {@link LSResourceResolver} or {@link ErrorHandler} 78 * {@code Object}s, e.g. {@link Object#equals(Object obj)}. 79 * It is guaranteed to have a functionally equal 80 * {@code LSResourceResolver} and {@code ErrorHandler}. 81 */ 82 public abstract void reset(); 83 84 /** 85 * Validates the specified input. 86 * 87 * <p>This is just a convenience method for 88 * {@link #validate(Source source, Result result)} 89 * with {@code result} of {@code null}. 90 * 91 * @param source 92 * XML to be validated. Must be an XML document or 93 * XML element and must not be null. For backwards compatibility, 94 * the results of attempting to validate anything other than 95 * a document or element are implementation-dependent. 96 * Implementations must either recognize and process the input 97 * or throw an IllegalArgumentException. 98 * 99 * @throws IllegalArgumentException 100 * If the {@code Source} 101 * is an XML artifact that the implementation cannot 102 * validate (for example, a processing instruction). 103 * 104 * @throws SAXException 105 * If the {@link ErrorHandler} throws a {@link SAXException} or 106 * if a fatal error is found and the {@link ErrorHandler} returns 107 * normally. 108 * 109 * @throws IOException 110 * If the validator is processing a 111 * {@link javax.xml.transform.sax.SAXSource} and the 112 * underlying {@link org.xml.sax.XMLReader} throws an 113 * {@link IOException}. 114 * 115 * 116 * @throws NullPointerException If {@code source} is 117 * {@code null}. 118 * 119 * @see #validate(Source source, Result result) 120 */ 121 public void validate(Source source) 122 throws SAXException, IOException { 123 124 validate(source, null); 125 } 126 127 /** 128 * Validates the specified input and send the augmented validation 129 * result to the specified output. 130 * 131 * <p>This method places the following restrictions on the types of 132 * the {@link Source}/{@link Result} accepted. 133 * 134 * <table class="plain"> 135 * <caption>{@code Source} / {@code Result} Accepted</caption> 136 * <thead> 137 * <tr> 138 * <th></th> 139 * <th scope="col">{@link javax.xml.transform.stream.StreamSource}</th> 140 * <th scope="col">{@link javax.xml.transform.sax.SAXSource}</th> 141 * <th scope="col">{@link javax.xml.transform.dom.DOMSource}</th> 142 * <th scope="col">{@link javax.xml.transform.stax.StAXSource}</th> 143 * </tr> 144 * </thead> 145 * <tbody style="text-align:center"> 146 * <tr> 147 * <th scope="row">{@code null}</th> 148 * <td>OK</td> 149 * <td>OK</td> 150 * <td>OK</td> 151 * <td>OK</td> 152 * </tr> 153 * <tr> 154 * <th scope="row">{@link javax.xml.transform.stream.StreamResult}</th> 155 * <td>OK</td> 156 * <td>{@code IllegalArgumentException}</td> 157 * <td>{@code IllegalArgumentException}</td> 158 * <td>{@code IllegalArgumentException}</td> 159 * </tr> 160 * <tr> 161 * <th scope="row">{@link javax.xml.transform.sax.SAXResult}</th> 162 * <td>{@code IllegalArgumentException}</td> 163 * <td>OK</td> 164 * <td>{@code IllegalArgumentException}</td> 165 * <td>{@code IllegalArgumentException}</td> 166 * </tr> 167 * <tr> 168 * <th scope="row">{@link javax.xml.transform.dom.DOMResult}</th> 169 * <td>{@code IllegalArgumentException}</td> 170 * <td>{@code IllegalArgumentException}</td> 171 * <td>OK</td> 172 * <td>{@code IllegalArgumentException}</td> 173 * </tr> 174 * <tr> 175 * <th scope="row">{@link javax.xml.transform.stax.StAXResult}</th> 176 * <td>{@code IllegalArgumentException}</td> 177 * <td>{@code IllegalArgumentException}</td> 178 * <td>{@code IllegalArgumentException}</td> 179 * <td>OK</td> 180 * </tr> 181 * </tbody> 182 * </table> 183 * 184 * <p>To validate one {@code Source} into another kind of 185 * {@code Result}, use the identity transformer (see 186 * {@link javax.xml.transform.TransformerFactory#newTransformer()}). 187 * 188 * <p>Errors found during the validation is sent to the specified 189 * {@link ErrorHandler}. 190 * 191 * <p>If a document is valid, or if a document contains some errors 192 * but none of them were fatal and the {@code ErrorHandler} didn't 193 * throw any exception, then the method returns normally. 194 * 195 * @param source 196 * XML to be validated. Must be an XML document or 197 * XML element and must not be null. For backwards compatibility, 198 * the results of attempting to validate anything other than 199 * a document or element are implementation-dependent. 200 * Implementations must either recognize and process the input 201 * or throw an IllegalArgumentException. 202 * 203 * @param result 204 * The {@code Result} object that receives (possibly augmented) 205 * XML. This parameter can be null if the caller is not interested 206 * in it. 207 * 208 * Note that when a {@code DOMResult} is used, 209 * a validator might just pass the same DOM node from 210 * {@code DOMSource} to {@code DOMResult} 211 * (in which case {@code source.getNode()==result.getNode()}), 212 * it might copy the entire DOM tree, or it might alter the 213 * node given by the source. 214 * 215 * @throws IllegalArgumentException 216 * If the {@code Result} type doesn't match the 217 * {@code Source} type of if the {@code Source} 218 * is an XML artifact that the implementation cannot 219 * validate (for example, a processing instruction). 220 * @throws SAXException 221 * If the {@code ErrorHandler} throws a 222 * {@code SAXException} or 223 * if a fatal error is found and the {@code ErrorHandler} returns 224 * normally. 225 * @throws IOException 226 * If the validator is processing a 227 * {@code SAXSource} and the 228 * underlying {@link org.xml.sax.XMLReader} throws an 229 * {@code IOException}. 230 * @throws NullPointerException 231 * If the {@code source} parameter is {@code null}. 232 * 233 * @see #validate(Source source) 234 */ 235 public abstract void validate(Source source, Result result) 236 throws SAXException, IOException; 237 238 /** 239 * Sets the {@link ErrorHandler} to receive errors encountered 240 * during the {@code validate} method invocation. 241 * 242 * <p> 243 * Error handler can be used to customize the error handling process 244 * during a validation. When an {@link ErrorHandler} is set, 245 * errors found during the validation will be first sent 246 * to the {@link ErrorHandler}. 247 * 248 * <p> 249 * The error handler can abort further validation immediately 250 * by throwing {@link SAXException} from the handler. Or for example 251 * it can print an error to the screen and try to continue the 252 * validation by returning normally from the {@link ErrorHandler} 253 * 254 * <p> 255 * If any {@link Throwable} is thrown from an {@link ErrorHandler}, 256 * the caller of the {@code validate} method will be thrown 257 * the same {@link Throwable} object. 258 * 259 * <p> 260 * {@link Validator} is not allowed to 261 * throw {@link SAXException} without first reporting it to 262 * {@link ErrorHandler}. 263 * 264 * <p> 265 * When the {@link ErrorHandler} is null, the implementation will 266 * behave as if the following {@link ErrorHandler} is set: 267 * <pre> 268 * class DraconianErrorHandler implements {@link ErrorHandler} { 269 * public void fatalError( {@link org.xml.sax.SAXParseException} e ) throws {@link SAXException} { 270 * throw e; 271 * } 272 * public void error( {@link org.xml.sax.SAXParseException} e ) throws {@link SAXException} { 273 * throw e; 274 * } 275 * public void warning( {@link org.xml.sax.SAXParseException} e ) throws {@link SAXException} { 276 * // noop 277 * } 278 * } 279 * </pre> 280 * 281 * <p> 282 * When a new {@link Validator} object is created, initially 283 * this field is set to null. 284 * 285 * @param errorHandler 286 * A new error handler to be set. This parameter can be null. 287 */ 288 public abstract void setErrorHandler(ErrorHandler errorHandler); 289 290 /** 291 * Gets the current {@link ErrorHandler} set to this {@link Validator}. 292 * 293 * @return 294 * This method returns the object that was last set through 295 * the {@link #setErrorHandler(ErrorHandler)} method, or null 296 * if that method has never been called since this {@link Validator} 297 * has created. 298 * 299 * @see #setErrorHandler(ErrorHandler) 300 */ 301 public abstract ErrorHandler getErrorHandler(); 302 303 /** 304 * Sets the {@link LSResourceResolver} to customize 305 * resource resolution while in a validation episode. 306 * 307 * <p> 308 * {@link Validator} uses a {@link LSResourceResolver} 309 * when it needs to locate external resources while a validation, 310 * although exactly what constitutes "locating external resources" is 311 * up to each schema language. 312 * 313 * <p> 314 * When the {@link LSResourceResolver} is null, the implementation will 315 * behave as if the following {@link LSResourceResolver} is set: 316 * <pre> 317 * class DumbLSResourceResolver implements {@link LSResourceResolver} { 318 * public {@link org.w3c.dom.ls.LSInput} resolveResource( 319 * String publicId, String systemId, String baseURI) { 320 * 321 * return null; // always return null 322 * } 323 * } 324 * </pre> 325 * 326 * <p> 327 * If a {@link LSResourceResolver} throws a {@link RuntimeException} 328 * (or instances of its derived classes), 329 * then the {@link Validator} will abort the parsing and 330 * the caller of the {@code validate} method will receive 331 * the same {@link RuntimeException}. 332 * 333 * <p> 334 * When a new {@link Validator} object is created, initially 335 * this field is set to null. 336 * 337 * @param resourceResolver 338 * A new resource resolver to be set. This parameter can be null. 339 */ 340 public abstract void setResourceResolver(LSResourceResolver resourceResolver); 341 342 /** 343 * Gets the current {@link LSResourceResolver} set to this {@link Validator}. 344 * 345 * @return 346 * This method returns the object that was last set through 347 * the {@link #setResourceResolver(LSResourceResolver)} method, or null 348 * if that method has never been called since this {@link Validator} 349 * has created. 350 * 351 * @see #setErrorHandler(ErrorHandler) 352 */ 353 public abstract LSResourceResolver getResourceResolver(); 354 355 356 357 /** 358 * Look up the value of a feature flag. 359 * 360 * <p>The feature name is any fully-qualified URI. It is 361 * possible for a {@link Validator} to recognize a feature name but 362 * temporarily be unable to return its value. 363 * Some feature values may be available only in specific 364 * contexts, such as before, during, or after a validation. 365 * 366 * <p>Implementors are free (and encouraged) to invent their own features, 367 * using names built on their own URIs. 368 * 369 * @param name The feature name, which is a non-null fully-qualified URI. 370 * 371 * @return The current value of the feature (true or false). 372 * 373 * @throws SAXNotRecognizedException If the feature 374 * value can't be assigned or retrieved. 375 * @throws SAXNotSupportedException When the 376 * {@link Validator} recognizes the feature name but 377 * cannot determine its value at this time. 378 * @throws NullPointerException 379 * When the name parameter is null. 380 * 381 * @see #setFeature(String, boolean) 382 */ 383 public boolean getFeature(String name) 384 throws SAXNotRecognizedException, SAXNotSupportedException { 385 386 if (name == null) { 387 throw new NullPointerException("the name parameter is null"); 388 } 389 390 throw new SAXNotRecognizedException(name); 391 } 392 393 /** 394 * Set the value of a feature flag. 395 * 396 * <p> 397 * Feature can be used to control the way a {@link Validator} 398 * parses schemas, although {@link Validator}s are not required 399 * to recognize any specific feature names. 400 * 401 * <p>The feature name is any fully-qualified URI. It is 402 * possible for a {@link Validator} to expose a feature value but 403 * to be unable to change the current value. 404 * Some feature values may be immutable or mutable only 405 * in specific contexts, such as before, during, or after 406 * a validation. 407 * 408 * @param name The feature name, which is a non-null fully-qualified URI. 409 * @param value The requested value of the feature (true or false). 410 * 411 * @throws SAXNotRecognizedException If the feature 412 * value can't be assigned or retrieved. 413 * @throws SAXNotSupportedException When the 414 * {@link Validator} recognizes the feature name but 415 * cannot set the requested value. 416 * @throws NullPointerException 417 * When the name parameter is null. 418 * 419 * @see #getFeature(String) 420 */ 421 public void setFeature(String name, boolean value) 422 throws SAXNotRecognizedException, SAXNotSupportedException { 423 424 if (name == null) { 425 throw new NullPointerException("the name parameter is null"); 426 } 427 428 throw new SAXNotRecognizedException(name); 429 } 430 431 /** 432 * Set the value of a property. 433 * 434 * <p>The property name is any fully-qualified URI. It is 435 * possible for a {@link Validator} to recognize a property name but 436 * to be unable to change the current value. 437 * Some property values may be immutable or mutable only 438 * in specific contexts, such as before, during, or after 439 * a validation. 440 * 441 * <p> 442 * All implementations that implement JAXP 1.5 or newer are required to 443 * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} and 444 * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} properties. 445 * 446 * <ul> 447 * <li> 448 * <p>Access to external DTDs in source or Schema file is restricted to 449 * the protocols specified by the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} 450 * property. If access is denied during validation due to the restriction 451 * of this property, {@link org.xml.sax.SAXException} will be thrown by the 452 * {@link #validate(Source)} method. 453 * 454 * <p>Access to external reference set by the schemaLocation attribute is 455 * restricted to the protocols specified by the 456 * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} property. 457 * If access is denied during validation due to the restriction of this property, 458 * {@link org.xml.sax.SAXException} will be thrown by the 459 * {@link #validate(Source)} method. 460 * </li> 461 * </ul> 462 * 463 * @param name The property name, which is a non-null fully-qualified URI. 464 * @param object The requested value for the property. 465 * 466 * @throws SAXNotRecognizedException If the property 467 * value can't be assigned or retrieved. 468 * @throws SAXNotSupportedException When the 469 * {@link Validator} recognizes the property name but 470 * cannot set the requested value. 471 * @throws NullPointerException 472 * When the name parameter is null. 473 */ 474 public void setProperty(String name, Object object) 475 throws SAXNotRecognizedException, SAXNotSupportedException { 476 477 if (name == null) { 478 throw new NullPointerException("the name parameter is null"); 479 } 480 481 throw new SAXNotRecognizedException(name); 482 } 483 484 /** 485 * Look up the value of a property. 486 * 487 * <p>The property name is any fully-qualified URI. It is 488 * possible for a {@link Validator} to recognize a property name but 489 * temporarily be unable to return its value. 490 * Some property values may be available only in specific 491 * contexts, such as before, during, or after a validation. 492 * 493 * <p>{@link Validator}s are not required to recognize any specific 494 * property names. 495 * 496 * <p>Implementors are free (and encouraged) to invent their own properties, 497 * using names built on their own URIs. 498 * 499 * @param name The property name, which is a non-null fully-qualified URI. 500 * 501 * @return The current value of the property. 502 * 503 * @throws SAXNotRecognizedException If the property 504 * value can't be assigned or retrieved. 505 * @throws SAXNotSupportedException When the 506 * XMLReader recognizes the property name but 507 * cannot determine its value at this time. 508 * @throws NullPointerException 509 * When the name parameter is null. 510 * 511 * @see #setProperty(String, Object) 512 */ 513 public Object getProperty(String name) 514 throws SAXNotRecognizedException, SAXNotSupportedException { 515 516 if (name == null) { 517 throw new NullPointerException("the name parameter is null"); 518 } 519 520 throw new SAXNotRecognizedException(name); 521 } 522 }