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