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