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