public SchemaGrammar parseSchema(XMLInputSource is, XSDDescription desc,
Hashtable locationPairs)
throws IOException {
fLocationPairs = locationPairs;
fSchemaParser.resetNodePool();
SchemaGrammar grammar = null;
String schemaNamespace = null;
short referType = desc.getContextType();
// if loading using JAXP schemaSource property, or using grammar caching loadGrammar
// the desc.targetNamespace is always null.
// Therefore we should not attempt to find out if
// the schema is already in the bucket, since in the case we have
// no namespace schema in the bucket, findGrammar will always return the
// no namespace schema.
if (referType != XSDDescription.CONTEXT_PREPARSE){
// first try to find it in the bucket/pool, return if one is found
if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT && isExistingGrammar(desc)) {
grammar = fGrammarBucket.getGrammar(desc.getTargetNamespace());
}
else {
grammar = findGrammar(desc);
}
if (grammar != null)
return grammar;
schemaNamespace = desc.getTargetNamespace();
// handle empty string URI as null
if (schemaNamespace != null) {
schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
}
}
// before parsing a schema, need to clear registries associated with
// parsing schemas
prepareForParse();
Document schemaRootDoc = null;
Element schemaRoot = null;
// first phase: construct trees.
if (is instanceof DOMInputSource) {
//clean up the field fHiddenNodes, used for DOMInputSource
fHiddenNodes.clear();
Node domNode = ((DOMInputSource)is).getNode();
if (domNode instanceof Document) {
schemaRootDoc = (Document)domNode;
schemaRoot = DOMUtil.getRoot(schemaRootDoc);
}
else if (domNode instanceof Element) {
schemaRoot = (Element)domNode;
}
else {
return null;
}
} // DOMInputSource
else if (is instanceof SAXInputSource) {
XMLReader parser = ((SAXInputSource)is).getXMLReader();
InputSource inputSource = ((SAXInputSource)is).getInputSource();
boolean namespacePrefixes = false;
if (parser != null) {
try {
namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES);
}
catch (SAXException se) {}
}
else {
try {
parser = XMLReaderFactory.createXMLReader();
}
// If something went wrong with the factory
// just use our own SAX parser.
catch (SAXException se) {
parser = new SAXParser();
}
try {
parser.setFeature(NAMESPACE_PREFIXES, true);
namespacePrefixes = true;
}
catch (SAXException se) {}
}
// If XML names and Namespace URIs are already internalized we
// can avoid running them through the SymbolTable.
boolean stringsInternalized = false;
try {
stringsInternalized = parser.getFeature(STRING_INTERNING);
}
catch (SAXException exc) {
// The feature isn't recognized or getting it is not supported.
// In either case, assume that strings are not internalized.
}
if (fXSContentHandler == null) {
fXSContentHandler = new SchemaContentHandler();
}
fXSContentHandler.reset(fSchemaParser, fSymbolTable,
namespacePrefixes, stringsInternalized);
parser.setContentHandler(fXSContentHandler);
parser.setErrorHandler(fErrorReporter.getSAXErrorHandler());
try {
parser.parse(inputSource);
}
catch (SAXException se) {
return null;
}
schemaRootDoc = fXSContentHandler.getDocument();
if (schemaRootDoc == null) {
// something went wrong right off the hop
return null;
}
schemaRoot = DOMUtil.getRoot(schemaRootDoc);
}
else {
schemaRoot = getSchemaDocument(schemaNamespace, is,
referType == XSDDescription.CONTEXT_PREPARSE,
referType, null);
}//is instanceof XMLInputSource
if(schemaRoot == null){
// something went wrong right off the hop
return null;
}
if ( referType == XSDDescription.CONTEXT_PREPARSE) {
Element schemaElem = schemaRoot;
schemaNamespace = DOMUtil.getAttrValue(schemaElem, SchemaSymbols.ATT_TARGETNAMESPACE);
if(schemaNamespace != null && schemaNamespace.length() > 0) {
// Since now we've discovered a namespace, we need to update xsd key
// and store this schema in traversed schemas bucket
schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
desc.setTargetNamespace(schemaNamespace);
}
else {
schemaNamespace = null;
}
grammar = findGrammar(desc);
if (grammar != null)
return grammar;
String schemaId = XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false);
XSDKey key = new XSDKey(schemaId, referType, schemaNamespace);
fTraversed.put(key, schemaRoot);
if (schemaId != null) {
fDoc2SystemId.put(schemaRoot, schemaId);
}
}
// before constructing trees and traversing a schema, need to reset
// all traversers and clear all registries
prepareForTraverse();
fRoot = constructTrees(schemaRoot, is.getSystemId(), desc);
if (fRoot == null) {
return null;
}
// second phase: fill global registries.
buildGlobalNameRegistries();
// third phase: call traversers
ArrayList annotationInfo = fValidateAnnotations ? new ArrayList() : null;
traverseSchemas(annotationInfo);
// fourth phase: handle local element decls
traverseLocalElements();
// fifth phase: handle Keyrefs
resolveKeyRefs();
// sixth phase: validate attribute of non-schema namespaces
// REVISIT: skip this for now. we really don't want to do it.
//fAttributeChecker.checkNonSchemaAttributes(fGrammarBucket);
// seventh phase: store imported grammars
// for all grammars with <import>s
for (int i = fAllTNSs.size() - 1; i >= 0; i--) {
// get its target namespace
String tns = (String)fAllTNSs.elementAt(i);
// get all namespaces it imports
Vector ins = (Vector)fImportMap.get(tns);
// get the grammar
SchemaGrammar sg = fGrammarBucket.getGrammar(emptyString2Null(tns));
if (sg == null)
continue;
SchemaGrammar isg;
// for imported namespace
int count = 0;
for (int j = 0; j < ins.size(); j++) {
// get imported grammar
isg = fGrammarBucket.getGrammar((String)ins.elementAt(j));