LCOV - code coverage report
Current view: top level - xmlscript/source/xml_helper - xml_impctx.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 188 261 72.0 %
Date: 2014-11-03 Functions: 31 45 68.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <sal/config.h>
      21             : 
      22             : #include "unoservices.hxx"
      23             : #include "xml_import.hxx"
      24             : 
      25             : #include <cppuhelper/factory.hxx>
      26             : #include <cppuhelper/implementationentry.hxx>
      27             : #include <cppuhelper/implbase1.hxx>
      28             : #include <cppuhelper/implbase4.hxx>
      29             : #include <cppuhelper/supportsservice.hxx>
      30             : #include <com/sun/star/xml/input/XAttributes.hpp>
      31             : #include <com/sun/star/lang/XInitialization.hpp>
      32             : #include <com/sun/star/uno/XComponentContext.hpp>
      33             : #include <com/sun/star/lang/XServiceInfo.hpp>
      34             : #include <vector>
      35             : #include <boost/unordered_map.hpp>
      36             : 
      37             : #include <memory>
      38             : 
      39             : using namespace ::osl;
      40             : using namespace ::com::sun::star;
      41             : using namespace ::com::sun::star::uno;
      42             : 
      43             : namespace xmlscript
      44             : {
      45             : 
      46             : const sal_Int32 UID_UNKNOWN = -1;
      47             : 
      48           2 : Sequence< OUString > getSupportedServiceNames_DocumentHandlerImpl()
      49             : {
      50           2 :     OUString name( "com.sun.star.xml.input.SaxDocumentHandler" );
      51           2 :     return Sequence< OUString >( &name, 1 );
      52             : }
      53             : 
      54           8 : OUString getImplementationName_DocumentHandlerImpl()
      55             : {
      56           8 :     return OUString( "com.sun.star.comp.xml.input.SaxDocumentHandler" );
      57             : }
      58             : 
      59             : typedef ::boost::unordered_map< OUString, sal_Int32, OUStringHash > t_OUString2LongMap;
      60             : 
      61        4248 : struct PrefixEntry
      62             : {
      63             :     ::std::vector< sal_Int32 > m_Uids;
      64             : 
      65        4248 :     inline PrefixEntry()
      66        4248 :         { m_Uids.reserve( 4 ); }
      67             : };
      68             : 
      69             : typedef ::boost::unordered_map<
      70             :     OUString, PrefixEntry *, OUStringHash > t_OUString2PrefixMap;
      71             : 
      72       22250 : struct ElementEntry
      73             : {
      74             :     Reference< xml::input::XElement > m_xElement;
      75             :     ::std::vector< OUString > m_prefixes;
      76             : 
      77       22250 :     inline ElementEntry()
      78       22250 :         { m_prefixes.reserve( 2 ); }
      79             : };
      80             : 
      81             : typedef ::std::vector< ElementEntry * > t_ElementVector;
      82             : 
      83             : class ExtendedAttributes;
      84             : 
      85             : struct MGuard
      86             : {
      87             :     Mutex * m_pMutex;
      88      129854 :     explicit MGuard( Mutex * pMutex )
      89      129854 :         : m_pMutex( pMutex )
      90      129854 :         { if (m_pMutex) m_pMutex->acquire(); }
      91      129854 :     ~MGuard() throw ()
      92      129854 :         { if (m_pMutex) m_pMutex->release(); }
      93             : };
      94             : 
      95             : class DocumentHandlerImpl :
      96             :     public ::cppu::WeakImplHelper4< xml::sax::XDocumentHandler,
      97             :                                     xml::input::XNamespaceMapping,
      98             :                                     lang::XInitialization,
      99             :                                     com::sun::star::lang::XServiceInfo >
     100             : {
     101             :     friend class ExtendedAttributes;
     102             : 
     103             :     Reference< xml::input::XRoot > m_xRoot;
     104             : 
     105             :     t_OUString2LongMap m_URI2Uid;
     106             :     sal_Int32 m_uid_count;
     107             : 
     108             :     OUString m_sXMLNS_PREFIX_UNKNOWN;
     109             :     OUString m_sXMLNS;
     110             : 
     111             :     sal_Int32 m_nLastURI_lookup;
     112             :     OUString m_aLastURI_lookup;
     113             : 
     114             :     t_OUString2PrefixMap m_prefixes;
     115             :     sal_Int32 m_nLastPrefix_lookup;
     116             :     OUString m_aLastPrefix_lookup;
     117             : 
     118             :     t_ElementVector m_elements;
     119             :     sal_Int32 m_nSkipElements;
     120             : 
     121             :     Mutex * m_pMutex;
     122             : 
     123             :     inline Reference< xml::input::XElement > getCurrentElement() const;
     124             : 
     125             :     inline sal_Int32 getUidByURI( OUString const & rURI );
     126             :     inline sal_Int32 getUidByPrefix( OUString const & rPrefix );
     127             : 
     128             :     inline void pushPrefix(
     129             :         OUString const & rPrefix, OUString const & rURI );
     130             :     inline void popPrefix( OUString const & rPrefix );
     131             : 
     132             :     inline void getElementName(
     133             :         OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName );
     134             : 
     135             : public:
     136             :     DocumentHandlerImpl(
     137             :         Reference< xml::input::XRoot > const & xRoot,
     138             :         bool bSingleThreadedUse );
     139             :     virtual ~DocumentHandlerImpl() throw ();
     140             : 
     141             :     // XServiceInfo
     142             :     virtual OUString SAL_CALL getImplementationName()
     143             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     144             :     virtual sal_Bool SAL_CALL supportsService(
     145             :         OUString const & servicename )
     146             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     147             :     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
     148             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     149             : 
     150             :     // XInitialization
     151             :     virtual void SAL_CALL initialize(
     152             :         Sequence< Any > const & arguments )
     153             :         throw (Exception, std::exception) SAL_OVERRIDE;
     154             : 
     155             :     // XDocumentHandler
     156             :     virtual void SAL_CALL startDocument()
     157             :         throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     158             :     virtual void SAL_CALL endDocument()
     159             :         throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     160             :     virtual void SAL_CALL startElement(
     161             :         OUString const & rQElementName,
     162             :         Reference< xml::sax::XAttributeList > const & xAttribs )
     163             :         throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     164             :     virtual void SAL_CALL endElement(
     165             :         OUString const & rQElementName )
     166             :         throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     167             :     virtual void SAL_CALL characters(
     168             :         OUString const & rChars )
     169             :         throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     170             :     virtual void SAL_CALL ignorableWhitespace(
     171             :         OUString const & rWhitespaces )
     172             :         throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     173             :     virtual void SAL_CALL processingInstruction(
     174             :         OUString const & rTarget, OUString const & rData )
     175             :         throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     176             :     virtual void SAL_CALL setDocumentLocator(
     177             :         Reference< xml::sax::XLocator > const & xLocator )
     178             :         throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     179             : 
     180             :     // XNamespaceMapping
     181             :     virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri )
     182             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     183             :     virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid )
     184             :         throw (container::NoSuchElementException, RuntimeException, std::exception) SAL_OVERRIDE;
     185             : };
     186             : 
     187        3694 : DocumentHandlerImpl::DocumentHandlerImpl(
     188             :     Reference< xml::input::XRoot > const & xRoot,
     189             :     bool bSingleThreadedUse )
     190             :     : m_xRoot( xRoot ),
     191             :       m_uid_count( 0 ),
     192             :       m_sXMLNS_PREFIX_UNKNOWN( "<<< unknown prefix >>>" ),
     193             :       m_sXMLNS( "xmlns" ),
     194             :       m_nLastURI_lookup( UID_UNKNOWN ),
     195             :       m_aLastURI_lookup( "<<< unknown URI >>>" ),
     196             :       m_nLastPrefix_lookup( UID_UNKNOWN ),
     197             :       m_aLastPrefix_lookup( "<<< unknown URI >>>" ),
     198             :       m_nSkipElements( 0 ),
     199        3694 :       m_pMutex( 0 )
     200             : {
     201        3694 :     m_elements.reserve( 10 );
     202             : 
     203        3694 :     if (! bSingleThreadedUse)
     204           2 :         m_pMutex = new Mutex();
     205        3694 : }
     206             : 
     207       11070 : DocumentHandlerImpl::~DocumentHandlerImpl() throw ()
     208             : {
     209        3690 :     if (m_pMutex != 0)
     210             :     {
     211           2 :         delete m_pMutex;
     212             : #if OSL_DEBUG_LEVEL == 0
     213           2 :         m_pMutex = 0;
     214             : #endif
     215             :     }
     216        7380 : }
     217             : 
     218             : inline Reference< xml::input::XElement >
     219       51388 : DocumentHandlerImpl::getCurrentElement() const
     220             : {
     221       51388 :     MGuard aGuard( m_pMutex );
     222       51388 :     if (m_elements.empty())
     223           0 :         return Reference< xml::input::XElement >();
     224             :     else
     225       51388 :         return m_elements.back()->m_xElement;
     226             : }
     227             : 
     228       11714 : inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI )
     229             : {
     230       11714 :     MGuard guard( m_pMutex );
     231       11714 :     if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI)
     232             :     {
     233       11714 :         t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) );
     234       11714 :         if (iFind != m_URI2Uid.end()) // id found
     235             :         {
     236        4178 :             m_nLastURI_lookup = iFind->second;
     237        4178 :             m_aLastURI_lookup = rURI;
     238             :         }
     239             :         else
     240             :         {
     241        7536 :             m_nLastURI_lookup = m_uid_count;
     242        7536 :             ++m_uid_count;
     243        7536 :             m_URI2Uid[ rURI ] = m_nLastURI_lookup;
     244        7536 :             m_aLastURI_lookup = rURI;
     245             :         }
     246             :     }
     247       11714 :     return m_nLastURI_lookup;
     248             : }
     249             : 
     250       62766 : inline sal_Int32 DocumentHandlerImpl::getUidByPrefix(
     251             :     OUString const & rPrefix )
     252             : {
     253             :     // commonly the last added prefix is used often for several tags...
     254             :     // good guess
     255       62766 :     if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix)
     256             :     {
     257             :         t_OUString2PrefixMap::const_iterator iFind(
     258        6460 :             m_prefixes.find( rPrefix ) );
     259        6460 :         if (iFind != m_prefixes.end())
     260             :         {
     261        6460 :             const PrefixEntry & rPrefixEntry = *iFind->second;
     262             :             SAL_WARN_IF( rPrefixEntry.m_Uids.empty(), "xmlscript.xmlhelper", "rPrefixEntry.m_Uids is empty" );
     263        6460 :             m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back();
     264        6460 :             m_aLastPrefix_lookup = rPrefix;
     265             :         }
     266             :         else
     267             :         {
     268           0 :             m_nLastPrefix_lookup = UID_UNKNOWN;
     269           0 :             m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN;
     270             :         }
     271             :     }
     272       62766 :     return m_nLastPrefix_lookup;
     273             : }
     274             : 
     275        4248 : inline void DocumentHandlerImpl::pushPrefix(
     276             :     OUString const & rPrefix, OUString const & rURI )
     277             : {
     278             :     // lookup id for URI
     279        4248 :     sal_Int32 nUid = getUidByURI( rURI );
     280             : 
     281             :     // mark prefix with id
     282        4248 :     t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) );
     283        4248 :     if (iFind == m_prefixes.end()) // unused prefix
     284             :     {
     285        4248 :         PrefixEntry * pEntry = new PrefixEntry();
     286        4248 :         pEntry->m_Uids.push_back( nUid ); // latest id for prefix
     287        4248 :         m_prefixes[ rPrefix ] = pEntry;
     288             :     }
     289             :     else
     290             :     {
     291           0 :         PrefixEntry * pEntry = iFind->second;
     292             :         SAL_WARN_IF( pEntry->m_Uids.empty(), "xmlscript.xmlhelper", "pEntry->m_Uids is empty" );
     293           0 :         pEntry->m_Uids.push_back( nUid );
     294             :     }
     295             : 
     296        4248 :     m_aLastPrefix_lookup = rPrefix;
     297        4248 :     m_nLastPrefix_lookup = nUid;
     298        4248 : }
     299             : 
     300        4248 : inline void DocumentHandlerImpl::popPrefix(
     301             :     OUString const & rPrefix )
     302             : {
     303        4248 :     t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) );
     304        4248 :     if (iFind != m_prefixes.end()) // unused prefix
     305             :     {
     306        4248 :         PrefixEntry * pEntry = iFind->second;
     307        4248 :         pEntry->m_Uids.pop_back(); // pop last id for prefix
     308        4248 :         if (pEntry->m_Uids.empty()) // erase prefix key
     309             :         {
     310        4248 :             m_prefixes.erase( iFind );
     311        4248 :             delete pEntry;
     312             :         }
     313             :     }
     314             : 
     315        4248 :     m_nLastPrefix_lookup = UID_UNKNOWN;
     316        4248 :     m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN;
     317        4248 : }
     318             : 
     319       22250 : inline void DocumentHandlerImpl::getElementName(
     320             :     OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName )
     321             : {
     322       22250 :     sal_Int32 nColonPos = rQName.indexOf( (sal_Unicode)':' );
     323       22250 :     *pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName);
     324             :     *pUid = getUidByPrefix(
     325       22250 :         nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() );
     326       22250 : }
     327             : 
     328             : class ExtendedAttributes :
     329             :     public ::cppu::WeakImplHelper1< xml::input::XAttributes >
     330             : {
     331             :     sal_Int32 m_nAttributes;
     332             :     sal_Int32 * m_pUids;
     333             :     OUString * m_pPrefixes;
     334             :     OUString * m_pLocalNames;
     335             :     OUString * m_pQNames;
     336             :     OUString * m_pValues;
     337             : 
     338             :     DocumentHandlerImpl * m_pHandler;
     339             : 
     340             : public:
     341             :     inline ExtendedAttributes(
     342             :         sal_Int32 nAttributes,
     343             :         sal_Int32 * pUids, OUString * pPrefixes,
     344             :         OUString * pLocalNames, OUString * pQNames,
     345             :         Reference< xml::sax::XAttributeList > const & xAttributeList,
     346             :         DocumentHandlerImpl * pHandler );
     347             :     virtual ~ExtendedAttributes() throw ();
     348             : 
     349             :     // XAttributes
     350             :     virtual sal_Int32 SAL_CALL getLength()
     351             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     352             :     virtual sal_Int32 SAL_CALL getIndexByQName(
     353             :         OUString const & rQName )
     354             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     355             :     virtual sal_Int32 SAL_CALL getIndexByUidName(
     356             :         sal_Int32 nUid, OUString const & rLocalName )
     357             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     358             :     virtual OUString SAL_CALL getQNameByIndex(
     359             :         sal_Int32 nIndex )
     360             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     361             :     virtual sal_Int32 SAL_CALL getUidByIndex(
     362             :         sal_Int32 nIndex )
     363             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     364             :     virtual OUString SAL_CALL getLocalNameByIndex(
     365             :         sal_Int32 nIndex )
     366             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     367             :     virtual OUString SAL_CALL getValueByIndex(
     368             :         sal_Int32 nIndex )
     369             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     370             :     virtual OUString SAL_CALL getValueByUidName(
     371             :         sal_Int32 nUid, OUString const & rLocalName )
     372             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     373             :     virtual OUString SAL_CALL getTypeByIndex(
     374             :         sal_Int32 nIndex )
     375             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     376             : };
     377             : 
     378       22250 : inline ExtendedAttributes::ExtendedAttributes(
     379             :     sal_Int32 nAttributes,
     380             :     sal_Int32 * pUids, OUString * pPrefixes,
     381             :     OUString * pLocalNames, OUString * pQNames,
     382             :     Reference< xml::sax::XAttributeList > const & xAttributeList,
     383             :     DocumentHandlerImpl * pHandler )
     384             :     : m_nAttributes( nAttributes )
     385             :     , m_pUids( pUids )
     386             :     , m_pPrefixes( pPrefixes )
     387             :     , m_pLocalNames( pLocalNames )
     388             :     , m_pQNames( pQNames )
     389       44500 :     , m_pValues( new OUString[ nAttributes ] )
     390       66750 :     , m_pHandler( pHandler )
     391             : {
     392       22250 :     m_pHandler->acquire();
     393             : 
     394       67014 :     for ( sal_Int16 nPos = 0; nPos < nAttributes; ++nPos )
     395             :     {
     396       44764 :         m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos );
     397             :     }
     398       22250 : }
     399             : 
     400       66660 : ExtendedAttributes::~ExtendedAttributes() throw ()
     401             : {
     402       22220 :     m_pHandler->release();
     403             : 
     404       22220 :     delete [] m_pUids;
     405       22220 :     delete [] m_pPrefixes;
     406       22220 :     delete [] m_pLocalNames;
     407       22220 :     delete [] m_pQNames;
     408       22220 :     delete [] m_pValues;
     409       44440 : }
     410             : 
     411             : // XServiceInfo
     412             : 
     413           0 : OUString DocumentHandlerImpl::getImplementationName()
     414             :     throw (RuntimeException, std::exception)
     415             : {
     416           0 :     return getImplementationName_DocumentHandlerImpl();
     417             : }
     418             : 
     419           0 : sal_Bool DocumentHandlerImpl::supportsService( OUString const & servicename )
     420             :     throw (RuntimeException, std::exception)
     421             : {
     422           0 :     return cppu::supportsService(this, servicename);
     423             : }
     424             : 
     425           0 : Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames()
     426             :     throw (RuntimeException, std::exception)
     427             : {
     428           0 :     return getSupportedServiceNames_DocumentHandlerImpl();
     429             : }
     430             : 
     431             : // XInitialization
     432             : 
     433           2 : void DocumentHandlerImpl::initialize(
     434             :     Sequence< Any > const & arguments )
     435             :     throw (Exception, std::exception)
     436             : {
     437           2 :     MGuard guard( m_pMutex );
     438           4 :     Reference< xml::input::XRoot > xRoot;
     439           6 :     if (arguments.getLength() == 1 &&
     440           4 :         (arguments[ 0 ] >>= xRoot) &&
     441           2 :         xRoot.is())
     442             :     {
     443           2 :         m_xRoot = xRoot;
     444             :     }
     445             :     else
     446             :     {
     447           0 :         throw RuntimeException( "missing root instance!" );
     448           2 :     }
     449           2 : }
     450             : 
     451             : // XNamespaceMapping
     452             : 
     453        7466 : sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri )
     454             :     throw (RuntimeException, std::exception)
     455             : {
     456        7466 :     sal_Int32 uid = getUidByURI( Uri );
     457             :     SAL_WARN_IF( uid == UID_UNKNOWN, "xmlscript.xmlhelper", "uid UNKNOWN");
     458        7466 :     return uid;
     459             : }
     460             : 
     461           0 : OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid )
     462             :     throw (container::NoSuchElementException, RuntimeException, std::exception)
     463             : {
     464           0 :     MGuard guard( m_pMutex );
     465           0 :     t_OUString2LongMap::const_iterator iPos( m_URI2Uid.begin() );
     466           0 :     t_OUString2LongMap::const_iterator const iEnd( m_URI2Uid.end() );
     467           0 :     for ( ; iPos != iEnd; ++iPos )
     468             :     {
     469           0 :         if (iPos->second == Uid)
     470           0 :             return iPos->first;
     471             :     }
     472           0 :     throw container::NoSuchElementException( "no such xmlns uid!" , static_cast< OWeakObject * >(this) );
     473             : }
     474             : 
     475             : // XDocumentHandler
     476             : 
     477        3694 : void DocumentHandlerImpl::startDocument()
     478             :     throw (xml::sax::SAXException, RuntimeException, std::exception)
     479             : {
     480        3694 :     m_xRoot->startDocument( static_cast< xml::input::XNamespaceMapping * >( this ) );
     481        3694 : }
     482             : 
     483        3694 : void DocumentHandlerImpl::endDocument()
     484             :     throw (xml::sax::SAXException, RuntimeException, std::exception)
     485             : {
     486        3694 :     m_xRoot->endDocument();
     487        3694 : }
     488             : 
     489       22250 : void DocumentHandlerImpl::startElement(
     490             :     OUString const & rQElementName,
     491             :     Reference< xml::sax::XAttributeList > const & xAttribs )
     492             :     throw (xml::sax::SAXException, RuntimeException, std::exception)
     493             : {
     494       22250 :     Reference< xml::input::XElement > xCurrentElement;
     495       44500 :     Reference< xml::input::XAttributes > xAttributes;
     496             :     sal_Int32 nUid;
     497       44500 :     OUString aLocalName;
     498       44500 :     ::std::unique_ptr< ElementEntry > elementEntry( new ElementEntry );
     499             : 
     500             :     { // guard start:
     501       22250 :     MGuard aGuard( m_pMutex );
     502             :     // currently skipping elements and waiting for end tags?
     503       22250 :     if (m_nSkipElements > 0)
     504             :     {
     505           0 :         ++m_nSkipElements; // wait for another end tag
     506             : #if OSL_DEBUG_LEVEL > 1
     507             :         OString aQName(
     508             :             OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
     509             :         SAL_INFO("xmlscript.xmlhelper", "### no context given on createChildElement() => ignoring element \"" << aQName.getStr() << "\" ...");
     510             : #endif
     511       22250 :         return;
     512             :     }
     513             : 
     514       22250 :     sal_Int16 nAttribs = xAttribs->getLength();
     515             : 
     516             :     // save all namespace ids
     517       22250 :     sal_Int32 * pUids = new sal_Int32[ nAttribs ];
     518       22250 :     OUString * pPrefixes = new OUString[ nAttribs ];
     519       22250 :     OUString * pLocalNames = new OUString[ nAttribs ];
     520       22250 :     OUString * pQNames = new OUString[ nAttribs ];
     521             : 
     522             :     // first recognize all xmlns attributes
     523             :     sal_Int16 nPos;
     524       67014 :     for ( nPos = 0; nPos < nAttribs; ++nPos )
     525             :     {
     526             :         // mark attribute to be collected further
     527             :         // on with attribute's uid and current prefix
     528       44764 :         pUids[ nPos ] = 0; // modified
     529             : 
     530       44764 :         pQNames[ nPos ] = xAttribs->getNameByIndex( nPos );
     531       44764 :         OUString const & rQAttributeName = pQNames[ nPos ];
     532             : 
     533       44764 :         if (rQAttributeName.startsWith( m_sXMLNS ))
     534             :         {
     535        4248 :             if (rQAttributeName.getLength() == 5) // set default namespace
     536             :             {
     537           0 :                 OUString aDefNamespacePrefix;
     538             :                 pushPrefix(
     539             :                     aDefNamespacePrefix,
     540           0 :                     xAttribs->getValueByIndex( nPos ) );
     541           0 :                 elementEntry->m_prefixes.push_back( aDefNamespacePrefix );
     542           0 :                 pUids[ nPos ]          = UID_UNKNOWN;
     543           0 :                 pPrefixes[ nPos ]      = m_sXMLNS;
     544           0 :                 pLocalNames[ nPos ]    = aDefNamespacePrefix;
     545             :             }
     546        4248 :             else if ((sal_Unicode)':' == rQAttributeName[ 5 ]) // set prefix
     547             :             {
     548        4248 :                 OUString aPrefix( rQAttributeName.copy( 6 ) );
     549        4248 :                 pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) );
     550        4248 :                 elementEntry->m_prefixes.push_back( aPrefix );
     551        4248 :                 pUids[ nPos ]          = UID_UNKNOWN;
     552        4248 :                 pPrefixes[ nPos ]      = m_sXMLNS;
     553        4248 :                 pLocalNames[ nPos ]    = aPrefix;
     554             :             }
     555             :             // else just a name starting with xmlns, but no prefix
     556             :         }
     557             :     }
     558             : 
     559             :     // now read out attribute prefixes (all namespace prefixes have been set)
     560       67014 :     for ( nPos = 0; nPos < nAttribs; ++nPos )
     561             :     {
     562       44764 :         if (pUids[ nPos ] >= 0) // no xmlns: attribute
     563             :         {
     564       40516 :             OUString const & rQAttributeName = pQNames[ nPos ];
     565             :             SAL_WARN_IF(rQAttributeName.startsWith( "xmlns:" ), "xmlscript.xmlhelper", "### unexpected xmlns!" );
     566             : 
     567             :             // collect attribute's uid and current prefix
     568       40516 :             sal_Int32 nColonPos = rQAttributeName.indexOf( (sal_Unicode) ':' );
     569       40516 :             if (nColonPos >= 0)
     570             :             {
     571       40516 :                 pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos );
     572       40516 :                 pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 );
     573             :             }
     574             :             else
     575             :             {
     576           0 :                 pPrefixes[ nPos ] = OUString();
     577           0 :                 pLocalNames[ nPos ] = rQAttributeName;
     578             :                 // leave local names unmodified
     579             :             }
     580       40516 :             pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] );
     581             :         }
     582             :     }
     583             :     // ownership of arrays belongs to attribute list
     584             :     xAttributes = static_cast< xml::input::XAttributes * >(
     585             :         new ExtendedAttributes(
     586             :             nAttribs, pUids, pPrefixes, pLocalNames, pQNames,
     587       22250 :             xAttribs, this ) );
     588             : 
     589       22250 :     getElementName( rQElementName, &nUid, &aLocalName );
     590             : 
     591             :     // create new child context and append to list
     592       22250 :     if (! m_elements.empty())
     593       18556 :         xCurrentElement = m_elements.back()->m_xElement;
     594             :     } // :guard end
     595             : 
     596       22250 :     if (xCurrentElement.is())
     597             :     {
     598       37112 :         elementEntry->m_xElement =
     599       37112 :             xCurrentElement->startChildElement( nUid, aLocalName, xAttributes );
     600             :     }
     601             :     else
     602             :     {
     603        7388 :         elementEntry->m_xElement =
     604        7388 :             m_xRoot->startRootElement( nUid, aLocalName, xAttributes );
     605             :     }
     606             : 
     607             :     {
     608       22250 :     MGuard aGuard( m_pMutex );
     609       22250 :     if (elementEntry->m_xElement.is())
     610             :     {
     611       22250 :         m_elements.push_back( elementEntry.release() );
     612             :     }
     613             :     else
     614             :     {
     615           0 :         ++m_nSkipElements;
     616             : #if OSL_DEBUG_LEVEL > 1
     617             :         OString aQName(
     618             :             OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
     619             :         SAL_INFO("xmlscript.xmlhelper", "### no context given on createChildElement() => ignoring element \"" << aQName.getStr() << "\" ...");
     620             : #endif
     621       22250 :     }
     622       22250 :     }
     623             : }
     624             : 
     625       22250 : void DocumentHandlerImpl::endElement(
     626             :     OUString const & rQElementName )
     627             :     throw (xml::sax::SAXException, RuntimeException, std::exception)
     628             : {
     629       22250 :     Reference< xml::input::XElement > xCurrentElement;
     630             :     {
     631       22250 :     MGuard aGuard( m_pMutex );
     632       22250 :     if (m_nSkipElements)
     633             :     {
     634           0 :         --m_nSkipElements;
     635             : #if OSL_DEBUG_LEVEL > 1
     636             :         OString aQName(
     637             :             OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
     638             :         SAL_INFO("xmlscript.xmlhelper", "### received endElement() for \"" << aQName.getStr() << "\".");
     639             : #endif
     640             :         static_cast<void>(rQElementName);
     641       22250 :         return;
     642             :     }
     643             : 
     644             :     // popping context
     645             :     SAL_WARN_IF( m_elements.empty(), "xmlscript.xmlhelper", "m_elements is empty" );
     646       22250 :     ElementEntry * pEntry = m_elements.back();
     647       22250 :     xCurrentElement = pEntry->m_xElement;
     648             : 
     649             : #if OSL_DEBUG_LEVEL > 0
     650             :     sal_Int32 nUid;
     651             :     OUString aLocalName;
     652             :     getElementName( rQElementName, &nUid, &aLocalName );
     653             :     SAL_WARN_IF( xCurrentElement->getLocalName() != aLocalName, "xmlscript.xmlhelper", "xCurrentElement->getLocalName() != aLocalName" );
     654             :     SAL_WARN_IF( xCurrentElement->getUid() != nUid, "xmlscript.xmlhelper", "xCurrentElement->getUid() != nUid" );
     655             : #endif
     656             : 
     657             :     // pop prefixes
     658       48748 :     for ( sal_Int32 nPos = pEntry->m_prefixes.size(); nPos--; )
     659             :     {
     660        4248 :         popPrefix( pEntry->m_prefixes[ nPos ] );
     661             :     }
     662       22250 :     m_elements.pop_back();
     663       22250 :     delete pEntry;
     664             :     }
     665       22250 :     xCurrentElement->endElement();
     666             : }
     667             : 
     668       51388 : void DocumentHandlerImpl::characters( OUString const & rChars )
     669             :     throw (xml::sax::SAXException, RuntimeException, std::exception)
     670             : {
     671       51388 :     Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
     672       51388 :     if (xCurrentElement.is())
     673       51388 :         xCurrentElement->characters( rChars );
     674       51388 : }
     675             : 
     676           0 : void DocumentHandlerImpl::ignorableWhitespace(
     677             :     OUString const & rWhitespaces )
     678             :     throw (xml::sax::SAXException, RuntimeException, std::exception)
     679             : {
     680           0 :     Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
     681           0 :     if (xCurrentElement.is())
     682           0 :         xCurrentElement->ignorableWhitespace( rWhitespaces );
     683           0 : }
     684             : 
     685           0 : void DocumentHandlerImpl::processingInstruction(
     686             :     OUString const & rTarget, OUString const & rData )
     687             :     throw (xml::sax::SAXException, RuntimeException, std::exception)
     688             : {
     689           0 :     Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
     690           0 :     if (xCurrentElement.is())
     691           0 :         xCurrentElement->processingInstruction( rTarget, rData );
     692             :     else
     693           0 :         m_xRoot->processingInstruction( rTarget, rData );
     694           0 : }
     695             : 
     696        3692 : void DocumentHandlerImpl::setDocumentLocator(
     697             :     Reference< xml::sax::XLocator > const & xLocator )
     698             :     throw (xml::sax::SAXException, RuntimeException, std::exception)
     699             : {
     700        3692 :     m_xRoot->setDocumentLocator( xLocator );
     701        3692 : }
     702             : 
     703             : // XAttributes
     704             : 
     705           0 : sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName )
     706             :     throw (RuntimeException, std::exception)
     707             : {
     708           0 :     for ( sal_Int32 nPos = m_nAttributes; nPos--; )
     709             :     {
     710           0 :         if (m_pQNames[ nPos ].equals( rQName ))
     711             :         {
     712           0 :             return nPos;
     713             :         }
     714             :     }
     715           0 :     return -1;
     716             : }
     717             : 
     718           0 : sal_Int32 ExtendedAttributes::getLength()
     719             :     throw (RuntimeException, std::exception)
     720             : {
     721           0 :     return m_nAttributes;
     722             : }
     723             : 
     724           0 : OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex )
     725             :     throw (RuntimeException, std::exception)
     726             : {
     727           0 :     if (nIndex < m_nAttributes)
     728           0 :         return m_pLocalNames[ nIndex ];
     729             :     else
     730           0 :         return OUString();
     731             : }
     732             : 
     733           0 : OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex )
     734             :     throw (RuntimeException, std::exception)
     735             : {
     736           0 :     if (nIndex < m_nAttributes)
     737           0 :         return m_pQNames[ nIndex ];
     738             :     else
     739           0 :         return OUString();
     740             : }
     741             : 
     742           0 : OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex )
     743             :     throw (RuntimeException, std::exception)
     744             : {
     745             :     static_cast<void>(nIndex);
     746             :     SAL_WARN_IF( nIndex >= m_nAttributes , "xmlscript.xmlhelper", "nIndex is bigger then m_nAttributes");
     747           0 :     return OUString(); // unsupported
     748             : }
     749             : 
     750           0 : OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex )
     751             :     throw (RuntimeException, std::exception)
     752             : {
     753           0 :     if (nIndex < m_nAttributes)
     754           0 :         return m_pValues[ nIndex ];
     755             :     else
     756           0 :         return OUString();
     757             : }
     758             : 
     759           0 : sal_Int32 ExtendedAttributes::getIndexByUidName(
     760             :     sal_Int32 nUid, OUString const & rLocalName )
     761             :     throw (RuntimeException, std::exception)
     762             : {
     763           0 :     for ( sal_Int32 nPos = m_nAttributes; nPos--; )
     764             :     {
     765           0 :         if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
     766             :         {
     767           0 :             return nPos;
     768             :         }
     769             :     }
     770           0 :     return -1;
     771             : }
     772             : 
     773           0 : sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex )
     774             :     throw (RuntimeException, std::exception)
     775             : {
     776           0 :     if (nIndex < m_nAttributes)
     777           0 :         return m_pUids[ nIndex ];
     778             :     else
     779           0 :         return -1;
     780             : }
     781             : 
     782       44994 : OUString ExtendedAttributes::getValueByUidName(
     783             :     sal_Int32 nUid, OUString const & rLocalName )
     784             :     throw (RuntimeException, std::exception)
     785             : {
     786      159788 :     for ( sal_Int32 nPos = m_nAttributes; nPos--; )
     787             :     {
     788      107328 :         if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
     789             :         {
     790       37528 :             return m_pValues[ nPos ];
     791             :         }
     792             :     }
     793        7466 :     return OUString();
     794             : }
     795             : 
     796        3692 : Reference< xml::sax::XDocumentHandler > SAL_CALL createDocumentHandler(
     797             :     Reference< xml::input::XRoot > const & xRoot,
     798             :     bool bSingleThreadedUse )
     799             : {
     800             :     SAL_WARN_IF( !xRoot.is(), "xmlscript.xmlhelper", "xRoot is NULL" );
     801        3692 :     if (xRoot.is())
     802             :     {
     803             :         return static_cast< xml::sax::XDocumentHandler * >(
     804        3692 :             new DocumentHandlerImpl( xRoot, bSingleThreadedUse ) );
     805             :     }
     806           0 :     return Reference< xml::sax::XDocumentHandler >();
     807             : }
     808             : 
     809           2 : Reference< XInterface > SAL_CALL create_DocumentHandlerImpl(
     810             :     SAL_UNUSED_PARAMETER Reference< XComponentContext > const & )
     811             : {
     812             :     return static_cast< ::cppu::OWeakObject * >(
     813             :         new DocumentHandlerImpl(
     814           2 :             Reference< xml::input::XRoot >(), false /* mt use */ ) );
     815             : }
     816             : 
     817             : }
     818             : 
     819             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10