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

Generated by: LCOV version 1.11