KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > xs > traversers > XSDHandler


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl.xs.traversers;
18
19 import java.io.IOException JavaDoc;
20 import java.io.StringReader JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Hashtable JavaDoc;
23 import java.util.Stack JavaDoc;
24 import java.util.Vector JavaDoc;
25
26 import org.apache.xerces.impl.Constants;
27 import org.apache.xerces.impl.XMLEntityManager;
28 import org.apache.xerces.impl.XMLErrorReporter;
29 import org.apache.xerces.impl.xs.SchemaGrammar;
30 import org.apache.xerces.impl.xs.SchemaNamespaceSupport;
31 import org.apache.xerces.impl.xs.SchemaSymbols;
32 import org.apache.xerces.impl.xs.XMLSchemaException;
33 import org.apache.xerces.impl.xs.XMLSchemaLoader;
34 import org.apache.xerces.impl.xs.XSComplexTypeDecl;
35 import org.apache.xerces.impl.xs.XSDDescription;
36 import org.apache.xerces.impl.xs.XSDeclarationPool;
37 import org.apache.xerces.impl.xs.XSElementDecl;
38 import org.apache.xerces.impl.xs.XSGrammarBucket;
39 import org.apache.xerces.impl.xs.XSGroupDecl;
40 import org.apache.xerces.impl.xs.XSMessageFormatter;
41 import org.apache.xerces.impl.xs.XSModelGroupImpl;
42 import org.apache.xerces.impl.xs.XSParticleDecl;
43 import org.apache.xerces.impl.xs.opti.ElementImpl;
44 import org.apache.xerces.impl.xs.opti.SchemaDOMParser;
45 import org.apache.xerces.impl.xs.opti.SchemaParsingConfig;
46 import org.apache.xerces.impl.xs.util.SimpleLocator;
47
48 import org.apache.xerces.util.DOMUtil;
49 import org.apache.xerces.parsers.SAXParser;
50 import org.apache.xerces.parsers.XML11Configuration;
51 import org.apache.xerces.util.DOMInputSource;
52 import org.apache.xerces.util.DefaultErrorHandler;
53 import org.apache.xerces.util.SAXInputSource;
54 import org.apache.xerces.util.SymbolTable;
55 import org.apache.xerces.util.XMLSymbols;
56 import org.apache.xerces.util.URI.MalformedURIException;
57 import org.apache.xerces.xni.QName;
58 import org.apache.xerces.xni.grammars.Grammar;
59 import org.apache.xerces.xni.grammars.XMLGrammarDescription;
60 import org.apache.xerces.xni.grammars.XMLGrammarPool;
61 import org.apache.xerces.xni.grammars.XMLSchemaDescription;
62 import org.apache.xerces.xni.parser.XMLComponentManager;
63 import org.apache.xerces.xni.parser.XMLConfigurationException;
64 import org.apache.xerces.xni.parser.XMLEntityResolver;
65 import org.apache.xerces.xni.parser.XMLErrorHandler;
66 import org.apache.xerces.xni.parser.XMLInputSource;
67 import org.apache.xerces.xs.XSObject;
68 import org.apache.xerces.xs.XSParticle;
69 import org.w3c.dom.Document JavaDoc;
70 import org.w3c.dom.Element JavaDoc;
71 import org.w3c.dom.Node JavaDoc;
72 import org.xml.sax.InputSource JavaDoc;
73 import org.xml.sax.SAXException JavaDoc;
74 import org.xml.sax.XMLReader JavaDoc;
75 import org.xml.sax.helpers.XMLReaderFactory JavaDoc;
76
77
78 /**
79  * The purpose of this class is to co-ordinate the construction of a
80  * grammar object corresponding to a schema. To do this, it must be
81  * prepared to parse several schema documents (for instance if the
82  * schema document originally referred to contains <include> or
83  * <redefined> information items). If any of the schemas imports a
84  * schema, other grammars may be constructed as a side-effect.
85  *
86  * @xerces.internal
87  *
88  * @author Neil Graham, IBM
89  * @author Pavani Mukthipudi, Sun Microsystems
90  *
91  * @version $Id: XSDHandler.java,v 1.92 2005/06/24 17:56:41 mrglavas Exp $
92  */

