fastparser: fix load regression
Remove erroneous assert: maSavedException is indeed empty for
XML parser reported exceptions. Clean cut/paste code, and comment.
Change-Id: Ia538bcc87a7efcd079d3021e00ac4d2eb62f3e8d
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 04cfbee..3b93765 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -77,12 +77,12 @@ enum CallbackType { INVALID, START_ELEMENT, END_ELEMENT, CHARACTERS, DONE, EXCEP
struct Event
{
OUString msChars;
CallbackType maType;
sal_Int32 mnElementToken;
OUString msNamespace;
OUString msElementName;
rtl::Reference< FastAttributeList > mxAttributes;
CallbackType maType;
OUString msChars;
};
struct NameWithToken
@@ -165,9 +165,13 @@ struct Entity : public ParserData
XML_Parser mpParser;
::sax_expatwrap::XMLFile2UTFConverter maConverter;
// Exceptions cannot be thrown through the C-XmlParser (possible resource leaks),
// therefore the exception must be saved somewhere.
::com::sun::star::uno::Any maSavedException;
// Exceptions cannot be thrown through the C-XmlParser (possible
// resource leaks), therefore any exception thrown by a UNO callback
// must be saved somewhere until the C-XmlParser is stopped.
::com::sun::star::uno::Any maSavedException;
void saveException( const Exception &e );
void throwException( const ::rtl::Reference< FastLocatorImpl > &xDocumentLocator,
bool mbDuringParse );
::std::stack< NameWithToken > maNamespaceStack;
/* Context for main thread consuming events.
@@ -272,9 +276,10 @@ private:
{
mpParser->parse();
}
catch (const SAXParseException&)
catch (const Exception &e)
{
mpParser->getEntity().getEvent( EXCEPTION );
Entity &rEntity = mpParser->getEntity();
rEntity.getEvent( EXCEPTION );
mpParser->produce( EXCEPTION );
}
}
@@ -454,7 +459,7 @@ void Entity::startElement( Event *pEvent )
}
catch (const Exception& e)
{
maSavedException <<= e;
saveException( e );
}
}
@@ -467,7 +472,7 @@ void Entity::characters( const OUString& sChars )
}
catch (const Exception& e)
{
maSavedException <<= e;
saveException( e );
}
}
@@ -485,7 +490,7 @@ void Entity::endElement()
}
catch (const Exception& e)
{
maSavedException <<= e;
saveException( e );
}
maContextStack.pop();
}
@@ -781,7 +786,7 @@ void FastSaxParserImpl::parseStream( const InputSource& maStructSource) throw (S
{
popEntity();
XML_ParserFree( entity.mpParser );
throw;
throw;
}
catch (const IOException&)
{
@@ -958,7 +963,7 @@ bool FastSaxParserImpl::consume(EventList *pEventList)
{
Entity& rEntity = getEntity();
for (EventList::iterator aEventIt = pEventList->begin();
aEventIt != pEventList->end(); ++aEventIt)
aEventIt != pEventList->end(); ++aEventIt)
{
switch ((*aEventIt).maType)
{
@@ -974,28 +979,8 @@ bool FastSaxParserImpl::consume(EventList *pEventList)
case DONE:
return false;
case EXCEPTION:
{
assert( rEntity.maSavedException.hasValue() );
// Error during parsing !
XML_Error xmlE = XML_GetErrorCode( rEntity.mpParser );
OUString sSystemId = mxDocumentLocator->getSystemId();
sal_Int32 nLine = mxDocumentLocator->getLineNumber();
SAXParseException aExcept(
lclGetErrorMessage( xmlE, sSystemId, nLine ),
Reference< XInterface >(),
Any( &rEntity.maSavedException, getCppuType( &rEntity.maSavedException ) ),
mxDocumentLocator->getPublicId(),
mxDocumentLocator->getSystemId(),
mxDocumentLocator->getLineNumber(),
mxDocumentLocator->getColumnNumber()
);
// error handler is set, it may throw the exception
if( rEntity.mxErrorHandler.is() )
rEntity.mxErrorHandler->fatalError( Any( aExcept ) );
throw aExcept;
}
rEntity.throwException( mxDocumentLocator, false );
return false;
default:
assert(false);
return false;
@@ -1024,6 +1009,35 @@ const Entity& FastSaxParserImpl::getEntity() const
return maEntities.top();
}
// throw an exception, but avoid callback if
// during a threaded produce
void Entity::throwException( const ::rtl::Reference< FastLocatorImpl > &xDocumentLocator,
bool mbDuringParse )
{
// Error during parsing !
SAXParseException aExcept(
lclGetErrorMessage( XML_GetErrorCode( mpParser ),
xDocumentLocator->getSystemId(),
xDocumentLocator->getLineNumber() ),
Reference< XInterface >(),
Any( &maSavedException, getCppuType( &maSavedException ) ),
xDocumentLocator->getPublicId(),
xDocumentLocator->getSystemId(),
xDocumentLocator->getLineNumber(),
xDocumentLocator->getColumnNumber()
);
// error handler is set, it may throw the exception
if( !mbDuringParse || !mbEnableThreads )
{
if (mxErrorHandler.is() )
mxErrorHandler->fatalError( Any( aExcept ) );
}
// error handler has not thrown, but parsing must stop => throw ourselves
throw aExcept;
}
// starts parsing with actual parser !
void FastSaxParserImpl::parse()
{
@@ -1043,39 +1057,34 @@ void FastSaxParserImpl::parse()
bool const bContinue = XML_STATUS_ERROR != XML_Parse(rEntity.mpParser,
reinterpret_cast<const char*>(seqOut.getConstArray()), nRead, 0);
// callbacks used inside XML_Parse may have caught an exception
if( !bContinue || rEntity.maSavedException.hasValue() )
{
// Error during parsing !
XML_Error xmlE = XML_GetErrorCode( rEntity.mpParser );
OUString sSystemId = mxDocumentLocator->getSystemId();
sal_Int32 nLine = mxDocumentLocator->getLineNumber();
SAXParseException aExcept(
lclGetErrorMessage( xmlE, sSystemId, nLine ),
Reference< XInterface >(),
Any( &rEntity.maSavedException, getCppuType( &rEntity.maSavedException ) ),
mxDocumentLocator->getPublicId(),
mxDocumentLocator->getSystemId(),
mxDocumentLocator->getLineNumber(),
mxDocumentLocator->getColumnNumber()
);
// error handler is set, it may throw the exception
if( rEntity.mxErrorHandler.is() )
rEntity.mxErrorHandler->fatalError( Any( aExcept ) );
// error handler has not thrown, but parsing cannot go on, the
// exception MUST be thrown
throw aExcept;
}
rEntity.throwException( mxDocumentLocator, true );
}
while( nRead > 0 );
rEntity.getEvent( DONE );
if (rEntity.mbEnableThreads)
if( rEntity.mbEnableThreads )
produce( DONE );
}
// In the single threaded case we emit events via our C
// callbacks, so any exception caught must be queued up until
// we can safely re-throw it from our C++ parent of parse()
//
// If multi-threaded, we need to push an EXCEPTION event, at
// which point we transfer ownership of maSavedException to
// the consuming thread.
void Entity::saveException( const Exception &e )
{
// only store the first exception
if( !maSavedException.hasValue() )
{
maSavedException <<= e;
XML_StopParser( mpParser, /* resumable? */ XML_FALSE );
}
}
//------------------------------------------
//
// The C-Callbacks
@@ -1207,7 +1216,7 @@ void FastSaxParserImpl::callbackStartElement( const XML_Char* pwName, const XML_
}
catch (const Exception& e)
{
rEntity.maSavedException <<= e;
rEntity.saveException( e );
}
}
@@ -1253,13 +1262,13 @@ void FastSaxParserImpl::callbackEntityDecl(
if (value) { // value != 0 means internal entity
SAL_INFO("sax", "FastSaxParser: internal entity declaration, stopping");
XML_StopParser(getEntity().mpParser, XML_FALSE);
getEntity().maSavedException <<= SAXParseException(
getEntity().saveException( SAXParseException(
"FastSaxParser: internal entity declaration, stopping",
static_cast<OWeakObject*>(mpFront), Any(),
mxDocumentLocator->getPublicId(),
mxDocumentLocator->getSystemId(),
mxDocumentLocator->getLineNumber(),
mxDocumentLocator->getColumnNumber() );
mxDocumentLocator->getColumnNumber() ) );
} else {
SAL_INFO("sax", "FastSaxParser: ignoring external entity declaration");
}
@@ -1284,17 +1293,17 @@ int FastSaxParserImpl::callbackExternalEntityRef(
}
catch (const SAXParseException & e)
{
rCurrEntity.maSavedException <<= e;
rCurrEntity.saveException( e );
bOK = false;
}
catch (const SAXException& e)
{
rCurrEntity.maSavedException <<= SAXParseException(
rCurrEntity.saveException( SAXParseException(
e.Message, e.Context, e.WrappedException,
mxDocumentLocator->getPublicId(),
mxDocumentLocator->getSystemId(),
mxDocumentLocator->getLineNumber(),
mxDocumentLocator->getColumnNumber() );
mxDocumentLocator->getColumnNumber() ) );
bOK = false;
}
@@ -1314,21 +1323,21 @@ int FastSaxParserImpl::callbackExternalEntityRef(
}
catch (const SAXParseException& e)
{
rCurrEntity.maSavedException <<= e;
rCurrEntity.saveException( e );
bOK = false;
}
catch (const IOException& e)
{
SAXException aEx;
aEx.WrappedException <<= e;
rCurrEntity.maSavedException <<= aEx;
rCurrEntity.saveException( aEx );
bOK = false;
}
catch (const RuntimeException& e)
{
SAXException aEx;
aEx.WrappedException <<= e;
rCurrEntity.maSavedException <<= aEx;
rCurrEntity.saveException( aEx );
bOK = false;
}