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