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