1 16 17 package jaxp; 18 19 import java.io.PrintWriter ; 20 import java.util.Collections ; 21 import java.util.HashMap ; 22 import java.util.HashSet ; 23 import java.util.Iterator ; 24 import java.util.NoSuchElementException ; 25 import java.util.Vector ; 26 27 import javax.xml.XMLConstants ; 28 import javax.xml.namespace.NamespaceContext ; 29 import javax.xml.parsers.DocumentBuilder ; 30 import javax.xml.parsers.DocumentBuilderFactory ; 31 import javax.xml.transform.Source ; 32 import javax.xml.transform.dom.DOMSource ; 33 import javax.xml.validation.Schema ; 34 import javax.xml.validation.SchemaFactory ; 35 import javax.xml.validation.Validator ; 36 import javax.xml.xpath.XPath ; 37 import javax.xml.xpath.XPathConstants ; 38 import javax.xml.xpath.XPathExpression ; 39 import javax.xml.xpath.XPathFactory ; 40 41 import org.w3c.dom.Document ; 42 import org.w3c.dom.NodeList ; 43 import org.xml.sax.ErrorHandler ; 44 import org.xml.sax.SAXException ; 45 import org.xml.sax.SAXNotRecognizedException ; 46 import org.xml.sax.SAXNotSupportedException ; 47 import org.xml.sax.SAXParseException ; 48 49 70 public class InlineSchemaValidator 71 implements ErrorHandler , NamespaceContext { 72 73 77 79 80 protected static final String SCHEMA_FULL_CHECKING_FEATURE_ID = "http://apache.org/xml/features/validation/schema-full-checking"; 81 82 83 protected static final String HONOUR_ALL_SCHEMA_LOCATIONS_ID = "http://apache.org/xml/features/honour-all-schemaLocations"; 84 85 86 protected static final String VALIDATE_ANNOTATIONS_ID = "http://apache.org/xml/features/validate-annotations"; 87 88 89 protected static final String GENERATE_SYNTHETIC_ANNOTATIONS_ID = "http://apache.org/xml/features/generate-synthetic-annotations"; 90 91 93 94 protected static final int DEFAULT_REPETITION = 1; 95 96 97 protected static final boolean DEFAULT_SCHEMA_FULL_CHECKING = false; 98 99 100 protected static final boolean DEFAULT_HONOUR_ALL_SCHEMA_LOCATIONS = false; 101 102 103 protected static final boolean DEFAULT_VALIDATE_ANNOTATIONS = false; 104 105 106 protected static final boolean DEFAULT_GENERATE_SYNTHETIC_ANNOTATIONS = false; 107 108 109 protected static final boolean DEFAULT_MEMORY_USAGE = false; 110 111 115 116 protected PrintWriter fOut = new PrintWriter (System.out); 117 118 119 protected HashMap fPrefixToURIMappings; 120 121 122 protected HashMap fURIToPrefixMappings; 123 124 128 public InlineSchemaValidator(HashMap prefixToURIMappings, HashMap uriToPrefixMappings) { 129 fPrefixToURIMappings = prefixToURIMappings; 130 fURIToPrefixMappings = uriToPrefixMappings; 131 } 133 137 public void validate(Validator validator, 138 Source source, String systemId, 139 int repetitions, boolean memoryUsage) { 140 try { 141 long timeBefore = System.currentTimeMillis(); 142 long memoryBefore = Runtime.getRuntime().freeMemory(); 143 for (int j = 0; j < repetitions; ++j) { 144 validator.validate(source); 145 } 146 long memoryAfter = Runtime.getRuntime().freeMemory(); 147 long timeAfter = System.currentTimeMillis(); 148 149 long time = timeAfter - timeBefore; 150 long memory = memoryUsage 151 ? memoryBefore - memoryAfter : Long.MIN_VALUE; 152 printResults(fOut, systemId, time, memory, repetitions); 153 } 154 catch (SAXParseException e) { 155 } 157 catch (Exception e) { 158 System.err.println("error: Parse error occurred - "+e.getMessage()); 159 Exception se = e; 160 if (e instanceof SAXException ) { 161 se = ((SAXException )e).getException(); 162 } 163 if (se != null) 164 se.printStackTrace(System.err); 165 else 166 e.printStackTrace(System.err); 167 168 } 169 } 171 172 public void printResults(PrintWriter out, String uri, long time, 173 long memory, int repetition) { 174 175 out.print(uri); 177 out.print(": "); 178 if (repetition == 1) { 179 out.print(time); 180 } 181 else { 182 out.print(time); 183 out.print('/'); 184 out.print(repetition); 185 out.print('='); 186 out.print(((float)time)/repetition); 187 } 188 out.print(" ms"); 189 if (memory != Long.MIN_VALUE) { 190 out.print(", "); 191 out.print(memory); 192 out.print(" bytes"); 193 } 194 out.println(); 195 out.flush(); 196 197 } 199 203 204 public void warning(SAXParseException ex) throws SAXException { 205 printError("Warning", ex); 206 } 208 209 public void error(SAXParseException ex) throws SAXException { 210 printError("Error", ex); 211 } 213 214 public void fatalError(SAXParseException ex) throws SAXException { 215 printError("Fatal Error", ex); 216 throw ex; 217 } 219 223 public String getNamespaceURI(String prefix) { 224 if (prefix == null) { 225 throw new IllegalArgumentException ("Prefix cannot be null."); 226 } 227 else if (XMLConstants.XML_NS_PREFIX.equals(prefix)) { 228 return XMLConstants.XML_NS_URI; 229 } 230 else if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) { 231 return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; 232 } 233 else if (fPrefixToURIMappings != null) { 234 String uri = (String ) fPrefixToURIMappings.get(prefix); 235 if (uri != null) { 236 return uri; 237 } 238 } 239 return XMLConstants.NULL_NS_URI; 240 } 242 public String getPrefix(String namespaceURI) { 243 if (namespaceURI == null) { 244 throw new IllegalArgumentException ("Namespace URI cannot be null."); 245 } 246 else if (XMLConstants.XML_NS_URI.equals(namespaceURI)) { 247 return XMLConstants.XML_NS_PREFIX; 248 } 249 else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { 250 return XMLConstants.XMLNS_ATTRIBUTE; 251 } 252 else if (fURIToPrefixMappings != null) { 253 HashSet prefixes = (HashSet ) fURIToPrefixMappings.get(namespaceURI); 254 if (prefixes != null && prefixes.size() > 0) { 255 return (String ) prefixes.iterator().next(); 256 } 257 } 258 return null; 259 } 261 public Iterator getPrefixes(String namespaceURI) { 262 if (namespaceURI == null) { 263 throw new IllegalArgumentException ("Namespace URI cannot be null."); 264 } 265 else if (XMLConstants.XML_NS_URI.equals(namespaceURI)) { 266 return new Iterator () { 267 boolean more = true; 268 public boolean hasNext() { 269 return more; 270 } 271 public Object next() { 272 if (!hasNext()) { 273 throw new NoSuchElementException (); 274 } 275 more = false; 276 return XMLConstants.XML_NS_PREFIX; 277 } 278 public void remove() { 279 throw new UnsupportedOperationException (); 280 } 281 }; 282 } 283 else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { 284 return new Iterator () { 285 boolean more = true; 286 public boolean hasNext() { 287 return more; 288 } 289 public Object next() { 290 if (!hasNext()) { 291 throw new NoSuchElementException (); 292 } 293 more = false; 294 return XMLConstants.XMLNS_ATTRIBUTE; 295 } 296 public void remove() { 297 throw new UnsupportedOperationException (); 298 } 299 }; 300 } 301 else if (fURIToPrefixMappings != null) { 302 HashSet prefixes = (HashSet ) fURIToPrefixMappings.get(namespaceURI); 303 if (prefixes != null && prefixes.size() > 0) { 304 return prefixes.iterator(); 305 } 306 } 307 return Collections.EMPTY_LIST.iterator(); 308 } 310 314 315 protected void printError(String type, SAXParseException ex) { 316 317 System.err.print("["); 318 System.err.print(type); 319 System.err.print("] "); 320 String systemId = ex.getSystemId(); 321 if (systemId != null) { 322 int index = systemId.lastIndexOf('/'); 323 if (index != -1) 324 systemId = systemId.substring(index + 1); 325 System.err.print(systemId); 326 } 327 System.err.print(':'); 328 System.err.print(ex.getLineNumber()); 329 System.err.print(':'); 330 System.err.print(ex.getColumnNumber()); 331 System.err.print(": "); 332 System.err.print(ex.getMessage()); 333 System.err.println(); 334 System.err.flush(); 335 336 } 338 342 343 public static void main (String [] argv) { 344 345 if (argv.length == 0) { 347 printUsage(); 348 System.exit(1); 349 } 350 351 Vector schemas = null; 353 Vector instances = null; 354 HashMap prefixMappings = null; 355 HashMap uriMappings = null; 356 String docURI = argv[argv.length - 1]; 357 int repetition = DEFAULT_REPETITION; 358 boolean schemaFullChecking = DEFAULT_SCHEMA_FULL_CHECKING; 359 boolean honourAllSchemaLocations = DEFAULT_HONOUR_ALL_SCHEMA_LOCATIONS; 360 boolean validateAnnotations = DEFAULT_VALIDATE_ANNOTATIONS; 361 boolean generateSyntheticAnnotations = DEFAULT_GENERATE_SYNTHETIC_ANNOTATIONS; 362 boolean memoryUsage = DEFAULT_MEMORY_USAGE; 363 364 for (int i = 0; i < argv.length - 1; ++i) { 366 String arg = argv[i]; 367 if (arg.startsWith("-")) { 368 String option = arg.substring(1); 369 if (option.equals("x")) { 370 if (++i == argv.length) { 371 System.err.println("error: Missing argument to -x option."); 372 continue; 373 } 374 String number = argv[i]; 375 try { 376 int value = Integer.parseInt(number); 377 if (value < 1) { 378 System.err.println("error: Repetition must be at least 1."); 379 continue; 380 } 381 repetition = value; 382 } 383 catch (NumberFormatException e) { 384 System.err.println("error: invalid number ("+number+")."); 385 } 386 continue; 387 } 388 if (arg.equals("-a")) { 389 if (schemas == null) { 391 schemas = new Vector (); 392 } 393 while (i + 1 < argv.length - 1 && !(arg = argv[i + 1]).startsWith("-")) { 394 schemas.add(arg); 395 ++i; 396 } 397 continue; 398 } 399 if (arg.equals("-i")) { 400 if (instances == null) { 402 instances = new Vector (); 403 } 404 while (i + 1 < argv.length - 1 && !(arg = argv[i + 1]).startsWith("-")) { 405 instances.add(arg); 406 ++i; 407 } 408 continue; 409 } 410 if (arg.equals("-nm")) { 411 String prefix; 412 String uri; 413 while (i + 2 < argv.length - 1 && !(prefix = argv[i + 1]).startsWith("-") && 414 !(uri = argv[i + 2]).startsWith("-")) { 415 if (prefixMappings == null) { 416 prefixMappings = new HashMap (); 417 uriMappings = new HashMap (); 418 } 419 prefixMappings.put(prefix, uri); 420 HashSet prefixes = (HashSet ) uriMappings.get(uri); 421 if (prefixes == null) { 422 prefixes = new HashSet (); 423 uriMappings.put(uri, prefixes); 424 } 425 prefixes.add(prefix); 426 i += 2; 427 } 428 continue; 429 } 430 if (option.equalsIgnoreCase("f")) { 431 schemaFullChecking = option.equals("f"); 432 continue; 433 } 434 if (option.equalsIgnoreCase("hs")) { 435 honourAllSchemaLocations = option.equals("hs"); 436 continue; 437 } 438 if (option.equalsIgnoreCase("va")) { 439 validateAnnotations = option.equals("va"); 440 continue; 441 } 442 if (option.equalsIgnoreCase("ga")) { 443 generateSyntheticAnnotations = option.equals("ga"); 444 continue; 445 } 446 if (option.equalsIgnoreCase("m")) { 447 memoryUsage = option.equals("m"); 448 continue; 449 } 450 if (option.equals("h")) { 451 printUsage(); 452 continue; 453 } 454 System.err.println("error: unknown option ("+option+")."); 455 continue; 456 } 457 } 458 459 try { 460 InlineSchemaValidator inlineSchemaValidator = new InlineSchemaValidator(prefixMappings, uriMappings); 462 463 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 465 dbf.setNamespaceAware(true); 466 DocumentBuilder db = dbf.newDocumentBuilder(); 467 db.setErrorHandler(inlineSchemaValidator); 468 Document doc = db.parse(docURI); 469 470 XPathFactory xpf = XPathFactory.newInstance(); 472 XPath xpath = xpf.newXPath(); 473 xpath.setNamespaceContext(inlineSchemaValidator); 474 475 NodeList [] schemaNodes = new NodeList [schemas != null ? schemas.size() : 0]; 477 for (int i = 0; i < schemaNodes.length; ++i) { 478 XPathExpression xpathSchema = xpath.compile((String )schemas.elementAt(i)); 479 schemaNodes[i] = (NodeList ) xpathSchema.evaluate(doc, XPathConstants.NODESET); 480 } 481 482 NodeList [] instanceNodes = new NodeList [instances != null ? instances.size() : 0]; 484 for (int i = 0; i < instanceNodes.length; ++i) { 485 XPathExpression xpathInstance = xpath.compile((String )instances.elementAt(i)); 486 instanceNodes[i] = (NodeList ) xpathInstance.evaluate(doc, XPathConstants.NODESET); 487 } 488 489 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 491 factory.setErrorHandler(inlineSchemaValidator); 492 493 try { 494 factory.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, schemaFullChecking); 495 } 496 catch (SAXNotRecognizedException e) { 497 System.err.println("warning: SchemaFactory does not recognize feature ("+SCHEMA_FULL_CHECKING_FEATURE_ID+")"); 498 } 499 catch (SAXNotSupportedException e) { 500 System.err.println("warning: SchemaFactory does not support feature ("+SCHEMA_FULL_CHECKING_FEATURE_ID+")"); 501 } 502 try { 503 factory.setFeature(HONOUR_ALL_SCHEMA_LOCATIONS_ID, honourAllSchemaLocations); 504 } 505 catch (SAXNotRecognizedException e) { 506 System.err.println("warning: SchemaFactory does not recognize feature ("+HONOUR_ALL_SCHEMA_LOCATIONS_ID+")"); 507 } 508 catch (SAXNotSupportedException e) { 509 System.err.println("warning: SchemaFactory does not support feature ("+HONOUR_ALL_SCHEMA_LOCATIONS_ID+")"); 510 } 511 try { 512 factory.setFeature(VALIDATE_ANNOTATIONS_ID, validateAnnotations); 513 } 514 catch (SAXNotRecognizedException e) { 515 System.err.println("warning: SchemaFactory does not recognize feature ("+VALIDATE_ANNOTATIONS_ID+")"); 516 } 517 catch (SAXNotSupportedException e) { 518 System.err.println("warning: SchemaFactory does not support feature ("+VALIDATE_ANNOTATIONS_ID+")"); 519 } 520 try { 521 factory.setFeature(GENERATE_SYNTHETIC_ANNOTATIONS_ID, generateSyntheticAnnotations); 522 } 523 catch (SAXNotRecognizedException e) { 524 System.err.println("warning: SchemaFactory does not recognize feature ("+GENERATE_SYNTHETIC_ANNOTATIONS_ID+")"); 525 } 526 catch (SAXNotSupportedException e) { 527 System.err.println("warning: SchemaFactory does not support feature ("+GENERATE_SYNTHETIC_ANNOTATIONS_ID+")"); 528 } 529 530 Schema schema; 532 { 533 DOMSource [] sources; 534 int size = 0; 535 for (int i = 0; i < schemaNodes.length; ++i) { 536 size += schemaNodes[i].getLength(); 537 } 538 sources = new DOMSource [size]; 539 if (size == 0) { 540 schema = factory.newSchema(); 541 } 542 else { 543 int count = 0; 544 for (int i = 0; i < schemaNodes.length; ++i) { 545 NodeList nodeList = schemaNodes[i]; 546 int nodeListLength = nodeList.getLength(); 547 for (int j = 0; j < nodeListLength; ++j) { 548 sources[count++] = new DOMSource (nodeList.item(j)); 549 } 550 } 551 schema = factory.newSchema(sources); 552 } 553 } 554 555 Validator validator = schema.newValidator(); 557 validator.setErrorHandler(inlineSchemaValidator); 558 559 try { 560 validator.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, schemaFullChecking); 561 } 562 catch (SAXNotRecognizedException e) { 563 System.err.println("warning: Validator does not recognize feature ("+SCHEMA_FULL_CHECKING_FEATURE_ID+")"); 564 } 565 catch (SAXNotSupportedException e) { 566 System.err.println("warning: Validator does not support feature ("+SCHEMA_FULL_CHECKING_FEATURE_ID+")"); 567 } 568 try { 569 validator.setFeature(HONOUR_ALL_SCHEMA_LOCATIONS_ID, honourAllSchemaLocations); 570 } 571 catch (SAXNotRecognizedException e) { 572 System.err.println("warning: Validator does not recognize feature ("+HONOUR_ALL_SCHEMA_LOCATIONS_ID+")"); 573 } 574 catch (SAXNotSupportedException e) { 575 System.err.println("warning: Validator does not support feature ("+HONOUR_ALL_SCHEMA_LOCATIONS_ID+")"); 576 } 577 try { 578 validator.setFeature(VALIDATE_ANNOTATIONS_ID, validateAnnotations); 579 } 580 catch (SAXNotRecognizedException e) { 581 System.err.println("warning: Validator does not recognize feature ("+VALIDATE_ANNOTATIONS_ID+")"); 582 } 583 catch (SAXNotSupportedException e) { 584 System.err.println("warning: Validator does not support feature ("+VALIDATE_ANNOTATIONS_ID+")"); 585 } 586 try { 587 validator.setFeature(GENERATE_SYNTHETIC_ANNOTATIONS_ID, generateSyntheticAnnotations); 588 } 589 catch (SAXNotRecognizedException e) { 590 System.err.println("warning: Validator does not recognize feature ("+GENERATE_SYNTHETIC_ANNOTATIONS_ID+")"); 591 } 592 catch (SAXNotSupportedException e) { 593 System.err.println("warning: Validator does not support feature ("+GENERATE_SYNTHETIC_ANNOTATIONS_ID+")"); 594 } 595 596 for (int i = 0; i < instanceNodes.length; ++i) { 598 NodeList nodeList = instanceNodes[i]; 599 int nodeListLength = nodeList.getLength(); 600 for (int j = 0; j < nodeListLength; ++j) { 601 DOMSource source = new DOMSource (nodeList.item(j)); 602 source.setSystemId(docURI); 603 inlineSchemaValidator.validate(validator, source, docURI, repetition, memoryUsage); 604 } 605 } 606 } 607 catch (SAXParseException e) { 608 } 610 catch (Exception e) { 611 System.err.println("error: Parse error occurred - "+e.getMessage()); 612 if (e instanceof SAXException ) { 613 Exception nested = ((SAXException )e).getException(); 614 if (nested != null) { 615 e = nested; 616 } 617 } 618 e.printStackTrace(System.err); 619 } 620 } 622 626 627 private static void printUsage() { 628 629 System.err.println("usage: java jaxp.InlineSchemaValidator (options) uri ..."); 630 System.err.println(); 631 632 System.err.println("options:"); 633 System.err.println(" -x number Select number of repetitions."); 634 System.err.println(" -a xpath ... Provide a list of XPath expressions for schema roots"); 635 System.err.println(" -i xpath ... Provide a list of XPath expressions for validation roots"); 636 System.err.println(" -nm pre uri ... Provide a list of prefix to namespace URI mappings for the XPath expressions."); 637 System.err.println(" -f | -F Turn on/off Schema full checking."); 638 System.err.println(" NOTE: Not supported by all schema factories and validators."); 639 System.err.println(" -hs | -HS Turn on/off honouring of all schema locations."); 640 System.err.println(" NOTE: Not supported by all schema factories and validators."); 641 System.err.println(" -va | -VA Turn on/off validation of schema annotations."); 642 System.err.println(" NOTE: Not supported by all schema factories and validators."); 643 System.err.println(" -ga | -GA Turn on/off generation of synthetic schema annotations."); 644 System.err.println(" NOTE: Not supported by all schema factories and validators."); 645 System.err.println(" -m | -M Turn on/off memory usage report"); 646 System.err.println(" -h This help screen."); 647 648 System.err.println(); 649 System.err.println("defaults:"); 650 System.err.println(" Repetition: " + DEFAULT_REPETITION); 651 System.err.print(" Schema full checking: "); 652 System.err.println(DEFAULT_SCHEMA_FULL_CHECKING ? "on" : "off"); 653 System.err.print(" Honour all schema locations: "); 654 System.err.println(DEFAULT_HONOUR_ALL_SCHEMA_LOCATIONS ? "on" : "off"); 655 System.err.print(" Validate annotations: "); 656 System.err.println(DEFAULT_VALIDATE_ANNOTATIONS ? "on" : "off"); 657 System.err.print(" Generate synthetic annotations: "); 658 System.err.println(DEFAULT_GENERATE_SYNTHETIC_ANNOTATIONS ? "on" : "off"); 659 System.err.print(" Memory: "); 660 System.err.println(DEFAULT_MEMORY_USAGE ? "on" : "off"); 661 662 System.err.println(); 663 System.err.println("notes:"); 664 System.err.println(" The speed and memory results from this program should NOT be used as the"); 665 System.err.println(" basis of parser performance comparison! Real analytical methods should be"); 666 System.err.println(" used. For better results, perform multiple document validations within the"); 667 System.err.println(" same virtual machine to remove class loading from parse time and memory usage."); 668 669 } 671 } | Popular Tags |