blob: d24646d113337fda538b44f4640e39c0abf4b618 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: XMLValidator.cpp 568078 2007-08-21 11:43:25Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/framework/XMLValidator.hpp>
#include <xercesc/util/Mutexes.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLInitializer.hpp>
#include <xercesc/util/XMLMsgLoader.hpp>
#include <xercesc/util/XMLRegisterCleanup.hpp>
#include <xercesc/internal/XMLScanner.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// Local static functions
// ---------------------------------------------------------------------------
static XMLMutex* sMsgMutex = 0;
static XMLRegisterCleanup msgLoaderCleanup;
static XMLMsgLoader* sMsgLoader = 0;
static XMLRegisterCleanup validatorMutexCleanup;
//
// We need to fault in this mutex. But, since its used for synchronization
// itself, we have to do this the low level way using a compare and swap.
//
static XMLMutex& gValidatorMutex()
{
if (!sMsgMutex)
{
XMLMutexLock lockInit(XMLPlatformUtils::fgAtomicMutex);
if (!sMsgMutex)
{
sMsgMutex = new (XMLPlatformUtils::fgMemoryManager) XMLMutex(XMLPlatformUtils::fgMemoryManager);
validatorMutexCleanup.registerCleanup(XMLValidator::reinitMsgMutex);
}
}
return *sMsgMutex;
}
static XMLMsgLoader& getMsgLoader()
{
if (!sMsgLoader)
{
// Lock the mutex
XMLMutexLock lockInit(&gValidatorMutex());
if (!sMsgLoader)
{
sMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgValidityDomain);
if (!sMsgLoader)
XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
//
// Register this XMLMsgLoader for cleanup at Termination.
//
msgLoaderCleanup.registerCleanup(XMLValidator::reinitMsgLoader);
}
}
return *sMsgLoader;
}
void XMLInitializer::initializeValidatorMsgLoader()
{
sMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgValidityDomain);
// Register this XMLMsgLoader for cleanup at Termination.
if (sMsgLoader) {
msgLoaderCleanup.registerCleanup(XMLValidator::reinitMsgLoader);
}
}
// ---------------------------------------------------------------------------
// XMLValidator: Error emitting methods
// ---------------------------------------------------------------------------
//
// These methods are called whenever the scanner wants to emit an error.
// It handles getting the message loaded, doing token replacement, etc...
// and then calling the error handler, if its installed.
//
void XMLValidator::emitError(const XMLValid::Codes toEmit)
{
// Bump the error count if it is not a warning
if (XMLValid::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
fScanner->incrementErrorCount();
// Call error reporter if we have one
if (fErrorReporter)
{
// Load the message into a local for display
const unsigned int msgSize = 1023;
XMLCh errText[msgSize + 1];
// load the text
if (!getMsgLoader().loadMsg(toEmit, errText, msgSize))
{
// <TBD> Probably should load a default msg here
}
//
// Create a LastExtEntityInfo structure and get the reader manager
// to fill it in for us. This will give us the information about
// the last reader on the stack that was an external entity of some
// sort (i.e. it will ignore internal entities.
//
ReaderMgr::LastExtEntityInfo lastInfo;
fReaderMgr->getLastExtEntityInfo(lastInfo);
fErrorReporter->error
(
toEmit
, XMLUni::fgValidityDomain
, XMLValid::errorType(toEmit)
, errText
, lastInfo.systemId
, lastInfo.publicId
, lastInfo.lineNumber
, lastInfo.colNumber
);
}
// Bail out if its fatal an we are to give up on the first fatal error
if (((XMLValid::isError(toEmit) && fScanner->getValidationConstraintFatal())
|| XMLValid::isFatal(toEmit))
&& fScanner->getExitOnFirstFatal()
&& !fScanner->getInException())
{
throw toEmit;
}
}
void XMLValidator::emitError(const XMLValid::Codes toEmit
, const XMLCh* const text1
, const XMLCh* const text2
, const XMLCh* const text3
, const XMLCh* const text4)
{
// Bump the error count if it is not a warning
if (XMLValid::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
fScanner->incrementErrorCount();
// Call error reporter if we have one
if (fErrorReporter)
{
//
// Load the message into alocal and replace any tokens found in
// the text.
//
const unsigned int maxChars = 2047;
XMLCh errText[maxChars + 1];
// load the text
if (!getMsgLoader().loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fScanner->getMemoryManager()))
{
// <TBD> Should probably load a default message here
}
//
// Create a LastExtEntityInfo structure and get the reader manager
// to fill it in for us. This will give us the information about
// the last reader on the stack that was an external entity of some
// sort (i.e. it will ignore internal entities.
//
ReaderMgr::LastExtEntityInfo lastInfo;
fReaderMgr->getLastExtEntityInfo(lastInfo);
fErrorReporter->error
(
toEmit
, XMLUni::fgValidityDomain
, XMLValid::errorType(toEmit)
, errText
, lastInfo.systemId
, lastInfo.publicId
, lastInfo.lineNumber
, lastInfo.colNumber
);
}
// Bail out if its fatal an we are to give up on the first fatal error
if (((XMLValid::isError(toEmit) && fScanner->getValidationConstraintFatal())
|| XMLValid::isFatal(toEmit))
&& fScanner->getExitOnFirstFatal()
&& !fScanner->getInException())
{
throw toEmit;
}
}
void XMLValidator::emitError(const XMLValid::Codes toEmit
, const char* const text1
, const char* const text2
, const char* const text3
, const char* const text4)
{
// Bump the error count if it is not a warning
if (XMLValid::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
fScanner->incrementErrorCount();
// Call error reporter if we have one
if (fErrorReporter)
{
//
// Load the message into alocal and replace any tokens found in
// the text.
//
const unsigned int maxChars = 2047;
XMLCh errText[maxChars + 1];
// load the text
if (!getMsgLoader().loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fScanner->getMemoryManager()))
{
// <TBD> Should probably load a default message here
}
//
// Create a LastExtEntityInfo structure and get the reader manager
// to fill it in for us. This will give us the information about
// the last reader on the stack that was an external entity of some
// sort (i.e. it will ignore internal entities.
//
ReaderMgr::LastExtEntityInfo lastInfo;
fReaderMgr->getLastExtEntityInfo(lastInfo);
fErrorReporter->error
(
toEmit
, XMLUni::fgValidityDomain
, XMLValid::errorType(toEmit)
, errText
, lastInfo.systemId
, lastInfo.publicId
, lastInfo.lineNumber
, lastInfo.colNumber
);
}
// Bail out if its fatal an we are to give up on the first fatal error
if (((XMLValid::isError(toEmit) && fScanner->getValidationConstraintFatal())
|| XMLValid::isFatal(toEmit))
&& fScanner->getExitOnFirstFatal()
&& !fScanner->getInException())
{
throw toEmit;
}
}
void XMLValidator::emitError(const XMLValid::Codes toEmit
, const XMLExcepts::Codes originalExceptCode
, const XMLCh* const text1
, const XMLCh* const text2
, const XMLCh* const text3
, const XMLCh* const text4)
{
// Bump the error count if it is not a warning
if (XMLValid::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
fScanner->incrementErrorCount();
// Call error reporter if we have one
if (fErrorReporter)
{
//
// Load the message into alocal and replace any tokens found in
// the text.
//
const unsigned int maxChars = 2047;
XMLCh errText[maxChars + 1];
// load the text
if (!getMsgLoader().loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fScanner->getMemoryManager()))
{
// <TBD> Should probably load a default message here
}
//
// Create a LastExtEntityInfo structure and get the reader manager
// to fill it in for us. This will give us the information about
// the last reader on the stack that was an external entity of some
// sort (i.e. it will ignore internal entities.
//
ReaderMgr::LastExtEntityInfo lastInfo;
fReaderMgr->getLastExtEntityInfo(lastInfo);
fErrorReporter->error
(
originalExceptCode
, XMLUni::fgExceptDomain //XMLUni::fgValidityDomain
, XMLValid::errorType(toEmit)
, errText
, lastInfo.systemId
, lastInfo.publicId
, lastInfo.lineNumber
, lastInfo.colNumber
);
}
// Bail out if its fatal an we are to give up on the first fatal error
if (((XMLValid::isError(toEmit) && fScanner->getValidationConstraintFatal())
|| XMLValid::isFatal(toEmit))
&& fScanner->getExitOnFirstFatal()
&& !fScanner->getInException())
{
throw toEmit;
}
}
// ---------------------------------------------------------------------------
// XMLValidator: Hidden Constructors
// ---------------------------------------------------------------------------
XMLValidator::XMLValidator(XMLErrorReporter* const errReporter) :
fBufMgr(0)
, fErrorReporter(errReporter)
, fReaderMgr(0)
, fScanner(0)
{
}
// -----------------------------------------------------------------------
// Notification that lazy data has been deleted
// -----------------------------------------------------------------------
void XMLValidator::reinitMsgMutex()
{
delete sMsgMutex;
sMsgMutex = 0;
}
// -----------------------------------------------------------------------
// Reinitialise the message loader
// -----------------------------------------------------------------------
void XMLValidator::reinitMsgLoader()
{
delete sMsgLoader;
sMsgLoader = 0;
}
XERCES_CPP_NAMESPACE_END