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