diff options
author | Michael Meeks <michael.meeks@collabora.com> | 2013-12-20 16:18:48 +0000 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2013-12-23 13:52:38 +0000 |
commit | 0b4f41eb0ee0fdcb22403f943f8f34911a463cb6 (patch) | |
tree | 3bf7d7fcaddfa6560e35d05a6ecf1cf1771d8e31 /sax | |
parent | 1b215d42075ca7cb6afb50cde59261664f9ba545 (diff) |
fastparser: fix load regression
Remove erroneous assert: maSavedException is indeed empty for
XML parser reported exceptions. Clean cut/paste code, and comment.
Cleanup conflicts, and squash subsequent fixup patches too.
Change-Id: Ia538bcc87a7efcd079d3021e00ac4d2eb62f3e8d
Diffstat (limited to 'sax')
-rw-r--r-- | sax/source/fastparser/fastparser.cxx | 271 |
1 files changed, 131 insertions, 140 deletions
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index 4f835d5c2dd5..88bef41c6d9c 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -56,8 +56,9 @@ using namespace ::com::sun::star::lang; using namespace ::com::sun::star::xml::sax; using namespace ::com::sun::star::io; using namespace com::sun::star; +using namespace sax_fastparser; -namespace sax_fastparser { +namespace { struct Event; class FastLocatorImpl; @@ -75,12 +76,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 @@ -163,9 +164,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. @@ -186,9 +191,9 @@ struct Entity : public ParserData Event& getEvent( CallbackType aType ); }; -// -------------------------------------------------------------------- -// FastSaxParser implementation -// -------------------------------------------------------------------- +} // namespace + +namespace sax_fastparser { class FastSaxParserImpl { @@ -262,6 +267,10 @@ private: FastTokenLookup maTokenLookup; }; +} // namespace sax_fastparser + +namespace { + class ParserThread: public salhelper::Thread { FastSaxParserImpl *mpParser; @@ -274,16 +283,15 @@ private: { mpParser->parse(); } - catch (const SAXParseException&) + catch (const Exception &e) { - mpParser->getEntity().getEvent( EXCEPTION ); + Entity &rEntity = mpParser->getEntity(); + rEntity.getEvent( EXCEPTION ); mpParser->produce( EXCEPTION ); } } }; -} - extern "C" { static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts) @@ -323,8 +331,6 @@ static int call_callbackExternalEntityRef( XML_Parser parser, } -namespace sax_fastparser { - // -------------------------------------------------------------------- // FastLocatorImpl // -------------------------------------------------------------------- @@ -347,18 +353,6 @@ private: FastSaxParserImpl *mpParser; }; -// -------------------------------------------------------------------- -// FastSaxParser -// -------------------------------------------------------------------- - -//--------------------------------------------- -// the implementation part -//--------------------------------------------- - - -// -------------------------------------------------------------------- -// FastLocatorImpl implementation -// -------------------------------------------------------------------- sal_Int32 SAL_CALL FastLocatorImpl::getColumnNumber(void) throw (RuntimeException) { @@ -477,7 +471,7 @@ void Entity::startElement( Event *pEvent ) } catch (const Exception& e) { - maSavedException <<= e; + saveException( e ); } } @@ -490,7 +484,7 @@ void Entity::characters( const OUString& sChars ) } catch (const Exception& e) { - maSavedException <<= e; + saveException( e ); } } @@ -508,7 +502,7 @@ void Entity::endElement() } catch (const Exception& e) { - maSavedException <<= e; + saveException( e ); } maContextStack.pop(); } @@ -546,6 +540,97 @@ Event& Entity::getEvent( CallbackType aType ) return rEvent; } +OUString lclGetErrorMessage( XML_Error xmlE, const OUString& sSystemId, sal_Int32 nLine ) +{ + const sal_Char* pMessage = ""; + switch( xmlE ) + { + case XML_ERROR_NONE: pMessage = "No"; break; + case XML_ERROR_NO_MEMORY: pMessage = "no memory"; break; + case XML_ERROR_SYNTAX: pMessage = "syntax"; break; + case XML_ERROR_NO_ELEMENTS: pMessage = "no elements"; break; + case XML_ERROR_INVALID_TOKEN: pMessage = "invalid token"; break; + case XML_ERROR_UNCLOSED_TOKEN: pMessage = "unclosed token"; break; + case XML_ERROR_PARTIAL_CHAR: pMessage = "partial char"; break; + case XML_ERROR_TAG_MISMATCH: pMessage = "tag mismatch"; break; + case XML_ERROR_DUPLICATE_ATTRIBUTE: pMessage = "duplicate attribute"; break; + case XML_ERROR_JUNK_AFTER_DOC_ELEMENT: pMessage = "junk after doc element"; break; + case XML_ERROR_PARAM_ENTITY_REF: pMessage = "parameter entity reference"; break; + case XML_ERROR_UNDEFINED_ENTITY: pMessage = "undefined entity"; break; + case XML_ERROR_RECURSIVE_ENTITY_REF: pMessage = "recursive entity reference"; break; + case XML_ERROR_ASYNC_ENTITY: pMessage = "async entity"; break; + case XML_ERROR_BAD_CHAR_REF: pMessage = "bad char reference"; break; + case XML_ERROR_BINARY_ENTITY_REF: pMessage = "binary entity reference"; break; + case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF: pMessage = "attribute external entity reference"; break; + case XML_ERROR_MISPLACED_XML_PI: pMessage = "misplaced xml processing instruction"; break; + case XML_ERROR_UNKNOWN_ENCODING: pMessage = "unknown encoding"; break; + case XML_ERROR_INCORRECT_ENCODING: pMessage = "incorrect encoding"; break; + case XML_ERROR_UNCLOSED_CDATA_SECTION: pMessage = "unclosed cdata section"; break; + case XML_ERROR_EXTERNAL_ENTITY_HANDLING: pMessage = "external entity reference"; break; + case XML_ERROR_NOT_STANDALONE: pMessage = "not standalone"; break; + default:; + } + + OUStringBuffer aBuffer( '[' ); + aBuffer.append( sSystemId ); + aBuffer.append( " line " ); + aBuffer.append( nLine ); + aBuffer.append( "]: " ); + aBuffer.appendAscii( pMessage ); + aBuffer.append( " error" ); + return aBuffer.makeStringAndClear(); +} + +// 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; +} + +// 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 ); + } +} + +} // namespace + +namespace sax_fastparser { + FastSaxParserImpl::FastSaxParserImpl( FastSaxParser* pFront ) : mpFront(pFront) { mxDocumentLocator.set( new FastLocatorImpl( this ) ); @@ -800,7 +885,7 @@ void FastSaxParserImpl::parseStream( const InputSource& maStructSource) throw (S { popEntity(); XML_ParserFree( entity.mpParser ); - throw; + throw; } catch (const IOException&) { @@ -898,58 +983,6 @@ Sequence< OUString > FastSaxParserImpl::getSupportedServiceNames(void) throw (Ru return seq; } - -/*--------------------------------------- -* -* Helper functions and classes -* -*-------------------------------------------*/ - -namespace { - -OUString lclGetErrorMessage( XML_Error xmlE, const OUString& sSystemId, sal_Int32 nLine ) -{ - const sal_Char* pMessage = ""; - switch( xmlE ) - { - case XML_ERROR_NONE: pMessage = "No"; break; - case XML_ERROR_NO_MEMORY: pMessage = "no memory"; break; - case XML_ERROR_SYNTAX: pMessage = "syntax"; break; - case XML_ERROR_NO_ELEMENTS: pMessage = "no elements"; break; - case XML_ERROR_INVALID_TOKEN: pMessage = "invalid token"; break; - case XML_ERROR_UNCLOSED_TOKEN: pMessage = "unclosed token"; break; - case XML_ERROR_PARTIAL_CHAR: pMessage = "partial char"; break; - case XML_ERROR_TAG_MISMATCH: pMessage = "tag mismatch"; break; - case XML_ERROR_DUPLICATE_ATTRIBUTE: pMessage = "duplicate attribute"; break; - case XML_ERROR_JUNK_AFTER_DOC_ELEMENT: pMessage = "junk after doc element"; break; - case XML_ERROR_PARAM_ENTITY_REF: pMessage = "parameter entity reference"; break; - case XML_ERROR_UNDEFINED_ENTITY: pMessage = "undefined entity"; break; - case XML_ERROR_RECURSIVE_ENTITY_REF: pMessage = "recursive entity reference"; break; - case XML_ERROR_ASYNC_ENTITY: pMessage = "async entity"; break; - case XML_ERROR_BAD_CHAR_REF: pMessage = "bad char reference"; break; - case XML_ERROR_BINARY_ENTITY_REF: pMessage = "binary entity reference"; break; - case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF: pMessage = "attribute external entity reference"; break; - case XML_ERROR_MISPLACED_XML_PI: pMessage = "misplaced xml processing instruction"; break; - case XML_ERROR_UNKNOWN_ENCODING: pMessage = "unknown encoding"; break; - case XML_ERROR_INCORRECT_ENCODING: pMessage = "incorrect encoding"; break; - case XML_ERROR_UNCLOSED_CDATA_SECTION: pMessage = "unclosed cdata section"; break; - case XML_ERROR_EXTERNAL_ENTITY_HANDLING: pMessage = "external entity reference"; break; - case XML_ERROR_NOT_STANDALONE: pMessage = "not standalone"; break; - default:; - } - - OUStringBuffer aBuffer( '[' ); - aBuffer.append( sSystemId ); - aBuffer.append( " line " ); - aBuffer.append( nLine ); - aBuffer.append( "]: " ); - aBuffer.appendAscii( pMessage ); - aBuffer.append( " error" ); - return aBuffer.makeStringAndClear(); -} - -} // namespace - void FastSaxParserImpl::deleteUsedEvents() { Entity& rEntity = getEntity(); @@ -1016,7 +1049,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) { @@ -1032,28 +1065,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; @@ -1101,36 +1114,14 @@ 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 ); } @@ -1265,7 +1256,7 @@ void FastSaxParserImpl::callbackStartElement( const XML_Char* pwName, const XML_ } catch (const Exception& e) { - rEntity.maSavedException <<= e; + rEntity.saveException( e ); } } @@ -1311,13 +1302,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"); } @@ -1342,17 +1333,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; } @@ -1372,21 +1363,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; } |