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