93 public class XSDHandler {
94     
95     /** Feature identifier: validation. */
96     protected static final String JavaDoc VALIDATION =
97         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
98     
99     /** feature identifier: XML Schema validation */
100     protected static final String JavaDoc XMLSCHEMA_VALIDATION =
101         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
102     
103     /** Feature identifier: allow java encodings */
104     protected static final String JavaDoc ALLOW_JAVA_ENCODINGS =
105         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
106     
107     /** Feature identifier: continue after fatal error */
108     protected static final String JavaDoc CONTINUE_AFTER_FATAL_ERROR =
109         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
110     
111     /** Feature identifier: allow java encodings */
112     protected static final String JavaDoc STANDARD_URI_CONFORMANT_FEATURE =
113         Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
114     
115     /** Feature: disallow doctype*/
116     protected static final String JavaDoc DISALLOW_DOCTYPE =
117         Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
118     
119     /** Feature: generate synthetic annotations */
120     protected static final String JavaDoc GENERATE_SYNTHETIC_ANNOTATIONS =
121         Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
122     
123     /** Feature identifier: validate annotations. */
124     protected static final String JavaDoc VALIDATE_ANNOTATIONS =
125         Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
126     
127     /** Feature identifier: honour all schemaLocations */
128     protected static final String JavaDoc HONOUR_ALL_SCHEMALOCATIONS =
129       Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
130     
131     /** Feature identifier: namespace prefixes. */
132     private static final String JavaDoc NAMESPACE_PREFIXES =
133         Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
134     
135     /** Feature identifier: string interning. */
136     protected static final String JavaDoc STRING_INTERNING =
137         Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
138    
139     /** Property identifier: error handler. */
140     protected static final String JavaDoc ERROR_HANDLER =
141         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
142     
143     /** Property identifier: JAXP schema source. */
144     protected static final String JavaDoc JAXP_SCHEMA_SOURCE =
145         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
146     
147     /** Property identifier: entity resolver. */
148     public static final String JavaDoc ENTITY_RESOLVER =
149         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
150     /** Property identifier: entity manager. */
151     protected static final String JavaDoc ENTITY_MANAGER =
152         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
153     
154     /** Property identifier: error reporter. */
155     public static final String JavaDoc ERROR_REPORTER =
156         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
157     
158     /** Property identifier: grammar pool. */
159     public static final String JavaDoc XMLGRAMMAR_POOL =
160         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
161     
162     /** Property identifier: symbol table. */
163     public static final String JavaDoc SYMBOL_TABLE =
164         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
165     
166     /** Property identifier: security manager. */
167     protected static final String JavaDoc SECURITY_MANAGER =
168         Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
169     
170     protected static final boolean DEBUG_NODE_POOL = false;
171     
172     // Data
173

174     // different sorts of declarations; should make lookup and
175
// traverser calling more efficient/less bulky.
176
final static int ATTRIBUTE_TYPE = 1;
177     final static int ATTRIBUTEGROUP_TYPE = 2;
178     final static int ELEMENT_TYPE = 3;
179     final static int GROUP_TYPE = 4;
180     final static int IDENTITYCONSTRAINT_TYPE = 5;
181     final static int NOTATION_TYPE = 6;
182     final static int TYPEDECL_TYPE = 7;
183     
184     // this string gets appended to redefined names; it's purpose is to be
185
// as unlikely as possible to cause collisions.
186
public final static String JavaDoc REDEF_IDENTIFIER = "_fn3dktizrknc9pi";
187     
188     //
189
//protected data that can be accessable by any traverser
190
// stores <notation> decl
191
protected Hashtable JavaDoc fNotationRegistry = new Hashtable JavaDoc();
192     
193     protected XSDeclarationPool fDeclPool = null;
194     
195     
196     // These tables correspond to the symbol spaces defined in the
197
// spec.
198
// They are keyed with a QName (that is, String("URI,localpart) and
199
// their values are nodes corresponding to the given name's decl.
200
// By asking the node for its ownerDocument and looking in
201
// XSDocumentInfoRegistry we can easily get the corresponding
202
// XSDocumentInfo object.
203
private Hashtable JavaDoc fUnparsedAttributeRegistry = new Hashtable JavaDoc();
204     private Hashtable JavaDoc fUnparsedAttributeGroupRegistry = new Hashtable JavaDoc();
205     private Hashtable JavaDoc fUnparsedElementRegistry = new Hashtable JavaDoc();
206     private Hashtable JavaDoc fUnparsedGroupRegistry = new Hashtable JavaDoc();
207     private Hashtable JavaDoc fUnparsedIdentityConstraintRegistry = new Hashtable JavaDoc();
208     private Hashtable JavaDoc fUnparsedNotationRegistry = new Hashtable JavaDoc();
209     private Hashtable JavaDoc fUnparsedTypeRegistry = new Hashtable JavaDoc();
210     // Compensation for the above hashtables to locate XSDocumentInfo,
211
// Since we may take Schema Element directly, so can not get the
212
// corresponding XSDocumentInfo object just using above hashtables.
213
private Hashtable JavaDoc fUnparsedAttributeRegistrySub = new Hashtable JavaDoc();
214     private Hashtable JavaDoc fUnparsedAttributeGroupRegistrySub = new Hashtable JavaDoc();
215     private Hashtable JavaDoc fUnparsedElementRegistrySub = new Hashtable JavaDoc();
216     private Hashtable JavaDoc fUnparsedGroupRegistrySub = new Hashtable JavaDoc();
217     private Hashtable JavaDoc fUnparsedIdentityConstraintRegistrySub = new Hashtable JavaDoc();
218     private Hashtable JavaDoc fUnparsedNotationRegistrySub = new Hashtable JavaDoc();
219     private Hashtable JavaDoc fUnparsedTypeRegistrySub = new Hashtable JavaDoc();
220     
221     // this is keyed with a documentNode (or the schemaRoot nodes
222
// contained in the XSDocumentInfo objects) and its value is the
223
// XSDocumentInfo object corresponding to that document.
224
// Basically, the function of this registry is to be a link
225
// between the nodes we fetch from calls to the fUnparsed*
226
// arrays and the XSDocumentInfos they live in.
227
private Hashtable JavaDoc fXSDocumentInfoRegistry = new Hashtable JavaDoc();
228     
229     // this hashtable is keyed on by XSDocumentInfo objects. Its values
230
// are Vectors containing the XSDocumentInfo objects <include>d,
231
// <import>ed or <redefine>d by the key XSDocumentInfo.
232
private Hashtable JavaDoc fDependencyMap = new Hashtable JavaDoc();
233     
234     // this hashtable is keyed on by a target namespace. Its values
235
// are Vectors containing namespaces imported by schema documents
236
// with the key target namespace.
237
// if an imprted schema has absent namespace, the value "null" is stored.
238
private Hashtable JavaDoc fImportMap = new Hashtable JavaDoc();
239     // all namespaces that imports other namespaces
240
// if the importing schema has absent namespace, empty string is stored.
241
// (because the key of a hashtable can't be null.)
242
private Vector JavaDoc fAllTNSs = new Vector JavaDoc();
243     // stores instance document mappings between namespaces and schema hints
244
private Hashtable JavaDoc fLocationPairs = null;
245     
246     //this hashtable is keyded on by DOM node objects.
247
//The table stores the hidden nodes
248
private Hashtable JavaDoc fHiddenNodes = null;
249     
250     // convenience methods
251
private String JavaDoc null2EmptyString(String JavaDoc ns) {
252         return ns == null ? XMLSymbols.EMPTY_STRING : ns;
253     }
254     private String JavaDoc emptyString2Null(String JavaDoc ns) {
255         return ns == XMLSymbols.EMPTY_STRING ? null : ns;
256     }
257     // use Schema Element to lookup the SystemId.
258
private String JavaDoc doc2SystemId(Element JavaDoc ele) {
259         String JavaDoc documentURI = null;
260         /**
261          * REVISIT: Casting until DOM Level 3 interfaces are available. -- mrglavas
262          */

263         if(ele.getOwnerDocument() instanceof org.apache.xerces.impl.xs.opti.SchemaDOM){
264             documentURI = ((org.apache.xerces.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI();
265         }
266         return documentURI != null ? documentURI : (String JavaDoc) fDoc2SystemId.get(ele);
267     }
268     
269     // This vector stores strings which are combinations of the
270
// publicId and systemId of the inputSource corresponding to a
271
// schema document. This combination is used so that the user's
272
// EntityResolver can provide a consistent way of identifying a
273
// schema document that is included in multiple other schemas.
274
private Hashtable JavaDoc fTraversed = new Hashtable JavaDoc();
275     
276     // this hashtable contains a mapping from Schema Element to its systemId
277
// this is useful to resolve a uri relative to the referring document
278
private Hashtable JavaDoc fDoc2SystemId = new Hashtable JavaDoc();
279     
280     // the primary XSDocumentInfo we were called to parse
281
private XSDocumentInfo fRoot = null;
282     
283     // This hashtable's job is to act as a link between the Schema Element and its
284
// XSDocumentInfo object.
285
private Hashtable JavaDoc fDoc2XSDocumentMap = new Hashtable JavaDoc();
286     
287     // map between <redefine> elements and the XSDocumentInfo
288
// objects that correspond to the documents being redefined.
289
private Hashtable JavaDoc fRedefine2XSDMap = new Hashtable JavaDoc();
290     
291     // map between <redefine> elements and the namespace support
292
private Hashtable JavaDoc fRedefine2NSSupport = new Hashtable JavaDoc();
293     
294     // these objects store a mapping between the names of redefining
295
// groups/attributeGroups and the groups/AttributeGroups which
296
// they redefine by restriction (implicitly). It is up to the
297
// Group and AttributeGroup traversers to check these restrictions for
298
// validity.
299
private Hashtable JavaDoc fRedefinedRestrictedAttributeGroupRegistry = new Hashtable JavaDoc();
300     private Hashtable JavaDoc fRedefinedRestrictedGroupRegistry = new Hashtable JavaDoc();
301     
302     // a variable storing whether the last schema document
303
// processed (by getSchema) was a duplicate.
304
private boolean fLastSchemaWasDuplicate;
305     
306     // validate annotations feature
307
private boolean fValidateAnnotations = false;
308     
309     //handle multiple import feature
310
private boolean fHonourAllSchemaLocations = false;
311
312     // the XMLErrorReporter
313
private XMLErrorReporter fErrorReporter;
314     private XMLEntityResolver fEntityResolver;
315     
316     // the XSAttributeChecker
317
private XSAttributeChecker fAttributeChecker;
318     
319     // the symbol table
320
private SymbolTable fSymbolTable;
321     
322     // the GrammarResolver
323
private XSGrammarBucket fGrammarBucket;
324     
325     // the Grammar description
326
private XSDDescription fSchemaGrammarDescription;
327     
328     // the Grammar Pool
329
private XMLGrammarPool fGrammarPool;
330     
331     //************ Traversers **********
332
XSDAttributeGroupTraverser fAttributeGroupTraverser;
333     XSDAttributeTraverser fAttributeTraverser;
334     XSDComplexTypeTraverser fComplexTypeTraverser;
335     XSDElementTraverser fElementTraverser;
336     XSDGroupTraverser fGroupTraverser;
337     XSDKeyrefTraverser fKeyrefTraverser;
338     XSDNotationTraverser fNotationTraverser;
339     XSDSimpleTypeTraverser fSimpleTypeTraverser;
340     XSDUniqueOrKeyTraverser fUniqueOrKeyTraverser;
341     XSDWildcardTraverser fWildCardTraverser;
342     
343     SchemaDOMParser fSchemaParser;
344     SchemaContentHandler fXSContentHandler;
345     XML11Configuration fAnnotationValidator;
346     XSAnnotationGrammarPool fGrammarBucketAdapter;
347     
348     // these data members are needed for the deferred traversal
349
// of local elements.
350

351     // the initial size of the array to store deferred local elements
352
private static final int INIT_STACK_SIZE = 30;
353     // the incremental size of the array to store deferred local elements
354
private static final int INC_STACK_SIZE = 10;
355     // current position of the array (# of deferred local elements)
356
private int fLocalElemStackPos = 0;
357     
358     private XSParticleDecl[] fParticle = new XSParticleDecl[INIT_STACK_SIZE];
359     private Element JavaDoc[] fLocalElementDecl = new Element JavaDoc[INIT_STACK_SIZE];
360     private XSDocumentInfo[] fLocalElementDecl_schema = new XSDocumentInfo[INIT_STACK_SIZE]; //JACK
361
private int[] fAllContext = new int[INIT_STACK_SIZE];
362     private XSObject[] fParent = new XSObject[INIT_STACK_SIZE];
363     private String JavaDoc [][] fLocalElemNamespaceContext = new String JavaDoc [INIT_STACK_SIZE][1];
364     
365     // these data members are needed for the deferred traversal
366
// of keyrefs.
367

368     // the initial size of the array to store deferred keyrefs
369
private static final int INIT_KEYREF_STACK = 2;
370     // the incremental size of the array to store deferred keyrefs
371
private static final int INC_KEYREF_STACK_AMOUNT = 2;
372     // current position of the array (# of deferred keyrefs)
373
private int fKeyrefStackPos = 0;
374     
375     private Element JavaDoc [] fKeyrefs = new Element JavaDoc[INIT_KEYREF_STACK];
376     private XSDocumentInfo [] fKeyrefsMapXSDocumentInfo = new XSDocumentInfo[INIT_KEYREF_STACK];
377     private XSElementDecl [] fKeyrefElems = new XSElementDecl [INIT_KEYREF_STACK];
378     private String JavaDoc [][] fKeyrefNamespaceContext = new String JavaDoc[INIT_KEYREF_STACK][1];
379     
380     // Constructors
381
public XSDHandler(){
382         fHiddenNodes = new Hashtable JavaDoc();
383         fSchemaParser = new SchemaDOMParser(new SchemaParsingConfig());
384     }
385     
386     // it should be possible to use the same XSDHandler to parse
387
// multiple schema documents; this will allow one to be
388
// constructed.
389
public XSDHandler (XSGrammarBucket gBucket) {
390         this();
391         fGrammarBucket = gBucket;
392         
393         // Note: don't use SchemaConfiguration internally
394
// we will get stack overflaw because
395
// XMLSchemaValidator will be instantiating XSDHandler...
396
fSchemaGrammarDescription = new XSDDescription();
397     } // end constructor
398

399     /**
400      * This method initiates the parse of a schema. It will likely be
401      * called from the Validator and it will make the
402      * resulting grammar available; it returns a reference to this object just
403      * in case. A reset(XMLComponentManager) must be called before this methods is called.
404      * @param is
405      * @param desc
406      * @param locationPairs
407      * @return
408      * @throws IOException
409      */

410     public SchemaGrammar parseSchema(XMLInputSource is, XSDDescription desc,
411             Hashtable JavaDoc locationPairs)
412     throws IOException JavaDoc {
413         fLocationPairs = locationPairs;
414         fSchemaParser.resetNodePool();
415         SchemaGrammar grammar = null;
416         String JavaDoc schemaNamespace = null;
417         short referType = desc.getContextType();
418         // if loading using JAXP schemaSource property, or using grammar caching loadGrammar
419
// the desc.targetNamespace is always null.
420
// Therefore we should not attempt to find out if
421
// the schema is already in the bucket, since in the case we have
422
// no namespace schema in the bucket, findGrammar will always return the
423
// no namespace schema.
424
if (referType != XSDDescription.CONTEXT_PREPARSE){
425             // first try to find it in the bucket/pool, return if one is found
426
if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT && isExistingGrammar(desc)) {
427                 grammar = fGrammarBucket.getGrammar(desc.getTargetNamespace());
428             }
429             else {
430                 grammar = findGrammar(desc);
431             }
432             if (grammar != null)
433                 return grammar;
434             schemaNamespace = desc.getTargetNamespace();
435             // handle empty string URI as null
436
if (schemaNamespace != null) {
437                 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
438             }
439         }
440         
441         // before parsing a schema, need to clear registries associated with
442
// parsing schemas
443
prepareForParse();
444         
445         Document JavaDoc schemaRootDoc = null;
446         Element JavaDoc schemaRoot = null;
447         // first phase: construct trees.
448
if (is instanceof DOMInputSource) {
449             //clean up the field fHiddenNodes, used for DOMInputSource
450
fHiddenNodes.clear();
451             Node JavaDoc domNode = ((DOMInputSource)is).getNode();
452             
453             if (domNode instanceof Document JavaDoc) {
454                 schemaRootDoc = (Document JavaDoc)domNode;
455                 schemaRoot = DOMUtil.getRoot(schemaRootDoc);
456             }
457             else if (domNode instanceof Element JavaDoc) {
458                 schemaRoot = (Element JavaDoc)domNode;
459             }
460             else {
461                 return null;
462             }
463         } // DOMInputSource
464
else if (is instanceof SAXInputSource) {
465             XMLReader JavaDoc parser = ((SAXInputSource)is).getXMLReader();
466             InputSource inputSource = ((SAXInputSource)is).getInputSource();
467             boolean namespacePrefixes = false;
468             if (parser != null) {
469                 try {
470                     namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES);
471                 }
472                 catch (SAXException JavaDoc se) {}
473             }
474             else {
475                 try {
476                     parser = XMLReaderFactory.createXMLReader();
477                 }
478                 // If something went wrong with the factory
479
// just use our own SAX parser.
480
catch (SAXException JavaDoc se) {
481                     parser = new SAXParser();
482                 }
483                 try {
484                     parser.setFeature(NAMESPACE_PREFIXES, true);
485                     namespacePrefixes = true;
486                 }
487                 catch (SAXException JavaDoc se) {}
488             }
489             // If XML names and Namespace URIs are already internalized we
490
// can avoid running them through the SymbolTable.
491
boolean stringsInternalized = false;
492             try {
493                 stringsInternalized = parser.getFeature(STRING_INTERNING);
494             }
495             catch (SAXException JavaDoc exc) {
496                 // The feature isn't recognized or getting it is not supported.
497
// In either case, assume that strings are not internalized.
498
}
499             if (fXSContentHandler == null) {
500                 fXSContentHandler = new SchemaContentHandler();
501             }
502             fXSContentHandler.reset(fSchemaParser, fSymbolTable,
503                     namespacePrefixes, stringsInternalized);
504             parser.setContentHandler(fXSContentHandler);
505             parser.setErrorHandler(fErrorReporter.getSAXErrorHandler());
506             try {
507                 parser.parse(inputSource);
508             }
509             catch (SAXException JavaDoc se) {
510                 return null;
511             }
512             schemaRootDoc = fXSContentHandler.getDocument();
513             if (schemaRootDoc == null) {
514                 // something went wrong right off the hop
515
return null;
516             }
517             schemaRoot = DOMUtil.getRoot(schemaRootDoc);
518         }
519         else {
520             schemaRoot = getSchemaDocument(schemaNamespace, is,
521                   referType == XSDDescription.CONTEXT_PREPARSE,
522                   referType, null);
523              
524         }//is instanceof XMLInputSource
525

526         if(schemaRoot == null){
527             // something went wrong right off the hop
528
return null;
529         }
530         
531         if ( referType == XSDDescription.CONTEXT_PREPARSE) {
532             Element JavaDoc schemaElem = schemaRoot;
533             schemaNamespace = DOMUtil.getAttrValue(schemaElem, SchemaSymbols.ATT_TARGETNAMESPACE);
534             if(schemaNamespace != null && schemaNamespace.length() > 0) {
535                 // Since now we've discovered a namespace, we need to update xsd key
536
// and store this schema in traversed schemas bucket
537
schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
538                 desc.setTargetNamespace(schemaNamespace);
539             }
540             else {
541                 schemaNamespace = null;
542             }
543             grammar = findGrammar(desc);
544             if (grammar != null)
545                 return grammar;
546             String JavaDoc schemaId = XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false);
547             XSDKey key = new XSDKey(schemaId, referType, schemaNamespace);
548             fTraversed.put(key, schemaRoot);
549             if (schemaId != null) {
550                 fDoc2SystemId.put(schemaRoot, schemaId);
551             }
552         }
553         
554         // before constructing trees and traversing a schema, need to reset
555
// all traversers and clear all registries
556
prepareForTraverse();
557         
558         fRoot = constructTrees(schemaRoot, is.getSystemId(), desc);
559         if (fRoot == null) {
560             return null;
561         }
562         
563         // second phase: fill global registries.
564
buildGlobalNameRegistries();
565         
566         // third phase: call traversers
567
ArrayList JavaDoc annotationInfo = fValidateAnnotations ? new ArrayList JavaDoc() : null;
568         traverseSchemas(annotationInfo);
569         
570         // fourth phase: handle local element decls
571
traverseLocalElements();
572         
573         // fifth phase: handle Keyrefs
574
resolveKeyRefs();
575         
576         // sixth phase: validate attribute of non-schema namespaces
577
// REVISIT: skip this for now. we really don't want to do it.
578
//fAttributeChecker.checkNonSchemaAttributes(fGrammarBucket);
579

580         // seventh phase: store imported grammars
581
// for all grammars with <import>s
582
for (int i = fAllTNSs.size() - 1; i >= 0; i--) {
583             // get its target namespace
584
String JavaDoc tns = (String JavaDoc)fAllTNSs.elementAt(i);
585             // get all namespaces it imports
586
Vector JavaDoc ins = (Vector JavaDoc)fImportMap.get(tns);
587             // get the grammar
588
SchemaGrammar sg = fGrammarBucket.getGrammar(emptyString2Null(tns));
589             if (sg == null)
590                 continue;
591             SchemaGrammar isg;
592             // for imported namespace
593
int count = 0;
594             for (int j = 0; j < ins.size(); j++) {
595                 // get imported grammar
596
isg = fGrammarBucket.getGrammar((String JavaDoc)ins.elementAt(j));
597                 // reuse the same vector
598
if (isg != null)
599                     ins.setElementAt(isg, count++);
600             }
601             ins.setSize(count);
602             // set the imported grammars
603
sg.setImportedGrammars(ins);
604         }
605         
606         /** validate annotations **/
607         if (fValidateAnnotations && annotationInfo.size() > 0) {
608             validateAnnotations(annotationInfo);
609         }
610
611         // and return.
612
return fGrammarBucket.getGrammar(fRoot.fTargetNamespace);
613     } // end parseSchema
614

