diff options
Diffstat (limited to 'xmlscript/source/xml_helper')
-rw-r--r-- | xmlscript/source/xml_helper/makefile.mk | 50 | ||||
-rw-r--r-- | xmlscript/source/xml_helper/xml_byteseq.cxx | 173 | ||||
-rw-r--r-- | xmlscript/source/xml_helper/xml_element.cxx | 132 | ||||
-rw-r--r-- | xmlscript/source/xml_helper/xml_impctx.cxx | 904 |
4 files changed, 1259 insertions, 0 deletions
diff --git a/xmlscript/source/xml_helper/makefile.mk b/xmlscript/source/xml_helper/makefile.mk new file mode 100644 index 000000000000..7b48695bae64 --- /dev/null +++ b/xmlscript/source/xml_helper/makefile.mk @@ -0,0 +1,50 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=xmlscript +TARGET=xml_helper +NO_BSYMBOLIC=TRUE +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.IF "$(L10N_framework)"=="" +#----------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/xml_impctx.obj \ + $(SLO)$/xml_element.obj \ + $(SLO)$/xml_byteseq.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : $(PRJ)$/util$/target.pmk +.ENDIF # L10N_framework + +.INCLUDE : target.mk diff --git a/xmlscript/source/xml_helper/xml_byteseq.cxx b/xmlscript/source/xml_helper/xml_byteseq.cxx new file mode 100644 index 000000000000..a570db629aca --- /dev/null +++ b/xmlscript/source/xml_helper/xml_byteseq.cxx @@ -0,0 +1,173 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlscript.hxx" +#include <rtl/memory.h> + +#include <cppuhelper/implbase1.hxx> +#include <xmlscript/xml_helper.hxx> + + +using namespace rtl; +using namespace osl; +using namespace com::sun::star; +using namespace com::sun::star::uno; + + +namespace xmlscript +{ + +//================================================================================================== +class BSeqInputStream + : public ::cppu::WeakImplHelper1< io::XInputStream > +{ + ByteSequence _seq; + sal_Int32 _nPos; + +public: + inline BSeqInputStream( ByteSequence const & rSeq ) + SAL_THROW( () ) + : _seq( rSeq ) + , _nPos( 0 ) + {} + + // XInputStream + virtual sal_Int32 SAL_CALL readBytes( + Sequence< sal_Int8 > & rData, sal_Int32 nBytesToRead ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException); + virtual sal_Int32 SAL_CALL readSomeBytes( + Sequence< sal_Int8 > & rData, sal_Int32 nMaxBytesToRead ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException); + virtual void SAL_CALL skipBytes( + sal_Int32 nBytesToSkip ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException); + virtual sal_Int32 SAL_CALL available() + throw (io::NotConnectedException, io::IOException, RuntimeException); + virtual void SAL_CALL closeInput() + throw (io::NotConnectedException, io::IOException, RuntimeException); +}; +//__________________________________________________________________________________________________ +sal_Int32 BSeqInputStream::readBytes( + Sequence< sal_Int8 > & rData, sal_Int32 nBytesToRead ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException) +{ + nBytesToRead = ((nBytesToRead > _seq.getLength() - _nPos) + ? _seq.getLength() - _nPos + : nBytesToRead); + + ByteSequence aBytes( _seq.getConstArray() + _nPos, nBytesToRead ); + rData = toUnoSequence( aBytes ); + _nPos += nBytesToRead; + return nBytesToRead; +} +//__________________________________________________________________________________________________ +sal_Int32 BSeqInputStream::readSomeBytes( + Sequence< sal_Int8 > & rData, sal_Int32 nMaxBytesToRead ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException) +{ + return readBytes( rData, nMaxBytesToRead ); +} +//__________________________________________________________________________________________________ +void BSeqInputStream::skipBytes( + sal_Int32 /*nBytesToSkip*/ ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException) +{ +} +//__________________________________________________________________________________________________ +sal_Int32 BSeqInputStream::available() + throw (io::NotConnectedException, io::IOException, RuntimeException) +{ + return (_seq.getLength() - _nPos); +} +//__________________________________________________________________________________________________ +void BSeqInputStream::closeInput() + throw (io::NotConnectedException, io::IOException, RuntimeException) +{ +} + +//################################################################################################## + +//================================================================================================== +class BSeqOutputStream + : public ::cppu::WeakImplHelper1< io::XOutputStream > +{ + ByteSequence * _seq; + +public: + inline BSeqOutputStream( ByteSequence * seq ) + SAL_THROW( () ) + : _seq( seq ) + {} + + // XOutputStream + virtual void SAL_CALL writeBytes( + Sequence< sal_Int8 > const & rData ) + throw (io::NotConnectedException, io::BufferSizeExceededException, RuntimeException); + virtual void SAL_CALL flush() + throw (io::NotConnectedException, io::BufferSizeExceededException, RuntimeException); + virtual void SAL_CALL closeOutput() + throw (io::NotConnectedException, io::BufferSizeExceededException, RuntimeException); +}; +//__________________________________________________________________________________________________ +void BSeqOutputStream::writeBytes( Sequence< sal_Int8 > const & rData ) + throw (io::NotConnectedException, io::BufferSizeExceededException, RuntimeException) +{ + sal_Int32 nPos = _seq->getLength(); + _seq->realloc( nPos + rData.getLength() ); + ::rtl_copyMemory( (char *)_seq->getArray() + nPos, + (char const *)rData.getConstArray(), + rData.getLength() ); +} +//__________________________________________________________________________________________________ +void BSeqOutputStream::flush() + throw (io::NotConnectedException, io::BufferSizeExceededException, RuntimeException) +{ +} +//__________________________________________________________________________________________________ +void BSeqOutputStream::closeOutput() + throw (io::NotConnectedException, io::BufferSizeExceededException, RuntimeException) +{ +} + +//################################################################################################## + +//================================================================================================== +Reference< io::XInputStream > SAL_CALL createInputStream( ByteSequence const & rInData ) + SAL_THROW( () ) +{ + return new BSeqInputStream( rInData ); +} + +//================================================================================================== +Reference< io::XOutputStream > SAL_CALL createOutputStream( ByteSequence * pOutData ) + SAL_THROW( () ) +{ + return new BSeqOutputStream( pOutData ); +} + +} diff --git a/xmlscript/source/xml_helper/xml_element.cxx b/xmlscript/source/xml_helper/xml_element.cxx new file mode 100644 index 000000000000..7fe5436ffd86 --- /dev/null +++ b/xmlscript/source/xml_helper/xml_element.cxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlscript.hxx" +#include <xmlscript/xml_helper.hxx> + + +using namespace rtl; +using namespace com::sun::star; +using namespace com::sun::star::uno; + + +namespace xmlscript +{ + +//__________________________________________________________________________________________________ +void XMLElement::addAttribute( OUString const & rAttrName, OUString const & rValue ) + SAL_THROW( () ) +{ + _attrNames.push_back( rAttrName ); + _attrValues.push_back( rValue ); +} +//__________________________________________________________________________________________________ +void XMLElement::addSubElement( Reference< xml::sax::XAttributeList > const & xElem ) + SAL_THROW( () ) +{ + _subElems.push_back( xElem ); +} +//__________________________________________________________________________________________________ +Reference< xml::sax::XAttributeList > XMLElement::getSubElement( sal_Int32 nIndex ) + SAL_THROW( () ) +{ + return _subElems[ (size_t)nIndex ]; +} +//__________________________________________________________________________________________________ +void XMLElement::dumpSubElements( Reference< xml::sax::XDocumentHandler > const & xOut ) +{ + for ( size_t nPos = 0; nPos < _subElems.size(); ++nPos ) + { + XMLElement * pElem = static_cast< XMLElement * >( _subElems[ nPos ].get() ); + pElem->dump( xOut ); + } +} +//__________________________________________________________________________________________________ +void XMLElement::dump( Reference< xml::sax::XDocumentHandler > const & xOut ) +{ + xOut->ignorableWhitespace( OUString() ); + xOut->startElement( _name, static_cast< xml::sax::XAttributeList * >( this ) ); + // write sub elements + dumpSubElements( xOut ); + // + xOut->ignorableWhitespace( OUString() ); + xOut->endElement( _name ); +} + +// XAttributeList +//__________________________________________________________________________________________________ +sal_Int16 XMLElement::getLength() + throw (RuntimeException) +{ + return static_cast<sal_Int16>(_attrNames.size()); +} +//__________________________________________________________________________________________________ +OUString XMLElement::getNameByIndex( sal_Int16 nPos ) + throw (RuntimeException) +{ + OSL_ASSERT( (size_t)nPos < _attrNames.size() ); + return _attrNames[ nPos ]; +} +//__________________________________________________________________________________________________ +OUString XMLElement::getTypeByIndex( sal_Int16 nPos ) + throw (RuntimeException) +{ + OSL_ASSERT( (size_t)nPos < _attrNames.size() ); + static_cast<void>(nPos); + // xxx todo + return OUString(); +} +//__________________________________________________________________________________________________ +OUString XMLElement::getTypeByName( OUString const & /*rName*/ ) + throw (RuntimeException) +{ + // xxx todo + return OUString(); +} +//__________________________________________________________________________________________________ +OUString XMLElement::getValueByIndex( sal_Int16 nPos ) + throw (RuntimeException) +{ + OSL_ASSERT( (size_t)nPos < _attrNames.size() ); + return _attrValues[ nPos ]; +} +//__________________________________________________________________________________________________ +OUString XMLElement::getValueByName( OUString const & rName ) + throw (RuntimeException) +{ + for ( size_t nPos = 0; nPos < _attrNames.size(); ++nPos ) + { + if (_attrNames[ nPos ] == rName) + { + return _attrValues[ nPos ]; + } + } + return OUString(); +} + +} diff --git a/xmlscript/source/xml_helper/xml_impctx.cxx b/xmlscript/source/xml_helper/xml_impctx.cxx new file mode 100644 index 000000000000..754b546a112c --- /dev/null +++ b/xmlscript/source/xml_helper/xml_impctx.cxx @@ -0,0 +1,904 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlscript.hxx" + +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "rtl/ustrbuf.hxx" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase3.hxx" +#include "xmlscript/xml_import.hxx" + +#include "com/sun/star/xml/input/XAttributes.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" + +#include <vector> +#include <hash_map> + +#include <memory> + + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace xmlscript +{ + +const sal_Int32 UID_UNKNOWN = -1; + +Sequence< OUString > getSupportedServiceNames_DocumentHandlerImpl() +{ + OUString name( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.input.SaxDocumentHandler") ); + return Sequence< OUString >( &name, 1 ); +} + +OUString getImplementationName_DocumentHandlerImpl() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.xml.input.SaxDocumentHandler") ); +} + +typedef ::std::hash_map< OUString, sal_Int32, OUStringHash > t_OUString2LongMap; +typedef ::std::hash_map< sal_Int32, OUString > t_Long2OUStringMap; + +struct PrefixEntry +{ + ::std::vector< sal_Int32 > m_Uids; + + inline PrefixEntry() SAL_THROW( () ) + { m_Uids.reserve( 4 ); } +}; + +typedef ::std::hash_map< + OUString, PrefixEntry *, OUStringHash > t_OUString2PrefixMap; + +struct ElementEntry +{ + Reference< xml::input::XElement > m_xElement; + ::std::vector< OUString > m_prefixes; + + inline ElementEntry() + { m_prefixes.reserve( 2 ); } +}; + +typedef ::std::vector< ElementEntry * > t_ElementVector; + +class ExtendedAttributes; + +//============================================================================== +struct MGuard +{ + Mutex * m_pMutex; + explicit MGuard( Mutex * pMutex ) + : m_pMutex( pMutex ) + { if (m_pMutex) m_pMutex->acquire(); } + ~MGuard() throw () + { if (m_pMutex) m_pMutex->release(); } +}; + +//============================================================================== +class DocumentHandlerImpl : + public ::cppu::WeakImplHelper3< xml::sax::XDocumentHandler, + xml::input::XNamespaceMapping, + lang::XInitialization > +{ + friend class ExtendedAttributes; + + Reference< xml::input::XRoot > m_xRoot; + + t_OUString2LongMap m_URI2Uid; + sal_Int32 m_uid_count; + + OUString m_sXMLNS_PREFIX_UNKNOWN; + OUString m_sXMLNS; + + sal_Int32 m_nLastURI_lookup; + OUString m_aLastURI_lookup; + + t_OUString2PrefixMap m_prefixes; + sal_Int32 m_nLastPrefix_lookup; + OUString m_aLastPrefix_lookup; + + t_ElementVector m_elements; + sal_Int32 m_nSkipElements; + + Mutex * m_pMutex; + + inline Reference< xml::input::XElement > getCurrentElement() const; + + inline sal_Int32 getUidByURI( OUString const & rURI ); + inline sal_Int32 getUidByPrefix( OUString const & rPrefix ); + + inline void pushPrefix( + OUString const & rPrefix, OUString const & rURI ); + inline void popPrefix( OUString const & rPrefix ); + + inline void getElementName( + OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName ); + +public: + DocumentHandlerImpl( + Reference< xml::input::XRoot > const & xRoot, + bool bSingleThreadedUse ); + virtual ~DocumentHandlerImpl() throw (); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( + OUString const & servicename ) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( + Sequence< Any > const & arguments ) + throw (Exception); + + // XDocumentHandler + virtual void SAL_CALL startDocument() + throw (xml::sax::SAXException, RuntimeException); + virtual void SAL_CALL endDocument() + throw (xml::sax::SAXException, RuntimeException); + virtual void SAL_CALL startElement( + OUString const & rQElementName, + Reference< xml::sax::XAttributeList > const & xAttribs ) + throw (xml::sax::SAXException, RuntimeException); + virtual void SAL_CALL endElement( + OUString const & rQElementName ) + throw (xml::sax::SAXException, RuntimeException); + virtual void SAL_CALL characters( + OUString const & rChars ) + throw (xml::sax::SAXException, RuntimeException); + virtual void SAL_CALL ignorableWhitespace( + OUString const & rWhitespaces ) + throw (xml::sax::SAXException, RuntimeException); + virtual void SAL_CALL processingInstruction( + OUString const & rTarget, OUString const & rData ) + throw (xml::sax::SAXException, RuntimeException); + virtual void SAL_CALL setDocumentLocator( + Reference< xml::sax::XLocator > const & xLocator ) + throw (xml::sax::SAXException, RuntimeException); + + // XNamespaceMapping + virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri ) + throw (RuntimeException); + virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid ) + throw (container::NoSuchElementException, RuntimeException); +}; + +//______________________________________________________________________________ +DocumentHandlerImpl::DocumentHandlerImpl( + Reference< xml::input::XRoot > const & xRoot, + bool bSingleThreadedUse ) + : m_xRoot( xRoot ), + m_uid_count( 0 ), + m_sXMLNS_PREFIX_UNKNOWN( + RTL_CONSTASCII_USTRINGPARAM("<<< unknown prefix >>>") ), + m_sXMLNS( RTL_CONSTASCII_USTRINGPARAM("xmlns") ), + m_nLastURI_lookup( UID_UNKNOWN ), + m_aLastURI_lookup( RTL_CONSTASCII_USTRINGPARAM("<<< unknown URI >>>") ), + m_nLastPrefix_lookup( UID_UNKNOWN ), + m_aLastPrefix_lookup( + RTL_CONSTASCII_USTRINGPARAM("<<< unknown URI >>>") ), + m_nSkipElements( 0 ), + m_pMutex( 0 ) +{ + m_elements.reserve( 10 ); + + if (! bSingleThreadedUse) + m_pMutex = new Mutex(); +} + +//______________________________________________________________________________ +DocumentHandlerImpl::~DocumentHandlerImpl() throw () +{ + if (m_pMutex != 0) + { + delete m_pMutex; +#if OSL_DEBUG_LEVEL == 0 + m_pMutex = 0; +#endif + } +} + +//______________________________________________________________________________ +inline Reference< xml::input::XElement > +DocumentHandlerImpl::getCurrentElement() const +{ + MGuard aGuard( m_pMutex ); + if (m_elements.empty()) + return Reference< xml::input::XElement >(); + else + return m_elements.back()->m_xElement; +} + +//______________________________________________________________________________ +inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI ) +{ + MGuard guard( m_pMutex ); + if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI) + { + t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) ); + if (iFind != m_URI2Uid.end()) // id found + { + m_nLastURI_lookup = iFind->second; + m_aLastURI_lookup = rURI; + } + else + { + m_nLastURI_lookup = m_uid_count; + ++m_uid_count; + m_URI2Uid[ rURI ] = m_nLastURI_lookup; + m_aLastURI_lookup = rURI; + } + } + return m_nLastURI_lookup; +} + +//______________________________________________________________________________ +inline sal_Int32 DocumentHandlerImpl::getUidByPrefix( + OUString const & rPrefix ) +{ + // commonly the last added prefix is used often for several tags... + // good guess + if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix) + { + t_OUString2PrefixMap::const_iterator iFind( + m_prefixes.find( rPrefix ) ); + if (iFind != m_prefixes.end()) + { + const PrefixEntry & rPrefixEntry = *iFind->second; + OSL_ASSERT( ! rPrefixEntry.m_Uids.empty() ); + m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back(); + m_aLastPrefix_lookup = rPrefix; + } + else + { + m_nLastPrefix_lookup = UID_UNKNOWN; + m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN; + } + } + return m_nLastPrefix_lookup; +} + +//______________________________________________________________________________ +inline void DocumentHandlerImpl::pushPrefix( + OUString const & rPrefix, OUString const & rURI ) +{ + // lookup id for URI + sal_Int32 nUid = getUidByURI( rURI ); + + // mark prefix with id + t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) ); + if (iFind == m_prefixes.end()) // unused prefix + { + PrefixEntry * pEntry = new PrefixEntry(); + pEntry->m_Uids.push_back( nUid ); // latest id for prefix + m_prefixes[ rPrefix ] = pEntry; + } + else + { + PrefixEntry * pEntry = iFind->second; + OSL_ASSERT( ! pEntry->m_Uids.empty() ); + pEntry->m_Uids.push_back( nUid ); + } + + m_aLastPrefix_lookup = rPrefix; + m_nLastPrefix_lookup = nUid; +} + +//______________________________________________________________________________ +inline void DocumentHandlerImpl::popPrefix( + OUString const & rPrefix ) +{ + t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) ); + if (iFind != m_prefixes.end()) // unused prefix + { + PrefixEntry * pEntry = iFind->second; + pEntry->m_Uids.pop_back(); // pop last id for prefix + if (pEntry->m_Uids.empty()) // erase prefix key + { + m_prefixes.erase( iFind ); + delete pEntry; + } + } + + m_nLastPrefix_lookup = UID_UNKNOWN; + m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN; +} + +//______________________________________________________________________________ +inline void DocumentHandlerImpl::getElementName( + OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName ) +{ + sal_Int32 nColonPos = rQName.indexOf( (sal_Unicode)':' ); + *pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName); + *pUid = getUidByPrefix( + nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() ); +} + + +//============================================================================== +class ExtendedAttributes : + public ::cppu::WeakImplHelper1< xml::input::XAttributes > +{ + sal_Int32 m_nAttributes; + sal_Int32 * m_pUids; + OUString * m_pPrefixes; + OUString * m_pLocalNames; + OUString * m_pQNames; + OUString * m_pValues; + + DocumentHandlerImpl * m_pHandler; + +public: + inline ExtendedAttributes( + sal_Int32 nAttributes, + sal_Int32 * pUids, OUString * pPrefixes, + OUString * pLocalNames, OUString * pQNames, + Reference< xml::sax::XAttributeList > const & xAttributeList, + DocumentHandlerImpl * pHandler ); + virtual ~ExtendedAttributes() throw (); + + // XAttributes + virtual sal_Int32 SAL_CALL getLength() + throw (RuntimeException); + virtual sal_Int32 SAL_CALL getIndexByQName( + OUString const & rQName ) + throw (RuntimeException); + virtual sal_Int32 SAL_CALL getIndexByUidName( + sal_Int32 nUid, OUString const & rLocalName ) + throw (RuntimeException); + virtual OUString SAL_CALL getQNameByIndex( + sal_Int32 nIndex ) + throw (RuntimeException); + virtual sal_Int32 SAL_CALL getUidByIndex( + sal_Int32 nIndex ) + throw (RuntimeException); + virtual OUString SAL_CALL getLocalNameByIndex( + sal_Int32 nIndex ) + throw (RuntimeException); + virtual OUString SAL_CALL getValueByIndex( + sal_Int32 nIndex ) + throw (RuntimeException); + virtual OUString SAL_CALL getValueByUidName( + sal_Int32 nUid, OUString const & rLocalName ) + throw (RuntimeException); + virtual OUString SAL_CALL getTypeByIndex( + sal_Int32 nIndex ) + throw (RuntimeException); +}; + +//______________________________________________________________________________ +inline ExtendedAttributes::ExtendedAttributes( + sal_Int32 nAttributes, + sal_Int32 * pUids, OUString * pPrefixes, + OUString * pLocalNames, OUString * pQNames, + Reference< xml::sax::XAttributeList > const & xAttributeList, + DocumentHandlerImpl * pHandler ) + : m_nAttributes( nAttributes ) + , m_pUids( pUids ) + , m_pPrefixes( pPrefixes ) + , m_pLocalNames( pLocalNames ) + , m_pQNames( pQNames ) + , m_pValues( new OUString[ nAttributes ] ) + , m_pHandler( pHandler ) +{ + m_pHandler->acquire(); + + for ( sal_Int16 nPos = 0; nPos < nAttributes; ++nPos ) + { + m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos ); + } +} + +//______________________________________________________________________________ +ExtendedAttributes::~ExtendedAttributes() throw () +{ + m_pHandler->release(); + + delete [] m_pUids; + delete [] m_pPrefixes; + delete [] m_pLocalNames; + delete [] m_pQNames; + delete [] m_pValues; +} + + +//############################################################################## + +// XServiceInfo + +//______________________________________________________________________________ +OUString DocumentHandlerImpl::getImplementationName() + throw (RuntimeException) +{ + return getImplementationName_DocumentHandlerImpl(); +} + +//______________________________________________________________________________ +sal_Bool DocumentHandlerImpl::supportsService( + OUString const & servicename ) + throw (RuntimeException) +{ + Sequence< OUString > names( getSupportedServiceNames_DocumentHandlerImpl() ); + for ( sal_Int32 nPos = names.getLength(); nPos--; ) + { + if (names[ nPos ].equals( servicename )) + return sal_True; + } + return sal_False; +} + +//______________________________________________________________________________ +Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames() + throw (RuntimeException) +{ + return getSupportedServiceNames_DocumentHandlerImpl(); +} + +// XInitialization + +//______________________________________________________________________________ +void DocumentHandlerImpl::initialize( + Sequence< Any > const & arguments ) + throw (Exception) +{ + MGuard guard( m_pMutex ); + Reference< xml::input::XRoot > xRoot; + if (arguments.getLength() == 1 && + (arguments[ 0 ] >>= xRoot) && + xRoot.is()) + { + m_xRoot = xRoot; + } + else + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "missing root instance!") ), + Reference< XInterface >() ); + } +} + + +// XNamespaceMapping + +//______________________________________________________________________________ +sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri ) + throw (RuntimeException) +{ + sal_Int32 uid = getUidByURI( Uri ); + OSL_ASSERT( uid != UID_UNKNOWN ); + return uid; +} + +//______________________________________________________________________________ +OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid ) + throw (container::NoSuchElementException, RuntimeException) +{ + MGuard guard( m_pMutex ); + t_OUString2LongMap::const_iterator iPos( m_URI2Uid.begin() ); + t_OUString2LongMap::const_iterator const iEnd( m_URI2Uid.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + if (iPos->second == Uid) + return iPos->first; + } + throw container::NoSuchElementException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no such xmlns uid!") ), + static_cast< OWeakObject * >(this) ); +} + + +// XDocumentHandler + +//______________________________________________________________________________ +void DocumentHandlerImpl::startDocument() + throw (xml::sax::SAXException, RuntimeException) +{ + m_xRoot->startDocument( + static_cast< xml::input::XNamespaceMapping * >( this ) ); +} + +//______________________________________________________________________________ +void DocumentHandlerImpl::endDocument() + throw (xml::sax::SAXException, RuntimeException) +{ + m_xRoot->endDocument(); +} + +//______________________________________________________________________________ +void DocumentHandlerImpl::startElement( + OUString const & rQElementName, + Reference< xml::sax::XAttributeList > const & xAttribs ) + throw (xml::sax::SAXException, RuntimeException) +{ + Reference< xml::input::XElement > xCurrentElement; + Reference< xml::input::XAttributes > xAttributes; + sal_Int32 nUid; + OUString aLocalName; + ::std::auto_ptr< ElementEntry > elementEntry( new ElementEntry ); + + { // guard start: + MGuard aGuard( m_pMutex ); + // currently skipping elements and waiting for end tags? + if (m_nSkipElements > 0) + { + ++m_nSkipElements; // wait for another end tag +#if OSL_DEBUG_LEVEL > 1 + OString aQName( + OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### no context given on createChildElement() " + "=> ignoring element \"%s\" ...", aQName.getStr() ); +#endif + return; + } + + sal_Int16 nAttribs = xAttribs->getLength(); + + // save all namespace ids + sal_Int32 * pUids = new sal_Int32[ nAttribs ]; + OUString * pPrefixes = new OUString[ nAttribs ]; + OUString * pLocalNames = new OUString[ nAttribs ]; + OUString * pQNames = new OUString[ nAttribs ]; + + // first recognize all xmlns attributes + sal_Int16 nPos; + for ( nPos = 0; nPos < nAttribs; ++nPos ) + { + // mark attribute to be collected further + // on with attribute's uid and current prefix + pUids[ nPos ] = 0; // modified + + pQNames[ nPos ] = xAttribs->getNameByIndex( nPos ); + OUString const & rQAttributeName = pQNames[ nPos ]; + + if (rQAttributeName.compareTo( m_sXMLNS, 5 ) == 0) + { + if (rQAttributeName.getLength() == 5) // set default namespace + { + OUString aDefNamespacePrefix; + pushPrefix( + aDefNamespacePrefix, + xAttribs->getValueByIndex( nPos ) ); + elementEntry->m_prefixes.push_back( aDefNamespacePrefix ); + pUids[ nPos ] = UID_UNKNOWN; + pPrefixes[ nPos ] = m_sXMLNS; + pLocalNames[ nPos ] = aDefNamespacePrefix; + } + else if ((sal_Unicode)':' == rQAttributeName[ 5 ]) // set prefix + { + OUString aPrefix( rQAttributeName.copy( 6 ) ); + pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) ); + elementEntry->m_prefixes.push_back( aPrefix ); + pUids[ nPos ] = UID_UNKNOWN; + pPrefixes[ nPos ] = m_sXMLNS; + pLocalNames[ nPos ] = aPrefix; + } + // else just a name starting with xmlns, but no prefix + } + } + + // now read out attribute prefixes (all namespace prefixes have been set) + for ( nPos = 0; nPos < nAttribs; ++nPos ) + { + if (pUids[ nPos ] >= 0) // no xmlns: attribute + { + OUString const & rQAttributeName = pQNames[ nPos ]; + OSL_ENSURE( + rQAttributeName.compareToAscii( + RTL_CONSTASCII_STRINGPARAM("xmlns:") ) != 0, + "### unexpected xmlns!" ); + + // collect attribute's uid and current prefix + sal_Int32 nColonPos = rQAttributeName.indexOf( (sal_Unicode) ':' ); + if (nColonPos >= 0) + { + pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos ); + pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 ); + } + else + { + pPrefixes[ nPos ] = OUString(); + pLocalNames[ nPos ] = rQAttributeName; + // leave local names unmodified + } + pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] ); + } + } + // ownership of arrays belongs to attribute list + xAttributes = static_cast< xml::input::XAttributes * >( + new ExtendedAttributes( + nAttribs, pUids, pPrefixes, pLocalNames, pQNames, + xAttribs, this ) ); + + getElementName( rQElementName, &nUid, &aLocalName ); + + // create new child context and append to list + if (! m_elements.empty()) + xCurrentElement = m_elements.back()->m_xElement; + } // :guard end + + if (xCurrentElement.is()) + { + elementEntry->m_xElement = + xCurrentElement->startChildElement( nUid, aLocalName, xAttributes ); + } + else + { + elementEntry->m_xElement = + m_xRoot->startRootElement( nUid, aLocalName, xAttributes ); + } + + { + MGuard aGuard( m_pMutex ); + if (elementEntry->m_xElement.is()) + { + m_elements.push_back( elementEntry.release() ); + } + else + { + ++m_nSkipElements; +#if OSL_DEBUG_LEVEL > 1 + OString aQName( + OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( + "### no context given on createChildElement() => " + "ignoring element \"%s\" ...", aQName.getStr() ); +#endif + } + } +} + +//______________________________________________________________________________ +void DocumentHandlerImpl::endElement( + OUString const & rQElementName ) + throw (xml::sax::SAXException, RuntimeException) +{ + Reference< xml::input::XElement > xCurrentElement; + { + MGuard aGuard( m_pMutex ); + if (m_nSkipElements) + { + --m_nSkipElements; +#if OSL_DEBUG_LEVEL > 1 + OString aQName( + OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### received endElement() for \"%s\".", aQName.getStr() ); +#endif + static_cast<void>(rQElementName); + return; + } + + // popping context + OSL_ASSERT( ! m_elements.empty() ); + ElementEntry * pEntry = m_elements.back(); + xCurrentElement = pEntry->m_xElement; + +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nUid; + OUString aLocalName; + getElementName( rQElementName, &nUid, &aLocalName ); + OSL_ASSERT( xCurrentElement->getLocalName() == aLocalName ); + OSL_ASSERT( xCurrentElement->getUid() == nUid ); +#endif + + // pop prefixes + for ( sal_Int32 nPos = pEntry->m_prefixes.size(); nPos--; ) + { + popPrefix( pEntry->m_prefixes[ nPos ] ); + } + m_elements.pop_back(); + delete pEntry; + } + xCurrentElement->endElement(); +} + +//______________________________________________________________________________ +void DocumentHandlerImpl::characters( OUString const & rChars ) + throw (xml::sax::SAXException, RuntimeException) +{ + Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); + if (xCurrentElement.is()) + xCurrentElement->characters( rChars ); +} + +//______________________________________________________________________________ +void DocumentHandlerImpl::ignorableWhitespace( + OUString const & rWhitespaces ) + throw (xml::sax::SAXException, RuntimeException) +{ + Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); + if (xCurrentElement.is()) + xCurrentElement->ignorableWhitespace( rWhitespaces ); +} + +//______________________________________________________________________________ +void DocumentHandlerImpl::processingInstruction( + OUString const & rTarget, OUString const & rData ) + throw (xml::sax::SAXException, RuntimeException) +{ + Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); + if (xCurrentElement.is()) + xCurrentElement->processingInstruction( rTarget, rData ); + else + m_xRoot->processingInstruction( rTarget, rData ); +} + +//______________________________________________________________________________ +void DocumentHandlerImpl::setDocumentLocator( + Reference< xml::sax::XLocator > const & xLocator ) + throw (xml::sax::SAXException, RuntimeException) +{ + m_xRoot->setDocumentLocator( xLocator ); +} + +//############################################################################## + +// XAttributes + +//______________________________________________________________________________ +sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName ) + throw (RuntimeException) +{ + for ( sal_Int32 nPos = m_nAttributes; nPos--; ) + { + if (m_pQNames[ nPos ].equals( rQName )) + { + return nPos; + } + } + return -1; +} + +//______________________________________________________________________________ +sal_Int32 ExtendedAttributes::getLength() + throw (RuntimeException) +{ + return m_nAttributes; +} + +//______________________________________________________________________________ +OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex ) + throw (RuntimeException) +{ + if (nIndex < m_nAttributes) + return m_pLocalNames[ nIndex ]; + else + return OUString(); +} + +//______________________________________________________________________________ +OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex ) + throw (RuntimeException) +{ + if (nIndex < m_nAttributes) + return m_pQNames[ nIndex ]; + else + return OUString(); +} + +//______________________________________________________________________________ +OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex ) + throw (RuntimeException) +{ + static_cast<void>(nIndex); + OSL_ASSERT( nIndex < m_nAttributes ); + return OUString(); // unsupported +} + +//______________________________________________________________________________ +OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex ) + throw (RuntimeException) +{ + if (nIndex < m_nAttributes) + return m_pValues[ nIndex ]; + else + return OUString(); +} + +//______________________________________________________________________________ +sal_Int32 ExtendedAttributes::getIndexByUidName( + sal_Int32 nUid, OUString const & rLocalName ) + throw (RuntimeException) +{ + for ( sal_Int32 nPos = m_nAttributes; nPos--; ) + { + if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName) + { + return nPos; + } + } + return -1; +} + +//______________________________________________________________________________ +sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex ) + throw (RuntimeException) +{ + if (nIndex < m_nAttributes) + return m_pUids[ nIndex ]; + else + return -1; +} + +//______________________________________________________________________________ +OUString ExtendedAttributes::getValueByUidName( + sal_Int32 nUid, OUString const & rLocalName ) + throw (RuntimeException) +{ + for ( sal_Int32 nPos = m_nAttributes; nPos--; ) + { + if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName) + { + return m_pValues[ nPos ]; + } + } + return OUString(); +} + + +//############################################################################## + + +//============================================================================== +Reference< xml::sax::XDocumentHandler > SAL_CALL createDocumentHandler( + Reference< xml::input::XRoot > const & xRoot, + bool bSingleThreadedUse ) + SAL_THROW( () ) +{ + OSL_ASSERT( xRoot.is() ); + if (xRoot.is()) + { + return static_cast< xml::sax::XDocumentHandler * >( + new DocumentHandlerImpl( xRoot, bSingleThreadedUse ) ); + } + return Reference< xml::sax::XDocumentHandler >(); +} + +//------------------------------------------------------------------------------ +Reference< XInterface > SAL_CALL create_DocumentHandlerImpl( + Reference< XComponentContext > const & ) + SAL_THROW( (Exception) ) +{ + return static_cast< ::cppu::OWeakObject * >( + new DocumentHandlerImpl( + Reference< xml::input::XRoot >(), false /* mt use */ ) ); +} + +} |