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