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