1 /* 2 * Copyright (c) 2007, 2019, 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.traversers; 22 23 import com.sun.org.apache.xerces.internal.impl.Constants; 24 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; 25 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; 26 import com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory; 27 import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl; 28 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar; 29 import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport; 30 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols; 31 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaException; 32 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader; 33 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeDecl; 34 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl; 35 import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl; 36 import com.sun.org.apache.xerces.internal.impl.xs.XSDDescription; 37 import com.sun.org.apache.xerces.internal.impl.xs.XSDeclarationPool; 38 import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl; 39 import com.sun.org.apache.xerces.internal.impl.xs.XSGrammarBucket; 40 import com.sun.org.apache.xerces.internal.impl.xs.XSGroupDecl; 41 import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter; 42 import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl; 43 import com.sun.org.apache.xerces.internal.impl.xs.XSNotationDecl; 44 import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl; 45 import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint; 46 import com.sun.org.apache.xerces.internal.impl.xs.opti.ElementImpl; 47 import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOMParser; 48 import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaParsingConfig; 49 import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator; 50 import com.sun.org.apache.xerces.internal.impl.xs.util.XSInputSource; 51 import com.sun.org.apache.xerces.internal.parsers.SAXParser; 52 import com.sun.org.apache.xerces.internal.parsers.XML11Configuration; 53 import com.sun.org.apache.xerces.internal.util.DOMInputSource; 54 import com.sun.org.apache.xerces.internal.util.DOMUtil; 55 import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler; 56 import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper; 57 import com.sun.org.apache.xerces.internal.util.SAXInputSource; 58 import com.sun.org.apache.xerces.internal.util.StAXInputSource; 59 import com.sun.org.apache.xerces.internal.util.StAXLocationWrapper; 60 import com.sun.org.apache.xerces.internal.util.SymbolHash; 61 import com.sun.org.apache.xerces.internal.util.SymbolTable; 62 import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException; 63 import com.sun.org.apache.xerces.internal.util.XMLChar; 64 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 65 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; 66 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; 67 import com.sun.org.apache.xerces.internal.xni.QName; 68 import com.sun.org.apache.xerces.internal.xni.XNIException; 69 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; 70 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; 71 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; 72 import com.sun.org.apache.xerces.internal.xni.grammars.XMLSchemaDescription; 73 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; 74 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 75 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; 76 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; 77 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 78 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; 79 import com.sun.org.apache.xerces.internal.xs.StringList; 80 import com.sun.org.apache.xerces.internal.xs.XSAttributeDeclaration; 81 import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition; 82 import com.sun.org.apache.xerces.internal.xs.XSAttributeUse; 83 import com.sun.org.apache.xerces.internal.xs.XSConstants; 84 import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration; 85 import com.sun.org.apache.xerces.internal.xs.XSModelGroup; 86 import com.sun.org.apache.xerces.internal.xs.XSModelGroupDefinition; 87 import com.sun.org.apache.xerces.internal.xs.XSNamedMap; 88 import com.sun.org.apache.xerces.internal.xs.XSObject; 89 import com.sun.org.apache.xerces.internal.xs.XSObjectList; 90 import com.sun.org.apache.xerces.internal.xs.XSParticle; 91 import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition; 92 import com.sun.org.apache.xerces.internal.xs.XSTerm; 93 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; 94 import com.sun.org.apache.xerces.internal.xs.datatypes.ObjectList; 95 import java.io.IOException; 96 import java.io.StringReader; 97 import java.util.ArrayList; 98 import java.util.Collections; 99 import java.util.HashMap; 100 import java.util.List; 101 import java.util.Locale; 102 import java.util.Map; 103 import java.util.Stack; 104 import javax.xml.XMLConstants; 105 import javax.xml.catalog.CatalogFeatures; 106 import javax.xml.stream.XMLEventReader; 107 import javax.xml.stream.XMLStreamException; 108 import javax.xml.stream.XMLStreamReader; 109 import jdk.xml.internal.JdkXmlUtils; 110 import jdk.xml.internal.SecuritySupport; 111 import org.w3c.dom.Document; 112 import org.w3c.dom.Element; 113 import org.w3c.dom.Node; 114 import org.xml.sax.InputSource; 115 import org.xml.sax.SAXException; 116 import org.xml.sax.SAXNotRecognizedException; 117 import org.xml.sax.SAXParseException; 118 import org.xml.sax.XMLReader; 119 120 /** 121 * The purpose of this class is to co-ordinate the construction of a 122 * grammar object corresponding to a schema. To do this, it must be 123 * prepared to parse several schema documents (for instance if the 124 * schema document originally referred to contains <include> or 125 * <redefined> information items). If any of the schemas imports a 126 * schema, other grammars may be constructed as a side-effect. 127 * 128 * @xerces.internal 129 * 130 * @author Neil Graham, IBM 131 * @author Pavani Mukthipudi, Sun Microsystems 132 * 133 * @LastModified: Apr 2019 134 */ 135 @SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory 136 public class XSDHandler { 137 138 /** Feature identifier: validation. */ 139 protected static final String VALIDATION = 140 Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; 141 142 /** feature identifier: XML Schema validation */ 143 protected static final String XMLSCHEMA_VALIDATION = 144 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE; 145 146 /** Feature identifier: allow java encodings */ 147 protected static final String ALLOW_JAVA_ENCODINGS = 148 Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE; 149 150 /** Feature identifier: continue after fatal error */ 151 protected static final String CONTINUE_AFTER_FATAL_ERROR = 152 Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE; 153 154 /** Feature identifier: allow java encodings */ 155 protected static final String STANDARD_URI_CONFORMANT_FEATURE = 156 Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE; 157 158 /** Feature: disallow doctype*/ 159 protected static final String DISALLOW_DOCTYPE = 160 Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE; 161 162 /** Feature: generate synthetic annotations */ 163 protected static final String GENERATE_SYNTHETIC_ANNOTATIONS = 164 Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE; 165 166 /** Feature identifier: validate annotations. */ 167 protected static final String VALIDATE_ANNOTATIONS = 168 Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE; 169 170 /** Feature identifier: honour all schemaLocations */ 171 protected static final String HONOUR_ALL_SCHEMALOCATIONS = 172 Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE; 173 174 /** Feature identifier: namespace growth */ 175 protected static final String NAMESPACE_GROWTH = 176 Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE; 177 178 /** Feature identifier: tolerate duplicates */ 179 protected static final String TOLERATE_DUPLICATES = 180 Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE; 181 182 /** Feature identifier: namespace prefixes. */ 183 private static final String NAMESPACE_PREFIXES = 184 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE; 185 186 /** Feature identifier: string interning. */ 187 protected static final String STRING_INTERNING = 188 Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE; 189 190 /** Property identifier: error handler. */ 191 protected static final String ERROR_HANDLER = 192 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; 193 194 /** Property identifier: JAXP schema source. */ 195 protected static final String JAXP_SCHEMA_SOURCE = 196 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE; 197 198 /** Property identifier: entity resolver. */ 199 public static final String ENTITY_RESOLVER = 200 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; 201 202 /** Property identifier: entity manager. */ 203 protected static final String ENTITY_MANAGER = 204 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; 205 206 /** Property identifier: error reporter. */ 207 public static final String ERROR_REPORTER = 208 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; 209 210 /** Property identifier: grammar pool. */ 211 public static final String XMLGRAMMAR_POOL = 212 Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; 213 214 /** Property identifier: symbol table. */ 215 public static final String SYMBOL_TABLE = 216 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 217 218 /** Property identifier: security manager. */ 219 protected static final String SECURITY_MANAGER = 220 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; 221 222 /** Property identifier: locale. */ 223 protected static final String LOCALE = 224 Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_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 protected static final boolean DEBUG_NODE_POOL = false; 231 232 // Data 233 234 // different sorts of declarations; should make lookup and 235 // traverser calling more efficient/less bulky. 236 final static int ATTRIBUTE_TYPE = 1; 237 final static int ATTRIBUTEGROUP_TYPE = 2; 238 final static int ELEMENT_TYPE = 3; 239 final static int GROUP_TYPE = 4; 240 final static int IDENTITYCONSTRAINT_TYPE = 5; 241 final static int NOTATION_TYPE = 6; 242 final static int TYPEDECL_TYPE = 7; 243 244 // this string gets appended to redefined names; it's purpose is to be 245 // as unlikely as possible to cause collisions. 246 public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi"; 247 248 //protected data that can be accessible by any traverser 249 250 protected XSDeclarationPool fDeclPool = null; 251 252 // the Security manager in effect. 253 protected XMLSecurityManager fSecurityManager = null; 254 255 private String fAccessExternalSchema; 256 private String fAccessExternalDTD; 257 258 // These tables correspond to the symbol spaces defined in the 259 // spec. 260 // They are keyed with a QName (that is, String("URI,localpart) and 261 // their values are nodes corresponding to the given name's decl. 262 // By asking the node for its ownerDocument and looking in 263 // XSDocumentInfoRegistry we can easily get the corresponding 264 // XSDocumentInfo object. 265 private boolean registryEmpty = true; 266 private Map<String, Element> fUnparsedAttributeRegistry = new HashMap<>(); 267 private Map<String, Element> fUnparsedAttributeGroupRegistry = new HashMap<>(); 268 private Map<String, Element> fUnparsedElementRegistry = new HashMap<>(); 269 private Map<String, Element> fUnparsedGroupRegistry = new HashMap<>(); 270 private Map<String, Element> fUnparsedIdentityConstraintRegistry = new HashMap<>(); 271 private Map<String, Element> fUnparsedNotationRegistry = new HashMap<>(); 272 private Map<String, Element> fUnparsedTypeRegistry = new HashMap<>(); 273 // Compensation for the above maps to locate XSDocumentInfo, 274 // Since we may take Schema Element directly, so can not get the 275 // corresponding XSDocumentInfo object just using above maps. 276 private Map<String, XSDocumentInfo> fUnparsedAttributeRegistrySub = new HashMap<>(); 277 private Map<String, XSDocumentInfo> fUnparsedAttributeGroupRegistrySub = new HashMap<>(); 278 private Map<String, XSDocumentInfo> fUnparsedElementRegistrySub = new HashMap<>(); 279 private Map<String, XSDocumentInfo> fUnparsedGroupRegistrySub = new HashMap<>(); 280 private Map<String, XSDocumentInfo> fUnparsedIdentityConstraintRegistrySub = new HashMap<>(); 281 private Map<String, XSDocumentInfo> fUnparsedNotationRegistrySub = new HashMap<>(); 282 private Map<String, XSDocumentInfo> fUnparsedTypeRegistrySub = new HashMap<>(); 283 284 // Stores XSDocumentInfo (keyed by component name), to check for duplicate 285 // components declared within the same xsd document 286 @SuppressWarnings({"rawtypes", "unchecked"}) 287 private Map<String, XSDocumentInfo> fUnparsedRegistriesExt[] = new HashMap[] { 288 null, 289 null, // ATTRIBUTE_TYPE 290 null, // ATTRIBUTEGROUP_TYPE 291 null, // ELEMENT_TYPE 292 null, // GROUP_TYPE 293 null, // IDENTITYCONSTRAINT_TYPE 294 null, // NOTATION_TYPE 295 null, // TYPEDECL_TYPE 296 }; 297 298 // this map is keyed on by XSDocumentInfo objects. Its values 299 // are Vectors containing the XSDocumentInfo objects <include>d, 300 // <import>ed or <redefine>d by the key XSDocumentInfo. 301 private Map<XSDocumentInfo, List<XSDocumentInfo>> fDependencyMap = new HashMap<>(); 302 303 // this map is keyed on by a target namespace. Its values 304 // are Vectors containing namespaces imported by schema documents 305 // with the key target namespace. 306 // if an imported schema has absent namespace, the value "null" is stored. 307 private Map<String, List<String>> fImportMap = new HashMap<> (); 308 309 // all namespaces that imports other namespaces 310 // if the importing schema has absent namespace, empty string is stored. 311 // (because the key of a map can't be null.) 312 private List<String> fAllTNSs = new ArrayList<>(); 313 314 // stores instance document mappings between namespaces and schema hints 315 private Map<String, XMLSchemaLoader.LocationArray> fLocationPairs = null; 316 317 // Records which nodes are hidden when the input is a DOMInputSource. 318 Map<Node, String> fHiddenNodes = null; 319 320 // convenience methods 321 private String null2EmptyString(String ns) { 322 return ns == null ? XMLSymbols.EMPTY_STRING : ns; 323 } 324 private String emptyString2Null(String ns) { 325 return ns == XMLSymbols.EMPTY_STRING ? null : ns; 326 } 327 // use Schema Element to lookup the SystemId. 328 private String doc2SystemId(Element ele) { 329 String documentURI = null; 330 /** 331 * REVISIT: Casting until DOM Level 3 interfaces are available. -- mrglavas 332 */ 333 if(ele.getOwnerDocument() instanceof com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM){ 334 documentURI = ((com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI(); 335 } 336 return documentURI != null ? documentURI : fDoc2SystemId.get(ele); 337 } 338 339 // This vector stores strings which are combinations of the 340 // publicId and systemId of the inputSource corresponding to a 341 // schema document. This combination is used so that the user's 342 // EntityResolver can provide a consistent way of identifying a 343 // schema document that is included in multiple other schemas. 344 private Map<XSDKey, Element> fTraversed = new HashMap<>(); 345 346 // this map contains a mapping from Schema Element to its systemId 347 // this is useful to resolve a uri relative to the referring document 348 private Map<Element, String> fDoc2SystemId = new HashMap<>(); 349 350 // the primary XSDocumentInfo we were called to parse 351 private XSDocumentInfo fRoot = null; 352 353 // This map's job is to act as a link between the Schema Element and its 354 // XSDocumentInfo object. 355 private Map<Element, XSDocumentInfo> fDoc2XSDocumentMap = new HashMap<>(); 356 357 // map between <redefine> elements and the XSDocumentInfo 358 // objects that correspond to the documents being redefined. 359 private Map<Element, XSDocumentInfo> fRedefine2XSDMap = null; 360 361 // map between <redefine> elements and the namespace support 362 private Map<Element, SchemaNamespaceSupport> fRedefine2NSSupport = null; 363 364 // these objects store a mapping between the names of redefining 365 // groups/attributeGroups and the groups/AttributeGroups which 366 // they redefine by restriction (implicitly). It is up to the 367 // Group and AttributeGroup traversers to check these restrictions for 368 // validity. 369 private final Map<String, String> fRedefinedRestrictedAttributeGroupRegistry = new HashMap<>(); 370 private final Map<String, String> fRedefinedRestrictedGroupRegistry = new HashMap<>(); 371 372 // a variable storing whether the last schema document 373 // processed (by getSchema) was a duplicate. 374 private boolean fLastSchemaWasDuplicate; 375 376 // validate annotations feature 377 private boolean fValidateAnnotations = false; 378 379 //handle multiple import feature 380 private boolean fHonourAllSchemaLocations = false; 381 382 //handle namespace growth feature 383 boolean fNamespaceGrowth = false; 384 385 // handle tolerate duplicates feature 386 boolean fTolerateDuplicates = false; 387 388 // the XMLErrorReporter 389 private XMLErrorReporter fErrorReporter; 390 391 // the XMLErrorHandler 392 private XMLErrorHandler fErrorHandler; 393 394 // the Locale 395 private Locale fLocale; 396 397 // the XMLEntityManager 398 private XMLEntityManager fEntityManager; 399 400 // the XSAttributeChecker 401 private XSAttributeChecker fAttributeChecker; 402 403 // the symbol table 404 private SymbolTable fSymbolTable; 405 406 // the GrammarResolver 407 private XSGrammarBucket fGrammarBucket; 408 409 // the Grammar description 410 private XSDDescription fSchemaGrammarDescription; 411 412 // the Grammar Pool 413 private XMLGrammarPool fGrammarPool; 414 415 // the security property manager 416 private XMLSecurityPropertyManager fSecurityPropertyMgr = null; 417 418 /** indicate whether Catalog should be used for resolving external resources */ 419 private boolean fUseCatalog = true; 420 private String fCatalogFile; 421 private String fDefer; 422 private String fPrefer; 423 private String fResolve; 424 425 private boolean fOverrideDefaultParser; 426 427 //************ Traversers ********** 428 XSDAttributeGroupTraverser fAttributeGroupTraverser; 429 XSDAttributeTraverser fAttributeTraverser; 430 XSDComplexTypeTraverser fComplexTypeTraverser; 431 XSDElementTraverser fElementTraverser; 432 XSDGroupTraverser fGroupTraverser; 433 XSDKeyrefTraverser fKeyrefTraverser; 434 XSDNotationTraverser fNotationTraverser; 435 XSDSimpleTypeTraverser fSimpleTypeTraverser; 436 XSDUniqueOrKeyTraverser fUniqueOrKeyTraverser; 437 XSDWildcardTraverser fWildCardTraverser; 438 439 SchemaDVFactory fDVFactory; 440 SchemaDOMParser fSchemaParser; 441 SchemaContentHandler fXSContentHandler; 442 StAXSchemaParser fStAXSchemaParser; 443 XML11Configuration fAnnotationValidator; 444 XSAnnotationGrammarPool fGrammarBucketAdapter; 445 446 // these data members are needed for the deferred traversal 447 // of local elements. 448 449 // the initial size of the array to store deferred local elements 450 private static final int INIT_STACK_SIZE = 30; 451 // the incremental size of the array to store deferred local elements 452 private static final int INC_STACK_SIZE = 10; 453 // current position of the array (# of deferred local elements) 454 private int fLocalElemStackPos = 0; 455 456 private XSParticleDecl[] fParticle = new XSParticleDecl[INIT_STACK_SIZE]; 457 private Element[] fLocalElementDecl = new Element[INIT_STACK_SIZE]; 458 private XSDocumentInfo[] fLocalElementDecl_schema = new XSDocumentInfo[INIT_STACK_SIZE]; //JACK 459 private int[] fAllContext = new int[INIT_STACK_SIZE]; 460 private XSObject[] fParent = new XSObject[INIT_STACK_SIZE]; 461 private String [][] fLocalElemNamespaceContext = new String [INIT_STACK_SIZE][1]; 462 463 // these data members are needed for the deferred traversal 464 // of keyrefs. 465 466 // the initial size of the array to store deferred keyrefs 467 private static final int INIT_KEYREF_STACK = 2; 468 // the incremental size of the array to store deferred keyrefs 469 private static final int INC_KEYREF_STACK_AMOUNT = 2; 470 // current position of the array (# of deferred keyrefs) 471 private int fKeyrefStackPos = 0; 472 473 private Element [] fKeyrefs = new Element[INIT_KEYREF_STACK]; 474 private XSDocumentInfo [] fKeyrefsMapXSDocumentInfo = new XSDocumentInfo[INIT_KEYREF_STACK]; 475 private XSElementDecl [] fKeyrefElems = new XSElementDecl [INIT_KEYREF_STACK]; 476 private String [][] fKeyrefNamespaceContext = new String[INIT_KEYREF_STACK][1]; 477 478 // global decls: map from decl name to decl object 479 SymbolHash fGlobalAttrDecls = new SymbolHash(12); 480 SymbolHash fGlobalAttrGrpDecls = new SymbolHash(5); 481 SymbolHash fGlobalElemDecls = new SymbolHash(25); 482 SymbolHash fGlobalGroupDecls = new SymbolHash(5); 483 SymbolHash fGlobalNotationDecls = new SymbolHash(1); 484 SymbolHash fGlobalIDConstraintDecls = new SymbolHash(3); 485 SymbolHash fGlobalTypeDecls = new SymbolHash(25); 486 487 // Constructors 488 public XSDHandler(){ 489 fHiddenNodes = new HashMap<>(); 490 fSchemaParser = new SchemaDOMParser(new SchemaParsingConfig()); 491 } 492 493 // it should be possible to use the same XSDHandler to parse 494 // multiple schema documents; this will allow one to be 495 // constructed. 496 public XSDHandler (XSGrammarBucket gBucket) { 497 this(); 498 fGrammarBucket = gBucket; 499 500 // Note: don't use SchemaConfiguration internally 501 // we will get stack overflaw because 502 // XMLSchemaValidator will be instantiating XSDHandler... 503 fSchemaGrammarDescription = new XSDDescription(); 504 } // end constructor 505 506 /** 507 * This method initiates the parse of a schema. It will likely be 508 * called from the Validator and it will make the 509 * resulting grammar available; it returns a reference to this object just 510 * in case. A reset(XMLComponentManager) must be called before this methods is called. 511 * @param is 512 * @param desc 513 * @param locationPairs 514 * @return the SchemaGrammar 515 * @throws IOException 516 */ 517 public SchemaGrammar parseSchema(XMLInputSource is, XSDDescription desc, 518 Map<String, XMLSchemaLoader.LocationArray> locationPairs) 519 throws IOException { 520 fLocationPairs = locationPairs; 521 fSchemaParser.resetNodePool(); 522 SchemaGrammar grammar = null; 523 String schemaNamespace = null; 524 short referType = desc.getContextType(); 525 526 // if loading using JAXP schemaSource property, or using grammar caching loadGrammar 527 // the desc.targetNamespace is always null. 528 // Therefore we should not attempt to find out if 529 // the schema is already in the bucket, since in the case we have 530 // no namespace schema in the bucket, findGrammar will always return the 531 // no namespace schema. 532 if (referType != XSDDescription.CONTEXT_PREPARSE){ 533 // first try to find it in the bucket/pool, return if one is found 534 if (fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT && isExistingGrammar(desc, fNamespaceGrowth)) { 535 grammar = fGrammarBucket.getGrammar(desc.getTargetNamespace()); 536 } 537 else { 538 grammar = findGrammar(desc, fNamespaceGrowth); 539 } 540 if (grammar != null) { 541 if (!fNamespaceGrowth) { 542 return grammar; 543 } 544 else { 545 try { 546 if (grammar.getDocumentLocations().contains(XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false))) { 547 return grammar; 548 } 549 } 550 catch (MalformedURIException e) { 551 //REVISIT: return the grammar? 552 } 553 } 554 } 555 556 schemaNamespace = desc.getTargetNamespace(); 557 // handle empty string URI as null 558 if (schemaNamespace != null) { 559 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); 560 } 561 } 562 563 // before parsing a schema, need to clear registries associated with 564 // parsing schemas 565 prepareForParse(); 566 567 Element schemaRoot = null; 568 // first phase: construct trees. 569 if (is instanceof DOMInputSource) { 570 schemaRoot = getSchemaDocument(schemaNamespace, (DOMInputSource) is, 571 referType == XSDDescription.CONTEXT_PREPARSE, 572 referType, null); 573 } // DOMInputSource 574 else if (is instanceof SAXInputSource) { 575 schemaRoot = getSchemaDocument(schemaNamespace, (SAXInputSource) is, 576 referType == XSDDescription.CONTEXT_PREPARSE, 577 referType, null); 578 } // SAXInputSource 579 else if (is instanceof StAXInputSource) { 580 schemaRoot = getSchemaDocument(schemaNamespace, (StAXInputSource) is, 581 referType == XSDDescription.CONTEXT_PREPARSE, 582 referType, null); 583 } // StAXInputSource 584 else if (is instanceof XSInputSource) { 585 schemaRoot = getSchemaDocument((XSInputSource) is, desc); 586 } // XSInputSource 587 else { 588 schemaRoot = getSchemaDocument(schemaNamespace, is, 589 referType == XSDDescription.CONTEXT_PREPARSE, 590 referType, null); 591 592 } //is instanceof XMLInputSource 593 594 if (schemaRoot == null) { 595 if (is instanceof XSInputSource) { 596 // Need to return a grammar. If the XSInputSource has a list 597 // of grammar objects, then get the first one and return it. 598 // If it has a list of components, then get the grammar that 599 // contains the first component and return it. 600 // If we return null, the XMLSchemaLoader will think nothing 601 // was loaded, and will not try to put the grammar objects 602 // into the grammar pool. 603 XSInputSource xsinput = (XSInputSource)is; 604 SchemaGrammar[] grammars = xsinput.getGrammars(); 605 if (grammars != null && grammars.length > 0) { 606 grammar = fGrammarBucket.getGrammar(grammars[0].getTargetNamespace()); 607 } 608 else { 609 XSObject[] components = xsinput.getComponents(); 610 if (components != null && components.length > 0) { 611 grammar = fGrammarBucket.getGrammar(components[0].getNamespace()); 612 } 613 } 614 } 615 // something went wrong right off the hop 616 return grammar; 617 } 618 619 if (referType == XSDDescription.CONTEXT_PREPARSE) { 620 Element schemaElem = schemaRoot; 621 schemaNamespace = DOMUtil.getAttrValue(schemaElem, SchemaSymbols.ATT_TARGETNAMESPACE); 622 if(schemaNamespace != null && schemaNamespace.length() > 0) { 623 // Since now we've discovered a namespace, we need to update xsd key 624 // and store this schema in traversed schemas bucket 625 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); 626 desc.setTargetNamespace(schemaNamespace); 627 } 628 else { 629 schemaNamespace = null; 630 } 631 grammar = findGrammar(desc, fNamespaceGrowth); 632 String schemaId = XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false); 633 if (grammar != null) { 634 // When namespace growth is enabled and a null location is provided we cannot tell 635 // whether we've loaded this schema document before so we must assume that we haven't. 636 if (!fNamespaceGrowth || (schemaId != null && grammar.getDocumentLocations().contains(schemaId))) { 637 return grammar; 638 } 639 } 640 641 XSDKey key = new XSDKey(schemaId, referType, schemaNamespace); 642 fTraversed.put(key, schemaRoot); 643 if (schemaId != null) { 644 fDoc2SystemId.put(schemaRoot, schemaId); 645 } 646 } 647 648 // before constructing trees and traversing a schema, need to reset 649 // all traversers and clear all registries 650 prepareForTraverse(); 651 652 fRoot = constructTrees(schemaRoot, is.getSystemId(), desc, grammar != null); 653 if (fRoot == null) { 654 return null; 655 } 656 657 // second phase: fill global registries. 658 buildGlobalNameRegistries(); 659 660 // third phase: call traversers 661 List<Object> annotationInfo = fValidateAnnotations ? new ArrayList<>() : null; 662 traverseSchemas(annotationInfo); 663 664 // fourth phase: handle local element decls 665 traverseLocalElements(); 666 667 // fifth phase: handle Keyrefs 668 resolveKeyRefs(); 669 670 // sixth phase: validate attribute of non-schema namespaces 671 // REVISIT: skip this for now. we really don't want to do it. 672 //fAttributeChecker.checkNonSchemaAttributes(fGrammarBucket); 673 674 // seventh phase: store imported grammars 675 // for all grammars with <import>s 676 for (int i = fAllTNSs.size() - 1; i >= 0; i--) { 677 // get its target namespace 678 String tns = fAllTNSs.get(i); 679 // get all namespaces it imports 680 List<String> ins = fImportMap.get(tns); 681 List<SchemaGrammar> grammars = new ArrayList<>(); 682 // get the grammar 683 SchemaGrammar sg = fGrammarBucket.getGrammar(emptyString2Null(tns)); 684 if (sg == null) 685 continue; 686 SchemaGrammar isg; 687 // for imported namespace 688 int count = 0; 689 for (int j = 0; j < ins.size(); j++) { 690 // get imported grammar 691 isg = fGrammarBucket.getGrammar(ins.get(j)); 692 // reuse the same vector 693 if (isg != null) { 694 grammars.add(isg); 695 } 696 } 697 // set the imported grammars 698 sg.setImportedGrammars(grammars); 699 } 700 701 /** validate annotations **/ 702 if (fValidateAnnotations && annotationInfo.size() > 0) { 703 validateAnnotations(annotationInfo); 704 } 705 706 // and return. 707 return fGrammarBucket.getGrammar(fRoot.fTargetNamespace); 708 } // end parseSchema 709 710 private void validateAnnotations(List<Object> annotationInfo) { 711 if (fAnnotationValidator == null) { 712 createAnnotationValidator(); 713 } 714 final int size = annotationInfo.size(); 715 final XMLInputSource src = new XMLInputSource(null, null, null, false); 716 fGrammarBucketAdapter.refreshGrammars(fGrammarBucket); 717 for (int i = 0; i < size; i += 2) { 718 src.setSystemId((String) annotationInfo.get(i)); 719 XSAnnotationInfo annotation = (XSAnnotationInfo) annotationInfo.get(i+1); 720 while (annotation != null) { 721 src.setCharacterStream(new StringReader(annotation.fAnnotation)); 722 try { 723 fAnnotationValidator.parse(src); 724 } 725 catch (IOException exc) {} 726 annotation = annotation.next; 727 } 728 } 729 } 730 731 private void createAnnotationValidator() { 732 fAnnotationValidator = new XML11Configuration(); 733 fGrammarBucketAdapter = new XSAnnotationGrammarPool(); 734 fAnnotationValidator.setFeature(VALIDATION, true); 735 fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true); 736 fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter); 737 /** set security manager and XML Security Property Manager **/ 738 fAnnotationValidator.setProperty(SECURITY_MANAGER, (fSecurityManager != null) ? fSecurityManager : new XMLSecurityManager(true)); 739 fAnnotationValidator.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); 740 /** Set error handler. **/ 741 fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); 742 /** Set locale. **/ 743 fAnnotationValidator.setProperty(LOCALE, fLocale); 744 745 // Passing on the Catalog settings 746 fAnnotationValidator.setFeature(XMLConstants.USE_CATALOG, fUseCatalog); 747 fAnnotationValidator.setProperty(JdkXmlUtils.CATALOG_FILES, fCatalogFile); 748 fAnnotationValidator.setProperty(JdkXmlUtils.CATALOG_DEFER, fDefer); 749 fAnnotationValidator.setProperty(JdkXmlUtils.CATALOG_PREFER, fPrefer); 750 fAnnotationValidator.setProperty(JdkXmlUtils.CATALOG_RESOLVE, fResolve); 751 } 752 753 /** 754 * Pull the grammar out of the bucket simply using 755 * its TNS as a key 756 */ 757 SchemaGrammar getGrammar(String tns) { 758 return fGrammarBucket.getGrammar(tns); 759 } 760 761 /** 762 * First try to find a grammar in the bucket, if failed, consult the 763 * grammar pool. If a grammar is found in the pool, then add it (and all 764 * imported ones) into the bucket. 765 */ 766 protected SchemaGrammar findGrammar(XSDDescription desc, boolean ignoreConflict) { 767 SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace()); 768 if (sg == null) { 769 if (fGrammarPool != null) { 770 sg = (SchemaGrammar)fGrammarPool.retrieveGrammar(desc); 771 if (sg != null) { 772 // put this grammar into the bucket, along with grammars 773 // imported by it (directly or indirectly) 774 if (!fGrammarBucket.putGrammar(sg, true, ignoreConflict)) { 775 // REVISIT: a conflict between new grammar(s) and grammars 776 // in the bucket. What to do? A warning? An exception? 777 reportSchemaWarning("GrammarConflict", null, null); 778 sg = null; 779 } 780 } 781 } 782 } 783 return sg; 784 } 785 786 // may wish to have setter methods for ErrorHandler, 787 // EntityResolver... 788 789 private static final String[][] NS_ERROR_CODES = { 790 {"src-include.2.1", "src-include.2.1"}, 791 {"src-redefine.3.1", "src-redefine.3.1"}, 792 {"src-import.3.1", "src-import.3.2"}, 793 null, 794 {"TargetNamespace.1", "TargetNamespace.2"}, 795 {"TargetNamespace.1", "TargetNamespace.2"}, 796 {"TargetNamespace.1", "TargetNamespace.2"}, 797 {"TargetNamespace.1", "TargetNamespace.2"} 798 }; 799 800 private static final String[] ELE_ERROR_CODES = { 801 "src-include.1", "src-redefine.2", "src-import.2", "schema_reference.4", 802 "schema_reference.4", "schema_reference.4", "schema_reference.4", "schema_reference.4" 803 }; 804 805 // This method does several things: 806 // It constructs an instance of an XSDocumentInfo object using the 807 // schemaRoot node. Then, for each <include>, 808 // <redefine>, and <import> children, it attempts to resolve the 809 // requested schema document, initiates a DOM parse, and calls 810 // itself recursively on that document's root. It also records in 811 // the DependencyMap object what XSDocumentInfo objects its XSDocumentInfo 812 // depends on. 813 // It also makes sure the targetNamespace of the schema it was 814 // called to parse is correct. 815 protected XSDocumentInfo constructTrees(Element schemaRoot, String locationHint, XSDDescription desc, boolean nsCollision) { 816 if (schemaRoot == null) return null; 817 String callerTNS = desc.getTargetNamespace(); 818 short referType = desc.getContextType(); 819 820 XSDocumentInfo currSchemaInfo = null; 821 try { 822 // note that attributes are freed at end of traverseSchemas() 823 currSchemaInfo = new XSDocumentInfo(schemaRoot, fAttributeChecker, fSymbolTable); 824 } catch (XMLSchemaException se) { 825 reportSchemaError(ELE_ERROR_CODES[referType], 826 new Object[]{locationHint}, 827 schemaRoot); 828 return null; 829 } 830 // targetNamespace="" is not valid, issue a warning, and ignore it 831 if (currSchemaInfo.fTargetNamespace != null && 832 currSchemaInfo.fTargetNamespace.length() == 0) { 833 reportSchemaWarning("EmptyTargetNamespace", 834 new Object[]{locationHint}, 835 schemaRoot); 836 currSchemaInfo.fTargetNamespace = null; 837 } 838 839 if (callerTNS != null) { 840 // the second index to the NS_ERROR_CODES array 841 // if the caller/expected NS is not absent, we use the first column 842 int secondIdx = 0; 843 // for include and redefine 844 if (referType == XSDDescription.CONTEXT_INCLUDE || 845 referType == XSDDescription.CONTEXT_REDEFINE) { 846 // if the referred document has no targetNamespace, 847 // it's a chameleon schema 848 if (currSchemaInfo.fTargetNamespace == null) { 849 currSchemaInfo.fTargetNamespace = callerTNS; 850 currSchemaInfo.fIsChameleonSchema = true; 851 } 852 // if the referred document has a target namespace differing 853 // from the caller, it's an error 854 else if (callerTNS != currSchemaInfo.fTargetNamespace) { 855 reportSchemaError(NS_ERROR_CODES[referType][secondIdx], 856 new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, 857 schemaRoot); 858 return null; 859 } 860 } 861 // for instance and import, the two NS's must be the same 862 else if (referType != XSDDescription.CONTEXT_PREPARSE && callerTNS != currSchemaInfo.fTargetNamespace) { 863 reportSchemaError(NS_ERROR_CODES[referType][secondIdx], 864 new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, 865 schemaRoot); 866 return null; 867 } 868 } 869 // now there is no caller/expected NS, it's an error for the referred 870 // document to have a target namespace, unless we are preparsing a schema 871 else if (currSchemaInfo.fTargetNamespace != null) { 872 // set the target namespace of the description 873 if (referType == XSDDescription.CONTEXT_PREPARSE) { 874 desc.setTargetNamespace(currSchemaInfo.fTargetNamespace); 875 callerTNS = currSchemaInfo.fTargetNamespace; 876 } 877 else { 878 // the second index to the NS_ERROR_CODES array 879 // if the caller/expected NS is absent, we use the second column 880 int secondIdx = 1; 881 reportSchemaError(NS_ERROR_CODES[referType][secondIdx], 882 new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, 883 schemaRoot); 884 return null; 885 } 886 } 887 // the other cases (callerTNS == currSchemaInfo.fTargetNamespce == null) 888 // are valid 889 890 // a schema document can always access it's own target namespace 891 currSchemaInfo.addAllowedNS(currSchemaInfo.fTargetNamespace); 892 893 SchemaGrammar sg = null; 894 895 // we have a namespace collision 896 if (nsCollision) { 897 SchemaGrammar sg2 = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace); 898 if (sg2.isImmutable()) { 899 sg = new SchemaGrammar(sg2); 900 fGrammarBucket.putGrammar(sg); 901 // update all the grammars in the bucket to point to the new grammar. 902 updateImportListWith(sg); 903 } 904 else { 905 sg = sg2; 906 } 907 908 // update import list of the new grammar 909 updateImportListFor(sg); 910 } 911 else if (referType == XSDDescription.CONTEXT_INCLUDE || 912 referType == XSDDescription.CONTEXT_REDEFINE) { 913 sg = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace); 914 } 915 else if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT) { 916 sg = findGrammar(desc, false); 917 if(sg == null) { 918 sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable); 919 fGrammarBucket.putGrammar(sg); 920 } 921 } 922 else { 923 sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable); 924 fGrammarBucket.putGrammar(sg); 925 } 926 927 // store the document and its location 928 // REVISIT: don't expose the DOM tree 929 sg.addDocument(null, fDoc2SystemId.get(currSchemaInfo.fSchemaElement)); 930 931 fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo); 932 List<XSDocumentInfo> dependencies = new ArrayList<>(); 933 Element rootNode = schemaRoot; 934 935 Element newSchemaRoot = null; 936 for (Element child = DOMUtil.getFirstChildElement(rootNode); 937 child != null; 938 child = DOMUtil.getNextSiblingElement(child)) { 939 String schemaNamespace=null; 940 String schemaHint=null; 941 String localName = DOMUtil.getLocalName(child); 942 943 short refType = -1; 944 boolean importCollision = false; 945 946 if (localName.equals(SchemaSymbols.ELT_ANNOTATION)) 947 continue; 948 else if (localName.equals(SchemaSymbols.ELT_IMPORT)) { 949 refType = XSDDescription.CONTEXT_IMPORT; 950 // have to handle some validation here too! 951 // call XSAttributeChecker to fill in attrs 952 Object[] importAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo); 953 schemaHint = (String)importAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION]; 954 schemaNamespace = (String)importAttrs[XSAttributeChecker.ATTIDX_NAMESPACE]; 955 if (schemaNamespace != null) 956 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); 957 958 // check contents and process optional annotations 959 Element importChild = DOMUtil.getFirstChildElement(child); 960 if(importChild != null ) { 961 String importComponentType = DOMUtil.getLocalName(importChild); 962 if (importComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { 963 // promoting annotations to parent component 964 sg.addAnnotation( 965 fElementTraverser.traverseAnnotationDecl(importChild, importAttrs, true, currSchemaInfo)); 966 } else { 967 reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", importComponentType}, child); 968 } 969 if(DOMUtil.getNextSiblingElement(importChild) != null) { 970 reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(importChild))}, child); 971 } 972 } 973 else { 974 String text = DOMUtil.getSyntheticAnnotation(child); 975 if (text != null) { 976 sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, importAttrs, true, currSchemaInfo)); 977 } 978 } 979 fAttributeChecker.returnAttrArray(importAttrs, currSchemaInfo); 980 981 // a document can't import another document with the same namespace 982 if (schemaNamespace == currSchemaInfo.fTargetNamespace) { 983 reportSchemaError(schemaNamespace != null ? 984 "src-import.1.1" : "src-import.1.2", new Object [] {schemaNamespace}, child); 985 continue; 986 } 987 988 // if this namespace has not been imported by this document, 989 // then import if multiple imports support is enabled. 990 if(currSchemaInfo.isAllowedNS(schemaNamespace)) { 991 if(!fHonourAllSchemaLocations && !fNamespaceGrowth) 992 continue; 993 } 994 else { 995 currSchemaInfo.addAllowedNS(schemaNamespace); 996 } 997 // also record the fact that one namespace imports another one 998 // convert null to "" 999 String tns = null2EmptyString(currSchemaInfo.fTargetNamespace); 1000 // get all namespaces imported by this one 1001 List<String> ins = fImportMap.get(tns); 1002 // if no namespace was imported, create new ArrayList<> 1003 if (ins == null) { 1004 // record that this one imports other(s) 1005 fAllTNSs.add(tns); 1006 ins = new ArrayList<>(); 1007 fImportMap.put(tns, ins); 1008 ins.add(schemaNamespace); 1009 } 1010 else if (!ins.contains(schemaNamespace)){ 1011 ins.add(schemaNamespace); 1012 } 1013 1014 fSchemaGrammarDescription.reset(); 1015 fSchemaGrammarDescription.setContextType(XSDDescription.CONTEXT_IMPORT); 1016 fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot)); 1017 fSchemaGrammarDescription.setLiteralSystemId(schemaHint); 1018 fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint}); 1019 fSchemaGrammarDescription.setTargetNamespace(schemaNamespace); 1020 1021 // if a grammar with the same namespace and location exists (or being 1022 // built), ignore this one (don't traverse it). 1023 SchemaGrammar isg = findGrammar(fSchemaGrammarDescription, fNamespaceGrowth); 1024 if (isg != null) { 1025 if (fNamespaceGrowth) { 1026 try { 1027 if (isg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(schemaHint, fSchemaGrammarDescription.getBaseSystemId(), false))) { 1028 continue; 1029 } 1030 else { 1031 importCollision = true; 1032 } 1033 } 1034 catch (MalformedURIException e) { 1035 } 1036 } 1037 else if (!fHonourAllSchemaLocations || isExistingGrammar(fSchemaGrammarDescription, false)) { 1038 continue; 1039 } 1040 } 1041 //if ((!fHonourAllSchemaLocations && findGrammar(fSchemaGrammarDescription) != null) || isExistingGrammar(fSchemaGrammarDescription)) 1042 // continue; 1043 1044 // If "findGrammar" returns a grammar, then this is not the 1045 // the first time we see a location for a given namespace. 1046 // Don't consult the location pair map in this case, 1047 // otherwise the location will be ignored because it'll get 1048 // resolved to the same location as the first hint. 1049 newSchemaRoot = resolveSchema(fSchemaGrammarDescription, false, child, isg == null); 1050 } 1051 else if ((localName.equals(SchemaSymbols.ELT_INCLUDE)) || 1052 (localName.equals(SchemaSymbols.ELT_REDEFINE))) { 1053 // validation for redefine/include will be the same here; just 1054 // make sure TNS is right (don't care about redef contents 1055 // yet). 1056 Object[] includeAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo); 1057 schemaHint = (String)includeAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION]; 1058 // store the namespace decls of the redefine element 1059 if (localName.equals(SchemaSymbols.ELT_REDEFINE)) { 1060 if (fRedefine2NSSupport == null) fRedefine2NSSupport = new HashMap<>(); 1061 fRedefine2NSSupport.put(child, new SchemaNamespaceSupport(currSchemaInfo.fNamespaceSupport)); 1062 } 1063 1064 // check annotations. Must do this here to avoid having to 1065 // re-parse attributes later 1066 if(localName.equals(SchemaSymbols.ELT_INCLUDE)) { 1067 Element includeChild = DOMUtil.getFirstChildElement(child); 1068 if(includeChild != null ) { 1069 String includeComponentType = DOMUtil.getLocalName(includeChild); 1070 if (includeComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { 1071 // promoting annotations to parent component 1072 sg.addAnnotation( 1073 fElementTraverser.traverseAnnotationDecl(includeChild, includeAttrs, true, currSchemaInfo)); 1074 } else { 1075 reportSchemaError("s4s-elt-must-match.1", 1076 new Object [] {localName, "annotation?", includeComponentType}, child); 1077 } 1078 if(DOMUtil.getNextSiblingElement(includeChild) != null) { 1079 reportSchemaError("s4s-elt-must-match.1", 1080 new Object [] {localName, "annotation?", 1081 DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(includeChild))}, child); 1082 } 1083 } 1084 else { 1085 String text = DOMUtil.getSyntheticAnnotation(child); 1086 if (text != null) { 1087 sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo)); 1088 } 1089 } 1090 } 1091 else { 1092 for (Element redefinedChild = DOMUtil.getFirstChildElement(child); 1093 redefinedChild != null; 1094 redefinedChild = DOMUtil.getNextSiblingElement(redefinedChild)) { 1095 String redefinedComponentType = DOMUtil.getLocalName(redefinedChild); 1096 if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { 1097 // promoting annotations to parent component 1098 sg.addAnnotation( 1099 fElementTraverser.traverseAnnotationDecl(redefinedChild, includeAttrs, true, currSchemaInfo)); 1100 DOMUtil.setHidden(redefinedChild, fHiddenNodes); 1101 } 1102 else { 1103 String text = DOMUtil.getSyntheticAnnotation(child); 1104 if (text != null) { 1105 sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo)); 1106 } 1107 } 1108 // catch all other content errors later 1109 } 1110 } 1111 fAttributeChecker.returnAttrArray(includeAttrs, currSchemaInfo); 1112 // schemaLocation is required on <include> and <redefine> 1113 if (schemaHint == null) { 1114 reportSchemaError("s4s-att-must-appear", new Object [] { 1115 "<include> or <redefine>", "schemaLocation"}, 1116 child); 1117 } 1118 // pass the systemId of the current document as the base systemId 1119 boolean mustResolve = false; 1120 refType = XSDDescription.CONTEXT_INCLUDE; 1121 if(localName.equals(SchemaSymbols.ELT_REDEFINE)) { 1122 mustResolve = nonAnnotationContent(child); 1123 refType = XSDDescription.CONTEXT_REDEFINE; 1124 } 1125 fSchemaGrammarDescription.reset(); 1126 fSchemaGrammarDescription.setContextType(refType); 1127 fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot)); 1128 fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint}); 1129 fSchemaGrammarDescription.setTargetNamespace(callerTNS); 1130 1131 boolean alreadyTraversed = false; 1132 XMLInputSource schemaSource = 1133 resolveSchemaSource(fSchemaGrammarDescription, mustResolve, child, true); 1134 if (fNamespaceGrowth && refType == XSDDescription.CONTEXT_INCLUDE) { 1135 try { 1136 final String schemaId = XMLEntityManager.expandSystemId( 1137 schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); 1138 alreadyTraversed = sg.getDocumentLocations().contains(schemaId); 1139 } 1140 catch(MalformedURIException e) { 1141 1142 } 1143 } 1144 1145 if (!alreadyTraversed) { 1146 newSchemaRoot = resolveSchema(schemaSource, fSchemaGrammarDescription, mustResolve, child); 1147 schemaNamespace = currSchemaInfo.fTargetNamespace; 1148 } 1149 else { 1150 fLastSchemaWasDuplicate = true; 1151 } 1152 } 1153 else { 1154 // no more possibility of schema references in well-formed 1155 // schema... 1156 break; 1157 } 1158 1159 // If the schema is duplicate, we needn't call constructTrees() again. 1160 // To handle mutual <include>s 1161 XSDocumentInfo newSchemaInfo = null; 1162 if (fLastSchemaWasDuplicate) { 1163 newSchemaInfo = newSchemaRoot == null ? null : fDoc2XSDocumentMap.get(newSchemaRoot); 1164 } 1165 else { 1166 newSchemaInfo = constructTrees(newSchemaRoot, schemaHint, 1167 fSchemaGrammarDescription, importCollision); 1168 } 1169 1170 if (localName.equals(SchemaSymbols.ELT_REDEFINE) && 1171 newSchemaInfo != null) { 1172 // must record which schema we're redefining so that we can 1173 // rename the right things later! 1174 if (fRedefine2XSDMap == null) fRedefine2XSDMap = new HashMap<>(); 1175 fRedefine2XSDMap.put(child, newSchemaInfo); 1176 } 1177 if (newSchemaRoot != null) { 1178 if (newSchemaInfo != null) 1179 dependencies.add(newSchemaInfo); 1180 newSchemaRoot = null; 1181 } 1182 } 1183 1184 fDependencyMap.put(currSchemaInfo, dependencies); 1185 return currSchemaInfo; 1186 } // end constructTrees 1187 1188 private boolean isExistingGrammar(XSDDescription desc, boolean ignoreConflict) { 1189 SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace()); 1190 if (sg == null) { 1191 return findGrammar(desc, ignoreConflict) != null; 1192 } 1193 else if (sg.isImmutable()) { 1194 return true; 1195 } 1196 else { 1197 try { 1198 return sg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(desc.getLiteralSystemId(), desc.getBaseSystemId(), false)); 1199 } 1200 catch (MalformedURIException e) { 1201 return false; 1202 } 1203 } 1204 } 1205 1206 /** 1207 * Namespace growth 1208 * 1209 * Go through the import list of a given grammar and for each imported 1210 * grammar, check to see if the grammar bucket has a newer version. 1211 * If a new instance is found, we update the import list with the 1212 * newer version. 1213 */ 1214 private void updateImportListFor(SchemaGrammar grammar) { 1215 List<SchemaGrammar> importedGrammars = grammar.getImportedGrammars(); 1216 if (importedGrammars != null) { 1217 for (int i=0; i<importedGrammars.size(); i++) { 1218 SchemaGrammar isg1 = importedGrammars.get(i); 1219 SchemaGrammar isg2 = fGrammarBucket.getGrammar(isg1.getTargetNamespace()); 1220 if (isg2 != null && isg1 != isg2) { 1221 importedGrammars.set(i, isg2); 1222 } 1223 } 1224 } 1225 } 1226 1227 /** 1228 * Namespace growth 1229 * 1230 * Go throuth the grammar bucket, and for each grammar in the bucket 1231 * check the import list. If there exists a grammar in import list 1232 * that has the same namespace as newGrammar, but a different instance, 1233 * then update the import list and replace the old grammar instance with 1234 * the new one 1235 */ 1236 private void updateImportListWith(SchemaGrammar newGrammar) { 1237 SchemaGrammar[] schemaGrammars = fGrammarBucket.getGrammars(); 1238 for (int i = 0; i < schemaGrammars.length; ++i) { 1239 SchemaGrammar sg = schemaGrammars[i]; 1240 if (sg != newGrammar) { 1241 List<SchemaGrammar> importedGrammars = sg.getImportedGrammars(); 1242 if (importedGrammars != null) { 1243 for (int j=0; j<importedGrammars.size(); j++) { 1244 SchemaGrammar isg = importedGrammars.get(j); 1245 if (null2EmptyString(isg.getTargetNamespace()).equals( 1246 null2EmptyString(newGrammar.getTargetNamespace()))) { 1247 if (isg != newGrammar) { 1248 importedGrammars.set(j, newGrammar); 1249 } 1250 break; 1251 } 1252 } 1253 } 1254 } 1255 } 1256 } 1257 1258 // This method builds registries for all globally-referenceable 1259 // names. A registry will be built for each symbol space defined 1260 // by the spec. It is also this method's job to rename redefined 1261 // components, and to record which components redefine others (so 1262 // that implicit redefinitions of groups and attributeGroups can be handled). 1263 protected void buildGlobalNameRegistries() { 1264 1265 registryEmpty = false; 1266 // Starting with fRoot, we examine each child of the schema 1267 // element. Skipping all imports and includes, we record the names 1268 // of all other global components (and children of <redefine>). We 1269 // also put <redefine> names in a registry that we look through in 1270 // case something needs renaming. Once we're done with a schema we 1271 // set its Document node to hidden so that we don't try to traverse 1272 // it again; then we look to its Dependency map entry. We keep a 1273 // stack of schemas that we haven't yet finished processing; this 1274 // is a depth-first traversal. 1275 1276 Stack<XSDocumentInfo> schemasToProcess = new Stack<>(); 1277 schemasToProcess.push(fRoot); 1278 1279 while (!schemasToProcess.empty()) { 1280 XSDocumentInfo currSchemaDoc = schemasToProcess.pop(); 1281 Element currDoc = currSchemaDoc.fSchemaElement; 1282 if(DOMUtil.isHidden(currDoc, fHiddenNodes)){ 1283 // must have processed this already! 1284 continue; 1285 } 1286 1287 Element currRoot = currDoc; 1288 // process this schema's global decls 1289 boolean dependenciesCanOccur = true; 1290 for (Element globalComp = 1291 DOMUtil.getFirstChildElement(currRoot); 1292 globalComp != null; 1293 globalComp = DOMUtil.getNextSiblingElement(globalComp)) { 1294 // this loop makes sure the <schema> element ordering is 1295 // also valid. 1296 if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_ANNOTATION)) { 1297 //skip it; traverse it later 1298 continue; 1299 } 1300 else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_INCLUDE) || 1301 DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_IMPORT)) { 1302 if (!dependenciesCanOccur) { 1303 reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp); 1304 } 1305 DOMUtil.setHidden(globalComp, fHiddenNodes); 1306 } 1307 else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) { 1308 if (!dependenciesCanOccur) { 1309 reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp); 1310 } 1311 for (Element redefineComp = DOMUtil.getFirstChildElement(globalComp); 1312 redefineComp != null; 1313 redefineComp = DOMUtil.getNextSiblingElement(redefineComp)) { 1314 String lName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME); 1315 if (lName.length() == 0) // an error we'll catch later 1316 continue; 1317 String qName = currSchemaDoc.fTargetNamespace == null ? 1318 ","+lName: 1319 currSchemaDoc.fTargetNamespace +","+lName; 1320 qName = XMLChar.trim(qName); 1321 String componentType = DOMUtil.getLocalName(redefineComp); 1322 if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { 1323 checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, redefineComp, currSchemaDoc); 1324 // the check will have changed our name; 1325 String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER; 1326 // and all we need to do is error-check+rename our kkids: 1327 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_ATTRIBUTEGROUP, 1328 lName, targetLName); 1329 } 1330 else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) || 1331 (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) { 1332 checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, redefineComp, currSchemaDoc); 1333 // the check will have changed our name; 1334 String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME) + REDEF_IDENTIFIER; 1335 // and all we need to do is error-check+rename our kkids: 1336 if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { 1337 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_COMPLEXTYPE, 1338 lName, targetLName); 1339 } 1340 else { // must be simpleType 1341 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_SIMPLETYPE, 1342 lName, targetLName); 1343 } 1344 } 1345 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { 1346 checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, redefineComp, currSchemaDoc); 1347 // the check will have changed our name; 1348 String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER; 1349 // and all we need to do is error-check+rename our kids: 1350 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_GROUP, 1351 lName, targetLName); 1352 } 1353 } // end march through <redefine> children 1354 // and now set as traversed 1355 //DOMUtil.setHidden(globalComp); 1356 } 1357 else { 1358 dependenciesCanOccur = false; 1359 String lName = DOMUtil.getAttrValue(globalComp, SchemaSymbols.ATT_NAME); 1360 if (lName.length() == 0) // an error we'll catch later 1361 continue; 1362 String qName = currSchemaDoc.fTargetNamespace == null? 1363 ","+lName: 1364 currSchemaDoc.fTargetNamespace +","+lName; 1365 qName = XMLChar.trim(qName); 1366 String componentType = DOMUtil.getLocalName(globalComp); 1367 1368 if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) { 1369 checkForDuplicateNames(qName, ATTRIBUTE_TYPE, fUnparsedAttributeRegistry, fUnparsedAttributeRegistrySub, globalComp, currSchemaDoc); 1370 } 1371 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { 1372 checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, globalComp, currSchemaDoc); 1373 } 1374 else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) || 1375 (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) { 1376 checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, globalComp, currSchemaDoc); 1377 } 1378 else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) { 1379 checkForDuplicateNames(qName, ELEMENT_TYPE, fUnparsedElementRegistry, fUnparsedElementRegistrySub, globalComp, currSchemaDoc); 1380 } 1381 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { 1382 checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, globalComp, currSchemaDoc); 1383 } 1384 else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) { 1385 checkForDuplicateNames(qName, NOTATION_TYPE, fUnparsedNotationRegistry, fUnparsedNotationRegistrySub, globalComp, currSchemaDoc); 1386 } 1387 } 1388 } // end for 1389 1390 // now we're done with this one! 1391 DOMUtil.setHidden(currDoc, fHiddenNodes); 1392 // now add the schemas this guy depends on 1393 List<XSDocumentInfo> currSchemaDepends = fDependencyMap.get(currSchemaDoc); 1394 for (XSDocumentInfo currSchemaDepend : currSchemaDepends) { 1395 schemasToProcess.push(currSchemaDepend); 1396 } 1397 } // while 1398 1399 } // end buildGlobalNameRegistries 1400 1401 // Beginning at the first schema processing was requested for 1402 // (fRoot), this method 1403 // examines each child (global schema information item) of each 1404 // schema document (and of each <redefine> element) 1405 // corresponding to an XSDocumentInfo object. If the 1406 // readOnly field on that node has not been set, it calls an 1407 // appropriate traverser to traverse it. Once all global decls in 1408 // an XSDocumentInfo object have been traversed, it marks that object 1409 // as traversed (or hidden) in order to avoid infinite loops. It completes 1410 // when it has visited all XSDocumentInfo objects in the 1411 // DependencyMap and marked them as traversed. 1412 protected void traverseSchemas(List<Object> annotationInfo) { 1413 // the process here is very similar to that in 1414 // buildGlobalRegistries, except we can't set our schemas as 1415 // hidden for a second time; so make them all visible again 1416 // first! 1417 setSchemasVisible(fRoot); 1418 Stack<XSDocumentInfo> schemasToProcess = new Stack<>(); 1419 schemasToProcess.push(fRoot); 1420 while (!schemasToProcess.empty()) { 1421 XSDocumentInfo currSchemaDoc = schemasToProcess.pop(); 1422 Element currDoc = currSchemaDoc.fSchemaElement; 1423 1424 SchemaGrammar currSG = fGrammarBucket.getGrammar(currSchemaDoc.fTargetNamespace); 1425 1426 if(DOMUtil.isHidden(currDoc, fHiddenNodes)) { 1427 // must have processed this already! 1428 continue; 1429 } 1430 Element currRoot = currDoc; 1431 boolean sawAnnotation = false; 1432 // traverse this schema's global decls 1433 for (Element globalComp = 1434 DOMUtil.getFirstVisibleChildElement(currRoot, fHiddenNodes); 1435 globalComp != null; 1436 globalComp = DOMUtil.getNextVisibleSiblingElement(globalComp, fHiddenNodes)) { 1437 DOMUtil.setHidden(globalComp, fHiddenNodes); 1438 String componentType = DOMUtil.getLocalName(globalComp); 1439 // includes and imports will not show up here! 1440 if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) { 1441 // use the namespace decls for the redefine, instead of for the parent <schema> 1442 currSchemaDoc.backupNSSupport((fRedefine2NSSupport!=null) ? 1443 fRedefine2NSSupport.get(globalComp) : null); 1444 for (Element redefinedComp = DOMUtil.getFirstVisibleChildElement(globalComp, fHiddenNodes); 1445 redefinedComp != null; 1446 redefinedComp = DOMUtil.getNextVisibleSiblingElement(redefinedComp, fHiddenNodes)) { 1447 String redefinedComponentType = DOMUtil.getLocalName(redefinedComp); 1448 DOMUtil.setHidden(redefinedComp, fHiddenNodes); 1449 if (redefinedComponentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { 1450 fAttributeGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); 1451 } 1452 else if (redefinedComponentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { 1453 fComplexTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); 1454 } 1455 else if (redefinedComponentType.equals(SchemaSymbols.ELT_GROUP)) { 1456 fGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); 1457 } 1458 else if (redefinedComponentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { 1459 fSimpleTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); 1460 } 1461 // annotations will have been processed already; this is now 1462 // unnecessary 1463 //else if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { 1464 // fElementTraverser.traverseAnnotationDecl(redefinedComp, null, true, currSchemaDoc); 1465 //} 1466 else { 1467 reportSchemaError("s4s-elt-must-match.1", new Object [] {DOMUtil.getLocalName(globalComp), "(annotation | (simpleType | complexType | group | attributeGroup))*", redefinedComponentType}, redefinedComp); 1468 } 1469 } // end march through <redefine> children 1470 currSchemaDoc.restoreNSSupport(); 1471 } 1472 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) { 1473 fAttributeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); 1474 } 1475 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { 1476 fAttributeGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); 1477 } 1478 else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { 1479 fComplexTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); 1480 } 1481 else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) { 1482 fElementTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); 1483 } 1484 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { 1485 fGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); 1486 } 1487 else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) { 1488 fNotationTraverser.traverse(globalComp, currSchemaDoc, currSG); 1489 } 1490 else if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { 1491 fSimpleTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); 1492 } 1493 else if (componentType.equals(SchemaSymbols.ELT_ANNOTATION)) { 1494 currSG.addAnnotation(fElementTraverser.traverseAnnotationDecl(globalComp, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc)); 1495 sawAnnotation = true; 1496 } 1497 else { 1498 reportSchemaError("s4s-elt-invalid-content.1", new Object [] {SchemaSymbols.ELT_SCHEMA, DOMUtil.getLocalName(globalComp)}, globalComp); 1499 } 1500 } // end for 1501 1502 if (!sawAnnotation) { 1503 String text = DOMUtil.getSyntheticAnnotation(currRoot); 1504 if (text != null) { 1505 currSG.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(currRoot, text, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc)); 1506 } 1507 } 1508 1509 /** Collect annotation information for validation. **/ 1510 if (annotationInfo != null) { 1511 XSAnnotationInfo info = currSchemaDoc.getAnnotations(); 1512 /** Only add annotations to the list if there were any in this document. **/ 1513 if (info != null) { 1514 annotationInfo.add(doc2SystemId(currDoc)); 1515 annotationInfo.add(info); 1516 } 1517 } 1518 // now we're done with this one! 1519 currSchemaDoc.returnSchemaAttrs(); 1520 DOMUtil.setHidden(currDoc, fHiddenNodes); 1521 1522 // now add the schemas this guy depends on 1523 List<XSDocumentInfo> currSchemaDepends = fDependencyMap.get(currSchemaDoc); 1524 for (XSDocumentInfo currSchemaDepend : currSchemaDepends) { 1525 schemasToProcess.push(currSchemaDepend); 1526 } 1527 } // while 1528 } // end traverseSchemas 1529 1530 // store whether we have reported an error about that no grammar 1531 // is found for the given namespace uri 1532 private List<String> fReportedTNS = null; 1533 // check whether we need to report an error against the given uri. 1534 // if we have reported an error, then we don't need to report again; 1535 // otherwise we reported the error, and remember this fact. 1536 private final boolean needReportTNSError(String uri) { 1537 if (fReportedTNS == null) 1538 fReportedTNS = new ArrayList<>(); 1539 else if (fReportedTNS.contains(uri)) 1540 return false; 1541 fReportedTNS.add(uri); 1542 return true; 1543 } 1544 1545 private static final String[] COMP_TYPE = { 1546 null, // index 0 1547 "attribute declaration", 1548 "attribute group", 1549 "element declaration", 1550 "group", 1551 "identity constraint", 1552 "notation", 1553 "type definition", 1554 }; 1555 1556 private static final String[] CIRCULAR_CODES = { 1557 "Internal-Error", 1558 "Internal-Error", 1559 "src-attribute_group.3", 1560 "e-props-correct.6", 1561 "mg-props-correct.2", 1562 "Internal-Error", 1563 "Internal-Error", 1564 "st-props-correct.2", //or ct-props-correct.3 1565 }; 1566 1567 // add a global attribute decl from a current schema load (only if no existing decl is found) 1568 void addGlobalAttributeDecl(XSAttributeDecl decl) { 1569 final String namespace = decl.getNamespace(); 1570 final String declKey = (namespace == null || namespace.length() == 0) 1571 ? "," + decl.getName() : namespace + "," + decl.getName(); 1572 1573 if (fGlobalAttrDecls.get(declKey) == null) { 1574 fGlobalAttrDecls.put(declKey, decl); 1575 } 1576 } 1577 1578 // add a global attribute group decl from a current schema load (only if no existing decl is found) 1579 void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) { 1580 final String namespace = decl.getNamespace(); 1581 final String declKey = (namespace == null || namespace.length() == 0) 1582 ? "," + decl.getName() : namespace + "," + decl.getName(); 1583 1584 if (fGlobalAttrGrpDecls.get(declKey) == null) { 1585 fGlobalAttrGrpDecls.put(declKey, decl); 1586 } 1587 } 1588 1589 // add a global element decl from a current schema load (only if no existing decl is found) 1590 void addGlobalElementDecl(XSElementDecl decl) { 1591 final String namespace = decl.getNamespace(); 1592 final String declKey = (namespace == null || namespace.length() == 0) 1593 ? "," + decl.getName() : namespace + "," + decl.getName(); 1594 1595 if (fGlobalElemDecls.get(declKey) == null) { 1596 fGlobalElemDecls.put(declKey, decl); 1597 } 1598 } 1599 1600 // add a global group decl from a current schema load (only if no existing decl is found) 1601 void addGlobalGroupDecl(XSGroupDecl decl) { 1602 final String namespace = decl.getNamespace(); 1603 final String declKey = (namespace == null || namespace.length() == 0) 1604 ? "," + decl.getName() : namespace + "," + decl.getName(); 1605 1606 if (fGlobalGroupDecls.get(declKey) == null) { 1607 fGlobalGroupDecls.put(declKey, decl); 1608 } 1609 } 1610 1611 // add a global notation decl from a current schema load (only if no existing decl is found) 1612 void addGlobalNotationDecl(XSNotationDecl decl) { 1613 final String namespace = decl.getNamespace(); 1614 final String declKey = (namespace == null || namespace.length() == 0) 1615 ? "," + decl.getName() : namespace + "," + decl.getName(); 1616 1617 if (fGlobalNotationDecls.get(declKey) == null) { 1618 fGlobalNotationDecls.put(declKey, decl); 1619 } 1620 } 1621 1622 // add a global type decl from a current schema load (only if no existing decl is found) 1623 void addGlobalTypeDecl(XSTypeDefinition decl) { 1624 final String namespace = decl.getNamespace(); 1625 final String declKey = (namespace == null || namespace.length() == 0) 1626 ? "," + decl.getName() : namespace + "," + decl.getName(); 1627 1628 if (fGlobalTypeDecls.get(declKey) == null) { 1629 fGlobalTypeDecls.put(declKey, decl); 1630 } 1631 } 1632 1633 // add a identity constraint decl from a current schema load (only if no existing decl is found) 1634 void addIDConstraintDecl(IdentityConstraint decl) { 1635 final String namespace = decl.getNamespace(); 1636 final String declKey = (namespace == null || namespace.length() == 0) 1637 ? "," + decl.getIdentityConstraintName() : namespace + "," + decl.getIdentityConstraintName(); 1638 1639 if (fGlobalIDConstraintDecls.get(declKey) == null) { 1640 fGlobalIDConstraintDecls.put(declKey, decl); 1641 } 1642 } 1643 1644 private XSAttributeDecl getGlobalAttributeDecl(String declKey) { 1645 return (XSAttributeDecl)fGlobalAttrDecls.get(declKey); 1646 } 1647 1648 private XSAttributeGroupDecl getGlobalAttributeGroupDecl(String declKey) { 1649 return (XSAttributeGroupDecl)fGlobalAttrGrpDecls.get(declKey); 1650 } 1651 1652 private XSElementDecl getGlobalElementDecl(String declKey) { 1653 return (XSElementDecl)fGlobalElemDecls.get(declKey); 1654 } 1655 1656 private XSGroupDecl getGlobalGroupDecl(String declKey) { 1657 return (XSGroupDecl)fGlobalGroupDecls.get(declKey); 1658 } 1659 1660 private XSNotationDecl getGlobalNotationDecl(String declKey) { 1661 return (XSNotationDecl)fGlobalNotationDecls.get(declKey); 1662 } 1663 1664 private XSTypeDefinition getGlobalTypeDecl(String declKey) { 1665 return (XSTypeDefinition)fGlobalTypeDecls.get(declKey); 1666 } 1667 1668 private IdentityConstraint getIDConstraintDecl(String declKey) { 1669 return (IdentityConstraint)fGlobalIDConstraintDecls.get(declKey); 1670 } 1671 1672 // since it is forbidden for traversers to talk to each other 1673 // directly (except wen a traverser encounters a local declaration), 1674 // this provides a generic means for a traverser to call 1675 // for the traversal of some declaration. An XSDocumentInfo is 1676 // required because the XSDocumentInfo that the traverser is traversing 1677 // may bear no relation to the one the handler is operating on. 1678 // This method will: 1679 // 1. See if a global definition matching declToTraverse exists; 1680 // 2. if so, determine if there is a path from currSchema to the 1681 // schema document where declToTraverse lives (i.e., do a lookup 1682 // in DependencyMap); 1683 // 3. depending on declType (which will be relevant to step 1 as 1684 // well), call the appropriate traverser with the appropriate 1685 // XSDocumentInfo object. 1686 // This method returns whatever the traverser it called returned; 1687 // this will be an Object of some kind 1688 // that lives in the Grammar. 1689 protected Object getGlobalDecl(XSDocumentInfo currSchema, 1690 int declType, 1691 QName declToTraverse, 1692 Element elmNode) { 1693 1694 if (DEBUG_NODE_POOL) { 1695 System.out.println("TRAVERSE_GL: "+declToTraverse.toString()); 1696 } 1697 1698 // from the schema spec, all built-in types are present in all schemas, 1699 // so if the requested component is a type, and could be found in the 1700 // default schema grammar, we should return that type. 1701 // otherwise (since we would support user-defined schema grammar) we'll 1702 // use the normal way to get the decl 1703 if (declToTraverse.uri != null && 1704 declToTraverse.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) { 1705 if (declType == TYPEDECL_TYPE) { 1706 Object retObj = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(declToTraverse.localpart); 1707 if (retObj != null) 1708 return retObj; 1709 } 1710 } 1711 1712 // now check whether this document can access the requsted namespace 1713 if (!currSchema.isAllowedNS(declToTraverse.uri)) { 1714 // cannot get to this schema from the one containing the requesting decl 1715 if (currSchema.needReportTNSError(declToTraverse.uri)) { 1716 String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2"; 1717 reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode); 1718 } 1719 // Recover and continue to look for the component. 1720 // return null; 1721 } 1722 1723 // check whether there is grammar for the requested namespace 1724 SchemaGrammar sGrammar = fGrammarBucket.getGrammar(declToTraverse.uri); 1725 if (sGrammar == null) { 1726 if (needReportTNSError(declToTraverse.uri)) 1727 reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode); 1728 return null; 1729 } 1730 1731 // if there is such grammar, check whether the requested component is in the grammar 1732 Object retObj = getGlobalDeclFromGrammar(sGrammar, declType, declToTraverse.localpart); 1733 String declKey = declToTraverse.uri == null? ","+declToTraverse.localpart: 1734 declToTraverse.uri+","+declToTraverse.localpart; 1735 1736 // if the component is parsed, return it 1737 if (!fTolerateDuplicates) { 1738 if (retObj != null) { 1739 return retObj; 1740 } 1741 } 1742 else { 1743 Object retObj2 = getGlobalDecl(declKey, declType); 1744 if (retObj2 != null) { 1745 return retObj2; 1746 } 1747 } 1748 1749 XSDocumentInfo schemaWithDecl = null; 1750 Element decl = null; 1751 XSDocumentInfo declDoc = null; 1752 1753 // the component is not parsed, try to find a DOM element for it 1754 switch (declType) { 1755 case ATTRIBUTE_TYPE : 1756 decl = getElementFromMap(fUnparsedAttributeRegistry, declKey); 1757 declDoc = getDocInfoFromMap(fUnparsedAttributeRegistrySub, declKey); 1758 break; 1759 case ATTRIBUTEGROUP_TYPE : 1760 decl = getElementFromMap(fUnparsedAttributeGroupRegistry, declKey); 1761 declDoc = getDocInfoFromMap(fUnparsedAttributeGroupRegistrySub, declKey); 1762 break; 1763 case ELEMENT_TYPE : 1764 decl = getElementFromMap(fUnparsedElementRegistry, declKey); 1765 declDoc = getDocInfoFromMap(fUnparsedElementRegistrySub, declKey); 1766 break; 1767 case GROUP_TYPE : 1768 decl = getElementFromMap(fUnparsedGroupRegistry, declKey); 1769 declDoc = getDocInfoFromMap(fUnparsedGroupRegistrySub, declKey); 1770 break; 1771 case IDENTITYCONSTRAINT_TYPE : 1772 decl = getElementFromMap(fUnparsedIdentityConstraintRegistry, declKey); 1773 declDoc = getDocInfoFromMap(fUnparsedIdentityConstraintRegistrySub, declKey); 1774 break; 1775 case NOTATION_TYPE : 1776 decl = getElementFromMap(fUnparsedNotationRegistry, declKey); 1777 declDoc = getDocInfoFromMap(fUnparsedNotationRegistrySub, declKey); 1778 break; 1779 case TYPEDECL_TYPE : 1780 decl = getElementFromMap(fUnparsedTypeRegistry, declKey); 1781 declDoc = getDocInfoFromMap(fUnparsedTypeRegistrySub, declKey); 1782 break; 1783 default: 1784 reportSchemaError("Internal-Error", new Object [] {"XSDHandler asked to locate component of type " + declType + "; it does not recognize this type!"}, elmNode); 1785 } 1786 1787 // no DOM element found, so the component can't be located 1788 if (decl == null) { 1789 if (retObj == null) { 1790 reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode); 1791 } 1792 return retObj; 1793 } 1794 1795 // get the schema doc containing the component to be parsed 1796 // it should always return non-null value, but since null-checking 1797 // comes for free, let's be safe and check again 1798 schemaWithDecl = findXSDocumentForDecl(currSchema, decl, declDoc); 1799 if (schemaWithDecl == null) { 1800 // cannot get to this schema from the one containing the requesting decl 1801 if (retObj == null) { 1802 String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2"; 1803 reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode); 1804 } 1805 return retObj; 1806 } 1807 1808 // a component is hidden, meaning either it's traversed, or being traversed. 1809 // but we didn't find it in the grammar, so it's the latter case, and 1810 // a circular reference. error! 1811 if (DOMUtil.isHidden(decl, fHiddenNodes)) { 1812 if (retObj == null) { 1813 String code = CIRCULAR_CODES[declType]; 1814 if (declType == TYPEDECL_TYPE) { 1815 if (SchemaSymbols.ELT_COMPLEXTYPE.equals(DOMUtil.getLocalName(decl))) { 1816 code = "ct-props-correct.3"; 1817 } 1818 } 1819 // decl must not be null if we're here... 1820 reportSchemaError(code, new Object [] {declToTraverse.prefix+":"+declToTraverse.localpart}, elmNode); 1821 } 1822 return retObj; 1823 } 1824 1825 return traverseGlobalDecl(declType, decl, schemaWithDecl, sGrammar); 1826 } // getGlobalDecl(XSDocumentInfo, int, QName): Object 1827 1828 // If we are tolerating duplicate declarations and allowing namespace growth 1829 // use the declaration from the current schema load (if it exists) 1830 protected Object getGlobalDecl(String declKey, int declType) { 1831 Object retObj = null; 1832 1833 switch (declType) { 1834 case ATTRIBUTE_TYPE : 1835 retObj = getGlobalAttributeDecl(declKey); 1836 break; 1837 case ATTRIBUTEGROUP_TYPE : 1838 retObj = getGlobalAttributeGroupDecl(declKey); 1839 break; 1840 case ELEMENT_TYPE : 1841 retObj = getGlobalElementDecl(declKey); 1842 break; 1843 case GROUP_TYPE : 1844 retObj = getGlobalGroupDecl(declKey); 1845 break; 1846 case IDENTITYCONSTRAINT_TYPE : 1847 retObj = getIDConstraintDecl(declKey); 1848 break; 1849 case NOTATION_TYPE : 1850 retObj = getGlobalNotationDecl(declKey); 1851 break; 1852 case TYPEDECL_TYPE : 1853 retObj = getGlobalTypeDecl(declKey); 1854 break; 1855 } 1856 1857 return retObj; 1858 } 1859 1860 protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart) { 1861 Object retObj = null; 1862 1863 switch (declType) { 1864 case ATTRIBUTE_TYPE : 1865 retObj = sGrammar.getGlobalAttributeDecl(localpart); 1866 break; 1867 case ATTRIBUTEGROUP_TYPE : 1868 retObj = sGrammar.getGlobalAttributeGroupDecl(localpart); 1869 break; 1870 case ELEMENT_TYPE : 1871 retObj = sGrammar.getGlobalElementDecl(localpart); 1872 break; 1873 case GROUP_TYPE : 1874 retObj = sGrammar.getGlobalGroupDecl(localpart); 1875 break; 1876 case IDENTITYCONSTRAINT_TYPE : 1877 retObj = sGrammar.getIDConstraintDecl(localpart); 1878 break; 1879 case NOTATION_TYPE : 1880 retObj = sGrammar.getGlobalNotationDecl(localpart); 1881 break; 1882 case TYPEDECL_TYPE : 1883 retObj = sGrammar.getGlobalTypeDecl(localpart); 1884 break; 1885 } 1886 1887 return retObj; 1888 } 1889 1890 protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart, String schemaLoc) { 1891 Object retObj = null; 1892 1893 switch (declType) { 1894 case ATTRIBUTE_TYPE : 1895 retObj = sGrammar.getGlobalAttributeDecl(localpart, schemaLoc); 1896 break; 1897 case ATTRIBUTEGROUP_TYPE : 1898 retObj = sGrammar.getGlobalAttributeGroupDecl(localpart, schemaLoc); 1899 break; 1900 case ELEMENT_TYPE : 1901 retObj = sGrammar.getGlobalElementDecl(localpart, schemaLoc); 1902 break; 1903 case GROUP_TYPE : 1904 retObj = sGrammar.getGlobalGroupDecl(localpart, schemaLoc); 1905 break; 1906 case IDENTITYCONSTRAINT_TYPE : 1907 retObj = sGrammar.getIDConstraintDecl(localpart, schemaLoc); 1908 break; 1909 case NOTATION_TYPE : 1910 retObj = sGrammar.getGlobalNotationDecl(localpart, schemaLoc); 1911 break; 1912 case TYPEDECL_TYPE : 1913 retObj = sGrammar.getGlobalTypeDecl(localpart, schemaLoc); 1914 break; 1915 } 1916 1917 return retObj; 1918 } 1919 1920 protected Object traverseGlobalDecl(int declType, Element decl, 1921 XSDocumentInfo schemaDoc, SchemaGrammar grammar) { 1922 Object retObj = null; 1923 1924 DOMUtil.setHidden(decl, fHiddenNodes); 1925 SchemaNamespaceSupport nsSupport = null; 1926 // if the parent is <redefine> use the namespace delcs for it. 1927 Element parent = DOMUtil.getParent(decl); 1928 if (DOMUtil.getLocalName(parent).equals(SchemaSymbols.ELT_REDEFINE)) 1929 nsSupport = (fRedefine2NSSupport!=null) ? fRedefine2NSSupport.get(parent) : null; 1930 // back up the current SchemaNamespaceSupport, because we need to provide 1931 // a fresh one to the traverseGlobal methods. 1932 schemaDoc.backupNSSupport(nsSupport); 1933 1934 // traverse the referenced global component 1935 switch (declType) { 1936 case TYPEDECL_TYPE : 1937 if (DOMUtil.getLocalName(decl).equals(SchemaSymbols.ELT_COMPLEXTYPE)) { 1938 retObj = fComplexTypeTraverser.traverseGlobal(decl, schemaDoc, grammar); 1939 } 1940 else { 1941 retObj = fSimpleTypeTraverser.traverseGlobal(decl, schemaDoc, grammar); 1942 } 1943 break; 1944 case ATTRIBUTE_TYPE : 1945 retObj = fAttributeTraverser.traverseGlobal(decl, schemaDoc, grammar); 1946 break; 1947 case ELEMENT_TYPE : 1948 retObj = fElementTraverser.traverseGlobal(decl, schemaDoc, grammar); 1949 break; 1950 case ATTRIBUTEGROUP_TYPE : 1951 retObj = fAttributeGroupTraverser.traverseGlobal(decl, schemaDoc, grammar); 1952 break; 1953 case GROUP_TYPE : 1954 retObj = fGroupTraverser.traverseGlobal(decl, schemaDoc, grammar); 1955 break; 1956 case NOTATION_TYPE : 1957 retObj = fNotationTraverser.traverse(decl, schemaDoc, grammar); 1958 break; 1959 case IDENTITYCONSTRAINT_TYPE : 1960 // identity constraints should have been parsed already... 1961 // we should never get here 1962 break; 1963 } 1964 1965 // restore the previous SchemaNamespaceSupport, so that the caller can get 1966 // proper namespace binding. 1967 schemaDoc.restoreNSSupport(); 1968 1969 return retObj; 1970 } 1971 1972 public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) { 1973 return fDoc2SystemId.get(schemaDoc.fSchemaElement); 1974 } 1975 1976 // This method determines whether there is a group 1977 // (attributeGroup) which the given one has redefined by 1978 // restriction. If so, it returns it; else it returns null. 1979 // @param type: whether what's been redefined is an 1980 // attributeGroup or a group; 1981 // @param name: the QName of the component doing the redefining. 1982 // @param currSchema: schema doc in which the redefining component lives. 1983 // @return: Object representing decl redefined if present, null 1984 // otherwise. 1985 Object getGrpOrAttrGrpRedefinedByRestriction(int type, QName name, XSDocumentInfo currSchema, Element elmNode) { 1986 String realName = name.uri != null?name.uri+","+name.localpart: 1987 ","+name.localpart; 1988 String nameToFind = null; 1989 switch (type) { 1990 case ATTRIBUTEGROUP_TYPE: 1991 nameToFind = fRedefinedRestrictedAttributeGroupRegistry.get(realName); 1992 break; 1993 case GROUP_TYPE: 1994 nameToFind = fRedefinedRestrictedGroupRegistry.get(realName); 1995 break; 1996 default: 1997 return null; 1998 } 1999 if (nameToFind == null) return null; 2000 int commaPos = nameToFind.indexOf(","); 2001 QName qNameToFind = new QName(XMLSymbols.EMPTY_STRING, nameToFind.substring(commaPos+1), 2002 nameToFind.substring(commaPos), (commaPos == 0)? null : nameToFind.substring(0, commaPos)); 2003 Object retObj = getGlobalDecl(currSchema, type, qNameToFind, elmNode); 2004 if(retObj == null) { 2005 switch (type) { 2006 case ATTRIBUTEGROUP_TYPE: 2007 reportSchemaError("src-redefine.7.2.1", new Object []{name.localpart}, elmNode); 2008 break; 2009 case GROUP_TYPE: 2010 reportSchemaError("src-redefine.6.2.1", new Object []{name.localpart}, elmNode); 2011 break; 2012 } 2013 return null; 2014 } 2015 return retObj; 2016 } // getGrpOrAttrGrpRedefinedByRestriction(int, QName, XSDocumentInfo): Object 2017 2018 // Since ID constraints can occur in local elements, unless we 2019 // wish to completely traverse all our DOM trees looking for ID 2020 // constraints while we're building our global name registries, 2021 // which seems terribly inefficient, we need to resolve keyrefs 2022 // after all parsing is complete. This we can simply do by running through 2023 // fIdentityConstraintRegistry and calling traverseKeyRef on all 2024 // of the KeyRef nodes. This unfortunately removes this knowledge 2025 // from the elementTraverser class (which must ignore keyrefs), 2026 // but there seems to be no efficient way around this... 2027 protected void resolveKeyRefs() { 2028 for (int i=0; i<fKeyrefStackPos; i++) { 2029 XSDocumentInfo keyrefSchemaDoc = fKeyrefsMapXSDocumentInfo[i]; 2030 keyrefSchemaDoc.fNamespaceSupport.makeGlobal(); 2031 keyrefSchemaDoc.fNamespaceSupport.setEffectiveContext( fKeyrefNamespaceContext[i] ); 2032 SchemaGrammar keyrefGrammar = fGrammarBucket.getGrammar(keyrefSchemaDoc.fTargetNamespace); 2033 // need to set <keyref> to hidden before traversing it, 2034 // because it has global scope 2035 DOMUtil.setHidden(fKeyrefs[i], fHiddenNodes); 2036 fKeyrefTraverser.traverse(fKeyrefs[i], fKeyrefElems[i], keyrefSchemaDoc, keyrefGrammar); 2037 } 2038 } // end resolveKeyRefs 2039 2040 // an accessor method. Just makes sure callers 2041 // who want the Identity constraint registry vaguely know what they're about. 2042 protected Map<String, Element> getIDRegistry() { 2043 return fUnparsedIdentityConstraintRegistry; 2044 } 2045 // an accessor method. 2046 protected Map<String, XSDocumentInfo> getIDRegistry_sub() { 2047 return fUnparsedIdentityConstraintRegistrySub; 2048 } 2049 2050 2051 2052 // This method squirrels away <keyref> declarations--along with the element 2053 // decls and namespace bindings they might find handy. 2054 protected void storeKeyRef (Element keyrefToStore, XSDocumentInfo schemaDoc, 2055 XSElementDecl currElemDecl) { 2056 String keyrefName = DOMUtil.getAttrValue(keyrefToStore, SchemaSymbols.ATT_NAME); 2057 if (keyrefName.length() != 0) { 2058 String keyrefQName = schemaDoc.fTargetNamespace == null? 2059 "," + keyrefName: schemaDoc.fTargetNamespace+","+keyrefName; 2060 checkForDuplicateNames(keyrefQName, IDENTITYCONSTRAINT_TYPE, fUnparsedIdentityConstraintRegistry, fUnparsedIdentityConstraintRegistrySub, keyrefToStore, schemaDoc); 2061 } 2062 // now set up all the registries we'll need... 2063 2064 // check array sizes 2065 if (fKeyrefStackPos == fKeyrefs.length) { 2066 Element [] elemArray = new Element [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; 2067 System.arraycopy(fKeyrefs, 0, elemArray, 0, fKeyrefStackPos); 2068 fKeyrefs = elemArray; 2069 XSElementDecl [] declArray = new XSElementDecl [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; 2070 System.arraycopy(fKeyrefElems, 0, declArray, 0, fKeyrefStackPos); 2071 fKeyrefElems = declArray; 2072 String[][] stringArray = new String [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT][]; 2073 System.arraycopy(fKeyrefNamespaceContext, 0, stringArray, 0, fKeyrefStackPos); 2074 fKeyrefNamespaceContext = stringArray; 2075 2076 XSDocumentInfo [] xsDocumentInfo = new XSDocumentInfo [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; 2077 System.arraycopy(fKeyrefsMapXSDocumentInfo, 0, xsDocumentInfo, 0, fKeyrefStackPos); 2078 fKeyrefsMapXSDocumentInfo = xsDocumentInfo; 2079 2080 } 2081 fKeyrefs[fKeyrefStackPos] = keyrefToStore; 2082 fKeyrefElems[fKeyrefStackPos] = currElemDecl; 2083 fKeyrefNamespaceContext[fKeyrefStackPos] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext(); 2084 2085 fKeyrefsMapXSDocumentInfo[fKeyrefStackPos++] = schemaDoc; 2086 } // storeKeyref (Element, XSDocumentInfo, XSElementDecl): void 2087 2088 2089 /** 2090 * resolveSchema method is responsible for resolving location of the schema (using XMLEntityResolver), 2091 * and if it was successfully resolved getting the schema Document. 2092 * @param desc 2093 * @param mustResolve 2094 * @param referElement 2095 * @return A schema Element or null. 2096 */ 2097 private Element resolveSchema(XSDDescription desc, boolean mustResolve, 2098 Element referElement, boolean usePairs) { 2099 XMLInputSource schemaSource = null; 2100 try { 2101 Map<String, XMLSchemaLoader.LocationArray> pairs = usePairs ? fLocationPairs : Collections.emptyMap(); 2102 schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager); 2103 } 2104 catch (IOException ex) { 2105 if (mustResolve) { 2106 reportSchemaError("schema_reference.4", 2107 new Object[]{desc.getLocationHints()[0]}, 2108 referElement); 2109 } 2110 else { 2111 reportSchemaWarning("schema_reference.4", 2112 new Object[]{desc.getLocationHints()[0]}, 2113 referElement); 2114 } 2115 } 2116 if (schemaSource instanceof DOMInputSource) { 2117 return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); 2118 } // DOMInputSource 2119 else if (schemaSource instanceof SAXInputSource) { 2120 return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); 2121 } // SAXInputSource 2122 else if (schemaSource instanceof StAXInputSource) { 2123 return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); 2124 } // StAXInputSource 2125 else if (schemaSource instanceof XSInputSource) { 2126 return getSchemaDocument((XSInputSource) schemaSource, desc); 2127 } // XSInputSource 2128 return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement); 2129 } // getSchema(String, String, String, boolean, short): Document 2130 2131 private Element resolveSchema(XMLInputSource schemaSource, XSDDescription desc, 2132 boolean mustResolve, Element referElement) { 2133 2134 if (schemaSource instanceof DOMInputSource) { 2135 return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); 2136 } // DOMInputSource 2137 else if (schemaSource instanceof SAXInputSource) { 2138 return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); 2139 } // SAXInputSource 2140 else if (schemaSource instanceof StAXInputSource) { 2141 return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); 2142 } // StAXInputSource 2143 else if (schemaSource instanceof XSInputSource) { 2144 return getSchemaDocument((XSInputSource) schemaSource, desc); 2145 } // XSInputSource 2146 return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement); 2147 } 2148 2149 private XMLInputSource resolveSchemaSource(XSDDescription desc, boolean mustResolve, 2150 Element referElement, boolean usePairs) { 2151 2152 XMLInputSource schemaSource = null; 2153 try { 2154 Map<String, XMLSchemaLoader.LocationArray> pairs = usePairs ? fLocationPairs : Collections.emptyMap(); 2155 schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager); 2156 } 2157 catch (IOException ex) { 2158 if (mustResolve) { 2159 reportSchemaError("schema_reference.4", 2160 new Object[]{desc.getLocationHints()[0]}, 2161 referElement); 2162 } 2163 else { 2164 reportSchemaWarning("schema_reference.4", 2165 new Object[]{desc.getLocationHints()[0]}, 2166 referElement); 2167 } 2168 } 2169 2170 return schemaSource; 2171 } 2172 2173 /** 2174 * getSchemaDocument method uses XMLInputSource to parse a schema document. 2175 * @param schemaNamespace 2176 * @param schemaSource 2177 * @param mustResolve 2178 * @param referType 2179 * @param referElement 2180 * @return A schema Element. 2181 */ 2182 private Element getSchemaDocument(String schemaNamespace, XMLInputSource schemaSource, 2183 boolean mustResolve, short referType, Element referElement) { 2184 2185 boolean hasInput = true; 2186 IOException exception = null; 2187 // contents of this method will depend on the system we adopt for entity resolution--i.e., XMLEntityHandler, EntityHandler, etc. 2188 Element schemaElement = null; 2189 try { 2190 // when the system id and byte stream and character stream 2191 // of the input source are all null, it's 2192 // impossible to find the schema document. so we skip in 2193 // this case. otherwise we'll receive some NPE or 2194 // file not found errors. but schemaHint=="" is perfectly 2195 // legal for import. 2196 if (schemaSource != null && 2197 (schemaSource.getSystemId() != null || 2198 schemaSource.getByteStream() != null || 2199 schemaSource.getCharacterStream() != null)) { 2200 2201 // When the system id of the input source is used, first try to 2202 // expand it, and check whether the same document has been 2203 // parsed before. If so, return the document corresponding to 2204 // that system id. 2205 XSDKey key = null; 2206 String schemaId = null; 2207 if (referType != XSDDescription.CONTEXT_PREPARSE){ 2208 schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); 2209 key = new XSDKey(schemaId, referType, schemaNamespace); 2210 if((schemaElement = fTraversed.get(key)) != null) { 2211 fLastSchemaWasDuplicate = true; 2212 return schemaElement; 2213 } 2214 if ((!schemaSource.isCreatedByResolver()) && 2215 (referType == XSDDescription.CONTEXT_IMPORT || referType == XSDDescription.CONTEXT_INCLUDE 2216 || referType == XSDDescription.CONTEXT_REDEFINE)) { 2217 String accessError = SecuritySupport.checkAccess(schemaId, fAccessExternalSchema, Constants.ACCESS_EXTERNAL_ALL); 2218 if (accessError != null) { 2219 reportSchemaFatalError("schema_reference.access", 2220 new Object[] { SecuritySupport.sanitizePath(schemaId), accessError }, 2221 referElement); 2222 } 2223 } 2224 } 2225 2226 fSchemaParser.parse(schemaSource); 2227 Document schemaDocument = fSchemaParser.getDocument(); 2228 schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; 2229 return getSchemaDocument0(key, schemaId, schemaElement); 2230 } 2231 else { 2232 hasInput = false; 2233 } 2234 } 2235 catch (IOException ex) { 2236 exception = ex; 2237 } 2238 return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); 2239 } // getSchemaDocument(String, XMLInputSource, boolean, short, Element): Element 2240 2241 /** 2242 * getSchemaDocument method uses SAXInputSource to parse a schema document. 2243 * @param schemaNamespace 2244 * @param schemaSource 2245 * @param mustResolve 2246 * @param referType 2247 * @param referElement 2248 * @return A schema Element. 2249 */ 2250 private Element getSchemaDocument(String schemaNamespace, SAXInputSource schemaSource, 2251 boolean mustResolve, short referType, Element referElement) { 2252 XMLReader parser = schemaSource.getXMLReader(); 2253 InputSource inputSource = schemaSource.getInputSource(); 2254 boolean hasInput = true; 2255 IOException exception = null; 2256 Element schemaElement = null; 2257 try { 2258 if (inputSource != null && 2259 (inputSource.getSystemId() != null || 2260 inputSource.getByteStream() != null || 2261 inputSource.getCharacterStream() != null)) { 2262 2263 // check whether the same document has been parsed before. 2264 // If so, return the document corresponding to that system id. 2265 XSDKey key = null; 2266 String schemaId = null; 2267 if (referType != XSDDescription.CONTEXT_PREPARSE) { 2268 schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(), 2269 schemaSource.getBaseSystemId(), false); 2270 key = new XSDKey(schemaId, referType, schemaNamespace); 2271 if ((schemaElement = fTraversed.get(key)) != null) { 2272 fLastSchemaWasDuplicate = true; 2273 return schemaElement; 2274 } 2275 } 2276 2277 boolean namespacePrefixes = false; 2278 if (parser != null) { 2279 try { 2280 namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES); 2281 } 2282 catch (SAXException se) {} 2283 } 2284 else { 2285 parser = JdkXmlUtils.getXMLReader(fOverrideDefaultParser, 2286 fSecurityManager.isSecureProcessing()); 2287 2288 try { 2289 parser.setFeature(NAMESPACE_PREFIXES, true); 2290 namespacePrefixes = true; 2291 // If this is a Xerces SAX parser set the security manager if there is one 2292 if (parser instanceof SAXParser) { 2293 if (fSecurityManager != null) { 2294 parser.setProperty(SECURITY_MANAGER, fSecurityManager); 2295 } 2296 } 2297 } 2298 catch (SAXException se) {} 2299 2300 try { 2301 parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, fAccessExternalDTD); 2302 } catch (SAXNotRecognizedException exc) { 2303 XMLSecurityManager.printWarning(parser.getClass().getName(), 2304 XMLConstants.ACCESS_EXTERNAL_DTD, exc); 2305 } 2306 } 2307 // If XML names and Namespace URIs are already internalized we 2308 // can avoid running them through the SymbolTable. 2309 boolean stringsInternalized = false; 2310 try { 2311 stringsInternalized = parser.getFeature(STRING_INTERNING); 2312 } 2313 catch (SAXException exc) { 2314 // The feature isn't recognized or getting it is not supported. 2315 // In either case, assume that strings are not internalized. 2316 } 2317 if (fXSContentHandler == null) { 2318 fXSContentHandler = new SchemaContentHandler(); 2319 } 2320 fXSContentHandler.reset(fSchemaParser, fSymbolTable, 2321 namespacePrefixes, stringsInternalized); 2322 parser.setContentHandler(fXSContentHandler); 2323 parser.setErrorHandler(fErrorReporter.getSAXErrorHandler()); 2324 2325 parser.parse(inputSource); 2326 // Disconnect the schema loader and other objects from the XMLReader 2327 try { 2328 parser.setContentHandler(null); 2329 parser.setErrorHandler(null); 2330 } 2331 // Ignore any exceptions thrown by the XMLReader. Old versions of SAX 2332 // required an XMLReader to throw a NullPointerException if an attempt 2333 // to set a handler to null was made. 2334 catch (Exception e) {} 2335 2336 Document schemaDocument = fXSContentHandler.getDocument(); 2337 schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; 2338 return getSchemaDocument0(key, schemaId, schemaElement); 2339 } 2340 else { 2341 hasInput = false; 2342 } 2343 } 2344 catch (SAXParseException spe) { 2345 throw SAX2XNIUtil.createXMLParseException0(spe); 2346 } 2347 catch (SAXException se) { 2348 throw SAX2XNIUtil.createXNIException0(se); 2349 } 2350 catch (IOException ioe) { 2351 exception = ioe; 2352 } 2353 return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); 2354 } // getSchemaDocument(String, SAXInputSource, boolean, short, Element): Element 2355 2356 /** 2357 * getSchemaDocument method uses DOMInputSource to parse a schema document. 2358 * @param schemaNamespace 2359 * @param schemaSource 2360 * @param mustResolve 2361 * @param referType 2362 * @param referElement 2363 * @return A schema Element. 2364 */ 2365 private Element getSchemaDocument(String schemaNamespace, DOMInputSource schemaSource, 2366 boolean mustResolve, short referType, Element referElement) { 2367 boolean hasInput = true; 2368 IOException exception = null; 2369 Element schemaElement = null; 2370 Element schemaRootElement = null; 2371 2372 final Node node = schemaSource.getNode(); 2373 short nodeType = -1; 2374 if (node != null) { 2375 nodeType = node.getNodeType(); 2376 if (nodeType == Node.DOCUMENT_NODE) { 2377 schemaRootElement = DOMUtil.getRoot((Document) node); 2378 } 2379 else if (nodeType == Node.ELEMENT_NODE) { 2380 schemaRootElement = (Element) node; 2381 } 2382 } 2383 2384 try { 2385 if (schemaRootElement != null) { 2386 // check whether the same document has been parsed before. 2387 // If so, return the document corresponding to that system id. 2388 XSDKey key = null; 2389 String schemaId = null; 2390 if (referType != XSDDescription.CONTEXT_PREPARSE) { 2391 schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); 2392 boolean isDocument = (nodeType == Node.DOCUMENT_NODE); 2393 if (!isDocument) { 2394 Node parent = schemaRootElement.getParentNode(); 2395 if (parent != null) { 2396 isDocument = (parent.getNodeType() == Node.DOCUMENT_NODE); 2397 } 2398 } 2399 if (isDocument) { 2400 key = new XSDKey(schemaId, referType, schemaNamespace); 2401 if ((schemaElement = fTraversed.get(key)) != null) { 2402 fLastSchemaWasDuplicate = true; 2403 return schemaElement; 2404 } 2405 } 2406 } 2407 2408 schemaElement = schemaRootElement; 2409 return getSchemaDocument0(key, schemaId, schemaElement); 2410 } 2411 else { 2412 hasInput = false; 2413 } 2414 } 2415 catch (IOException ioe) { 2416 exception = ioe; 2417 } 2418 return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); 2419 } // getSchemaDocument(String, DOMInputSource, boolean, short, Element): Element 2420 2421 /** 2422 * getSchemaDocument method uses StAXInputSource to parse a schema document. 2423 * @param schemaNamespace 2424 * @param schemaSource 2425 * @param mustResolve 2426 * @param referType 2427 * @param referElement 2428 * @return A schema Element. 2429 */ 2430 private Element getSchemaDocument(String schemaNamespace, StAXInputSource schemaSource, 2431 boolean mustResolve, short referType, Element referElement) { 2432 IOException exception = null; 2433 Element schemaElement = null; 2434 try { 2435 final boolean consumeRemainingContent = schemaSource.shouldConsumeRemainingContent(); 2436 final XMLStreamReader streamReader = schemaSource.getXMLStreamReader(); 2437 final XMLEventReader eventReader = schemaSource.getXMLEventReader(); 2438 2439 // check whether the same document has been parsed before. 2440 // If so, return the document corresponding to that system id. 2441 XSDKey key = null; 2442 String schemaId = null; 2443 if (referType != XSDDescription.CONTEXT_PREPARSE) { 2444 schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); 2445 boolean isDocument = consumeRemainingContent; 2446 if (!isDocument) { 2447 if (streamReader != null) { 2448 isDocument = (streamReader.getEventType() == XMLStreamReader.START_DOCUMENT); 2449 } 2450 else { 2451 isDocument = eventReader.peek().isStartDocument(); 2452 } 2453 } 2454 if (isDocument) { 2455 key = new XSDKey(schemaId, referType, schemaNamespace); 2456 if ((schemaElement = fTraversed.get(key)) != null) { 2457 fLastSchemaWasDuplicate = true; 2458 return schemaElement; 2459 } 2460 } 2461 } 2462 2463 if (fStAXSchemaParser == null) { 2464 fStAXSchemaParser = new StAXSchemaParser(); 2465 } 2466 fStAXSchemaParser.reset(fSchemaParser, fSymbolTable); 2467 2468 if (streamReader != null) { 2469 fStAXSchemaParser.parse(streamReader); 2470 if (consumeRemainingContent) { 2471 while (streamReader.hasNext()) { 2472 streamReader.next(); 2473 } 2474 } 2475 } 2476 else { 2477 fStAXSchemaParser.parse(eventReader); 2478 if (consumeRemainingContent) { 2479 while (eventReader.hasNext()) { 2480 eventReader.nextEvent(); 2481 } 2482 } 2483 } 2484 Document schemaDocument = fStAXSchemaParser.getDocument(); 2485 schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; 2486 return getSchemaDocument0(key, schemaId, schemaElement); 2487 } 2488 catch (XMLStreamException e) { 2489 Throwable t = e.getNestedException(); 2490 if (t instanceof IOException) { 2491 exception = (IOException) t; 2492 } 2493 else { 2494 StAXLocationWrapper slw = new StAXLocationWrapper(); 2495 slw.setLocation(e.getLocation()); 2496 throw new XMLParseException(slw, e.getMessage(), e); 2497 } 2498 } 2499 catch (IOException e) { 2500 exception = e; 2501 } 2502 return getSchemaDocument1(mustResolve, true, schemaSource, referElement, exception); 2503 } // getSchemaDocument(String, StAXInputSource, boolean, short, Element): Element 2504 2505 /** 2506 * Code shared between the various getSchemaDocument() methods which 2507 * stores mapping information for the document. 2508 */ 2509 private Element getSchemaDocument0(XSDKey key, String schemaId, Element schemaElement) { 2510 // now we need to store the mapping information from system id 2511 // to the document. also from the document to the system id. 2512 if (key != null) { 2513 fTraversed.put(key, schemaElement); 2514 } 2515 if (schemaId != null) { 2516 fDoc2SystemId.put(schemaElement, schemaId); 2517 } 2518 fLastSchemaWasDuplicate = false; 2519 return schemaElement; 2520 } // getSchemaDocument0(XSDKey, String, Element): Element 2521 2522 /** 2523 * Error handling code shared between the various getSchemaDocument() methods. 2524 */ 2525 private Element getSchemaDocument1(boolean mustResolve, boolean hasInput, 2526 XMLInputSource schemaSource, Element referElement, IOException ioe) { 2527 // either an error occured (exception), or empty input source was 2528 // returned, we need to report an error or a warning 2529 if (mustResolve) { 2530 if (hasInput) { 2531 reportSchemaError("schema_reference.4", 2532 new Object[]{schemaSource.getSystemId()}, 2533 referElement, ioe); 2534 } 2535 else { 2536 reportSchemaError("schema_reference.4", 2537 new Object[]{schemaSource == null ? "" : schemaSource.getSystemId()}, 2538 referElement, ioe); 2539 } 2540 } 2541 else if (hasInput) { 2542 reportSchemaWarning("schema_reference.4", 2543 new Object[]{schemaSource.getSystemId()}, 2544 referElement, ioe); 2545 } 2546 2547 fLastSchemaWasDuplicate = false; 2548 return null; 2549 } // getSchemaDocument1(boolean, boolean, XMLInputSource, Element): Element 2550 2551 /** 2552 * getSchemaDocument method uses XMLInputSource to parse a schema document. 2553 * @param schemaNamespace 2554 * @param schemaSource 2555 * @param mustResolve 2556 * @param referType 2557 * @param referElement 2558 * @return A schema Element. 2559 */ 2560 private Element getSchemaDocument(XSInputSource schemaSource, XSDDescription desc) { 2561 2562 SchemaGrammar[] grammars = schemaSource.getGrammars(); 2563 short referType = desc.getContextType(); 2564 2565 if (grammars != null && grammars.length > 0) { 2566 List<SchemaGrammar> expandedGrammars = expandGrammars(grammars); 2567 // check for existing grammars in our bucket 2568 // and if there exist any, and namespace growth is 2569 // not enabled - we do nothing 2570 if (fNamespaceGrowth || !existingGrammars(expandedGrammars)) { 2571 addGrammars(expandedGrammars); 2572 if (referType == XSDDescription.CONTEXT_PREPARSE) { 2573 desc.setTargetNamespace(grammars[0].getTargetNamespace()); 2574 } 2575 } 2576 } 2577 else { 2578 XSObject[] components = schemaSource.getComponents(); 2579 if (components != null && components.length > 0) { 2580 Map<String, List<String>> importDependencies = new HashMap<>(); 2581 List<XSObject> expandedComponents = expandComponents(components, importDependencies); 2582 if (fNamespaceGrowth || canAddComponents(expandedComponents)) { 2583 addGlobalComponents(expandedComponents, importDependencies); 2584 if (referType == XSDDescription.CONTEXT_PREPARSE) { 2585 desc.setTargetNamespace(components[0].getNamespace()); 2586 } 2587 } 2588 } 2589 } 2590 return null; 2591 } // getSchemaDocument(String, XSInputSource, boolean, short, Element): Element 2592 2593 private List<SchemaGrammar> expandGrammars(SchemaGrammar[] grammars) { 2594 List<SchemaGrammar> currGrammars = new ArrayList<>(); 2595 2596 for (int i=0; i<grammars.length; i++) { 2597 if (!currGrammars.contains(grammars[i])) { 2598 currGrammars.add(grammars[i]); 2599 } 2600 } 2601 2602 // for all (recursively) imported grammars 2603 SchemaGrammar sg1, sg2; 2604 List<SchemaGrammar> gs; 2605 for (int i = 0; i < currGrammars.size(); i++) { 2606 // get the grammar 2607 sg1 = currGrammars.get(i); 2608 // we need to add grammars imported by sg1 too 2609 gs = sg1.getImportedGrammars(); 2610 // for all grammars imported by sg2, but not in the vector 2611 // we add them to the vector 2612 if (gs == null) { 2613 continue; 2614 } 2615 2616 for (int j = gs.size() - 1; j >= 0; j--) { 2617 sg2 = gs.get(j); 2618 if (!currGrammars.contains(sg2)) { 2619 currGrammars.add(sg2); 2620 } 2621 } 2622 } 2623 2624 return currGrammars; 2625 } 2626 2627 private boolean existingGrammars(List<SchemaGrammar> grammars) { 2628 int length = grammars.size(); 2629 final XSDDescription desc = new XSDDescription(); 2630 2631 for (int i=0; i < length; i++) { 2632 final SchemaGrammar sg1 = grammars.get(i); 2633 desc.setNamespace(sg1.getTargetNamespace()); 2634 2635 final SchemaGrammar sg2 = findGrammar(desc, false); 2636 if (sg2 != null) { 2637 return true; 2638 } 2639 } 2640 2641 return false; 2642 } 2643 2644 private boolean canAddComponents(List<XSObject> components) { 2645 final int size = components.size(); 2646 final XSDDescription desc = new XSDDescription(); 2647 for (int i=0; i<size; i++) { 2648 XSObject component = components.get(i); 2649 if (!canAddComponent(component, desc)) { 2650 return false; 2651 } 2652 } 2653 return true; 2654 } 2655 2656 private boolean canAddComponent(XSObject component, XSDDescription desc) { 2657 desc.setNamespace(component.getNamespace()); 2658 2659 final SchemaGrammar sg = findGrammar(desc, false); 2660 if (sg == null) { 2661 return true; 2662 } 2663 else if (sg.isImmutable()) { 2664 return false; 2665 } 2666 2667 short componentType = component.getType(); 2668 final String name = component.getName(); 2669 2670 switch (componentType) { 2671 case XSConstants.TYPE_DEFINITION : 2672 if (sg.getGlobalTypeDecl(name) == component) { 2673 return true; 2674 } 2675 break; 2676 case XSConstants.ATTRIBUTE_DECLARATION : 2677 if (sg.getGlobalAttributeDecl(name) == component) { 2678 return true; 2679 } 2680 break; 2681 case XSConstants.ATTRIBUTE_GROUP : 2682 if (sg.getGlobalAttributeDecl(name) == component) { 2683 return true; 2684 } 2685 break; 2686 case XSConstants.ELEMENT_DECLARATION : 2687 if (sg.getGlobalElementDecl(name) == component) { 2688 return true; 2689 } 2690 break; 2691 case XSConstants.MODEL_GROUP_DEFINITION : 2692 if (sg.getGlobalGroupDecl(name) == component) { 2693 return true; 2694 } 2695 break; 2696 case XSConstants.NOTATION_DECLARATION : 2697 if (sg.getGlobalNotationDecl(name) == component) { 2698 return true; 2699 } 2700 break; 2701 case XSConstants.IDENTITY_CONSTRAINT : 2702 case XSConstants.ATTRIBUTE_USE : 2703 default : 2704 return true; 2705 } 2706 return false; 2707 } 2708 2709 private void addGrammars(List<SchemaGrammar> grammars) { 2710 int length = grammars.size(); 2711 XSDDescription desc = new XSDDescription(); 2712 2713 for (int i=0; i < length; i++) { 2714 final SchemaGrammar sg1 = grammars.get(i); 2715 desc.setNamespace(sg1.getTargetNamespace()); 2716 2717 final SchemaGrammar sg2 = findGrammar(desc, fNamespaceGrowth); 2718 if (sg1 != sg2) { 2719 addGrammarComponents(sg1, sg2); 2720 } 2721 } 2722 } 2723 2724 private void addGrammarComponents(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2725 if (dstGrammar == null) { 2726 createGrammarFrom(srcGrammar); 2727 return; 2728 } 2729 2730 SchemaGrammar tmpGrammar = dstGrammar; 2731 if (tmpGrammar.isImmutable()) { 2732 tmpGrammar = createGrammarFrom(dstGrammar); 2733 } 2734 2735 // add any new locations 2736 addNewGrammarLocations(srcGrammar, tmpGrammar); 2737 2738 // add any new imported grammars 2739 addNewImportedGrammars(srcGrammar, tmpGrammar); 2740 2741 // add any new global components 2742 addNewGrammarComponents(srcGrammar, tmpGrammar); 2743 } 2744 2745 private SchemaGrammar createGrammarFrom(SchemaGrammar grammar) { 2746 SchemaGrammar newGrammar = new SchemaGrammar(grammar); 2747 fGrammarBucket.putGrammar(newGrammar); 2748 // update all the grammars in the bucket to point to the new grammar. 2749 updateImportListWith(newGrammar); 2750 // update import list of the new grammar 2751 updateImportListFor(newGrammar); 2752 return newGrammar; 2753 } 2754 2755 private void addNewGrammarLocations(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2756 final StringList locations = srcGrammar.getDocumentLocations(); 2757 final int locSize = locations.size(); 2758 final StringList locations2 = dstGrammar.getDocumentLocations(); 2759 2760 for (int i=0; i<locSize; i++) { 2761 String loc = locations.item(i); 2762 if (!locations2.contains(loc)) { 2763 dstGrammar.addDocument(null, loc); 2764 } 2765 } 2766 } 2767 2768 @SuppressWarnings("unchecked") 2769 private void addNewImportedGrammars(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2770 final ArrayList<SchemaGrammar> src = (ArrayList<SchemaGrammar>)srcGrammar.getImportedGrammars(); 2771 if (src != null) { 2772 ArrayList<SchemaGrammar> dst = (ArrayList<SchemaGrammar>)dstGrammar.getImportedGrammars(); 2773 if (dst == null) { 2774 dst = new ArrayList<>(); 2775 dstGrammar.setImportedGrammars(dst); 2776 } 2777 for (SchemaGrammar sg :src) { 2778 // Can't use the object from the source import list directly. 2779 // It's possible there is already a grammar with the same 2780 // namespace in the bucket but a different object. 2781 // This can happen if the bucket has grammar A1, and we try 2782 // to add B and A2, where A2 imports B. When B is added, we 2783 // create a new object B' and store it in the bucket. Then we 2784 // try to merge A2 and A1. We can't use B. Need to get B' from 2785 // the bucket and store it in A's import list. 2786 SchemaGrammar sg1 = fGrammarBucket.getGrammar(sg.getTargetNamespace()); 2787 if (sg1 != null) { 2788 sg = sg1; 2789 } 2790 if (!containedImportedGrammar(dst, sg)) { 2791 dst.add(sg); 2792 } 2793 } 2794 } 2795 } 2796 2797 private void updateImportList(List<SchemaGrammar> importedSrc, List<SchemaGrammar> importedDst) 2798 { 2799 final int size = importedSrc.size(); 2800 2801 for (int i=0; i<size; i++) { 2802 final SchemaGrammar sg = importedSrc.get(i); 2803 if (!containedImportedGrammar(importedDst, sg)) { 2804 importedDst.add(sg); 2805 } 2806 } 2807 } 2808 2809 private void addNewGrammarComponents(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2810 dstGrammar.resetComponents(); 2811 addGlobalElementDecls(srcGrammar, dstGrammar); 2812 addGlobalAttributeDecls(srcGrammar, dstGrammar); 2813 addGlobalAttributeGroupDecls(srcGrammar, dstGrammar); 2814 addGlobalGroupDecls(srcGrammar, dstGrammar); 2815 addGlobalTypeDecls(srcGrammar, dstGrammar); 2816 addGlobalNotationDecls(srcGrammar, dstGrammar); 2817 } 2818 2819 private void addGlobalElementDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2820 XSNamedMap components = srcGrammar.getComponents(XSConstants.ELEMENT_DECLARATION); 2821 int len = components.getLength(); 2822 XSElementDecl srcDecl, dstDecl; 2823 2824 // add global components 2825 for (int i=0; i<len; i++) { 2826 srcDecl = (XSElementDecl) components.item(i); 2827 dstDecl = dstGrammar.getGlobalElementDecl(srcDecl.getName()); 2828 if (dstDecl == null) { 2829 dstGrammar.addGlobalElementDecl(srcDecl); 2830 } 2831 else if (dstDecl != srcDecl){ 2832 // TODO: if not tolerating duplicate, generate an error message 2833 } 2834 } 2835 2836 // add any extended (duplicate) global components 2837 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ELEMENT_DECLARATION); 2838 len = componentsExt.getLength(); 2839 2840 for (int i=0; i<len; i+= 2) { 2841 final String key = (String) componentsExt.item(i); 2842 final int index = key.indexOf(','); 2843 final String location = key.substring(0, index); 2844 final String name = key.substring(index + 1, key.length()); 2845 2846 srcDecl = (XSElementDecl)componentsExt.item(i+1); 2847 dstDecl = dstGrammar.getGlobalElementDecl(name, location); 2848 if ( dstDecl == null) { 2849 dstGrammar.addGlobalElementDecl(srcDecl, location); 2850 } 2851 else if (dstDecl != srcDecl){ 2852 // TODO: if not tolerating duplicate, generate an error message 2853 } 2854 } 2855 } 2856 2857 private void addGlobalAttributeDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2858 XSNamedMap components = srcGrammar.getComponents(XSConstants.ATTRIBUTE_DECLARATION); 2859 int len = components.getLength(); 2860 XSAttributeDecl srcDecl, dstDecl; 2861 2862 // add global components 2863 for (int i=0; i<len; i++) { 2864 srcDecl = (XSAttributeDecl) components.item(i); 2865 dstDecl = dstGrammar.getGlobalAttributeDecl(srcDecl.getName()); 2866 if (dstDecl == null) { 2867 dstGrammar.addGlobalAttributeDecl(srcDecl); 2868 } 2869 else if (dstDecl != srcDecl && !fTolerateDuplicates) { 2870 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); 2871 } 2872 } 2873 2874 // add any extended (duplicate) global components 2875 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ATTRIBUTE_DECLARATION); 2876 len = componentsExt.getLength(); 2877 2878 for (int i=0; i<len; i+= 2) { 2879 final String key = (String) componentsExt.item(i); 2880 final int index = key.indexOf(','); 2881 final String location = key.substring(0, index); 2882 final String name = key.substring(index + 1, key.length()); 2883 2884 srcDecl = (XSAttributeDecl)componentsExt.item(i+1); 2885 dstDecl = dstGrammar.getGlobalAttributeDecl(name, location); 2886 if (dstDecl == null) { 2887 dstGrammar.addGlobalAttributeDecl(srcDecl, location); 2888 } 2889 // REVISIT - do we report an error? 2890 else if (dstDecl != srcDecl) { 2891 } 2892 } 2893 } 2894 2895 private void addGlobalAttributeGroupDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2896 XSNamedMap components = srcGrammar.getComponents(XSConstants.ATTRIBUTE_GROUP); 2897 int len = components.getLength(); 2898 XSAttributeGroupDecl srcDecl, dstDecl; 2899 2900 // add global components 2901 for (int i=0; i<len; i++) { 2902 srcDecl = (XSAttributeGroupDecl) components.item(i); 2903 dstDecl = dstGrammar.getGlobalAttributeGroupDecl(srcDecl.getName()); 2904 if (dstDecl == null) { 2905 dstGrammar.addGlobalAttributeGroupDecl(srcDecl); 2906 } 2907 else if (dstDecl != srcDecl && !fTolerateDuplicates) { 2908 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); 2909 } 2910 } 2911 2912 // add any extended (duplicate) global components 2913 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ATTRIBUTE_GROUP); 2914 len = componentsExt.getLength(); 2915 2916 for (int i=0; i<len; i+= 2) { 2917 final String key = (String) componentsExt.item(i); 2918 final int index = key.indexOf(','); 2919 final String location = key.substring(0, index); 2920 final String name = key.substring(index + 1, key.length()); 2921 2922 srcDecl = (XSAttributeGroupDecl)componentsExt.item(i+1); 2923 dstDecl = dstGrammar.getGlobalAttributeGroupDecl(name, location); 2924 if (dstDecl == null) { 2925 dstGrammar.addGlobalAttributeGroupDecl(srcDecl, location); 2926 } 2927 // REVISIT - do we report an error? 2928 else if (dstDecl != srcDecl) { 2929 } 2930 } 2931 } 2932 2933 private void addGlobalNotationDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2934 XSNamedMap components = srcGrammar.getComponents(XSConstants.NOTATION_DECLARATION); 2935 int len = components.getLength(); 2936 XSNotationDecl srcDecl, dstDecl; 2937 2938 // add global components 2939 for (int i=0; i<len; i++) { 2940 srcDecl = (XSNotationDecl) components.item(i); 2941 dstDecl = dstGrammar.getGlobalNotationDecl(srcDecl.getName()); 2942 if (dstDecl == null) { 2943 dstGrammar.addGlobalNotationDecl(srcDecl); 2944 } 2945 else if (dstDecl != srcDecl && !fTolerateDuplicates) { 2946 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); 2947 } 2948 } 2949 2950 // add any extended (duplicate) global components 2951 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.NOTATION_DECLARATION); 2952 len = componentsExt.getLength(); 2953 2954 for (int i=0; i<len; i+= 2) { 2955 final String key = (String) componentsExt.item(i); 2956 final int index = key.indexOf(','); 2957 final String location = key.substring(0, index); 2958 final String name = key.substring(index + 1, key.length()); 2959 2960 srcDecl = (XSNotationDecl)componentsExt.item(i+1); 2961 dstDecl = dstGrammar.getGlobalNotationDecl(name, location); 2962 if (dstDecl == null) { 2963 dstGrammar.addGlobalNotationDecl(srcDecl, location); 2964 } 2965 // REVISIT - do we report an error? 2966 else if (dstDecl != srcDecl) { 2967 } 2968 } 2969 } 2970 2971 private void addGlobalGroupDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 2972 XSNamedMap components = srcGrammar.getComponents(XSConstants.MODEL_GROUP_DEFINITION); 2973 int len = components.getLength(); 2974 XSGroupDecl srcDecl, dstDecl; 2975 2976 // add global components 2977 for (int i=0; i<len; i++) { 2978 srcDecl = (XSGroupDecl) components.item(i); 2979 dstDecl = dstGrammar.getGlobalGroupDecl(srcDecl.getName()); 2980 if (dstDecl == null) { 2981 dstGrammar.addGlobalGroupDecl(srcDecl); 2982 } 2983 else if (srcDecl != dstDecl && !fTolerateDuplicates) { 2984 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); 2985 } 2986 } 2987 2988 // add any extended (duplicate) global components 2989 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.MODEL_GROUP_DEFINITION); 2990 len = componentsExt.getLength(); 2991 2992 for (int i=0; i<len; i+= 2) { 2993 final String key = (String) componentsExt.item(i); 2994 final int index = key.indexOf(','); 2995 final String location = key.substring(0, index); 2996 final String name = key.substring(index + 1, key.length()); 2997 2998 srcDecl = (XSGroupDecl)componentsExt.item(i+1); 2999 dstDecl = dstGrammar.getGlobalGroupDecl(name, location); 3000 if (dstDecl == null) { 3001 dstGrammar.addGlobalGroupDecl(srcDecl, location); 3002 } 3003 // REVIST - do we report an error? 3004 else if (dstDecl != srcDecl) { 3005 } 3006 } 3007 } 3008 3009 private void addGlobalTypeDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { 3010 XSNamedMap components = srcGrammar.getComponents(XSConstants.TYPE_DEFINITION); 3011 int len = components.getLength(); 3012 XSTypeDefinition srcDecl, dstDecl; 3013 3014 // add global components 3015 for (int i=0; i<len; i++) { 3016 srcDecl = (XSTypeDefinition) components.item(i); 3017 dstDecl = dstGrammar.getGlobalTypeDecl(srcDecl.getName()); 3018 if (dstDecl == null) { 3019 dstGrammar.addGlobalTypeDecl(srcDecl); 3020 } 3021 else if (dstDecl != srcDecl && !fTolerateDuplicates) { 3022 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); 3023 } 3024 } 3025 3026 // add any extended (duplicate) global components 3027 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.TYPE_DEFINITION); 3028 len = componentsExt.getLength(); 3029 3030 for (int i=0; i<len; i+= 2) { 3031 final String key = (String) componentsExt.item(i); 3032 final int index = key.indexOf(','); 3033 final String location = key.substring(0, index); 3034 final String name = key.substring(index + 1, key.length()); 3035 3036 srcDecl = (XSTypeDefinition)componentsExt.item(i+1); 3037 dstDecl = dstGrammar.getGlobalTypeDecl(name, location); 3038 if (dstDecl == null) { 3039 dstGrammar.addGlobalTypeDecl(srcDecl, location); 3040 } 3041 // REVISIT - do we report an error? 3042 else if (dstDecl != srcDecl) { 3043 } 3044 } 3045 } 3046 3047 private List<XSObject> expandComponents(XSObject[] components, Map<String, List<String>> dependencies) { 3048 List<XSObject> newComponents = new ArrayList<>(); 3049 3050 for (int i=0; i<components.length; i++) { 3051 if (!newComponents.contains(components[i])) { 3052 newComponents.add(components[i]); 3053 } 3054 } 3055 3056 for (int i=0; i<newComponents.size(); i++) { 3057 final XSObject component = newComponents.get(i); 3058 expandRelatedComponents(component, newComponents, dependencies); 3059 } 3060 3061 return newComponents; 3062 } 3063 3064 @SuppressWarnings("fallthrough") 3065 private void expandRelatedComponents(XSObject component,List<XSObject>componentList, Map<String, List<String>> dependencies) { 3066 short componentType = component.getType(); 3067 switch (componentType) { 3068 case XSConstants.TYPE_DEFINITION : 3069 expandRelatedTypeComponents((XSTypeDefinition) component, componentList, component.getNamespace(), dependencies); 3070 break; 3071 case XSConstants.ATTRIBUTE_DECLARATION : 3072 expandRelatedAttributeComponents((XSAttributeDeclaration) component, componentList, component.getNamespace(), dependencies); 3073 break; 3074 case XSConstants.ATTRIBUTE_GROUP : 3075 expandRelatedAttributeGroupComponents((XSAttributeGroupDefinition) component, componentList, component.getNamespace(), dependencies); 3076 case XSConstants.ELEMENT_DECLARATION : 3077 expandRelatedElementComponents((XSElementDeclaration) component, componentList, component.getNamespace(), dependencies); 3078 break; 3079 case XSConstants.MODEL_GROUP_DEFINITION : 3080 expandRelatedModelGroupDefinitionComponents((XSModelGroupDefinition) component, componentList, component.getNamespace(), dependencies); 3081 case XSConstants.ATTRIBUTE_USE : 3082 //expandRelatedAttributeUseComponents((XSAttributeUse)component, componentList, dependencies); 3083 case XSConstants.NOTATION_DECLARATION : 3084 case XSConstants.IDENTITY_CONSTRAINT : 3085 default : 3086 break; 3087 } 3088 } 3089 3090 private void expandRelatedAttributeComponents(XSAttributeDeclaration decl, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) { 3091 addRelatedType(decl.getTypeDefinition(), componentList, namespace, dependencies); 3092 3093 /*final XSComplexTypeDefinition enclosingType = decl.getEnclosingCTDefinition(); 3094 if (enclosingType != null) { 3095 addRelatedType(enclosingType, componentList, namespace, dependencies); 3096 }*/ 3097 } 3098 3099 private void expandRelatedElementComponents(XSElementDeclaration decl, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) { 3100 addRelatedType(decl.getTypeDefinition(), componentList, namespace, dependencies); 3101 3102 /*final XSTypeDefinition enclosingType = decl.getEnclosingCTDefinition(); 3103 if (enclosingType != null) { 3104 addRelatedType(enclosingType, componentList, namespace, dependencies); 3105 }*/ 3106 3107 final XSElementDeclaration subElemDecl = decl.getSubstitutionGroupAffiliation(); 3108 if (subElemDecl != null) { 3109 addRelatedElement(subElemDecl, componentList, namespace, dependencies); 3110 } 3111 } 3112 3113 private void expandRelatedTypeComponents(XSTypeDefinition type, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) { 3114 if (type instanceof XSComplexTypeDecl) { 3115 expandRelatedComplexTypeComponents((XSComplexTypeDecl) type, componentList, namespace, dependencies); 3116 } 3117 else if (type instanceof XSSimpleTypeDecl) { 3118 expandRelatedSimpleTypeComponents((XSSimpleTypeDefinition) type, componentList, namespace, dependencies); 3119 } 3120 } 3121 3122 private void expandRelatedModelGroupDefinitionComponents(XSModelGroupDefinition modelGroupDef, List<XSObject>componentList, 3123 String namespace, Map<String, List<String>> dependencies) { 3124 expandRelatedModelGroupComponents(modelGroupDef.getModelGroup(), componentList, namespace, dependencies); 3125 } 3126 3127 private void expandRelatedAttributeGroupComponents(XSAttributeGroupDefinition attrGroup, List<XSObject> componentList 3128 , String namespace, Map<String, List<String>> dependencies) { 3129 expandRelatedAttributeUsesComponents(attrGroup.getAttributeUses(), componentList, namespace, dependencies); 3130 } 3131 3132 private void expandRelatedComplexTypeComponents(XSComplexTypeDecl type, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) { 3133 addRelatedType(type.getBaseType(), componentList, namespace, dependencies); 3134 expandRelatedAttributeUsesComponents(type.getAttributeUses(), componentList, namespace, dependencies); 3135 final XSParticle particle = type.getParticle(); 3136 if (particle != null) { 3137 expandRelatedParticleComponents(particle, componentList, namespace, dependencies); 3138 } 3139 } 3140 3141 private void expandRelatedSimpleTypeComponents(XSSimpleTypeDefinition type, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) { 3142 final XSTypeDefinition baseType = type.getBaseType(); 3143 if (baseType != null) { 3144 addRelatedType(baseType, componentList, namespace, dependencies); 3145 } 3146 3147 final XSTypeDefinition itemType = type.getItemType(); 3148 if (itemType != null) { 3149 addRelatedType(itemType, componentList, namespace, dependencies); 3150 } 3151 3152 final XSTypeDefinition primitiveType = type.getPrimitiveType(); 3153 if (primitiveType != null) { 3154 addRelatedType(primitiveType, componentList, namespace, dependencies); 3155 } 3156 3157 final XSObjectList memberTypes = type.getMemberTypes(); 3158 if (memberTypes.size() > 0) { 3159 for (int i=0; i<memberTypes.size(); i++) { 3160 addRelatedType((XSTypeDefinition)memberTypes.item(i), componentList, namespace, dependencies); 3161 } 3162 } 3163 } 3164 3165 private void expandRelatedAttributeUsesComponents(XSObjectList attrUses, List<XSObject> componentList, 3166 String namespace, Map<String, List<String>> dependencies) { 3167 final int attrUseSize = (attrUses == null) ? 0 : attrUses.size(); 3168 for (int i=0; i<attrUseSize; i++) { 3169 expandRelatedAttributeUseComponents((XSAttributeUse)attrUses.item(i), componentList, namespace, dependencies); 3170 } 3171 } 3172 3173 private void expandRelatedAttributeUseComponents(XSAttributeUse component, List<XSObject> componentList, 3174 String namespace, Map<String, List<String>> dependencies) { 3175 addRelatedAttribute(component.getAttrDeclaration(), componentList, namespace, dependencies); 3176 } 3177 3178 private void expandRelatedParticleComponents(XSParticle component, List<XSObject> componentList, 3179 String namespace, Map<String, List<String>> dependencies) { 3180 XSTerm term = component.getTerm(); 3181 switch (term.getType()) { 3182 case XSConstants.ELEMENT_DECLARATION : 3183 addRelatedElement((XSElementDeclaration) term, componentList, namespace, dependencies); 3184 break; 3185 case XSConstants.MODEL_GROUP : 3186 expandRelatedModelGroupComponents((XSModelGroup) term, componentList, namespace, dependencies); 3187 break; 3188 default: 3189 break; 3190 } 3191 } 3192 3193 private void expandRelatedModelGroupComponents(XSModelGroup modelGroup, List<XSObject> componentList, 3194 String namespace, Map<String, List<String>> dependencies) { 3195 XSObjectList particles = modelGroup.getParticles(); 3196 final int length = (particles == null) ? 0 : particles.getLength(); 3197 for (int i=0; i<length; i++) { 3198 expandRelatedParticleComponents((XSParticle)particles.item(i), componentList, namespace, dependencies); 3199 } 3200 } 3201 3202 private void addRelatedType(XSTypeDefinition type, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) { 3203 if (!type.getAnonymous()) { 3204 if (!SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(type.getNamespace())) { //REVISIT - do we use == instead 3205 if (!componentList.contains(type)) { 3206 final List<String> importedNamespaces = findDependentNamespaces(namespace, dependencies); 3207 addNamespaceDependency(namespace, type.getNamespace(), importedNamespaces); 3208 componentList.add(type); 3209 } 3210 } 3211 } 3212 else { 3213 expandRelatedTypeComponents(type, componentList, namespace, dependencies); 3214 } 3215 } 3216 3217 private void addRelatedElement(XSElementDeclaration decl, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) { 3218 if (decl.getScope() == XSConstants.SCOPE_GLOBAL) { 3219 if (!componentList.contains(decl)) { 3220 List<String> importedNamespaces = findDependentNamespaces(namespace, dependencies); 3221 addNamespaceDependency(namespace, decl.getNamespace(), importedNamespaces); 3222 componentList.add(decl); 3223 } 3224 } 3225 else { 3226 expandRelatedElementComponents(decl, componentList, namespace, dependencies); 3227 } 3228 } 3229 3230 private void addRelatedAttribute(XSAttributeDeclaration decl, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) { 3231 if (decl.getScope() == XSConstants.SCOPE_GLOBAL) { 3232 if (!componentList.contains(decl)) { 3233 List<String> importedNamespaces = findDependentNamespaces(namespace, dependencies); 3234 addNamespaceDependency(namespace, decl.getNamespace(), importedNamespaces); 3235 componentList.add(decl); 3236 } 3237 } 3238 else { 3239 expandRelatedAttributeComponents(decl, componentList, namespace, dependencies); 3240 } 3241 } 3242 3243 private void addGlobalComponents(List<XSObject> components, Map<String, List<String>> importDependencies) { 3244 final XSDDescription desc = new XSDDescription(); 3245 final int size = components.size(); 3246 3247 for (int i=0; i<size; i++) { 3248 addGlobalComponent(components.get(i), desc); 3249 } 3250 updateImportDependencies(importDependencies); 3251 } 3252 3253 private void addGlobalComponent(XSObject component, XSDDescription desc) { 3254 final String namespace = component.getNamespace(); 3255 3256 desc.setNamespace(namespace); 3257 final SchemaGrammar sg = getSchemaGrammar(desc); 3258 3259 short componentType = component.getType(); 3260 final String name = component.getName(); 3261 3262 switch (componentType) { 3263 case XSConstants.TYPE_DEFINITION : 3264 if (!((XSTypeDefinition) component).getAnonymous()) { 3265 if (sg.getGlobalTypeDecl(name) == null) { 3266 sg.addGlobalTypeDecl((XSTypeDefinition) component); 3267 } 3268 // store the declaration in the extended map, using an empty location 3269 if (sg.getGlobalTypeDecl(name, "") == null) { 3270 sg.addGlobalTypeDecl((XSTypeDefinition) component, ""); 3271 } 3272 } 3273 break; 3274 case XSConstants.ATTRIBUTE_DECLARATION : 3275 if (((XSAttributeDecl) component).getScope() == XSAttributeDecl.SCOPE_GLOBAL) { 3276 if (sg.getGlobalAttributeDecl(name) == null) { 3277 sg.addGlobalAttributeDecl((XSAttributeDecl) component); 3278 } 3279 // store the declaration in the extended map, using an empty location 3280 if (sg.getGlobalAttributeDecl(name, "") == null) { 3281 sg.addGlobalAttributeDecl((XSAttributeDecl) component, ""); 3282 } 3283 } 3284 break; 3285 case XSConstants.ATTRIBUTE_GROUP : 3286 if (sg.getGlobalAttributeDecl(name) == null) { 3287 sg.addGlobalAttributeGroupDecl((XSAttributeGroupDecl) component); 3288 } 3289 // store the declaration in the extended map, using an empty location 3290 if (sg.getGlobalAttributeDecl(name, "") == null) { 3291 sg.addGlobalAttributeGroupDecl((XSAttributeGroupDecl) component, ""); 3292 } 3293 break; 3294 case XSConstants.ELEMENT_DECLARATION : 3295 if (((XSElementDecl) component).getScope() == XSElementDecl.SCOPE_GLOBAL) { 3296 sg.addGlobalElementDeclAll((XSElementDecl) component); 3297 3298 if (sg.getGlobalElementDecl(name) == null) { 3299 sg.addGlobalElementDecl((XSElementDecl) component); 3300 } 3301 // store the declaration in the extended map, using an empty location 3302 if (sg.getGlobalElementDecl(name, "") == null) { 3303 sg.addGlobalElementDecl((XSElementDecl) component, ""); 3304 } 3305 } 3306 break; 3307 case XSConstants.MODEL_GROUP_DEFINITION : 3308 if (sg.getGlobalGroupDecl(name) == null) { 3309 sg.addGlobalGroupDecl((XSGroupDecl) component); 3310 } 3311 // store the declaration in the extended map, using an empty location 3312 if (sg.getGlobalGroupDecl(name, "") == null) { 3313 sg.addGlobalGroupDecl((XSGroupDecl) component, ""); 3314 } 3315 break; 3316 case XSConstants.NOTATION_DECLARATION : 3317 if (sg.getGlobalNotationDecl(name) == null) { 3318 sg.addGlobalNotationDecl((XSNotationDecl) component); 3319 } 3320 // store the declaration in the extended map, using an empty location 3321 if (sg.getGlobalNotationDecl(name, "") == null) { 3322 sg.addGlobalNotationDecl((XSNotationDecl) component, ""); 3323 } 3324 break; 3325 case XSConstants.IDENTITY_CONSTRAINT : 3326 case XSConstants.ATTRIBUTE_USE : 3327 default : 3328 break; 3329 } 3330 } 3331 3332 private void updateImportDependencies(Map<String, List<String>> table) { 3333 if (table == null) return; 3334 String namespace; 3335 List<String> importList; 3336 3337 for(Map.Entry<String, List<String>> entry : table.entrySet()){ 3338 namespace = entry.getKey(); 3339 importList = entry.getValue(); 3340 if (importList.size() > 0) { 3341 expandImportList(namespace, importList); 3342 } 3343 } 3344 } 3345 3346 private void expandImportList(String namespace, List<String> namespaceList) { 3347 SchemaGrammar sg = fGrammarBucket.getGrammar(namespace); 3348 // shouldn't be null 3349 if (sg != null) { 3350 List<SchemaGrammar> isgs = sg.getImportedGrammars(); 3351 if (isgs == null) { 3352 isgs = new ArrayList<>(); 3353 addImportList(sg, isgs, namespaceList); 3354 sg.setImportedGrammars(isgs); 3355 } 3356 else { 3357 updateImportList(sg, isgs, namespaceList); 3358 } 3359 } 3360 } 3361 3362 private void addImportList(SchemaGrammar sg, List<SchemaGrammar> importedGrammars, List<String> namespaceList) { 3363 final int size = namespaceList.size(); 3364 SchemaGrammar isg; 3365 3366 for (int i=0; i<size; i++) { 3367 isg = fGrammarBucket.getGrammar(namespaceList.get(i)); 3368 if (isg != null) { 3369 importedGrammars.add(isg); 3370 } 3371 else { 3372 //REVIST: report an error message 3373 } 3374 } 3375 } 3376 3377 private void updateImportList(SchemaGrammar sg, List<SchemaGrammar> importedGrammars, 3378 List<String> namespaceList) { 3379 final int size = namespaceList.size(); 3380 SchemaGrammar isg; 3381 3382 for (int i=0; i<size; i++) { 3383 isg = fGrammarBucket.getGrammar(namespaceList.get(i)); 3384 if (isg != null) { 3385 if (!containedImportedGrammar(importedGrammars, isg)) { 3386 importedGrammars.add(isg); 3387 } 3388 } 3389 else { 3390 //REVIST: report an error message 3391 } 3392 } 3393 } 3394 3395 private boolean containedImportedGrammar(List<SchemaGrammar> importedGrammar, SchemaGrammar grammar) { 3396 final int size = importedGrammar.size(); 3397 SchemaGrammar sg; 3398 3399 for (int i=0; i<size; i++) { 3400 sg = importedGrammar.get(i); 3401 if (null2EmptyString(sg.getTargetNamespace()).equals(null2EmptyString(grammar.getTargetNamespace()))) { 3402 return true; 3403 } 3404 } 3405 return false; 3406 } 3407 3408 // NOTE: always assuming that fNamespaceGrowth is enabled 3409 // otherwise the grammar should have existed 3410 private SchemaGrammar getSchemaGrammar(XSDDescription desc) { 3411 SchemaGrammar sg = findGrammar(desc, fNamespaceGrowth); 3412 3413 if (sg == null) { 3414 sg = new SchemaGrammar(desc.getNamespace(), desc.makeClone(), fSymbolTable); 3415 fGrammarBucket.putGrammar(sg); 3416 } 3417 else if (sg.isImmutable()){ 3418 sg = createGrammarFrom(sg); 3419 } 3420 3421 return sg; 3422 } 3423 3424 private List<String> findDependentNamespaces(String namespace, 3425 Map<String, List<String>> table) { 3426 final String ns = null2EmptyString(namespace); 3427 List<String> namespaceList = getFromMap(table, ns); 3428 3429 if (namespaceList == null) { 3430 namespaceList = new ArrayList<>(); 3431 table.put(ns, namespaceList); 3432 } 3433 3434 return namespaceList; 3435 } 3436 3437 private void addNamespaceDependency(String namespace1, String namespace2, List<String> list) { 3438 final String ns1 = null2EmptyString(namespace1); 3439 final String ns2 = null2EmptyString(namespace2); 3440 if (!ns1.equals(ns2)) { 3441 if (!list.contains(ns2)) { 3442 list.add(ns2); 3443 } 3444 } 3445 } 3446 3447 private void reportSharingError(String namespace, String name) { 3448 final String qName = (namespace == null) 3449 ? "," + name : namespace + "," + name; 3450 3451 reportSchemaError("sch-props-correct.2", new Object [] {qName}, null); 3452 } 3453 3454 // initialize all the traversers. 3455 // this should only need to be called once during the construction 3456 // of this object; it creates the traversers that will be used to 3457 3458 // construct schemaGrammars. 3459 private void createTraversers() { 3460 fAttributeChecker = new XSAttributeChecker(this); 3461 fAttributeGroupTraverser = new XSDAttributeGroupTraverser(this, fAttributeChecker); 3462 fAttributeTraverser = new XSDAttributeTraverser(this, fAttributeChecker); 3463 fComplexTypeTraverser = new XSDComplexTypeTraverser(this, fAttributeChecker); 3464 fElementTraverser = new XSDElementTraverser(this, fAttributeChecker); 3465 fGroupTraverser = new XSDGroupTraverser(this, fAttributeChecker); 3466 fKeyrefTraverser = new XSDKeyrefTraverser(this, fAttributeChecker); 3467 fNotationTraverser = new XSDNotationTraverser(this, fAttributeChecker); 3468 fSimpleTypeTraverser = new XSDSimpleTypeTraverser(this, fAttributeChecker); 3469 fUniqueOrKeyTraverser = new XSDUniqueOrKeyTraverser(this, fAttributeChecker); 3470 fWildCardTraverser = new XSDWildcardTraverser(this, fAttributeChecker); 3471 } // createTraversers() 3472 3473 // before parsing a schema, need to clear registries associated with 3474 // parsing schemas 3475 void prepareForParse() { 3476 fTraversed.clear(); 3477 fDoc2SystemId.clear(); 3478 fHiddenNodes.clear(); 3479 fLastSchemaWasDuplicate = false; 3480 } 3481 3482 // before traversing a schema's parse tree, need to reset all traversers and 3483 // clear all registries 3484 void prepareForTraverse() { 3485 if (!registryEmpty) { 3486 fUnparsedAttributeRegistry.clear(); 3487 fUnparsedAttributeGroupRegistry.clear(); 3488 fUnparsedElementRegistry.clear(); 3489 fUnparsedGroupRegistry.clear(); 3490 fUnparsedIdentityConstraintRegistry.clear(); 3491 fUnparsedNotationRegistry.clear(); 3492 fUnparsedTypeRegistry.clear(); 3493 3494 fUnparsedAttributeRegistrySub.clear(); 3495 fUnparsedAttributeGroupRegistrySub.clear(); 3496 fUnparsedElementRegistrySub.clear(); 3497 fUnparsedGroupRegistrySub.clear(); 3498 fUnparsedIdentityConstraintRegistrySub.clear(); 3499 fUnparsedNotationRegistrySub.clear(); 3500 fUnparsedTypeRegistrySub.clear(); 3501 } 3502 3503 for (int i=1; i<= TYPEDECL_TYPE; i++) { 3504 if (fUnparsedRegistriesExt[i] != null) 3505 fUnparsedRegistriesExt[i].clear(); 3506 } 3507 3508 fDependencyMap.clear(); 3509 fDoc2XSDocumentMap.clear(); 3510 if (fRedefine2XSDMap != null) fRedefine2XSDMap.clear(); 3511 if (fRedefine2NSSupport != null) fRedefine2NSSupport.clear(); 3512 fAllTNSs.clear(); 3513 fImportMap.clear(); 3514 fRoot = null; 3515 3516 // clear local element stack 3517 for (int i = 0; i < fLocalElemStackPos; i++) { 3518 fParticle[i] = null; 3519 fLocalElementDecl[i] = null; 3520 fLocalElementDecl_schema[i] = null; 3521 fLocalElemNamespaceContext[i] = null; 3522 } 3523 fLocalElemStackPos = 0; 3524 3525 // and do same for keyrefs. 3526 for (int i = 0; i < fKeyrefStackPos; i++) { 3527 fKeyrefs[i] = null; 3528 fKeyrefElems[i] = null; 3529 fKeyrefNamespaceContext[i] = null; 3530 fKeyrefsMapXSDocumentInfo[i] = null; 3531 } 3532 fKeyrefStackPos = 0; 3533 3534 // create traversers if necessary 3535 if (fAttributeChecker == null) { 3536 createTraversers(); 3537 } 3538 3539 // reset traversers 3540 Locale locale = fErrorReporter.getLocale(); 3541 fAttributeChecker.reset(fSymbolTable); 3542 fAttributeGroupTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3543 fAttributeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3544 fComplexTypeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3545 fElementTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3546 fGroupTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3547 fKeyrefTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3548 fNotationTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3549 fSimpleTypeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3550 fUniqueOrKeyTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3551 fWildCardTraverser.reset(fSymbolTable, fValidateAnnotations, locale); 3552 3553 fRedefinedRestrictedAttributeGroupRegistry.clear(); 3554 fRedefinedRestrictedGroupRegistry.clear(); 3555 3556 fGlobalAttrDecls.clear(); 3557 fGlobalAttrGrpDecls.clear(); 3558 fGlobalElemDecls.clear(); 3559 fGlobalGroupDecls.clear(); 3560 fGlobalNotationDecls.clear(); 3561 fGlobalIDConstraintDecls.clear(); 3562 fGlobalTypeDecls.clear(); 3563 } 3564 public void setDeclPool (XSDeclarationPool declPool){ 3565 fDeclPool = declPool; 3566 } 3567 public void setDVFactory(SchemaDVFactory dvFactory){ 3568 fDVFactory = dvFactory; 3569 } 3570 public SchemaDVFactory getDVFactory(){ 3571 return fDVFactory; 3572 } 3573 3574 public void reset(XMLComponentManager componentManager) { 3575 3576 // set symbol table 3577 fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE); 3578 3579 // set security manager 3580 fSecurityManager = (XMLSecurityManager) componentManager.getProperty(SECURITY_MANAGER, null); 3581 3582 //set entity manager 3583 fEntityManager = (XMLEntityManager) componentManager.getProperty(ENTITY_MANAGER); 3584 3585 //set entity resolver 3586 XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER); 3587 if (er != null) 3588 fSchemaParser.setEntityResolver(er); 3589 3590 // set error reporter 3591 fErrorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); 3592 fErrorHandler = fErrorReporter.getErrorHandler(); 3593 fLocale = fErrorReporter.getLocale(); 3594 3595 fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS, false); 3596 fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS, false); 3597 fNamespaceGrowth = componentManager.getFeature(NAMESPACE_GROWTH, false); 3598 fTolerateDuplicates = componentManager.getFeature(TOLERATE_DUPLICATES, false); 3599 3600 try { 3601 // Setting a parser property can be much more expensive 3602 // than checking its value. Don't set the ERROR_HANDLER 3603 // or LOCALE properties unless they've actually changed. 3604 if (fErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) { 3605 fSchemaParser.setProperty(ERROR_HANDLER, 3606 (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); 3607 if (fAnnotationValidator != null) { 3608 fAnnotationValidator.setProperty(ERROR_HANDLER, 3609 (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); 3610 } 3611 } 3612 if (fLocale != fSchemaParser.getProperty(LOCALE)) { 3613 fSchemaParser.setProperty(LOCALE, fLocale); 3614 if (fAnnotationValidator != null) { 3615 fAnnotationValidator.setProperty(LOCALE, fLocale); 3616 } 3617 } 3618 } 3619 catch (XMLConfigurationException e) {} 3620 3621 try { 3622 fSchemaParser.setFeature(CONTINUE_AFTER_FATAL_ERROR, 3623 fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR)); 3624 } catch (XMLConfigurationException e) {} 3625 3626 try { 3627 if (componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false)) { 3628 fSchemaParser.setFeature(ALLOW_JAVA_ENCODINGS, true); 3629 } 3630 } catch (XMLConfigurationException e) {} 3631 3632 try { 3633 if (componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE, false)) { 3634 fSchemaParser.setFeature(STANDARD_URI_CONFORMANT_FEATURE, true); 3635 } 3636 } catch (XMLConfigurationException e) {} 3637 3638 try { 3639 fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL); 3640 } catch (XMLConfigurationException e) { 3641 fGrammarPool = null; 3642 } 3643 3644 // security features 3645 try { 3646 if (componentManager.getFeature(DISALLOW_DOCTYPE, false)) { 3647 fSchemaParser.setFeature(DISALLOW_DOCTYPE, true); 3648 } 3649 } catch (XMLConfigurationException e) {} 3650 3651 try { 3652 if (fSecurityManager != null) { 3653 fSchemaParser.setProperty(SECURITY_MANAGER, fSecurityManager); 3654 } 3655 } catch (XMLConfigurationException e) {} 3656 3657 fSecurityPropertyMgr = (XMLSecurityPropertyManager) 3658 componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER); 3659 3660 //Passing on the setting to the parser 3661 fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); 3662 3663 fAccessExternalDTD = fSecurityPropertyMgr.getValue( 3664 XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD); 3665 fAccessExternalSchema = fSecurityPropertyMgr.getValue( 3666 XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA); 3667 3668 fOverrideDefaultParser = componentManager.getFeature(JdkXmlUtils.OVERRIDE_PARSER); 3669 fSchemaParser.setFeature(JdkXmlUtils.OVERRIDE_PARSER, fOverrideDefaultParser); 3670 fEntityManager.setFeature(JdkXmlUtils.OVERRIDE_PARSER, fOverrideDefaultParser); 3671 // Passing the Catalog settings to the parser 3672 fUseCatalog = componentManager.getFeature(XMLConstants.USE_CATALOG); 3673 fSchemaParser.setFeature(XMLConstants.USE_CATALOG, fUseCatalog); 3674 fEntityManager.setFeature(XMLConstants.USE_CATALOG, fUseCatalog); 3675 3676 fCatalogFile = (String)componentManager.getProperty(JdkXmlUtils.CATALOG_FILES); 3677 fDefer = (String)componentManager.getProperty(JdkXmlUtils.CATALOG_DEFER); 3678 fPrefer = (String)componentManager.getProperty(JdkXmlUtils.CATALOG_PREFER); 3679 fResolve = (String)componentManager.getProperty(JdkXmlUtils.CATALOG_RESOLVE); 3680 3681 for( CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) { 3682 fSchemaParser.setProperty(f.getPropertyName(), 3683 componentManager.getProperty(f.getPropertyName())); 3684 fEntityManager.setProperty(f.getPropertyName(), 3685 componentManager.getProperty(f.getPropertyName())); 3686 } 3687 3688 fSchemaParser.setProperty(JdkXmlUtils.CDATA_CHUNK_SIZE, 3689 componentManager.getProperty(JdkXmlUtils.CDATA_CHUNK_SIZE)); 3690 fEntityManager.setProperty(JdkXmlUtils.CDATA_CHUNK_SIZE, 3691 componentManager.getProperty(JdkXmlUtils.CDATA_CHUNK_SIZE)); 3692 } // reset(XMLComponentManager) 3693 3694 3695 /** 3696 * Traverse all the deferred local elements. This method should be called 3697 * by traverseSchemas after we've done with all the global declarations. 3698 */ 3699 void traverseLocalElements() { 3700 fElementTraverser.fDeferTraversingLocalElements = false; 3701 3702 for (int i = 0; i < fLocalElemStackPos; i++) { 3703 Element currElem = fLocalElementDecl[i]; 3704 XSDocumentInfo currSchema = fLocalElementDecl_schema[i]; 3705 SchemaGrammar currGrammar = fGrammarBucket.getGrammar(currSchema.fTargetNamespace); 3706 fElementTraverser.traverseLocal (fParticle[i], currElem, currSchema, 3707 currGrammar, fAllContext[i], fParent[i], fLocalElemNamespaceContext[i]); 3708 // If it's an empty particle, remove it from the containing component. 3709 if (fParticle[i].fType == XSParticleDecl.PARTICLE_EMPTY) { 3710 XSModelGroupImpl group = null; 3711 if (fParent[i] instanceof XSComplexTypeDecl) { 3712 XSParticle p = ((XSComplexTypeDecl)fParent[i]).getParticle(); 3713 if (p != null) 3714 group = (XSModelGroupImpl)p.getTerm(); 3715 } 3716 else { 3717 group = ((XSGroupDecl)fParent[i]).fModelGroup; 3718 } 3719 if (group != null) 3720 removeParticle(group, fParticle[i]); 3721 } 3722 } 3723 } 3724 3725 private boolean removeParticle(XSModelGroupImpl group, XSParticleDecl particle) { 3726 XSParticleDecl member; 3727 for (int i = 0; i < group.fParticleCount; i++) { 3728 member = group.fParticles[i]; 3729 if (member == particle) { 3730 for (int j = i; j < group.fParticleCount-1; j++) 3731 group.fParticles[j] = group.fParticles[j+1]; 3732 group.fParticleCount--; 3733 return true; 3734 } 3735 if (member.fType == XSParticleDecl.PARTICLE_MODELGROUP) { 3736 if (removeParticle((XSModelGroupImpl)member.fValue, particle)) 3737 return true; 3738 } 3739 } 3740 return false; 3741 } 3742 3743 // the purpose of this method is to keep up-to-date structures 3744 // we'll need for the feferred traversal of local elements. 3745 void fillInLocalElemInfo(Element elmDecl, 3746 XSDocumentInfo schemaDoc, 3747 int allContextFlags, 3748 XSObject parent, 3749 XSParticleDecl particle) { 3750 3751 // if the stack is full, increase the size 3752 if (fParticle.length == fLocalElemStackPos) { 3753 // increase size 3754 XSParticleDecl[] newStackP = new XSParticleDecl[fLocalElemStackPos+INC_STACK_SIZE]; 3755 System.arraycopy(fParticle, 0, newStackP, 0, fLocalElemStackPos); 3756 fParticle = newStackP; 3757 Element[] newStackE = new Element[fLocalElemStackPos+INC_STACK_SIZE]; 3758 System.arraycopy(fLocalElementDecl, 0, newStackE, 0, fLocalElemStackPos); 3759 fLocalElementDecl = newStackE; 3760 XSDocumentInfo [] newStackE_schema = new XSDocumentInfo[fLocalElemStackPos+INC_STACK_SIZE]; 3761 System.arraycopy(fLocalElementDecl_schema, 0, newStackE_schema, 0, fLocalElemStackPos); 3762 fLocalElementDecl_schema = newStackE_schema; 3763 int[] newStackI = new int[fLocalElemStackPos+INC_STACK_SIZE]; 3764 System.arraycopy(fAllContext, 0, newStackI, 0, fLocalElemStackPos); 3765 fAllContext = newStackI; 3766 XSObject[] newStackC = new XSObject[fLocalElemStackPos+INC_STACK_SIZE]; 3767 System.arraycopy(fParent, 0, newStackC, 0, fLocalElemStackPos); 3768 fParent = newStackC; 3769 String [][] newStackN = new String [fLocalElemStackPos+INC_STACK_SIZE][]; 3770 System.arraycopy(fLocalElemNamespaceContext, 0, newStackN, 0, fLocalElemStackPos); 3771 fLocalElemNamespaceContext = newStackN; 3772 } 3773 3774 fParticle[fLocalElemStackPos] = particle; 3775 fLocalElementDecl[fLocalElemStackPos] = elmDecl; 3776 fLocalElementDecl_schema[fLocalElemStackPos] = schemaDoc; 3777 fAllContext[fLocalElemStackPos] = allContextFlags; 3778 fParent[fLocalElemStackPos] = parent; 3779 fLocalElemNamespaceContext[fLocalElemStackPos++] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext(); 3780 } // end fillInLocalElemInfo(...) 3781 3782 /** This method makes sure that 3783 * if this component is being redefined that it lives in the 3784 * right schema. It then renames the component correctly. If it 3785 * detects a collision--a duplicate definition--then it complains. 3786 * Note that redefines must be handled carefully: if there 3787 * is a collision, it may be because we're redefining something we know about 3788 * or because we've found the thing we're redefining. 3789 */ 3790 void checkForDuplicateNames(String qName, int declType, 3791 Map<String,Element> registry, Map<String,XSDocumentInfo> registry_sub, Element currComp, 3792 XSDocumentInfo currSchema) { 3793 Object objElem = null; 3794 // REVISIT: when we add derivation checking, we'll have to make 3795 // sure that ID constraint collisions don't necessarily result in error messages. 3796 if ((objElem = registry.get(qName)) == null) { 3797 // need to check whether we have a global declaration in the corresponding 3798 // grammar 3799 if (fNamespaceGrowth && !fTolerateDuplicates) { 3800 checkForDuplicateNames(qName, declType, currComp); 3801 } 3802 // just add it in! 3803 registry.put(qName, currComp); 3804 registry_sub.put(qName, currSchema); 3805 } 3806 else { 3807 Element collidingElem = (Element)objElem; 3808 XSDocumentInfo collidingElemSchema = registry_sub.get(qName); 3809 if (collidingElem == currComp) return; 3810 Element elemParent = null; 3811 XSDocumentInfo redefinedSchema = null; 3812 // case where we've collided with a redefining element 3813 // (the parent of the colliding element is a redefine) 3814 boolean collidedWithRedefine = true; 3815 if ((DOMUtil.getLocalName((elemParent = DOMUtil.getParent(collidingElem))).equals(SchemaSymbols.ELT_REDEFINE))) { 3816 redefinedSchema = (fRedefine2XSDMap != null)? fRedefine2XSDMap.get(elemParent) : null; 3817 // case where we're a redefining element. 3818 } 3819 else if ((DOMUtil.getLocalName(DOMUtil.getParent(currComp)).equals(SchemaSymbols.ELT_REDEFINE))) { 3820 redefinedSchema = collidingElemSchema; 3821 collidedWithRedefine = false; 3822 } 3823 if (redefinedSchema != null) { //redefinition involved somehow 3824 // If both components belong to the same document then 3825 // report an error and return. 3826 if(collidingElemSchema == currSchema){ 3827 reportSchemaError("sch-props-correct.2", new Object[]{qName}, currComp); 3828 return; 3829 } 3830 3831 String newName = qName.substring(qName.lastIndexOf(',')+1)+REDEF_IDENTIFIER; 3832 if (redefinedSchema == currSchema) { // object comp. okay here 3833 // now have to do some renaming... 3834 currComp.setAttribute(SchemaSymbols.ATT_NAME, newName); 3835 if (currSchema.fTargetNamespace == null){ 3836 registry.put(","+newName, currComp); 3837 registry_sub.put(","+newName, currSchema); 3838 } 3839 else{ 3840 registry.put(currSchema.fTargetNamespace+","+newName, currComp); 3841 registry_sub.put(currSchema.fTargetNamespace+","+newName, currSchema); 3842 } 3843 // and take care of nested redefines by calling recursively: 3844 if (currSchema.fTargetNamespace == null) 3845 checkForDuplicateNames(","+newName, declType, registry, registry_sub, currComp, currSchema); 3846 else 3847 checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, declType, registry, registry_sub, currComp, currSchema); 3848 } 3849 else { // we may be redefining the wrong schema 3850 if (collidedWithRedefine) { 3851 if (currSchema.fTargetNamespace == null) 3852 checkForDuplicateNames(","+newName, declType, registry, registry_sub, currComp, currSchema); 3853 else 3854 checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, declType, registry, registry_sub, currComp, currSchema); 3855 } 3856 else { 3857 // error that redefined element in wrong schema 3858 reportSchemaError("sch-props-correct.2", new Object [] {qName}, currComp); 3859 } 3860 } 3861 } 3862 else { 3863 // we've just got a flat-out collision (we tolerate duplicate 3864 // declarations, only if they are defined in different schema 3865 // documents) 3866 if (!fTolerateDuplicates) { 3867 reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); 3868 } else if (fUnparsedRegistriesExt[declType] != null) { 3869 if (fUnparsedRegistriesExt[declType].get(qName) == currSchema) { 3870 reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); 3871 } 3872 } 3873 } 3874 } 3875 3876 // store the lastest current document info 3877 if (fTolerateDuplicates) { 3878 if (fUnparsedRegistriesExt[declType] == null) 3879 fUnparsedRegistriesExt[declType] = new HashMap<>(); 3880 fUnparsedRegistriesExt[declType].put(qName, currSchema); 3881 } 3882 3883 } // checkForDuplicateNames(String, Map, Element, XSDocumentInfo):void 3884 3885 void checkForDuplicateNames(String qName, int declType, Element currComp) { 3886 int namespaceEnd = qName.indexOf(','); 3887 String namespace = qName.substring(0, namespaceEnd); 3888 SchemaGrammar grammar = fGrammarBucket.getGrammar(emptyString2Null(namespace)); 3889 3890 if (grammar != null) { 3891 Object obj = getGlobalDeclFromGrammar(grammar, declType, qName.substring(namespaceEnd + 1)); 3892 if (obj != null) { 3893 reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); 3894 } 3895 } 3896 } 3897 3898 // the purpose of this method is to take the component of the 3899 // specified type and rename references to itself so that they 3900 // refer to the object being redefined. It takes special care of 3901 // <group>s and <attributeGroup>s to ensure that information 3902 // relating to implicit restrictions is preserved for those 3903 // traversers. 3904 private void renameRedefiningComponents(XSDocumentInfo currSchema, 3905 Element child, String componentType, 3906 String oldName, String newName) { 3907 if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { 3908 Element grandKid = DOMUtil.getFirstChildElement(child); 3909 if (grandKid == null) { 3910 reportSchemaError("src-redefine.5.a.a", null, child); 3911 } 3912 else { 3913 String grandKidName = DOMUtil.getLocalName(grandKid); 3914 if (grandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) { 3915 grandKid = DOMUtil.getNextSiblingElement(grandKid); 3916 } 3917 if (grandKid == null) { 3918 reportSchemaError("src-redefine.5.a.a", null, child); 3919 } 3920 else { 3921 grandKidName = DOMUtil.getLocalName(grandKid); 3922 if (!grandKidName.equals(SchemaSymbols.ELT_RESTRICTION)) { 3923 reportSchemaError("src-redefine.5.a.b", new Object[]{grandKidName}, child); 3924 } 3925 else { 3926 Object[] attrs = fAttributeChecker.checkAttributes(grandKid, false, currSchema); 3927 QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE]; 3928 if (derivedBase == null || 3929 derivedBase.uri != currSchema.fTargetNamespace || 3930 !derivedBase.localpart.equals(oldName)) { 3931 reportSchemaError("src-redefine.5.a.c", 3932 new Object[]{grandKidName, 3933 (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace) 3934 + "," + oldName}, 3935 child); 3936 } 3937 else { 3938 // now we have to do the renaming... 3939 if (derivedBase.prefix != null && derivedBase.prefix.length() > 0) 3940 grandKid.setAttribute( SchemaSymbols.ATT_BASE, 3941 derivedBase.prefix + ":" + newName ); 3942 else 3943 grandKid.setAttribute( SchemaSymbols.ATT_BASE, newName ); 3944 // return true; 3945 } 3946 fAttributeChecker.returnAttrArray(attrs, currSchema); 3947 } 3948 } 3949 } 3950 } 3951 else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { 3952 Element grandKid = DOMUtil.getFirstChildElement(child); 3953 if (grandKid == null) { 3954 reportSchemaError("src-redefine.5.b.a", null, child); 3955 } 3956 else { 3957 if (DOMUtil.getLocalName(grandKid).equals(SchemaSymbols.ELT_ANNOTATION)) { 3958 grandKid = DOMUtil.getNextSiblingElement(grandKid); 3959 } 3960 if (grandKid == null) { 3961 reportSchemaError("src-redefine.5.b.a", null, child); 3962 } 3963 else { 3964 // have to go one more level down; let another pass worry whether complexType is valid. 3965 Element greatGrandKid = DOMUtil.getFirstChildElement(grandKid); 3966 if (greatGrandKid == null) { 3967 reportSchemaError("src-redefine.5.b.b", null, grandKid); 3968 } 3969 else { 3970 String greatGrandKidName = DOMUtil.getLocalName(greatGrandKid); 3971 if (greatGrandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) { 3972 greatGrandKid = DOMUtil.getNextSiblingElement(greatGrandKid); 3973 } 3974 if (greatGrandKid == null) { 3975 reportSchemaError("src-redefine.5.b.b", null, grandKid); 3976 } 3977 else { 3978 greatGrandKidName = DOMUtil.getLocalName(greatGrandKid); 3979 if (!greatGrandKidName.equals(SchemaSymbols.ELT_RESTRICTION) && 3980 !greatGrandKidName.equals(SchemaSymbols.ELT_EXTENSION)) { 3981 reportSchemaError("src-redefine.5.b.c", new Object[]{greatGrandKidName}, greatGrandKid); 3982 } 3983 else { 3984 Object[] attrs = fAttributeChecker.checkAttributes(greatGrandKid, false, currSchema); 3985 QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE]; 3986 if (derivedBase == null || 3987 derivedBase.uri != currSchema.fTargetNamespace || 3988 !derivedBase.localpart.equals(oldName)) { 3989 reportSchemaError("src-redefine.5.b.d", 3990 new Object[]{greatGrandKidName, 3991 (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace) 3992 + "," + oldName}, 3993 greatGrandKid); 3994 } 3995 else { 3996 // now we have to do the renaming... 3997 if (derivedBase.prefix != null && derivedBase.prefix.length() > 0) 3998 greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE, 3999 derivedBase.prefix + ":" + newName ); 4000 else 4001 greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE, 4002 newName ); 4003 // return true; 4004 } 4005 } 4006 } 4007 } 4008 } 4009 } 4010 } 4011 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { 4012 String processedBaseName = (currSchema.fTargetNamespace == null)? 4013 ","+oldName:currSchema.fTargetNamespace+","+oldName; 4014 int attGroupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema); 4015 if (attGroupRefsCount > 1) { 4016 reportSchemaError("src-redefine.7.1", new Object []{new Integer(attGroupRefsCount)}, child); 4017 } 4018 else if (attGroupRefsCount == 1) { 4019 // return true; 4020 } 4021 else 4022 if (currSchema.fTargetNamespace == null) 4023 fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, ","+newName); 4024 else 4025 fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName); 4026 } 4027 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { 4028 String processedBaseName = (currSchema.fTargetNamespace == null)? 4029 ","+oldName:currSchema.fTargetNamespace+","+oldName; 4030 int groupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema); 4031 if (groupRefsCount > 1) { 4032 reportSchemaError("src-redefine.6.1.1", new Object []{new Integer(groupRefsCount)}, child); 4033 } 4034 else if (groupRefsCount == 1) { 4035 // return true; 4036 } 4037 else { 4038 if (currSchema.fTargetNamespace == null) 4039 fRedefinedRestrictedGroupRegistry.put(processedBaseName, ","+newName); 4040 else 4041 fRedefinedRestrictedGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName); 4042 } 4043 } 4044 else { 4045 reportSchemaError("Internal-Error", new Object [] {"could not handle this particular <redefine>; please submit your schemas and instance document in a bug report!"}, child); 4046 } 4047 // if we get here then we must have reported an error and failed somewhere... 4048 // return false; 4049 } // renameRedefiningComponents(XSDocumentInfo, Element, String, String, String):void 4050 4051 // this method takes a name of the form a:b, determines the URI mapped 4052 // to by a in the current SchemaNamespaceSupport object, and returns this 4053 // information in the form (nsURI,b) suitable for lookups in the global 4054 // decl maps. 4055 // REVISIT: should have it return QName, instead of String. this would 4056 // save lots of string concatenation time. we can use 4057 // QName#equals() to compare two QNames, and use QName directly 4058 // as a key to the SymbolHash. 4059 // And when the DV's are ready to return compiled values from 4060 // validate() method, we should just call QNameDV.validate() 4061 // in this method. 4062 private String findQName(String name, XSDocumentInfo schemaDoc) { 4063 SchemaNamespaceSupport currNSMap = schemaDoc.fNamespaceSupport; 4064 int colonPtr = name.indexOf(':'); 4065 String prefix = XMLSymbols.EMPTY_STRING; 4066 if (colonPtr > 0) 4067 prefix = name.substring(0, colonPtr); 4068 String uri = currNSMap.getURI(fSymbolTable.addSymbol(prefix)); 4069 String localpart = (colonPtr == 0)?name:name.substring(colonPtr+1); 4070 if (prefix == XMLSymbols.EMPTY_STRING && uri == null && schemaDoc.fIsChameleonSchema) 4071 uri = schemaDoc.fTargetNamespace; 4072 if (uri == null) 4073 return ","+localpart; 4074 return uri+","+localpart; 4075 } // findQName(String, XSDocumentInfo): String 4076 4077 // This function looks among the children of curr for an element of type elementSought. 4078 // If it finds one, it evaluates whether its ref attribute contains a reference 4079 // to originalQName. If it does, it returns 1 + the value returned by 4080 // calls to itself on all other children. In all other cases it returns 0 plus 4081 // the sum of the values returned by calls to itself on curr's children. 4082 // It also resets the value of ref so that it will refer to the renamed type from the schema 4083 // being redefined. 4084 private int changeRedefineGroup(String originalQName, String elementSought, 4085 String newName, Element curr, XSDocumentInfo schemaDoc) { 4086 int result = 0; 4087 for (Element child = DOMUtil.getFirstChildElement(curr); 4088 child != null; child = DOMUtil.getNextSiblingElement(child)) { 4089 String name = DOMUtil.getLocalName(child); 4090 if (!name.equals(elementSought)) 4091 result += changeRedefineGroup(originalQName, elementSought, newName, child, schemaDoc); 4092 else { 4093 String ref = child.getAttribute( SchemaSymbols.ATT_REF ); 4094 if (ref.length() != 0) { 4095 String processedRef = findQName(ref, schemaDoc); 4096 if (originalQName.equals(processedRef)) { 4097 String prefix = XMLSymbols.EMPTY_STRING; 4098 int colonptr = ref.indexOf(":"); 4099 if (colonptr > 0) { 4100 prefix = ref.substring(0,colonptr); 4101 child.setAttribute(SchemaSymbols.ATT_REF, prefix + ":" + newName); 4102 } 4103 else 4104 child.setAttribute(SchemaSymbols.ATT_REF, newName); 4105 result++; 4106 if (elementSought.equals(SchemaSymbols.ELT_GROUP)) { 4107 String minOccurs = child.getAttribute( SchemaSymbols.ATT_MINOCCURS ); 4108 String maxOccurs = child.getAttribute( SchemaSymbols.ATT_MAXOCCURS ); 4109 if (!((maxOccurs.length() == 0 || maxOccurs.equals("1")) 4110 && (minOccurs.length() == 0 || minOccurs.equals("1")))) { 4111 reportSchemaError("src-redefine.6.1.2", new Object [] {ref}, child); 4112 } 4113 } 4114 } 4115 } // if ref was null some other stage of processing will flag the error 4116 } 4117 } 4118 return result; 4119 } // changeRedefineGroup 4120 4121 // this method returns the XSDocumentInfo object that contains the 4122 // component corresponding to decl. If components from this 4123 // document cannot be referred to from those of currSchema, this 4124 // method returns null; it's up to the caller to throw an error. 4125 // @param: currSchema: the XSDocumentInfo object containing the 4126 // decl ref'ing us. 4127 // @param: decl: the declaration being ref'd. 4128 // this method is superficial now. ---Jack 4129 private XSDocumentInfo findXSDocumentForDecl(XSDocumentInfo currSchema, 4130 Element decl, XSDocumentInfo decl_Doc) { 4131 4132 if (DEBUG_NODE_POOL) { 4133 System.out.println("DOCUMENT NS:" + currSchema.fTargetNamespace + " hashcode:" + 4134 ((Object)currSchema.fSchemaElement).hashCode()); 4135 } 4136 Object temp = decl_Doc; 4137 if (temp == null) { 4138 // something went badly wrong; we don't know this doc? 4139 return null; 4140 } 4141 XSDocumentInfo declDocInfo = (XSDocumentInfo)temp; 4142 return declDocInfo; 4143 /********* 4144 Logic here is unnecessary after schema WG's recent decision to allow 4145 schema components from one document to refer to components of any other, 4146 so long as there's some include/import/redefine path amongst them. 4147 If they rver reverse this decision the code's right here though... - neilg 4148 // now look in fDependencyMap to see if this is reachable 4149 if((fDependencyMap.get(currSchema)).contains(declDocInfo)) { 4150 return declDocInfo; 4151 } 4152 // obviously the requesting doc didn't include, redefine or 4153 // import the one containing decl... 4154 return null; 4155 **********/ 4156 } // findXSDocumentForDecl(XSDocumentInfo, Element): XSDocumentInfo 4157 4158 // returns whether more than <annotation>s occur in children of elem 4159 private boolean nonAnnotationContent(Element elem) { 4160 for(Element child = DOMUtil.getFirstChildElement(elem); child != null; 4161 child = DOMUtil.getNextSiblingElement(child)) { 4162 if(!(DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION))) return true; 4163 } 4164 return false; 4165 } // nonAnnotationContent(Element): boolean 4166 4167 private void setSchemasVisible(XSDocumentInfo startSchema) { 4168 if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) { 4169 // make it visible 4170 DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes); 4171 List<XSDocumentInfo> dependingSchemas = fDependencyMap.get(startSchema); 4172 for (int i = 0; i < dependingSchemas.size(); i++) { 4173 setSchemasVisible(dependingSchemas.get(i)); 4174 } 4175 } 4176 // if it's visible already than so must be its children 4177 } // setSchemasVisible(XSDocumentInfo): void 4178 4179 private SimpleLocator xl = new SimpleLocator(); 4180 4181 /** 4182 * Extract location information from an Element node, and create a 4183 * new SimpleLocator object from such information. Returning null means 4184 * no information can be retrieved from the element. 4185 */ 4186 public SimpleLocator element2Locator(Element e) { 4187 if (!( e instanceof ElementImpl)) 4188 return null; 4189 4190 SimpleLocator l = new SimpleLocator(); 4191 return element2Locator(e, l) ? l : null; 4192 } 4193 4194 /** 4195 * Extract location information from an Element node, store such 4196 * information in the passed-in SimpleLocator object, then return 4197 * true. Returning false means can't extract or store such information. 4198 */ 4199 public boolean element2Locator(Element e, SimpleLocator l) { 4200 if (l == null) 4201 return false; 4202 if (e instanceof ElementImpl) { 4203 ElementImpl ele = (ElementImpl)e; 4204 // get system id from document object 4205 Document doc = ele.getOwnerDocument(); 4206 String sid = fDoc2SystemId.get(DOMUtil.getRoot(doc)); 4207 // line/column numbers are stored in the element node 4208 int line = ele.getLineNumber(); 4209 int column = ele.getColumnNumber(); 4210 l.setValues(sid, sid, line, column, ele.getCharacterOffset()); 4211 return true; 4212 } 4213 return false; 4214 } 4215 4216 private Element getElementFromMap(Map<String, Element> registry, String declKey) { 4217 if (registry == null) return null; 4218 return registry.get(declKey); 4219 } 4220 4221 private XSDocumentInfo getDocInfoFromMap(Map<String, XSDocumentInfo> registry, String declKey) { 4222 if (registry == null) return null; 4223 return registry.get(declKey); 4224 } 4225 4226 private List<String> getFromMap(Map<String, List<String>> registry, String key) { 4227 if (registry == null) return null; 4228 return registry.get(key); 4229 } 4230 4231 void reportSchemaFatalError(String key, Object[] args, Element ele) { 4232 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_FATAL_ERROR, null); 4233 } 4234 4235 void reportSchemaError(String key, Object[] args, Element ele) { 4236 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_ERROR, null); 4237 } 4238 4239 void reportSchemaError(String key, Object[] args, Element ele, Exception exception) { 4240 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_ERROR, exception); 4241 } 4242 4243 void reportSchemaWarning(String key, Object[] args, Element ele) { 4244 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_WARNING, null); 4245 } 4246 4247 void reportSchemaWarning(String key, Object[] args, Element ele, Exception exception) { 4248 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_WARNING, exception); 4249 } 4250 4251 void reportSchemaErr(String key, Object[] args, Element ele, short type, Exception exception) { 4252 if (element2Locator(ele, xl)) { 4253 fErrorReporter.reportError(xl, XSMessageFormatter.SCHEMA_DOMAIN, 4254 key, args, type, exception); 4255 } 4256 else { 4257 fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN, 4258 key, args, type, exception); 4259 } 4260 } 4261 4262 /** 4263 * Grammar pool used for validating annotations. This will return all of the 4264 * grammars from the grammar bucket. It will also return an object for the 4265 * schema for schemas which will contain at least the relevant declarations 4266 * for annotations. 4267 */ 4268 private static class XSAnnotationGrammarPool implements XMLGrammarPool { 4269 4270 private XSGrammarBucket fGrammarBucket; 4271 private Grammar [] fInitialGrammarSet; 4272 4273 public Grammar[] retrieveInitialGrammarSet(String grammarType) { 4274 if (grammarType == XMLGrammarDescription.XML_SCHEMA) { 4275 if (fInitialGrammarSet == null) { 4276 if (fGrammarBucket == null) { 4277 fInitialGrammarSet = new Grammar [] {SchemaGrammar.Schema4Annotations.INSTANCE}; 4278 } 4279 else { 4280 SchemaGrammar [] schemaGrammars = fGrammarBucket.getGrammars(); 4281 /** 4282 * If the grammar bucket already contains the schema for schemas 4283 * then we already have the definitions for the parts relevant 4284 * to annotations. 4285 */ 4286 for (int i = 0; i < schemaGrammars.length; ++i) { 4287 if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(schemaGrammars[i].getTargetNamespace())) { 4288 fInitialGrammarSet = schemaGrammars; 4289 return fInitialGrammarSet; 4290 } 4291 } 4292 Grammar [] grammars = new Grammar[schemaGrammars.length + 1]; 4293 System.arraycopy(schemaGrammars, 0, grammars, 0, schemaGrammars.length); 4294 grammars[grammars.length - 1] = SchemaGrammar.Schema4Annotations.INSTANCE; 4295 fInitialGrammarSet = grammars; 4296 } 4297 } 4298 return fInitialGrammarSet; 4299 } 4300 return new Grammar[0]; 4301 } 4302 4303 public void cacheGrammars(String grammarType, Grammar[] grammars) { 4304 4305 } 4306 4307 public Grammar retrieveGrammar(XMLGrammarDescription desc) { 4308 if (desc.getGrammarType() == XMLGrammarDescription.XML_SCHEMA) { 4309 final String tns = ((XMLSchemaDescription) desc).getTargetNamespace(); 4310 if (fGrammarBucket != null) { 4311 Grammar grammar = fGrammarBucket.getGrammar(tns); 4312 if (grammar != null) { 4313 return grammar; 4314 } 4315 } 4316 if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(tns)) { 4317 return SchemaGrammar.Schema4Annotations.INSTANCE; 4318 } 4319 } 4320 return null; 4321 } 4322 4323 public void refreshGrammars(XSGrammarBucket gBucket) { 4324 fGrammarBucket = gBucket; 4325 fInitialGrammarSet = null; 4326 } 4327 4328 public void lockPool() {} 4329 4330 public void unlockPool() {} 4331 4332 public void clear() {} 4333 } 4334 4335 /** 4336 * used to identify a reference to a schema document 4337 * if the same document is referenced twice with the same key, then 4338 * we only need to parse it once. 4339 * 4340 * When 2 XSDKey's are compared, the following table can be used to 4341 * determine whether they are equal: 4342 * inc red imp pre ins 4343 * inc N/L ? N/L N/L N/L 4344 * red ? N/L ? ? ? 4345 * imp N/L ? N/P N/P N/P 4346 * pre N/L ? N/P N/P N/P 4347 * ins N/L ? N/P N/P N/P 4348 * 4349 * Where: N/L: duplicate when they have the same namespace and location. 4350 * ? : not clear from the spec. 4351 * REVISIT: to simplify the process, also considering 4352 * it's very rare, we treat them as not duplicate. 4353 * N/P: not possible. imp/pre/ins are referenced by namespace. 4354 * when the first time we encounter a schema document for a 4355 * namespace, we create a grammar and store it in the grammar 4356 * bucket. when we see another reference to the same namespace, 4357 * we first check whether a grammar with the same namespace is 4358 * already in the bucket, which is true in this case, so we 4359 * won't create another XSDKey. 4360 * 4361 * Conclusion from the table: two XSDKey's are duplicate only when all of 4362 * the following are true: 4363 * 1. They are both "redefine", or neither is "redefine"; 4364 * 2. They have the same namespace; 4365 * 3. They have the same non-null location. 4366 * 4367 * About 3: if neither has a non-null location, then it's the case where 4368 * 2 input streams are provided, but no system ID is provided. We can't tell 4369 * whether the 2 streams have the same content, so we treat them as not 4370 * duplicate. 4371 */ 4372 private static class XSDKey { 4373 String systemId; 4374 short referType; 4375 // for inclue/redefine, this is the enclosing namespace 4376 // for import/preparse/instance, this is the target namespace 4377 String referNS; 4378 4379 XSDKey(String systemId, short referType, String referNS) { 4380 this.systemId = systemId; 4381 this.referType = referType; 4382 this.referNS = referNS; 4383 } 4384 4385 public int hashCode() { 4386 // according to the description at the beginning of this class, 4387 // we use the hashcode of the namespace as the hashcoe of this key. 4388 return referNS == null ? 0 : referNS.hashCode(); 4389 } 4390 4391 public boolean equals(Object obj) { 4392 if (!(obj instanceof XSDKey)) { 4393 return false; 4394 } 4395 XSDKey key = (XSDKey)obj; 4396 4397 // condition 1: both are redefine 4398 /** if (referType == XSDDescription.CONTEXT_REDEFINE || 4399 key.referType == XSDDescription.CONTEXT_REDEFINE) { 4400 if (referType != key.referType) 4401 return false; 4402 }**/ 4403 4404 // condition 2: same namespace 4405 if (referNS != key.referNS) 4406 return false; 4407 4408 // condition 3: same non-null location 4409 if (systemId == null || !systemId.equals(key.systemId)) { 4410 return false; 4411 } 4412 4413 return true; 4414 } 4415 } 4416 4417 private static final class SAX2XNIUtil extends ErrorHandlerWrapper { 4418 public static XMLParseException createXMLParseException0(SAXParseException exception) { 4419 return createXMLParseException(exception); 4420 } 4421 public static XNIException createXNIException0(SAXException exception) { 4422 return createXNIException(exception); 4423 } 4424 } 4425 4426 /** 4427 * @param state 4428 */ 4429 public void setGenerateSyntheticAnnotations(boolean state) { 4430 fSchemaParser.setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, state); 4431 } 4432 4433 } // XSDHandler