1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xerces.internal.impl.xs; 22 23 import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl; 24 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter; 25 import com.sun.org.apache.xerces.internal.dom.DOMStringListImpl; 26 import com.sun.org.apache.xerces.internal.impl.Constants; 27 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; 28 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; 29 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; 30 import com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory; 31 import com.sun.org.apache.xerces.internal.impl.dv.xs.SchemaDVFactoryImpl; 32 import com.sun.org.apache.xerces.internal.impl.xs.models.CMBuilder; 33 import com.sun.org.apache.xerces.internal.impl.xs.models.CMNodeFactory; 34 import com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler; 35 import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper; 36 import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper; 37 import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler; 38 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; 39 import com.sun.org.apache.xerces.internal.util.Status; 40 import com.sun.org.apache.xerces.internal.util.SymbolTable; 41 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 42 import com.sun.org.apache.xerces.internal.utils.SecuritySupport; 43 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; 44 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; 45 import com.sun.org.apache.xerces.internal.xni.XNIException; 46 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; 47 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; 48 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarLoader; 49 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; 50 import com.sun.org.apache.xerces.internal.xni.grammars.XSGrammar; 51 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent; 52 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; 53 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 54 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; 55 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; 56 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 57 import com.sun.org.apache.xerces.internal.xs.LSInputList; 58 import com.sun.org.apache.xerces.internal.xs.StringList; 59 import com.sun.org.apache.xerces.internal.xs.XSLoader; 60 import com.sun.org.apache.xerces.internal.xs.XSModel; 61 import java.io.BufferedInputStream; 62 import java.io.File; 63 import java.io.FileInputStream; 64 import java.io.FileNotFoundException; 65 import java.io.IOException; 66 import java.io.InputStream; 67 import java.io.Reader; 68 import java.io.StringReader; 69 import java.util.HashMap; 70 import java.util.Locale; 71 import java.util.Map; 72 import java.util.StringTokenizer; 73 import java.util.Vector; 74 import javax.xml.XMLConstants; 75 import jdk.xml.internal.JdkXmlUtils; 76 import org.w3c.dom.DOMConfiguration; 77 import org.w3c.dom.DOMError; 78 import org.w3c.dom.DOMErrorHandler; 79 import org.w3c.dom.DOMException; 80 import org.w3c.dom.DOMStringList; 81 import org.w3c.dom.ls.LSInput; 82 import org.w3c.dom.ls.LSResourceResolver; 83 import org.xml.sax.InputSource; 84 85 /** 86 * This class implements xni.grammars.XMLGrammarLoader. 87 * It also serves as implementation of xs.XSLoader interface and DOMConfiguration interface. 88 * 89 * This class is designed to interact either with a proxy for a user application 90 * which wants to preparse schemas, or with our own Schema validator. 91 * It is hoped that none of these "external" classes will therefore need to communicate directly 92 * with XSDHandler in future. 93 * <p>This class only knows how to make XSDHandler do its thing. 94 * The caller must ensure that all its properties (schemaLocation, JAXPSchemaSource 95 * etc.) have been properly set. 96 * 97 * @xerces.internal 98 * 99 * @author Neil Graham, IBM 100 */ 101 102 public class XMLSchemaLoader implements XMLGrammarLoader, XMLComponent, 103 // XML Component API 104 XSLoader, DOMConfiguration { 105 106 // Feature identifiers: 107 108 /** Feature identifier: schema full checking*/ 109 protected static final String SCHEMA_FULL_CHECKING = 110 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING; 111 112 /** Feature identifier: continue after fatal error. */ 113 protected static final String CONTINUE_AFTER_FATAL_ERROR = 114 Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE; 115 116 /** Feature identifier: allow java encodings to be recognized when parsing schema docs. */ 117 protected static final String ALLOW_JAVA_ENCODINGS = 118 Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE; 119 120 /** Feature identifier: standard uri conformant feature. */ 121 protected static final String STANDARD_URI_CONFORMANT_FEATURE = 122 Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE; 123 124 /** Feature identifier: validate annotations. */ 125 protected static final String VALIDATE_ANNOTATIONS = 126 Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE; 127 128 /** Feature: disallow doctype*/ 129 protected static final String DISALLOW_DOCTYPE = 130 Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE; 131 132 /** Feature: generate synthetic annotations */ 133 protected static final String GENERATE_SYNTHETIC_ANNOTATIONS = 134 Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE; 135 136 /** Feature identifier: honour all schemaLocations */ 137 protected static final String HONOUR_ALL_SCHEMALOCATIONS = 138 Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE; 139 140 protected static final String AUGMENT_PSVI = 141 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI; 142 143 protected static final String PARSER_SETTINGS = 144 Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS; 145 146 /** Feature identifier: namespace growth */ 147 protected static final String NAMESPACE_GROWTH = 148 Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE; 149 150 /** Feature identifier: tolerate duplicates */ 151 protected static final String TOLERATE_DUPLICATES = 152 Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE; 153 154 /** Property identifier: Schema DV Factory */ 155 protected static final String SCHEMA_DV_FACTORY = 156 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; 157 158 protected static final String OVERRIDE_PARSER = JdkXmlUtils.OVERRIDE_PARSER; 159 160 // recognized features: 161 private static final String[] RECOGNIZED_FEATURES = { 162 SCHEMA_FULL_CHECKING, 163 AUGMENT_PSVI, 164 CONTINUE_AFTER_FATAL_ERROR, 165 ALLOW_JAVA_ENCODINGS, 166 STANDARD_URI_CONFORMANT_FEATURE, 167 DISALLOW_DOCTYPE, 168 GENERATE_SYNTHETIC_ANNOTATIONS, 169 VALIDATE_ANNOTATIONS, 170 HONOUR_ALL_SCHEMALOCATIONS, 171 NAMESPACE_GROWTH, 172 TOLERATE_DUPLICATES, 173 OVERRIDE_PARSER 174 }; 175 176 // property identifiers 177 178 /** Property identifier: symbol table. */ 179 public static final String SYMBOL_TABLE = 180 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 181 182 /** Property identifier: error reporter. */ 183 public static final String ERROR_REPORTER = 184 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; 185 186 /** Property identifier: error handler. */ 187 protected static final String ERROR_HANDLER = 188 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; 189 190 /** Property identifier: entity resolver. */ 191 public static final String ENTITY_RESOLVER = 192 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; 193 194 /** Property identifier: grammar pool. */ 195 public static final String XMLGRAMMAR_POOL = 196 Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; 197 198 /** Property identifier: schema location. */ 199 protected static final String SCHEMA_LOCATION = 200 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION; 201 202 /** Property identifier: no namespace schema location. */ 203 protected static final String SCHEMA_NONS_LOCATION = 204 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION; 205 206 /** Property identifier: JAXP schema source. */ 207 protected static final String JAXP_SCHEMA_SOURCE = 208 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE; 209 210 protected static final String SECURITY_MANAGER = 211 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; 212 213 /** Property identifier: locale. */ 214 protected static final String LOCALE = 215 Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; 216 217 protected static final String ENTITY_MANAGER = 218 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; 219 220 /** Property identifier: Security property manager. */ 221 private static final String XML_SECURITY_PROPERTY_MANAGER = 222 Constants.XML_SECURITY_PROPERTY_MANAGER; 223 224 /** Property identifier: access to external dtd */ 225 public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; 226 227 /** Property identifier: access to external schema */ 228 public static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; 229 230 // recognized properties 231 private static final String [] RECOGNIZED_PROPERTIES = { 232 ENTITY_MANAGER, 233 SYMBOL_TABLE, 234 ERROR_REPORTER, 235 ERROR_HANDLER, 236 ENTITY_RESOLVER, 237 XMLGRAMMAR_POOL, 238 SCHEMA_LOCATION, 239 SCHEMA_NONS_LOCATION, 240 JAXP_SCHEMA_SOURCE, 241 SECURITY_MANAGER, 242 LOCALE, 243 SCHEMA_DV_FACTORY, 244 XML_SECURITY_PROPERTY_MANAGER 245 }; 246 247 // Data 248 249 // features and properties 250 private ParserConfigurationSettings fLoaderConfig = new ParserConfigurationSettings(); 251 private SymbolTable fSymbolTable = null; 252 private XMLErrorReporter fErrorReporter = new XMLErrorReporter (); 253 private XMLEntityManager fEntityManager = null; 254 private XMLEntityResolver fUserEntityResolver = null; 255 private XMLGrammarPool fGrammarPool = null; 256 private String fExternalSchemas = null; 257 private String fExternalNoNSSchema = null; 258 // JAXP property: schema source 259 private Object fJAXPSource = null; 260 // is Schema Full Checking enabled 261 private boolean fIsCheckedFully = false; 262 // boolean that tells whether we've tested the JAXP property. 263 private boolean fJAXPProcessed = false; 264 // if features/properties has not been changed, the value of this attribute is "false" 265 private boolean fSettingsChanged = true; 266 267 // xml schema parsing 268 private XSDHandler fSchemaHandler; 269 private XSGrammarBucket fGrammarBucket; 270 private XSDeclarationPool fDeclPool = null; 271 private SubstitutionGroupHandler fSubGroupHandler; 272 private final CMNodeFactory fNodeFactory = new CMNodeFactory(); //component mgr will be set later 273 private CMBuilder fCMBuilder; 274 private XSDDescription fXSDDescription = new XSDDescription(); 275 private String faccessExternalSchema = Constants.EXTERNAL_ACCESS_DEFAULT; 276 277 private Map fJAXPCache; 278 private Locale fLocale = Locale.getDefault(); 279 280 // XSLoader attributes 281 private DOMStringList fRecognizedParameters = null; 282 283 /** DOM L3 error handler */ 284 private DOMErrorHandlerWrapper fErrorHandler = null; 285 286 /** DOM L3 resource resolver */ 287 private DOMEntityResolverWrapper fResourceResolver = null; 288 289 // default constructor. Create objects we absolutely need: 290 public XMLSchemaLoader() { 291 this( new SymbolTable(), null, new XMLEntityManager(), null, null, null); 292 } 293 294 public XMLSchemaLoader(SymbolTable symbolTable) { 295 this( symbolTable, null, new XMLEntityManager(), null, null, null); 296 } 297 298 /** 299 * This constractor is used by the XMLSchemaValidator. Additional properties, i.e. XMLEntityManager, 300 * will be passed during reset(XMLComponentManager). 301 * @param errorReporter 302 * @param grammarBucket 303 * @param sHandler 304 * @param builder 305 */ 306 XMLSchemaLoader(XMLErrorReporter errorReporter, XSGrammarBucket grammarBucket, 307 SubstitutionGroupHandler sHandler, CMBuilder builder) { 308 this(null, errorReporter, null, grammarBucket, sHandler, builder); 309 } 310 311 XMLSchemaLoader(SymbolTable symbolTable, XMLErrorReporter errorReporter, 312 XMLEntityManager entityResolver, XSGrammarBucket grammarBucket, 313 SubstitutionGroupHandler sHandler, CMBuilder builder) { 314 315 // store properties and features in configuration 316 fLoaderConfig.addRecognizedFeatures(RECOGNIZED_FEATURES); 317 fLoaderConfig.addRecognizedProperties(RECOGNIZED_PROPERTIES); 318 if (symbolTable != null){ 319 fLoaderConfig.setProperty(SYMBOL_TABLE, symbolTable); 320 } 321 322 if(errorReporter == null) { 323 errorReporter = new XMLErrorReporter (); 324 errorReporter.setLocale(fLocale); 325 errorReporter.setProperty(ERROR_HANDLER, new DefaultErrorHandler()); 326 327 } 328 fErrorReporter = errorReporter; 329 // make sure error reporter knows about schemas... 330 if(fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) { 331 fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter()); 332 } 333 fLoaderConfig.setProperty(ERROR_REPORTER, fErrorReporter); 334 fEntityManager = entityResolver; 335 // entity manager is null if XMLSchemaValidator creates the loader 336 if (fEntityManager != null){ 337 fLoaderConfig.setProperty(ENTITY_MANAGER, fEntityManager); 338 } 339 340 // by default augment PSVI (i.e. don't use declaration pool) 341 fLoaderConfig.setFeature(AUGMENT_PSVI, true); 342 343 if(grammarBucket == null ) { 344 grammarBucket = new XSGrammarBucket(); 345 } 346 fGrammarBucket = grammarBucket; 347 if(sHandler == null) { 348 sHandler = new SubstitutionGroupHandler(fGrammarBucket); 349 } 350 fSubGroupHandler = sHandler; 351 352 if(builder == null) { 353 builder = new CMBuilder(fNodeFactory); 354 } 355 fCMBuilder = builder; 356 fSchemaHandler = new XSDHandler(fGrammarBucket); 357 if (fDeclPool != null) { 358 fDeclPool.reset(); 359 } 360 fJAXPCache = new HashMap(); 361 362 fSettingsChanged = true; 363 } 364 365 /** 366 * Returns a list of feature identifiers that are recognized by 367 * this XMLGrammarLoader. This method may return null if no features 368 * are recognized. 369 */ 370 public String[] getRecognizedFeatures() { 371 return (String[])(RECOGNIZED_FEATURES.clone()); 372 } // getRecognizedFeatures(): String[] 373 374 /** 375 * Returns the state of a feature. 376 * 377 * @param featureId The feature identifier. 378 * 379 * @throws XMLConfigurationException Thrown on configuration error. 380 */ 381 public boolean getFeature(String featureId) 382 throws XMLConfigurationException { 383 return fLoaderConfig.getFeature(featureId); 384 } // getFeature (String): boolean 385 386 /** 387 * Sets the state of a feature. 388 * 389 * @param featureId The feature identifier. 390 * @param state The state of the feature. 391 * 392 * @throws XMLConfigurationException Thrown when a feature is not 393 * recognized or cannot be set. 394 */ 395 public void setFeature(String featureId, 396 boolean state) throws XMLConfigurationException { 397 fSettingsChanged = true; 398 if(featureId.equals(CONTINUE_AFTER_FATAL_ERROR)) { 399 fErrorReporter.setFeature(CONTINUE_AFTER_FATAL_ERROR, state); 400 } 401 else if(featureId.equals(GENERATE_SYNTHETIC_ANNOTATIONS)) { 402 fSchemaHandler.setGenerateSyntheticAnnotations(state); 403 } 404 fLoaderConfig.setFeature(featureId, state); 405 } // setFeature(String, boolean) 406 407 /** 408 * Returns a list of property identifiers that are recognized by 409 * this XMLGrammarLoader. This method may return null if no properties 410 * are recognized. 411 */ 412 public String[] getRecognizedProperties() { 413 return (String[])(RECOGNIZED_PROPERTIES.clone()); 414 } // getRecognizedProperties(): String[] 415 416 /** 417 * Returns the state of a property. 418 * 419 * @param propertyId The property identifier. 420 * 421 * @throws XMLConfigurationException Thrown on configuration error. 422 */ 423 public Object getProperty(String propertyId) 424 throws XMLConfigurationException { 425 return fLoaderConfig.getProperty(propertyId); 426 } // getProperty(String): Object 427 428 /** 429 * Sets the state of a property. 430 * 431 * @param propertyId The property identifier. 432 * @param state The state of the property. 433 * 434 * @throws XMLConfigurationException Thrown when a property is not 435 * recognized or cannot be set. 436 */ 437 public void setProperty(String propertyId, 438 Object state) throws XMLConfigurationException { 439 fSettingsChanged = true; 440 fLoaderConfig.setProperty(propertyId, state); 441 if (propertyId.equals(JAXP_SCHEMA_SOURCE)) { 442 fJAXPSource = state; 443 fJAXPProcessed = false; 444 } 445 else if (propertyId.equals(XMLGRAMMAR_POOL)) { 446 fGrammarPool = (XMLGrammarPool)state; 447 } 448 else if (propertyId.equals(SCHEMA_LOCATION)) { 449 fExternalSchemas = (String)state; 450 } 451 else if (propertyId.equals(SCHEMA_NONS_LOCATION)) { 452 fExternalNoNSSchema = (String) state; 453 } 454 else if (propertyId.equals(LOCALE)) { 455 setLocale((Locale) state); 456 } 457 else if (propertyId.equals(ENTITY_RESOLVER)) { 458 fEntityManager.setProperty(ENTITY_RESOLVER, state); 459 } 460 else if (propertyId.equals(ERROR_REPORTER)) { 461 fErrorReporter = (XMLErrorReporter)state; 462 if (fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) { 463 fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter()); 464 } 465 } 466 else if (propertyId.equals(XML_SECURITY_PROPERTY_MANAGER)) { 467 XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)state; 468 faccessExternalSchema = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA); 469 } 470 } // setProperty(String, Object) 471 472 /** 473 * Set the locale to use for messages. 474 * 475 * @param locale The locale object to use for localization of messages. 476 * 477 * @exception XNIException Thrown if the parser does not support the 478 * specified locale. 479 */ 480 public void setLocale(Locale locale) { 481 fLocale = locale; 482 fErrorReporter.setLocale(locale); 483 } // setLocale(Locale) 484 485 /** Return the Locale the XMLGrammarLoader is using. */ 486 public Locale getLocale() { 487 return fLocale; 488 } // getLocale(): Locale 489 490 /** 491 * Sets the error handler. 492 * 493 * @param errorHandler The error handler. 494 */ 495 public void setErrorHandler(XMLErrorHandler errorHandler) { 496 fErrorReporter.setProperty(ERROR_HANDLER, errorHandler); 497 } // setErrorHandler(XMLErrorHandler) 498 499 /** Returns the registered error handler. */ 500 public XMLErrorHandler getErrorHandler() { 501 return fErrorReporter.getErrorHandler(); 502 } // getErrorHandler(): XMLErrorHandler 503 504 /** 505 * Sets the entity resolver. 506 * 507 * @param entityResolver The new entity resolver. 508 */ 509 public void setEntityResolver(XMLEntityResolver entityResolver) { 510 fUserEntityResolver = entityResolver; 511 fLoaderConfig.setProperty(ENTITY_RESOLVER, entityResolver); 512 fEntityManager.setProperty(ENTITY_RESOLVER, entityResolver); 513 } // setEntityResolver(XMLEntityResolver) 514 515 /** Returns the registered entity resolver. */ 516 public XMLEntityResolver getEntityResolver() { 517 return fUserEntityResolver; 518 } // getEntityResolver(): XMLEntityResolver 519 520 /** 521 * Returns a Grammar object by parsing the contents of the 522 * entities pointed to by sources. 523 * 524 * @param source[] the locations of the entity which forms 525 * the staring point of the grammars to be constructed 526 * @throws IOException when a problem is encounted reading the entity 527 * @throws XNIException when a condition arises (such as a FatalError) that requires parsing 528 * of the entity be terminated 529 */ 530 public void loadGrammar(XMLInputSource source[]) 531 throws IOException, XNIException { 532 int numSource = source.length; 533 for (int i = 0; i < numSource; ++i) { 534 loadGrammar(source[i]); 535 } 536 } 537 538 /** 539 * Returns a Grammar object by parsing the contents of the 540 * entity pointed to by source. 541 * 542 * @param source the location of the entity which forms 543 * the starting point of the grammar to be constructed. 544 * @throws IOException When a problem is encountered reading the entity 545 * XNIException When a condition arises (such as a FatalError) that requires parsing 546 * of the entity be terminated. 547 */ 548 public Grammar loadGrammar(XMLInputSource source) 549 throws IOException, XNIException { 550 551 // REVISIT: this method should have a namespace parameter specified by 552 // user. In this case we can easily detect if a schema asked to be loaded 553 // is already in the local cache. 554 555 reset(fLoaderConfig); 556 fSettingsChanged = false; 557 XSDDescription desc = new XSDDescription(); 558 desc.fContextType = XSDDescription.CONTEXT_PREPARSE; 559 desc.setBaseSystemId(source.getBaseSystemId()); 560 desc.setLiteralSystemId( source.getSystemId()); 561 // none of the other fields make sense for preparsing 562 Map locationPairs = new HashMap(); 563 // Process external schema location properties. 564 // We don't call tokenizeSchemaLocationStr here, because we also want 565 // to check whether the values are valid URI. 566 processExternalHints(fExternalSchemas, fExternalNoNSSchema, 567 locationPairs, fErrorReporter); 568 SchemaGrammar grammar = loadSchema(desc, source, locationPairs); 569 570 if(grammar != null && fGrammarPool != null) { 571 fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_SCHEMA, fGrammarBucket.getGrammars()); 572 // NOTE: we only need to verify full checking in case the schema was not provided via JAXP 573 // since full checking already verified for all JAXP schemas 574 if(fIsCheckedFully && fJAXPCache.get(grammar) != grammar) { 575 XSConstraints.fullSchemaChecking(fGrammarBucket, fSubGroupHandler, fCMBuilder, fErrorReporter); 576 } 577 } 578 return grammar; 579 } // loadGrammar(XMLInputSource): Grammar 580 581 /** 582 * This method is called either from XMLGrammarLoader.loadGrammar or from XMLSchemaValidator. 583 * Note: in either case, the EntityManager (or EntityResolvers) are not going to be invoked 584 * to resolve the location of the schema in XSDDescription 585 * @param desc 586 * @param source 587 * @param locationPairs 588 * @return An XML Schema grammar 589 * @throws IOException 590 * @throws XNIException 591 */ 592 SchemaGrammar loadSchema(XSDDescription desc, XMLInputSource source, 593 Map<String, LocationArray> locationPairs) throws IOException, XNIException { 594 595 // this should only be done once per invocation of this object; 596 // unless application alters JAXPSource in the mean time. 597 if(!fJAXPProcessed) { 598 processJAXPSchemaSource(locationPairs); 599 } 600 601 if (desc.isExternal()) { 602 String accessError = SecuritySupport.checkAccess(desc.getExpandedSystemId(), faccessExternalSchema, Constants.ACCESS_EXTERNAL_ALL); 603 if (accessError != null) { 604 throw new XNIException(fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN, 605 "schema_reference.access", 606 new Object[] { SecuritySupport.sanitizePath(desc.getExpandedSystemId()), accessError }, XMLErrorReporter.SEVERITY_ERROR)); 607 } 608 } 609 SchemaGrammar grammar = fSchemaHandler.parseSchema(source, desc, locationPairs); 610 611 return grammar; 612 } // loadSchema(XSDDescription, XMLInputSource): SchemaGrammar 613 614 /** This method tries to resolve location of the given schema. 615 * The loader stores the namespace/location pairs in a map (use "" as the 616 * namespace of absent namespace). When resolving an entity, loader first tries 617 * to find in the map whether there is a value for that namespace, 618 * if so, pass that location value to the user-defined entity resolver. 619 * 620 * @param desc 621 * @param locationPairs 622 * @param entityResolver 623 * @return 624 * @throws IOException 625 */ 626 public static XMLInputSource resolveDocument(XSDDescription desc, 627 Map<String, LocationArray> locationPairs, 628 XMLEntityResolver entityResolver) throws IOException { 629 String loc = null; 630 // we consider the schema location properties for import 631 if (desc.getContextType() == XSDDescription.CONTEXT_IMPORT || 632 desc.fromInstance()) { 633 // use empty string as the key for absent namespace 634 String namespace = desc.getTargetNamespace(); 635 String ns = namespace == null ? XMLSymbols.EMPTY_STRING : namespace; 636 // get the location hint for that namespace 637 LocationArray tempLA = locationPairs.get(ns); 638 if(tempLA != null) 639 loc = tempLA.getFirstLocation(); 640 } 641 642 // if it's not import, or if the target namespace is not set 643 // in the schema location properties, use location hint 644 if (loc == null) { 645 String[] hints = desc.getLocationHints(); 646 if (hints != null && hints.length > 0) 647 loc = hints[0]; 648 } 649 650 String expandedLoc = XMLEntityManager.expandSystemId(loc, desc.getBaseSystemId(), false); 651 desc.setLiteralSystemId(loc); 652 desc.setExpandedSystemId(expandedLoc); 653 return entityResolver.resolveEntity(desc); 654 } 655 656 // add external schema locations to the location pairs 657 public static void processExternalHints(String sl, String nsl, 658 Map<String, XMLSchemaLoader.LocationArray> locations, 659 XMLErrorReporter er) { 660 if (sl != null) { 661 try { 662 // get the attribute decl for xsi:schemaLocation 663 // because external schema location property has the same syntax 664 // as xsi:schemaLocation 665 XSAttributeDecl attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_SCHEMALOCATION); 666 // validation the string value to get the list of URI's 667 attrDecl.fType.validate(sl, null, null); 668 if (!tokenizeSchemaLocationStr(sl, locations)) { 669 // report warning (odd number of items) 670 er.reportError(XSMessageFormatter.SCHEMA_DOMAIN, 671 "SchemaLocation", 672 new Object[]{sl}, 673 XMLErrorReporter.SEVERITY_WARNING); 674 } 675 } 676 catch (InvalidDatatypeValueException ex) { 677 // report warning (not list of URI's) 678 er.reportError(XSMessageFormatter.SCHEMA_DOMAIN, 679 ex.getKey(), ex.getArgs(), 680 XMLErrorReporter.SEVERITY_WARNING); 681 } 682 } 683 684 if (nsl != null) { 685 try { 686 // similarly for no ns schema location property 687 XSAttributeDecl attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION); 688 attrDecl.fType.validate(nsl, null, null); 689 LocationArray la = ((LocationArray)locations.get(XMLSymbols.EMPTY_STRING)); 690 if(la == null) { 691 la = new LocationArray(); 692 locations.put(XMLSymbols.EMPTY_STRING, la); 693 } 694 la.addLocation(nsl); 695 } 696 catch (InvalidDatatypeValueException ex) { 697 // report warning (not a URI) 698 er.reportError(XSMessageFormatter.SCHEMA_DOMAIN, 699 ex.getKey(), ex.getArgs(), 700 XMLErrorReporter.SEVERITY_WARNING); 701 } 702 } 703 } 704 // this method takes a SchemaLocation string. 705 // If an error is encountered, false is returned; 706 // otherwise, true is returned. In either case, locations 707 // is augmented to include as many tokens as possible. 708 // @param schemaStr The schemaLocation string to tokenize 709 // @param locations HashMap mapping namespaces to LocationArray objects holding lists of locaitons 710 // @return true if no problems; false if string could not be tokenized 711 public static boolean tokenizeSchemaLocationStr(String schemaStr, 712 Map<String, XMLSchemaLoader.LocationArray> locations) { 713 if (schemaStr!= null) { 714 StringTokenizer t = new StringTokenizer(schemaStr, " \n\t\r"); 715 String namespace, location; 716 while (t.hasMoreTokens()) { 717 namespace = t.nextToken (); 718 if (!t.hasMoreTokens()) { 719 return false; // error! 720 } 721 location = t.nextToken(); 722 LocationArray la = locations.get(namespace); 723 if(la == null) { 724 la = new LocationArray(); 725 locations.put(namespace, la); 726 } 727 la.addLocation(location); 728 } 729 } 730 return true; 731 } // tokenizeSchemaLocation(String, HashMap): boolean 732 733 /** 734 * Translate the various JAXP SchemaSource property types to XNI 735 * XMLInputSource. Valid types are: String, org.xml.sax.InputSource, 736 * InputStream, File, or Object[] of any of previous types. 737 * REVISIT: the JAXP 1.2 spec is less than clear as to whether this property 738 * should be available to imported schemas. I have assumed 739 * that it should. - NG 740 * Note: all JAXP schema files will be checked for full-schema validity if the feature was set up 741 * 742 */ 743 private void processJAXPSchemaSource( 744 Map<String, LocationArray> locationPairs) throws IOException { 745 fJAXPProcessed = true; 746 if (fJAXPSource == null) { 747 return; 748 } 749 750 Class componentType = fJAXPSource.getClass().getComponentType(); 751 XMLInputSource xis = null; 752 String sid = null; 753 if (componentType == null) { 754 // Not an array 755 if(fJAXPSource instanceof InputStream || 756 fJAXPSource instanceof InputSource) { 757 SchemaGrammar g = (SchemaGrammar)fJAXPCache.get(fJAXPSource); 758 if(g != null) { 759 fGrammarBucket.putGrammar(g); 760 return; 761 } 762 } 763 fXSDDescription.reset(); 764 xis = xsdToXMLInputSource(fJAXPSource); 765 sid = xis.getSystemId(); 766 fXSDDescription.fContextType = XSDDescription.CONTEXT_PREPARSE; 767 if (sid != null) { 768 fXSDDescription.setBaseSystemId(xis.getBaseSystemId()); 769 fXSDDescription.setLiteralSystemId(sid); 770 fXSDDescription.setExpandedSystemId(sid); 771 fXSDDescription.fLocationHints = new String[]{sid}; 772 } 773 SchemaGrammar g = loadSchema(fXSDDescription, xis, locationPairs); 774 // it is possible that we won't be able to resolve JAXP schema-source location 775 if (g != null){ 776 if(fJAXPSource instanceof InputStream || 777 fJAXPSource instanceof InputSource) { 778 fJAXPCache.put(fJAXPSource, g); 779 if(fIsCheckedFully) { 780 XSConstraints.fullSchemaChecking(fGrammarBucket, fSubGroupHandler, fCMBuilder, fErrorReporter); 781 } 782 } 783 fGrammarBucket.putGrammar(g); 784 } 785 return ; 786 } else if ( (componentType != Object.class) && 787 (componentType != String.class) && 788 (componentType != File.class) && 789 (componentType != InputStream.class) && 790 (componentType != InputSource.class) 791 ) { 792 // Not an Object[], String[], File[], InputStream[], InputSource[] 793 throw new XMLConfigurationException( 794 Status.NOT_SUPPORTED, "\""+JAXP_SCHEMA_SOURCE+ 795 "\" property cannot have an array of type {"+componentType.getName()+ 796 "}. Possible types of the array supported are Object, String, File, "+ 797 "InputStream, InputSource."); 798 } 799 800 // JAXP spec. allow []s of type String, File, InputStream, 801 // InputSource also, apart from [] of type Object. 802 Object[] objArr = (Object[]) fJAXPSource; 803 //make local vector for storing targetn namespaces of schemasources specified in object arrays. 804 Vector jaxpSchemaSourceNamespaces = new Vector() ; 805 for (int i = 0; i < objArr.length; i++) { 806 if(objArr[i] instanceof InputStream || 807 objArr[i] instanceof InputSource) { 808 SchemaGrammar g = (SchemaGrammar)fJAXPCache.get(objArr[i]); 809 if (g != null) { 810 fGrammarBucket.putGrammar(g); 811 continue; 812 } 813 } 814 fXSDDescription.reset(); 815 xis = xsdToXMLInputSource(objArr[i]); 816 sid = xis.getSystemId(); 817 fXSDDescription.fContextType = XSDDescription.CONTEXT_PREPARSE; 818 if (sid != null) { 819 fXSDDescription.setBaseSystemId(xis.getBaseSystemId()); 820 fXSDDescription.setLiteralSystemId(sid); 821 fXSDDescription.setExpandedSystemId(sid); 822 fXSDDescription.fLocationHints = new String[]{sid}; 823 } 824 String targetNamespace = null ; 825 // load schema 826 SchemaGrammar grammar = fSchemaHandler.parseSchema(xis,fXSDDescription, locationPairs); 827 828 if(fIsCheckedFully) { 829 XSConstraints.fullSchemaChecking(fGrammarBucket, fSubGroupHandler, fCMBuilder, fErrorReporter); 830 } 831 if(grammar != null){ 832 targetNamespace = grammar.getTargetNamespace() ; 833 if(jaxpSchemaSourceNamespaces.contains(targetNamespace)){ 834 //when an array of objects is passed it is illegal to have two schemas that share same namespace. 835 throw new java.lang.IllegalArgumentException( 836 " When using array of Objects as the value of SCHEMA_SOURCE property , " + 837 "no two Schemas should share the same targetNamespace. " ); 838 } 839 else{ 840 jaxpSchemaSourceNamespaces.add(targetNamespace) ; 841 } 842 if(objArr[i] instanceof InputStream || 843 objArr[i] instanceof InputSource) { 844 fJAXPCache.put(objArr[i], grammar); 845 } 846 fGrammarBucket.putGrammar(grammar); 847 } 848 else{ 849 //REVISIT: What should be the acutal behavior if grammar can't be loaded as specified in schema source? 850 } 851 } 852 }//processJAXPSchemaSource 853 854 private XMLInputSource xsdToXMLInputSource( 855 Object val) 856 { 857 if (val instanceof String) { 858 // String value is treated as a URI that is passed through the 859 // EntityResolver 860 String loc = (String) val; 861 fXSDDescription.reset(); 862 fXSDDescription.setValues(null, loc, null, null); 863 XMLInputSource xis = null; 864 try { 865 xis = fEntityManager.resolveEntity(fXSDDescription); 866 } catch (IOException ex) { 867 fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN, 868 "schema_reference.4", 869 new Object[] { loc }, XMLErrorReporter.SEVERITY_ERROR); 870 } 871 if (xis == null) { 872 // REVISIT: can this happen? 873 // Treat value as a URI and pass in as systemId 874 return new XMLInputSource(null, loc, null); 875 } 876 return xis; 877 } else if (val instanceof InputSource) { 878 return saxToXMLInputSource((InputSource) val); 879 } else if (val instanceof InputStream) { 880 return new XMLInputSource(null, null, null, 881 (InputStream) val, null); 882 } else if (val instanceof File) { 883 File file = (File) val; 884 InputStream is = null; 885 try { 886 is = new BufferedInputStream(new FileInputStream(file)); 887 } catch (FileNotFoundException ex) { 888 fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN, 889 "schema_reference.4", new Object[] { file.toString() }, 890 XMLErrorReporter.SEVERITY_ERROR); 891 } 892 return new XMLInputSource(null, null, null, is, null); 893 } 894 throw new XMLConfigurationException( 895 Status.NOT_SUPPORTED, "\""+JAXP_SCHEMA_SOURCE+ 896 "\" property cannot have a value of type {"+val.getClass().getName()+ 897 "}. Possible types of the value supported are String, File, InputStream, "+ 898 "InputSource OR an array of these types."); 899 } 900 901 902 //Convert a SAX InputSource to an equivalent XNI XMLInputSource 903 904 private static XMLInputSource saxToXMLInputSource(InputSource sis) { 905 String publicId = sis.getPublicId(); 906 String systemId = sis.getSystemId(); 907 908 Reader charStream = sis.getCharacterStream(); 909 if (charStream != null) { 910 return new XMLInputSource(publicId, systemId, null, charStream, 911 null); 912 } 913 914 InputStream byteStream = sis.getByteStream(); 915 if (byteStream != null) { 916 return new XMLInputSource(publicId, systemId, null, byteStream, 917 sis.getEncoding()); 918 } 919 920 return new XMLInputSource(publicId, systemId, null); 921 } 922 923 public static class LocationArray{ 924 925 int length ; 926 String [] locations = new String[2]; 927 928 public void resize(int oldLength , int newLength){ 929 String [] temp = new String[newLength] ; 930 System.arraycopy(locations, 0, temp, 0, Math.min(oldLength, newLength)); 931 locations = temp ; 932 length = Math.min(oldLength, newLength); 933 } 934 935 public void addLocation(String location){ 936 if(length >= locations.length ){ 937 resize(length, Math.max(1, length*2)); 938 } 939 locations[length++] = location; 940 }//setLocation() 941 942 public String [] getLocationArray(){ 943 if(length < locations.length ){ 944 resize(locations.length, length); 945 } 946 return locations; 947 }//getLocationArray() 948 949 public String getFirstLocation(){ 950 return length > 0 ? locations[0] : null; 951 } 952 953 public int getLength(){ 954 return length ; 955 } 956 957 } //locationArray 958 959 /* (non-Javadoc) 960 * @see com.sun.org.apache.xerces.internal.xni.parser.XMLComponent#getFeatureDefault(java.lang.String) 961 */ 962 public Boolean getFeatureDefault(String featureId) { 963 if (featureId.equals(AUGMENT_PSVI)){ 964 return Boolean.TRUE; 965 } 966 return null; 967 } 968 969 /* (non-Javadoc) 970 * @see com.sun.org.apache.xerces.internal.xni.parser.XMLComponent#getPropertyDefault(java.lang.String) 971 */ 972 public Object getPropertyDefault(String propertyId) { 973 // TODO Auto-generated method stub 974 return null; 975 } 976 977 /* (non-Javadoc) 978 * @see com.sun.org.apache.xerces.internal.xni.parser.XMLComponent#reset(com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager) 979 */ 980 public void reset(XMLComponentManager componentManager) throws XMLConfigurationException { 981 982 XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER); 983 if (spm == null) { 984 spm = new XMLSecurityPropertyManager(); 985 setProperty(XML_SECURITY_PROPERTY_MANAGER, spm); 986 } 987 988 XMLSecurityManager sm = (XMLSecurityManager)componentManager.getProperty(SECURITY_MANAGER); 989 if (sm == null) 990 setProperty(SECURITY_MANAGER,new XMLSecurityManager(true)); 991 992 faccessExternalSchema = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA); 993 994 fGrammarBucket.reset(); 995 996 fSubGroupHandler.reset(); 997 998 boolean parser_settings = componentManager.getFeature(PARSER_SETTINGS, true); 999 1000 if (!parser_settings || !fSettingsChanged){ 1001 // need to reprocess JAXP schema sources 1002 fJAXPProcessed = false; 1003 // reinitialize grammar bucket 1004 initGrammarBucket(); 1005 return; 1006 } 1007 1008 //pass the component manager to the factory.. 1009 fNodeFactory.reset(componentManager); 1010 1011 // get registered entity manager to be able to resolve JAXP schema-source property: 1012 // Note: in case XMLSchemaValidator has created the loader, 1013 // the entity manager property is null 1014 fEntityManager = (XMLEntityManager)componentManager.getProperty(ENTITY_MANAGER); 1015 1016 // get the error reporter 1017 fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER); 1018 1019 // Determine schema dv factory to use 1020 SchemaDVFactory dvFactory = null; 1021 dvFactory = fSchemaHandler.getDVFactory(); 1022 if (dvFactory == null) { 1023 dvFactory = SchemaDVFactory.getInstance(); 1024 fSchemaHandler.setDVFactory(dvFactory); 1025 } 1026 1027 boolean psvi = componentManager.getFeature(AUGMENT_PSVI, false); 1028 1029 if (!psvi) { 1030 if (fDeclPool != null) { 1031 fDeclPool.reset(); 1032 } 1033 else { 1034 fDeclPool = new XSDeclarationPool(); 1035 } 1036 fCMBuilder.setDeclPool(fDeclPool); 1037 fSchemaHandler.setDeclPool(fDeclPool); 1038 if (dvFactory instanceof SchemaDVFactoryImpl) { 1039 fDeclPool.setDVFactory((SchemaDVFactoryImpl)dvFactory); 1040 ((SchemaDVFactoryImpl)dvFactory).setDeclPool(fDeclPool); 1041 } 1042 } else { 1043 fCMBuilder.setDeclPool(null); 1044 fSchemaHandler.setDeclPool(null); 1045 } 1046 1047 // get schema location properties 1048 try { 1049 fExternalSchemas = (String) componentManager.getProperty(SCHEMA_LOCATION); 1050 fExternalNoNSSchema = (String) componentManager.getProperty(SCHEMA_NONS_LOCATION); 1051 } catch (XMLConfigurationException e) { 1052 fExternalSchemas = null; 1053 fExternalNoNSSchema = null; 1054 } 1055 1056 // get JAXP sources if available 1057 fJAXPSource = componentManager.getProperty(JAXP_SCHEMA_SOURCE, null); 1058 fJAXPProcessed = false; 1059 1060 // clear grammars, and put the one for schema namespace there 1061 fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL, null); 1062 initGrammarBucket(); 1063 // get continue-after-fatal-error feature 1064 try { 1065 boolean fatalError = componentManager.getFeature(CONTINUE_AFTER_FATAL_ERROR, false); 1066 if (!fatalError) { 1067 fErrorReporter.setFeature(CONTINUE_AFTER_FATAL_ERROR, fatalError); 1068 } 1069 } catch (XMLConfigurationException e) { 1070 } 1071 // set full validation to false 1072 fIsCheckedFully = componentManager.getFeature(SCHEMA_FULL_CHECKING, false); 1073 1074 // get generate-synthetic-annotations feature 1075 fSchemaHandler.setGenerateSyntheticAnnotations(componentManager.getFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false)); 1076 fSchemaHandler.reset(componentManager); 1077 } 1078 1079 private void initGrammarBucket(){ 1080 if(fGrammarPool != null) { 1081 Grammar [] initialGrammars = fGrammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA); 1082 for (int i = 0; i < initialGrammars.length; i++) { 1083 // put this grammar into the bucket, along with grammars 1084 // imported by it (directly or indirectly) 1085 if (!fGrammarBucket.putGrammar((SchemaGrammar)(initialGrammars[i]), true)) { 1086 // REVISIT: a conflict between new grammar(s) and grammars 1087 // in the bucket. What to do? A warning? An exception? 1088 fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN, 1089 "GrammarConflict", null, 1090 XMLErrorReporter.SEVERITY_WARNING); 1091 } 1092 } 1093 } 1094 } 1095 1096 1097 /* (non-Javadoc) 1098 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#getConfig() 1099 */ 1100 public DOMConfiguration getConfig() { 1101 return this; 1102 } 1103 1104 /* (non-Javadoc) 1105 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#load(org.w3c.dom.ls.LSInput) 1106 */ 1107 public XSModel load(LSInput is) { 1108 try { 1109 Grammar g = loadGrammar(dom2xmlInputSource(is)); 1110 return ((XSGrammar) g).toXSModel(); 1111 } catch (Exception e) { 1112 reportDOMFatalError(e); 1113 return null; 1114 } 1115 } 1116 1117 /* (non-Javadoc) 1118 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#loadInputList(com.sun.org.apache.xerces.internal.xs.DOMInputList) 1119 */ 1120 public XSModel loadInputList(LSInputList is) { 1121 int length = is.getLength(); 1122 SchemaGrammar[] gs = new SchemaGrammar[length]; 1123 for (int i = 0; i < length; i++) { 1124 try { 1125 gs[i] = (SchemaGrammar) loadGrammar(dom2xmlInputSource(is.item(i))); 1126 } catch (Exception e) { 1127 reportDOMFatalError(e); 1128 return null; 1129 } 1130 } 1131 return new XSModelImpl(gs); 1132 } 1133 1134 /* (non-Javadoc) 1135 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#loadURI(java.lang.String) 1136 */ 1137 public XSModel loadURI(String uri) { 1138 try { 1139 Grammar g = loadGrammar(new XMLInputSource(null, uri, null)); 1140 return ((XSGrammar)g).toXSModel(); 1141 } 1142 catch (Exception e){ 1143 reportDOMFatalError(e); 1144 return null; 1145 } 1146 } 1147 1148 /* (non-Javadoc) 1149 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#loadURIList(com.sun.org.apache.xerces.internal.xs.StringList) 1150 */ 1151 public XSModel loadURIList(StringList uriList) { 1152 int length = uriList.getLength(); 1153 SchemaGrammar[] gs = new SchemaGrammar[length]; 1154 for (int i = 0; i < length; i++) { 1155 try { 1156 gs[i] = 1157 (SchemaGrammar) loadGrammar(new XMLInputSource(null, uriList.item(i), null)); 1158 } catch (Exception e) { 1159 reportDOMFatalError(e); 1160 return null; 1161 } 1162 } 1163 return new XSModelImpl(gs); 1164 } 1165 1166 void reportDOMFatalError(Exception e) { 1167 if (fErrorHandler != null) { 1168 DOMErrorImpl error = new DOMErrorImpl(); 1169 error.fException = e; 1170 error.fMessage = e.getMessage(); 1171 error.fSeverity = DOMError.SEVERITY_FATAL_ERROR; 1172 fErrorHandler.getErrorHandler().handleError(error); 1173 } 1174 } 1175 1176 /* (non-Javadoc) 1177 * @see DOMConfiguration#canSetParameter(String, Object) 1178 */ 1179 public boolean canSetParameter(String name, Object value) { 1180 if(value instanceof Boolean){ 1181 if (name.equals(Constants.DOM_VALIDATE) || 1182 name.equals(SCHEMA_FULL_CHECKING) || 1183 name.equals(VALIDATE_ANNOTATIONS) || 1184 name.equals(CONTINUE_AFTER_FATAL_ERROR) || 1185 name.equals(ALLOW_JAVA_ENCODINGS) || 1186 name.equals(STANDARD_URI_CONFORMANT_FEATURE) || 1187 name.equals(GENERATE_SYNTHETIC_ANNOTATIONS) || 1188 name.equals(HONOUR_ALL_SCHEMALOCATIONS) || 1189 name.equals(NAMESPACE_GROWTH) || 1190 name.equals(TOLERATE_DUPLICATES) || 1191 name.equals(OVERRIDE_PARSER)) { 1192 return true; 1193 1194 } 1195 return false; 1196 } 1197 if (name.equals(Constants.DOM_ERROR_HANDLER) || 1198 name.equals(Constants.DOM_RESOURCE_RESOLVER) || 1199 name.equals(SYMBOL_TABLE) || 1200 name.equals(ERROR_REPORTER) || 1201 name.equals(ERROR_HANDLER) || 1202 name.equals(ENTITY_RESOLVER) || 1203 name.equals(XMLGRAMMAR_POOL) || 1204 name.equals(SCHEMA_LOCATION) || 1205 name.equals(SCHEMA_NONS_LOCATION) || 1206 name.equals(JAXP_SCHEMA_SOURCE) || 1207 name.equals(SCHEMA_DV_FACTORY)) { 1208 return true; 1209 } 1210 return false; 1211 } 1212 1213 /* (non-Javadoc) 1214 * @see DOMConfiguration#getParameter(String) 1215 */ 1216 public Object getParameter(String name) throws DOMException { 1217 1218 if (name.equals(Constants.DOM_ERROR_HANDLER)){ 1219 return (fErrorHandler != null) ? fErrorHandler.getErrorHandler() : null; 1220 } 1221 else if (name.equals(Constants.DOM_RESOURCE_RESOLVER)) { 1222 return (fResourceResolver != null) ? fResourceResolver.getEntityResolver() : null; 1223 } 1224 1225 try { 1226 boolean feature = getFeature(name); 1227 return (feature) ? Boolean.TRUE : Boolean.FALSE; 1228 } catch (Exception e) { 1229 Object property; 1230 try { 1231 property = getProperty(name); 1232 return property; 1233 } catch (Exception ex) { 1234 String msg = 1235 DOMMessageFormatter.formatMessage( 1236 DOMMessageFormatter.DOM_DOMAIN, 1237 "FEATURE_NOT_SUPPORTED", 1238 new Object[] { name }); 1239 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); 1240 } 1241 } 1242 } 1243 1244 /* (non-Javadoc) 1245 * @see DOMConfiguration#getParameterNames() 1246 */ 1247 public DOMStringList getParameterNames() { 1248 if (fRecognizedParameters == null){ 1249 Vector v = new Vector(); 1250 v.add(Constants.DOM_VALIDATE); 1251 v.add(Constants.DOM_ERROR_HANDLER); 1252 v.add(Constants.DOM_RESOURCE_RESOLVER); 1253 v.add(SYMBOL_TABLE); 1254 v.add(ERROR_REPORTER); 1255 v.add(ERROR_HANDLER); 1256 v.add(ENTITY_RESOLVER); 1257 v.add(XMLGRAMMAR_POOL); 1258 v.add(SCHEMA_LOCATION); 1259 v.add(SCHEMA_NONS_LOCATION); 1260 v.add(JAXP_SCHEMA_SOURCE); 1261 v.add(SCHEMA_FULL_CHECKING); 1262 v.add(CONTINUE_AFTER_FATAL_ERROR); 1263 v.add(ALLOW_JAVA_ENCODINGS); 1264 v.add(STANDARD_URI_CONFORMANT_FEATURE); 1265 v.add(VALIDATE_ANNOTATIONS); 1266 v.add(GENERATE_SYNTHETIC_ANNOTATIONS); 1267 v.add(HONOUR_ALL_SCHEMALOCATIONS); 1268 v.add(NAMESPACE_GROWTH); 1269 v.add(TOLERATE_DUPLICATES); 1270 v.add(OVERRIDE_PARSER); 1271 fRecognizedParameters = new DOMStringListImpl(v); 1272 } 1273 return fRecognizedParameters; 1274 } 1275 1276 /* (non-Javadoc) 1277 * @see DOMConfiguration#setParameter(String, Object) 1278 */ 1279 public void setParameter(String name, Object value) throws DOMException { 1280 if (value instanceof Boolean) { 1281 boolean state = ((Boolean) value).booleanValue(); 1282 if (name.equals("validate") && state) { 1283 return; 1284 } 1285 try { 1286 setFeature(name, state); 1287 } catch (Exception e) { 1288 String msg = 1289 DOMMessageFormatter.formatMessage( 1290 DOMMessageFormatter.DOM_DOMAIN, 1291 "FEATURE_NOT_SUPPORTED", 1292 new Object[] { name }); 1293 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); 1294 } 1295 return; 1296 } 1297 if (name.equals(Constants.DOM_ERROR_HANDLER)) { 1298 if (value instanceof DOMErrorHandler) { 1299 try { 1300 fErrorHandler = new DOMErrorHandlerWrapper((DOMErrorHandler) value); 1301 setErrorHandler(fErrorHandler); 1302 } catch (XMLConfigurationException e) { 1303 } 1304 } else { 1305 // REVISIT: type mismatch 1306 String msg = 1307 DOMMessageFormatter.formatMessage( 1308 DOMMessageFormatter.DOM_DOMAIN, 1309 "FEATURE_NOT_SUPPORTED", 1310 new Object[] { name }); 1311 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); 1312 } 1313 return; 1314 1315 } 1316 if (name.equals(Constants.DOM_RESOURCE_RESOLVER)) { 1317 if (value instanceof LSResourceResolver) { 1318 try { 1319 fResourceResolver = new DOMEntityResolverWrapper((LSResourceResolver) value); 1320 setEntityResolver(fResourceResolver); 1321 } 1322 catch (XMLConfigurationException e) {} 1323 } else { 1324 // REVISIT: type mismatch 1325 String msg = 1326 DOMMessageFormatter.formatMessage( 1327 DOMMessageFormatter.DOM_DOMAIN, 1328 "FEATURE_NOT_SUPPORTED", 1329 new Object[] { name }); 1330 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); 1331 } 1332 return; 1333 } 1334 1335 try { 1336 setProperty(name, value); 1337 } catch (Exception ex) { 1338 1339 String msg = 1340 DOMMessageFormatter.formatMessage( 1341 DOMMessageFormatter.DOM_DOMAIN, 1342 "FEATURE_NOT_SUPPORTED", 1343 new Object[] { name }); 1344 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); 1345 1346 } 1347 1348 } 1349 1350 XMLInputSource dom2xmlInputSource(LSInput is) { 1351 // need to wrap the LSInput with an XMLInputSource 1352 XMLInputSource xis = null; 1353 1354 /** 1355 * An LSParser looks at inputs specified in LSInput in 1356 * the following order: characterStream, byteStream, 1357 * stringData, systemId, publicId. For consistency 1358 * have the same behaviour for XSLoader. 1359 */ 1360 1361 // check whether there is a Reader 1362 // according to DOM, we need to treat such reader as "UTF-16". 1363 if (is.getCharacterStream() != null) { 1364 xis = new XMLInputSource(is.getPublicId(), is.getSystemId(), 1365 is.getBaseURI(), is.getCharacterStream(), 1366 "UTF-16"); 1367 } 1368 // check whether there is an InputStream 1369 else if (is.getByteStream() != null) { 1370 xis = new XMLInputSource(is.getPublicId(), is.getSystemId(), 1371 is.getBaseURI(), is.getByteStream(), 1372 is.getEncoding()); 1373 } 1374 // if there is a string data, use a StringReader 1375 // according to DOM, we need to treat such data as "UTF-16". 1376 else if (is.getStringData() != null && is.getStringData().length() != 0) { 1377 xis = new XMLInputSource(is.getPublicId(), is.getSystemId(), 1378 is.getBaseURI(), new StringReader(is.getStringData()), 1379 "UTF-16"); 1380 } 1381 // otherwise, just use the public/system/base Ids 1382 else { 1383 xis = new XMLInputSource(is.getPublicId(), is.getSystemId(), 1384 is.getBaseURI()); 1385 } 1386 1387 return xis; 1388 } 1389 1390 } // XMLGrammarLoader