From 47d8eeed3f8258b4efceeb4b1dfb40fcde2afce5 Mon Sep 17 00:00:00 2001 From: Daniel Rentz Date: Wed, 5 May 2010 19:43:28 +0200 Subject: dr76: #i111404# make FastSaxParser reentrant --- sax/source/fastparser/fastparser.cxx | 152 ++++++++++++++++++----------------- sax/source/fastparser/fastparser.hxx | 60 +++++++------- 2 files changed, 107 insertions(+), 105 deletions(-) (limited to 'sax') diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index a43c7e52a353..e80a36b2d127 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -200,46 +200,43 @@ FastSaxParser::~FastSaxParser() void FastSaxParser::pushContext() { - bool bRootContext = false; - SaxContextImplPtr p; - if( maContextStack.empty() ) + Entity& rEntity = getEntity(); + if( rEntity.maContextStack.empty() ) { - p.reset( new SaxContextImpl() ); - bRootContext = true; + rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl ) ); + DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace"); } else { - p.reset( new SaxContextImpl( maContextStack.top() ) ); + rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl( rEntity.maContextStack.top() ) ) ); } - maContextStack.push( p ); - - if( bRootContext ) - DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace"); } // -------------------------------------------------------------------- void FastSaxParser::popContext() { - OSL_ENSURE( !maContextStack.empty(), "sax::FastSaxParser::popContext(), pop without push?" ); - if( !maContextStack.empty() ) - maContextStack.pop(); + Entity& rEntity = getEntity(); + OSL_ENSURE( !rEntity.maContextStack.empty(), "sax::FastSaxParser::popContext(), pop without push?" ); + if( !rEntity.maContextStack.empty() ) + rEntity.maContextStack.pop(); } // -------------------------------------------------------------------- void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL ) { - OSL_ENSURE( !maContextStack.empty(), "sax::FastSaxParser::DefineNamespace(), I need a context!" ); - if( !maContextStack.empty() ) + Entity& rEntity = getEntity(); + OSL_ENSURE( !rEntity.maContextStack.empty(), "sax::FastSaxParser::DefineNamespace(), I need a context!" ); + if( !rEntity.maContextStack.empty() ) { - sal_uInt32 nOffset = maContextStack.top()->mnNamespaceCount++; + sal_uInt32 nOffset = rEntity.maContextStack.top()->mnNamespaceCount++; - if( maNamespaceDefines.size() <= nOffset ) - maNamespaceDefines.resize( maNamespaceDefines.size() + 64 ); + if( rEntity.maNamespaceDefines.size() <= nOffset ) + rEntity.maNamespaceDefines.resize( rEntity.maNamespaceDefines.size() + 64 ); const OUString aNamespaceURL( pNamespaceURL, strlen( pNamespaceURL ), RTL_TEXTENCODING_UTF8 ); - maNamespaceDefines[nOffset].reset( new NamespaceDefine( rPrefix, GetNamespaceToken( aNamespaceURL ), aNamespaceURL ) ); + rEntity.maNamespaceDefines[nOffset].reset( new NamespaceDefine( rPrefix, GetNamespaceToken( aNamespaceURL ), aNamespaceURL ) ); } } @@ -268,12 +265,13 @@ sal_Int32 FastSaxParser::GetTokenWithPrefix( const OString& rPrefix, const OStri { sal_Int32 nNamespaceToken = FastToken::DONTKNOW; - sal_uInt32 nNamespace = maContextStack.top()->mnNamespaceCount; + Entity& rEntity = getEntity(); + sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount; while( nNamespace-- ) { - if( maNamespaceDefines[nNamespace]->maPrefix == rPrefix ) + if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix ) { - nNamespaceToken = maNamespaceDefines[nNamespace]->mnToken; + nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken; break; } @@ -295,14 +293,15 @@ sal_Int32 FastSaxParser::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefix { sal_Int32 nNamespaceToken = FastToken::DONTKNOW; - sal_uInt32 nNamespace = maContextStack.top()->mnNamespaceCount; + Entity& rEntity = getEntity(); + sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount; while( nNamespace-- ) { - const OString& rPrefix( maNamespaceDefines[nNamespace]->maPrefix ); + const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix ); if( (rPrefix.getLength() == nPrefixLen) && (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) ) { - nNamespaceToken = maNamespaceDefines[nNamespace]->mnToken; + nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken; break; } @@ -335,12 +334,13 @@ sal_Int32 FastSaxParser::GetNamespaceToken( const OUString& rNamespaceURL ) OUString FastSaxParser::GetNamespaceURL( const OString& rPrefix ) throw (SAXException) { - if( !maContextStack.empty() ) + Entity& rEntity = getEntity(); + if( !rEntity.maContextStack.empty() ) { - sal_uInt32 nNamespace = maContextStack.top()->mnNamespaceCount; + sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount; while( nNamespace-- ) - if( maNamespaceDefines[nNamespace]->maPrefix == rPrefix ) - return maNamespaceDefines[nNamespace]->maNamespaceURL; + if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix ) + return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL; } throw SAXException(); // prefix that has no defined namespace url @@ -348,16 +348,17 @@ OUString FastSaxParser::GetNamespaceURL( const OString& rPrefix ) throw (SAXExce OUString FastSaxParser::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw(SAXException) { - if( pPrefix && !maContextStack.empty() ) + Entity& rEntity = getEntity(); + if( pPrefix && !rEntity.maContextStack.empty() ) { - sal_uInt32 nNamespace = maContextStack.top()->mnNamespaceCount; + sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount; while( nNamespace-- ) { - const OString& rPrefix( maNamespaceDefines[nNamespace]->maPrefix ); + const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix ); if( (rPrefix.getLength() == nPrefixLen) && (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) ) { - return maNamespaceDefines[nNamespace]->maNamespaceURL; + return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL; } } } @@ -421,7 +422,7 @@ void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXEx // Only one text at one time MutexGuard guard( maMutex ); - struct Entity entity; + Entity entity; entity.maStructSource = maStructSource; if( !entity.maStructSource.aInputStream.is() ) @@ -442,9 +443,6 @@ void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXEx XML_SetCharacterDataHandler( entity.mpParser, call_callbackCharacters ); XML_SetExternalEntityRefHandler( entity.mpParser, call_callbackExternalEntityRef ); - // maSavedException used to transport exceptions through C callbacks - maSavedException.clear(); - pushEntity( entity ); try { @@ -619,29 +617,30 @@ void FastSaxParser::parse() const int BUFFER_SIZE = 16 * 1024; Sequence< sal_Int8 > seqOut( BUFFER_SIZE ); + Entity& rEntity = getEntity(); int nRead = 0; do { - nRead = getEntity().maConverter.readAndConvert( seqOut, BUFFER_SIZE ); + nRead = rEntity.maConverter.readAndConvert( seqOut, BUFFER_SIZE ); if( nRead <= 0 ) { - XML_Parse( getEntity().mpParser, (const char*) seqOut.getConstArray(), 0, 1 ); + XML_Parse( rEntity.mpParser, (const char*) seqOut.getConstArray(), 0, 1 ); break; } - bool bContinue = XML_Parse( getEntity().mpParser, (const char*) seqOut.getConstArray(), nRead, 0 ) != 0; + bool bContinue = XML_Parse( rEntity.mpParser, (const char*) seqOut.getConstArray(), nRead, 0 ) != 0; // callbacks used inside XML_Parse may have caught an exception - if( !bContinue || maSavedException.hasValue() ) + if( !bContinue || rEntity.maSavedException.hasValue() ) { // Error during parsing ! - XML_Error xmlE = XML_GetErrorCode( getEntity().mpParser ); + 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( &maSavedException, getCppuType( &maSavedException ) ), + Any( &rEntity.maSavedException, getCppuType( &rEntity.maSavedException ) ), mxDocumentLocator->getPublicId(), mxDocumentLocator->getSystemId(), mxDocumentLocator->getLineNumber(), @@ -680,9 +679,10 @@ struct AttributeData void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes ) { Reference< XFastContextHandler > xParentContext; - if( !maContextStack.empty() ) + Entity& rEntity = getEntity(); + if( !rEntity.maContextStack.empty() ) { - xParentContext = maContextStack.top()->mxContext; + xParentContext = rEntity.maContextStack.top()->mxContext; if( !xParentContext.is() ) { // we ignore current elements, so no processing needed @@ -734,7 +734,7 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) ) { // namespace of the element found - maContextStack.top()->maNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 ); + rEntity.maContextStack.top()->maNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 ); } else { @@ -770,22 +770,22 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen ); if( nPrefixLen > 0 ) nElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen ); - else if( maContextStack.top()->maNamespace.getLength() > 0 ) - nElementToken = GetTokenWithNamespaceURL( maContextStack.top()->maNamespace, pName, nNameLen ); + else if( rEntity.maContextStack.top()->maNamespace.getLength() > 0 ) + nElementToken = GetTokenWithNamespaceURL( rEntity.maContextStack.top()->maNamespace, pName, nNameLen ); else nElementToken = GetToken( pName ); - maContextStack.top()->mnElementToken = nElementToken; + rEntity.maContextStack.top()->mnElementToken = nElementToken; Reference< XFastAttributeList > xAttr( mxAttributes.get() ); Reference< XFastContextHandler > xContext; if( nElementToken == FastToken::DONTKNOW ) { if( nPrefixLen > 0 ) - maContextStack.top()->maNamespace = GetNamespaceURL( pPrefix, nPrefixLen ); + rEntity.maContextStack.top()->maNamespace = GetNamespaceURL( pPrefix, nPrefixLen ); - const OUString aNamespace( maContextStack.top()->maNamespace ); + const OUString aNamespace( rEntity.maContextStack.top()->maNamespace ); const OUString aElementName( pPrefix, nPrefixLen, RTL_TEXTENCODING_UTF8 ); - maContextStack.top()->maElementName = aElementName; + rEntity.maContextStack.top()->maElementName = aElementName; if( xParentContext.is() ) xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr ); @@ -794,7 +794,7 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char if( xContext.is() ) { - maContextStack.top()->mxContext = xContext; + rEntity.maContextStack.top()->mxContext = xContext; xContext->startUnknownElement( aNamespace, aElementName, xAttr ); } } @@ -808,23 +808,24 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char if( xContext.is() ) { - maContextStack.top()->mxContext = xContext; + rEntity.maContextStack.top()->mxContext = xContext; xContext->startFastElement( nElementToken, xAttr ); } } } catch( Exception& e ) { - maSavedException <<= e; + rEntity.maSavedException <<= e; } } void FastSaxParser::callbackEndElement( const XML_Char* ) { - OSL_ENSURE( !maContextStack.empty(), "FastSaxParser::callbackEndElement - no context" ); - if( !maContextStack.empty() ) + Entity& rEntity = getEntity(); + OSL_ENSURE( !rEntity.maContextStack.empty(), "FastSaxParser::callbackEndElement - no context" ); + if( !rEntity.maContextStack.empty() ) { - SaxContextImplPtr pContext( maContextStack.top() ); + SaxContextImplPtr pContext = rEntity.maContextStack.top(); const Reference< XFastContextHandler >& xContext( pContext->mxContext ); if( xContext.is() ) try { @@ -836,7 +837,7 @@ void FastSaxParser::callbackEndElement( const XML_Char* ) } catch( Exception& e ) { - maSavedException <<= e; + rEntity.maSavedException <<= e; } popContext(); @@ -846,14 +847,15 @@ void FastSaxParser::callbackEndElement( const XML_Char* ) void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen ) { - const Reference< XFastContextHandler >& xContext( maContextStack.top()->mxContext ); + Entity& rEntity = getEntity(); + const Reference< XFastContextHandler >& xContext( rEntity.maContextStack.top()->mxContext ); if( xContext.is() ) try { xContext->characters( OUString( s, nLen, RTL_TEXTENCODING_UTF8 ) ); } catch( Exception& e ) { - maSavedException <<= e; + rEntity.maSavedException <<= e; } } @@ -863,22 +865,23 @@ int FastSaxParser::callbackExternalEntityRef( XML_Parser parser, bool bOK = true; InputSource source; - struct Entity entity; + Entity& rCurrEntity = getEntity(); + Entity aNewEntity; if( mxEntityResolver.is() ) try { - entity.maStructSource = mxEntityResolver->resolveEntity( + aNewEntity.maStructSource = mxEntityResolver->resolveEntity( OUString( publicId, strlen( publicId ), RTL_TEXTENCODING_UTF8 ) , OUString( systemId, strlen( systemId ), RTL_TEXTENCODING_UTF8 ) ); } catch( SAXParseException & e ) { - maSavedException <<= e; + rCurrEntity.maSavedException <<= e; bOK = false; } catch( SAXException & e ) { - maSavedException <<= SAXParseException( + rCurrEntity.maSavedException <<= SAXParseException( e.Message, e.Context, e.WrappedException, mxDocumentLocator->getPublicId(), mxDocumentLocator->getSystemId(), @@ -887,43 +890,42 @@ int FastSaxParser::callbackExternalEntityRef( XML_Parser parser, bOK = false; } - if( entity.maStructSource.aInputStream.is() ) + if( aNewEntity.maStructSource.aInputStream.is() ) { - entity.mpParser = XML_ExternalEntityParserCreate( parser, context, 0 ); - if( ! entity.mpParser ) + aNewEntity.mpParser = XML_ExternalEntityParserCreate( parser, context, 0 ); + if( !aNewEntity.mpParser ) { return false; } - entity.maConverter.setInputStream( entity.maStructSource.aInputStream ); - pushEntity( entity ); + aNewEntity.maConverter.setInputStream( aNewEntity.maStructSource.aInputStream ); + pushEntity( aNewEntity ); try { parse(); } catch( SAXParseException & e ) { - maSavedException <<= e; + rCurrEntity.maSavedException <<= e; bOK = false; } catch( IOException &e ) { SAXException aEx; aEx.WrappedException <<= e; - maSavedException <<= aEx; + rCurrEntity.maSavedException <<= aEx; bOK = false; } catch( RuntimeException &e ) { SAXException aEx; aEx.WrappedException <<= e; - maSavedException <<= aEx; + rCurrEntity.maSavedException <<= aEx; bOK = false; } popEntity(); - - XML_ParserFree( entity.mpParser ); + XML_ParserFree( aNewEntity.mpParser ); } return bOK; diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx index 3d494a6d3c81..4802702bf098 100644 --- a/sax/source/fastparser/fastparser.hxx +++ b/sax/source/fastparser/fastparser.hxx @@ -47,25 +47,33 @@ #define PARSER_IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.FastParser" #define PARSER_SERVICE_NAME "com.sun.star.xml.sax.FastParser" -namespace sax_fastparser -{ +namespace sax_fastparser { + +class FastLocatorImpl; +struct NamespaceDefine; +struct SaxContextImpl; + +typedef ::boost::shared_ptr< SaxContextImpl > SaxContextImplPtr; +typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef; - class FastLocatorImpl; - struct NamespaceDefine; - struct SaxContextImpl; - typedef boost::shared_ptr< SaxContextImpl > SaxContextImplPtr; - typedef ::std::hash_map< ::rtl::OUString, sal_Int32, - ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > - > NamespaceMap; +typedef ::std::hash_map< ::rtl::OUString, sal_Int32, + ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > NamespaceMap; // -------------------------------------------------------------------- -// Entity binds all information neede for a single file +// Entity binds all information needed for a single file struct Entity { - ::com::sun::star::xml::sax::InputSource maStructSource; - XML_Parser mpParser; - sax_expatwrap::XMLFile2UTFConverter maConverter; + ::com::sun::star::xml::sax::InputSource maStructSource; + 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; + + ::std::stack< SaxContextImplPtr > maContextStack; + ::std::vector< NamespaceDefineRef > maNamespaceDefines; }; // -------------------------------------------------------------------- @@ -75,7 +83,7 @@ class FastSaxParser : public ::cppu::WeakImplHelper2< ::com::sun::star::xml::sax { public: FastSaxParser(); - ~FastSaxParser(); + virtual ~FastSaxParser(); // The implementation details static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void); @@ -100,9 +108,9 @@ public: void callbackCharacters( const XML_Char* s, int nLen ); int callbackExternalEntityRef( XML_Parser parser, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); - void pushEntity( const struct Entity &entity ) { vecEntity.push_back( entity ); } - void popEntity() { vecEntity.pop_back( ); } - struct Entity &getEntity() { return vecEntity.back(); } + inline void pushEntity( const Entity& rEntity ) { maEntities.push( rEntity ); } + inline void popEntity() { maEntities.pop(); } + Entity& getEntity() { return maEntities.top(); } private: void parse(); @@ -131,21 +139,13 @@ private: ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler > mxErrorHandler; ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver > mxEntityResolver; - rtl::Reference < FastLocatorImpl > mxDocumentLocator; - rtl::Reference < FastAttributeList > mxAttributes; + ::rtl::Reference< FastLocatorImpl > mxDocumentLocator; + ::rtl::Reference< FastAttributeList > mxAttributes; + ::com::sun::star::lang::Locale maLocale; + NamespaceMap maNamespaceMap; // External entity stack - std::vector< struct Entity > vecEntity; - - // Exceptions cannot be thrown through the C-XmlParser (possible resource leaks), - // therefore the exception must be saved somewhere. - ::com::sun::star::uno::Any maSavedException; - - ::com::sun::star::lang::Locale maLocale; - - std::stack< SaxContextImplPtr > maContextStack; - std::vector< boost::shared_ptr< NamespaceDefine > > maNamespaceDefines; - NamespaceMap maNamespaceMap; + ::std::stack< Entity > maEntities; }; } -- cgit