in src/xercesc/internal/SGXMLScanner.cpp [3586:3847]
void SGXMLScanner::resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri, bool ignoreLoadSchema) {
Grammar* grammar = 0;
{
XMLSchemaDescriptionImpl theSchemaDescription(uri, fMemoryManager);
theSchemaDescription.setLocationHints(loc);
grammar = fGrammarResolver->getGrammar(&theSchemaDescription);
}
// If multi-import is enabled, make sure the existing grammar came
// from the import directive. Otherwise we may end up reloading
// the same schema that came from the external grammar pool. Ideally,
// we would move fSchemaInfoList to XMLGrammarPool so that it survives
// the destruction of the scanner in which case we could rely on the
// same logic we use to weed out duplicate schemas below.
//
if (!grammar || grammar->getGrammarType() == Grammar::DTDGrammarType ||
(getHandleMultipleImports() &&
((XMLSchemaDescription*)grammar->getGrammarDescription())->
getContextType () == XMLSchemaDescription::CONTEXT_IMPORT))
{
if (fLoadSchema || ignoreLoadSchema)
{
XSDDOMParser parser(0, fMemoryManager, 0);
parser.setValidationScheme(XercesDOMParser::Val_Never);
parser.setDoNamespaces(true);
parser.setUserEntityHandler(fEntityHandler);
parser.setUserErrorReporter(fErrorReporter);
//Normalize sysId
XMLBufBid nnSys(&fBufMgr);
XMLBuffer& normalizedSysId = nnSys.getBuffer();
XMLString::removeChar(loc, 0xFFFF, normalizedSysId);
const XMLCh* normalizedURI = normalizedSysId.getRawBuffer();
// Create a buffer for expanding the system id
XMLBufBid bbSys(&fBufMgr);
XMLBuffer& expSysId = bbSys.getBuffer();
// Allow the entity handler to expand the system id if they choose
// to do so.
InputSource* srcToFill = 0;
if (fEntityHandler)
{
if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
expSysId.set(normalizedURI);
ReaderMgr::LastExtEntityInfo lastInfo;
fReaderMgr.getLastExtEntityInfo(lastInfo);
XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::SchemaGrammar,
expSysId.getRawBuffer(), uri, XMLUni::fgZeroLenString, lastInfo.systemId,
&fReaderMgr);
srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
}
else
{
expSysId.set(normalizedURI);
}
// If they didn't create a source via the entity handler, then we
// have to create one on our own.
if (!srcToFill)
{
if (fDisableDefaultEntityResolution)
return;
ReaderMgr::LastExtEntityInfo lastInfo;
fReaderMgr.getLastExtEntityInfo(lastInfo);
XMLURL urlTmp(fMemoryManager);
if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) ||
(urlTmp.isRelative()))
{
if (!fStandardUriConformant)
{
XMLBufBid ddSys(&fBufMgr);
XMLBuffer& resolvedSysId = ddSys.getBuffer();
XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
srcToFill = new (fMemoryManager) LocalFileInputSource
(
lastInfo.systemId
, resolvedSysId.getRawBuffer()
, fMemoryManager
);
}
else
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
}
else
{
if (fStandardUriConformant && urlTmp.hasInvalidChar())
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
}
}
// Put a janitor on the input source
Janitor<InputSource> janSrc(srcToFill);
// Check if this exact schema has already been seen.
//
const XMLCh* sysId = srcToFill->getSystemId();
unsigned int uriId = (uri && *uri) ? fURIStringPool->addOrFind(uri) : fEmptyNamespaceId;
SchemaInfo* importSchemaInfo = 0;
if (fUseCachedGrammar)
importSchemaInfo = fCachedSchemaInfoList->get(sysId, uriId);
if (!importSchemaInfo && !fToCacheGrammar)
importSchemaInfo = fSchemaInfoList->get(sysId, uriId);
if (importSchemaInfo)
{
// We haven't added any new grammars so it is safe to just
// return.
//
return;
}
// Should just issue warning if the schema is not found
bool flag = srcToFill->getIssueFatalErrorIfNotFound();
srcToFill->setIssueFatalErrorIfNotFound(false);
parser.parse(*srcToFill);
// Reset the InputSource
srcToFill->setIssueFatalErrorIfNotFound(flag);
if (parser.getSawFatal() && fExitOnFirstFatal)
emitError(XMLErrs::SchemaScanFatalError);
DOMDocument* document = parser.getDocument(); //Our Grammar
if (document != 0) {
DOMElement* root = document->getDocumentElement();// This is what we pass to TraverserSchema
if (root != 0)
{
const XMLCh* newUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
bool newGrammar = false;
if (!XMLString::equals(newUri, uri)) {
if (fValidate || fValScheme == Val_Auto) {
fValidator->emitError(XMLValid::WrongTargetNamespace, loc, uri);
}
grammar = fGrammarResolver->getGrammar(newUri);
newGrammar = true;
}
if (!grammar ||
grammar->getGrammarType() == Grammar::DTDGrammarType ||
(getHandleMultipleImports() &&
((XMLSchemaDescription*) grammar->getGrammarDescription())->
getContextType () == XMLSchemaDescription::CONTEXT_IMPORT))
{
// If we switched namespace URI, recheck the schema info.
//
if (newGrammar)
{
unsigned int newUriId = (newUri && *newUri) ? fURIStringPool->addOrFind(newUri) : fEmptyNamespaceId;
if (fUseCachedGrammar)
importSchemaInfo = fCachedSchemaInfoList->get(sysId, newUriId);
if (!importSchemaInfo && !fToCacheGrammar)
importSchemaInfo = fSchemaInfoList->get(sysId, newUriId);
if (importSchemaInfo)
return;
}
// Since we have seen a grammar, set our validation flag
// at this point if the validation scheme is auto
if (fValScheme == Val_Auto && !fValidate) {
fValidate = true;
fElemStack.setValidationFlag(fValidate);
}
bool grammarFound = grammar &&
grammar->getGrammarType() == Grammar::SchemaGrammarType;
SchemaGrammar* schemaGrammar;
if (grammarFound) {
schemaGrammar = (SchemaGrammar*) grammar;
}
else {
schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
}
XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription();
gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE);
gramDesc->setLocationHints(sysId);
TraverseSchema traverseSchema
(
root
, fURIStringPool
, schemaGrammar
, fGrammarResolver
, fUseCachedGrammar ? fCachedSchemaInfoList : fSchemaInfoList
, fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList
, this
, sysId
, fEntityHandler
, fErrorReporter
, fMemoryManager
, grammarFound
);
// Reset the now invalid schema roots in the collected
// schema info entries.
//
{
RefHash2KeysTableOfEnumerator<SchemaInfo> i (
fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList);
while (i.hasMoreElements ())
i.nextElement().resetRoot ();
}
if (fGrammarType == Grammar::DTDGrammarType) {
fGrammar = schemaGrammar;
fGrammarType = Grammar::SchemaGrammarType;
fValidator->setGrammar(fGrammar);
}
if (fValidate) {
// validate the Schema scan so far
fValidator->preContentValidation(false);
}
}
}
}
}
}
else
{
// Since we have seen a grammar, set our validation flag
// at this point if the validation scheme is auto
if (fValScheme == Val_Auto && !fValidate) {
fValidate = true;
fElemStack.setValidationFlag(fValidate);
}
// we have seen a schema, so set up the fValidator as fSchemaValidator
if (fGrammarType == Grammar::DTDGrammarType) {
fGrammar = grammar;
fGrammarType = Grammar::SchemaGrammarType;
fValidator->setGrammar(fGrammar);
}
}
// update fModel; rely on the grammar resolver to do this
// efficiently
if(getPSVIHandler())
fModel = fGrammarResolver->getXSModel();
}