615     private void validateAnnotations(ArrayList JavaDoc annotationInfo) {
616         if (fAnnotationValidator == null) {
617             createAnnotationValidator();
618         }
619         final int size = annotationInfo.size();
620         final XMLInputSource src = new XMLInputSource(null, null, null);
621         fGrammarBucketAdapter.refreshGrammars(fGrammarBucket);
622         for (int i = 0; i < size; i += 2) {
623             src.setSystemId((String JavaDoc) annotationInfo.get(i));
624             XSAnnotationInfo annotation = (XSAnnotationInfo) annotationInfo.get(i+1);
625             while (annotation != null) {
626                 src.setCharacterStream(new StringReader JavaDoc(annotation.fAnnotation));
627                 try {
628                     fAnnotationValidator.parse(src);
629                 }
630                 catch (IOException JavaDoc exc) {}
631                 annotation = annotation.next;
632             }
633         }
634     }
635     
636     private void createAnnotationValidator() {
637         fAnnotationValidator = new XML11Configuration();
638         fGrammarBucketAdapter = new XSAnnotationGrammarPool();
639         fAnnotationValidator.setFeature(VALIDATION, true);
640         fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true);
641         fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter);
642         /** Set error handler. **/
643         XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler();
644         fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler());
645     }
646
647     /**
648      * Pull the grammar out of the bucket simply using
649      * its TNS as a key
650      */

651     SchemaGrammar getGrammar(String JavaDoc tns) {
652         return fGrammarBucket.getGrammar(tns);
653     }
654     
655     /**
656      * First try to find a grammar in the bucket, if failed, consult the
657      * grammar pool. If a grammar is found in the pool, then add it (and all
658      * imported ones) into the bucket.
659      */

660     protected SchemaGrammar findGrammar(XSDDescription desc) {
661         SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace());
662         if (sg == null) {
663             if (fGrammarPool != null) {
664                 sg = (SchemaGrammar)fGrammarPool.retrieveGrammar(desc);
665                 if (sg != null) {
666                     // put this grammar into the bucket, along with grammars
667
// imported by it (directly or indirectly)
668
if (!fGrammarBucket.putGrammar(sg, true)) {
669                         // REVISIT: a conflict between new grammar(s) and grammars
670
// in the bucket. What to do? A warning? An exception?
671
reportSchemaWarning("GrammarConflict", null, null);
672                         sg = null;
673                     }
674                 }
675             }
676         }
677         return sg;
678     }
679     
680     // may wish to have setter methods for ErrorHandler,
681
// EntityResolver...
682

683     private static final String JavaDoc[][] NS_ERROR_CODES = {
684 </