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