LCOV - code coverage report
Current view: top level - unoxml/source/dom - node.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 381 451 84.5 %
Date: 2014-11-03 Functions: 44 48 91.7 %
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 <node.hxx>
      21             : 
      22             : #include <stdio.h>
      23             : #include <string.h>
      24             : 
      25             : #include <libxml/xmlstring.h>
      26             : 
      27             : #include <algorithm>
      28             : 
      29             : #include <boost/bind.hpp>
      30             : 
      31             : #include <rtl/uuid.h>
      32             : #include <rtl/instance.hxx>
      33             : #include <osl/mutex.hxx>
      34             : 
      35             : #include <com/sun/star/xml/sax/FastToken.hpp>
      36             : 
      37             : #include <comphelper/servicehelper.hxx>
      38             : 
      39             : #include <document.hxx>
      40             : #include <attr.hxx>
      41             : #include <childlist.hxx>
      42             : 
      43             : #include "../events/eventdispatcher.hxx"
      44             : #include "../events/mutationevent.hxx"
      45             : 
      46             : using namespace css;
      47             : using namespace css::uno;
      48             : using namespace css::xml::dom;
      49             : using namespace css::xml::dom::events;
      50             : using namespace css::xml::sax;
      51             : 
      52             : namespace
      53             : {
      54             :     class theCNodeUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theCNodeUnoTunnelId > {};
      55             : }
      56             : 
      57             : namespace DOM
      58             : {
      59      601822 :     void pushContext(Context& io_rContext)
      60             :     {
      61             :         // Explicitly use a temp. variable.
      62             :         // Windows/VC++ seems to mess up if .back() is directly passed as
      63             :         // parameter. i.e. Don't use push_back( .back() );
      64      601822 :         Context::NamespaceVectorType::value_type aVal = io_rContext.maNamespaces.back();
      65      601822 :         io_rContext.maNamespaces.push_back( aVal );
      66      601822 :     }
      67             : 
      68      601822 :     void popContext(Context& io_rContext)
      69             :     {
      70      601822 :         io_rContext.maNamespaces.pop_back();
      71      601822 :     }
      72             : 
      73      601822 :     void addNamespaces(Context& io_rContext, xmlNodePtr pNode)
      74             :     {
      75             :         // add node's namespaces to current context
      76      605458 :         for (xmlNsPtr pNs = pNode->nsDef; pNs != 0; pNs = pNs->next) {
      77        3636 :             const xmlChar *pPrefix = pNs->prefix;
      78             :             // prefix can be NULL when xmlns attribute is empty (xmlns="")
      79             :             OString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
      80        3636 :                            pPrefix ? strlen(reinterpret_cast<const char*>(pPrefix)) : 0);
      81        3636 :             const xmlChar *pHref = pNs->href;
      82             :             OUString val(reinterpret_cast<const sal_Char*>(pHref),
      83        3636 :                 strlen(reinterpret_cast<const char*>(pHref)),
      84        7272 :                 RTL_TEXTENCODING_UTF8);
      85             : 
      86             :             OSL_TRACE("Trying to add namespace %s (prefix %s)",
      87             :                       (const char*)pHref, (const char*)pPrefix);
      88             : 
      89             :             Context::NamespaceMapType::iterator aIter=
      90        3636 :                 io_rContext.maNamespaceMap.find(val);
      91        3636 :             if( aIter != io_rContext.maNamespaceMap.end() )
      92             :             {
      93        3266 :                 Context::Namespace aNS;
      94        3266 :                 aNS.maPrefix = prefix;
      95        3266 :                 aNS.mnToken = aIter->second;
      96        3266 :                 aNS.maNamespaceURL = val;
      97             : 
      98        3266 :                 io_rContext.maNamespaces.back().push_back(aNS);
      99             : 
     100        3266 :                 OSL_TRACE("Added with token 0x%x", aIter->second);
     101             :             }
     102        3636 :         }
     103      601822 :     }
     104             : 
     105     1343872 :     sal_Int32 getToken( const Context& rContext, const sal_Char* pToken )
     106             :     {
     107     1343872 :         const Sequence<sal_Int8> aSeq( (sal_Int8*)pToken, strlen( pToken ) );
     108     1343872 :         return rContext.mxTokenHandler->getTokenFromUTF8( aSeq );
     109             :     }
     110             : 
     111      602060 :     sal_Int32 getTokenWithPrefix( const Context& rContext, const sal_Char* pPrefix, const sal_Char* pName )
     112             :     {
     113      602060 :         sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
     114             :         OString prefix(pPrefix,
     115      602060 :                        strlen(reinterpret_cast<const char*>(pPrefix)));
     116             : 
     117             :         OSL_TRACE("getTokenWithPrefix(): prefix %s, name %s",
     118             :                   (const char*)pPrefix, (const char*)pName);
     119             : 
     120      602060 :         Context::NamespaceVectorType::value_type::const_iterator aIter;
     121     1806180 :         if( (aIter=std::find_if(rContext.maNamespaces.back().begin(),
     122      602060 :                                 rContext.maNamespaces.back().end(),
     123             :                                 boost::bind(std::equal_to<OString>(),
     124             :                                             boost::bind(&Context::Namespace::getPrefix,
     125             :                                                         _1),
     126     2408240 :                                             boost::cref(prefix)))) != rContext.maNamespaces.back().end() )
     127             :         {
     128      601816 :             nNamespaceToken = aIter->mnToken;
     129      601816 :             sal_Int32 nNameToken = getToken( rContext, pName );
     130      601816 :             if( nNameToken != FastToken::DONTKNOW )
     131      601816 :                 nNamespaceToken |= nNameToken;
     132             :         }
     133             : 
     134      602060 :         return nNamespaceToken;
     135             :     }
     136             : 
     137             : 
     138     2407337 :     CNode::CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex,
     139             :                 NodeType const& reNodeType, xmlNodePtr const& rpNode)
     140             :         :   m_bUnlinked(false)
     141             :         ,   m_aNodeType(reNodeType)
     142             :         ,   m_aNodePtr(rpNode)
     143             :         // keep containing document alive
     144             :         // (but not if this is a document; that would create a leak!)
     145     2407337 :         ,   m_xDocument( (m_aNodePtr->type != XML_DOCUMENT_NODE)
     146             :                 ? &const_cast<CDocument&>(rDocument) : 0 )
     147     4814674 :         ,   m_rMutex(const_cast< ::osl::Mutex & >(rMutex))
     148             :     {
     149             :         OSL_ASSERT(m_aNodePtr);
     150     2407337 :     }
     151             : 
     152     2407447 :     void CNode::invalidate()
     153             :     {
     154             :         //remove from list if this wrapper goes away
     155     2407447 :         if (m_aNodePtr != 0 && m_xDocument.is()) {
     156     2376642 :             m_xDocument->RemoveCNode(m_aNodePtr, this);
     157             :         }
     158             :         // #i113663#: unlinked nodes will not be freed by xmlFreeDoc
     159     2407447 :         if (m_bUnlinked) {
     160        6321 :             xmlFreeNode(m_aNodePtr);
     161             :         }
     162     2407447 :         m_aNodePtr = 0;
     163     2407447 :     }
     164             : 
     165     4814618 :     CNode::~CNode()
     166             :     {
     167             :         // if this is the document itself, the mutex is already freed!
     168     2407309 :         if (NodeType_DOCUMENT_NODE == m_aNodeType) {
     169       30667 :             invalidate();
     170             :         } else {
     171     2376642 :             ::osl::MutexGuard const g(m_rMutex);
     172     2376642 :             invalidate(); // other nodes are still alive so must lock mutex
     173             :         }
     174     2407309 :     }
     175             : 
     176             :     CNode *
     177      859188 :     CNode::GetImplementation(uno::Reference<uno::XInterface> const& xNode)
     178             :     {
     179      859188 :         uno::Reference<lang::XUnoTunnel> const xUnoTunnel(xNode, UNO_QUERY);
     180      859188 :         if (!xUnoTunnel.is()) { return 0; }
     181             :         CNode *const pCNode( reinterpret_cast< CNode* >(
     182             :                         ::sal::static_int_cast< sal_IntPtr >(
     183      859168 :                             xUnoTunnel->getSomething(theCNodeUnoTunnelId::get().getSeq()))));
     184      859168 :         return pCNode;
     185             :     }
     186             : 
     187     3462934 :     CDocument & CNode::GetOwnerDocument()
     188             :     {
     189             :         OSL_ASSERT(m_xDocument.is());
     190     3462934 :         return *m_xDocument; // needs overriding in CDocument!
     191             :     }
     192             : 
     193             : 
     194       55056 :     static void lcl_nsexchange(
     195             :             xmlNodePtr const aNode, xmlNsPtr const oldNs, xmlNsPtr const newNs)
     196             :     {
     197             :         // recursively exchange any references to oldNs with references to newNs
     198       55056 :         xmlNodePtr cur = aNode;
     199      162375 :         while (cur != 0)
     200             :         {
     201       52263 :             if (cur->ns == oldNs)
     202       18615 :                 cur->ns = newNs;
     203       52263 :             if (cur->type == XML_ELEMENT_NODE)
     204             :             {
     205       36413 :                 xmlAttrPtr curAttr = cur->properties;
     206       98036 :                 while(curAttr != 0)
     207             :                 {
     208       25210 :                     if (curAttr->ns == oldNs)
     209         810 :                         curAttr->ns = newNs;
     210       25210 :                     curAttr = curAttr->next;
     211             :                 }
     212       36413 :                 lcl_nsexchange(cur->children, oldNs, newNs);
     213             :             }
     214       52263 :             cur = cur->next;
     215             :         }
     216       55056 :     }
     217             : 
     218     1176786 :     /*static*/ void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent)
     219             :     {
     220     1176786 :         xmlNodePtr cur = aNode;
     221             : 
     222             :         //handle attributes
     223     1176786 :         if (cur != NULL && cur->type == XML_ELEMENT_NODE)
     224             :         {
     225      411327 :             xmlAttrPtr curAttr = cur->properties;
     226     1229910 :             while(curAttr != 0)
     227             :             {
     228      407256 :                 if (curAttr->ns != NULL)
     229             :                 {
     230       62402 :                     xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, curAttr->ns->prefix);
     231       62402 :                     if (ns != NULL)
     232        2380 :                         curAttr->ns = ns;
     233             :                 }
     234      407256 :                 curAttr = curAttr->next;
     235             :             }
     236             :         }
     237             : 
     238     3381441 :         while (cur != NULL)
     239             :         {
     240     1027869 :             nscleanup(cur->children, cur);
     241     1027869 :             if (cur->ns != NULL)
     242             :             {
     243      925593 :                 xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, cur->ns->prefix);
     244      925593 :                 if (ns != NULL && ns != cur->ns && strcmp((char*)ns->href, (char*)cur->ns->href)==0)
     245             :                 {
     246       18615 :                     xmlNsPtr curDef = cur->nsDef;
     247       18615 :                     xmlNsPtr *refp = &(cur->nsDef); // insert point
     248       55873 :                     while (curDef != NULL)
     249             :                     {
     250       18643 :                         ns = xmlSearchNs(cur->doc, aParent, curDef->prefix);
     251       18643 :                         if (ns != NULL && ns != curDef && strcmp((char*)ns->href, (char*)curDef->href)==0)
     252             :                         {
     253             :                             // reconnect ns pointers in sub-tree to newly found ns before
     254             :                             // removing redundant nsdecl to prevent dangling pointers.
     255       18643 :                             lcl_nsexchange(cur, curDef, ns);
     256       18643 :                             *refp = curDef->next;
     257       18643 :                             xmlFreeNs(curDef);
     258       18643 :                             curDef = *refp;
     259             :                         } else {
     260           0 :                             refp = &(curDef->next);
     261           0 :                             curDef = curDef->next;
     262             :                         }
     263             :                     }
     264             :                 }
     265             :             }
     266     1027869 :             cur = cur->next;
     267             :         }
     268     1176786 :     }
     269             : 
     270           0 :     void CNode::saxify(const Reference< XDocumentHandler >& i_xHandler)
     271             :     {
     272           0 :         if (!i_xHandler.is()) throw RuntimeException();
     273             :         // default: do nothing
     274           0 :     }
     275             : 
     276           2 :     void CNode::fastSaxify(Context& io_rContext)
     277             :     {
     278           2 :         if (!io_rContext.mxDocHandler.is()) throw RuntimeException();
     279             :         // default: do nothing
     280           2 :     }
     281             : 
     282           8 :     bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/)
     283             :     {
     284             :         // default: no children allowed
     285           8 :         return false;
     286             :     }
     287             : 
     288             :     /**
     289             :     Adds the node newChild to the end of the list of children of this node.
     290             :     */
     291      143003 :     Reference< XNode > SAL_CALL CNode::appendChild(
     292             :             Reference< XNode > const& xNewChild)
     293             :         throw (RuntimeException, DOMException, std::exception)
     294             :     {
     295      143003 :         ::osl::ClearableMutexGuard guard(m_rMutex);
     296             : 
     297      143003 :         if (0 == m_aNodePtr) { return 0; }
     298             : 
     299      143003 :         CNode *const pNewChild(CNode::GetImplementation(xNewChild));
     300      143003 :         if (!pNewChild) { throw RuntimeException(); }
     301      142985 :         xmlNodePtr const cur = pNewChild->GetNodePtr();
     302      142985 :         if (!cur) { throw RuntimeException(); }
     303             : 
     304             :         // error checks:
     305             :         // from other document
     306      142985 :         if (cur->doc != m_aNodePtr->doc) {
     307           0 :             DOMException e;
     308           0 :             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
     309           0 :             throw e;
     310             :         }
     311             :         // same node
     312      142985 :         if (cur == m_aNodePtr) {
     313           0 :             DOMException e;
     314           0 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     315           0 :             throw e;
     316             :         }
     317      142985 :         if (cur->parent != NULL) {
     318           0 :             DOMException e;
     319           0 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     320           0 :             throw e;
     321             :         }
     322      142985 :         if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) {
     323           8 :             DOMException e;
     324           8 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     325           8 :             throw e;
     326             :         }
     327             : 
     328             :         // check whether this is an attribute node; it needs special handling
     329      142977 :         xmlNodePtr res = NULL;
     330      142977 :         if (cur->type == XML_ATTRIBUTE_NODE)
     331             :         {
     332             :             xmlChar const*const pChildren((cur->children)
     333             :                     ? cur->children->content
     334           2 :                     : reinterpret_cast<xmlChar const*>(""));
     335           2 :             CAttr *const pCAttr(dynamic_cast<CAttr *>(pNewChild));
     336           2 :             if (!pCAttr) { throw RuntimeException(); }
     337           2 :             xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
     338           2 :             if (pNs) {
     339             :                 res = reinterpret_cast<xmlNodePtr>(
     340           0 :                         xmlNewNsProp(m_aNodePtr, pNs, cur->name, pChildren));
     341             :             } else {
     342             :                 res = reinterpret_cast<xmlNodePtr>(
     343           2 :                         xmlNewProp(m_aNodePtr, cur->name, pChildren));
     344             :             }
     345             :         }
     346             :         else
     347             :         {
     348      142975 :             res = xmlAddChild(m_aNodePtr, cur);
     349             : 
     350             :             // libxml can do optimization when appending nodes.
     351             :             // if res != cur, something was optimized and the newchild-wrapper
     352             :             // should be updated
     353      142975 :             if (res && (cur != res)) {
     354         130 :                 pNewChild->invalidate(); // cur has been freed
     355             :             }
     356             :         }
     357             : 
     358      142977 :         if (!res) { return 0; }
     359             : 
     360             :         // use custom ns cleanup instead of
     361             :         // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr);
     362             :         // because that will not remove unneeded ns decls
     363      142977 :         nscleanup(res, m_aNodePtr);
     364             : 
     365      285954 :         ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(res);
     366             : 
     367      142977 :         if (!pNode.is()) { return 0; }
     368             : 
     369             :         // dispatch DOMNodeInserted event, target is the new node
     370             :         // this node is the related node
     371             :         // does bubble
     372      142977 :         pNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
     373      285954 :         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
     374      142977 :         Reference< XMutationEvent > event(docevent->createEvent(
     375      285954 :             "DOMNodeInserted"), UNO_QUERY);
     376      142977 :         event->initMutationEvent("DOMNodeInserted", sal_True, sal_False, this,
     377      142977 :             OUString(), OUString(), OUString(), (AttrChangeType)0 );
     378             : 
     379             :         // the following dispatch functions use only UNO interfaces
     380             :         // and call event listeners, so release mutex to prevent deadlocks.
     381      142977 :         guard.clear();
     382             : 
     383      142977 :         dispatchEvent(event);
     384             :         // dispatch subtree modified for this node
     385      142977 :         dispatchSubtreeModified();
     386             : 
     387      285980 :         return pNode.get();
     388             :     }
     389             : 
     390             :     /**
     391             :     Returns a duplicate of this node, i.e., serves as a generic copy
     392             :     constructor for nodes.
     393             :     */
     394          32 :     Reference< XNode > SAL_CALL CNode::cloneNode(sal_Bool bDeep)
     395             :         throw (RuntimeException, std::exception)
     396             :     {
     397          32 :         ::osl::MutexGuard const g(m_rMutex);
     398             : 
     399          32 :         if (0 == m_aNodePtr) {
     400           0 :             return 0;
     401             :         }
     402          32 :         ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
     403          96 :             xmlCopyNode(m_aNodePtr, (bDeep) ? 1 : 0));
     404          32 :         if (!pNode.is()) { return 0; }
     405          32 :         pNode->m_bUnlinked = true; // not linked yet
     406          64 :         return pNode.get();
     407             :     }
     408             : 
     409             :     /**
     410             :     A NamedNodeMap containing the attributes of this node (if it is an Element)
     411             :     or null otherwise.
     412             :     */
     413          16 :     Reference< XNamedNodeMap > SAL_CALL CNode::getAttributes()
     414             :         throw (RuntimeException, std::exception)
     415             :     {
     416             :         // return empty reference; only element node may override this impl
     417          16 :         return Reference< XNamedNodeMap>();
     418             :     }
     419             : 
     420             :     /**
     421             :     A NodeList that contains all children of this node.
     422             :     */
     423        4780 :     Reference< XNodeList > SAL_CALL CNode::getChildNodes()
     424             :         throw (RuntimeException, std::exception)
     425             :     {
     426        4780 :         ::osl::MutexGuard const g(m_rMutex);
     427             : 
     428        4780 :         if (0 == m_aNodePtr) {
     429           0 :             return 0;
     430             :         }
     431        9560 :         Reference< XNodeList > const xNodeList(new CChildList(this, m_rMutex));
     432        9560 :         return xNodeList;
     433             :     }
     434             : 
     435             :     /**
     436             :     The first child of this node.
     437             :     */
     438       67066 :     Reference< XNode > SAL_CALL CNode::getFirstChild()
     439             :         throw (RuntimeException, std::exception)
     440             :     {
     441       67066 :         ::osl::MutexGuard const g(m_rMutex);
     442             : 
     443       67066 :         if (0 == m_aNodePtr) {
     444           0 :             return 0;
     445             :         }
     446             :         Reference< XNode > const xNode(
     447      134132 :                 GetOwnerDocument().GetCNode(m_aNodePtr->children).get());
     448      134132 :         return xNode;
     449             :     }
     450             : 
     451             :     /**
     452             :     The last child of this node.
     453             :     */
     454          40 :     Reference< XNode > SAL_CALL CNode::getLastChild()
     455             :         throw (RuntimeException, std::exception)
     456             :     {
     457          40 :         ::osl::MutexGuard const g(m_rMutex);
     458             : 
     459          40 :         if (0 == m_aNodePtr) {
     460           0 :             return 0;
     461             :         }
     462             :         Reference< XNode > const xNode(
     463          80 :             GetOwnerDocument().GetCNode(xmlGetLastChild(m_aNodePtr)).get());
     464          80 :         return xNode;
     465             :     }
     466             : 
     467             :     /**
     468             :     Returns the local part of the qualified name of this node.
     469             :     */
     470          14 :     OUString SAL_CALL CNode::getLocalName()
     471             :         throw (RuntimeException, std::exception)
     472             :     {
     473             :         // see CElement/CAttr
     474          14 :         return OUString();
     475             :     }
     476             : 
     477             : 
     478             :     /**
     479             :     The namespace URI of this node, or null if it is unspecified.
     480             :     */
     481       33474 :     OUString SAL_CALL CNode::getNamespaceURI()
     482             :         throw (RuntimeException, std::exception)
     483             :     {
     484       33474 :         ::osl::MutexGuard const g(m_rMutex);
     485             : 
     486       33474 :         OUString aURI;
     487       66948 :         if (m_aNodePtr != NULL &&
     488       84496 :             (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
     489       33460 :             m_aNodePtr->ns != NULL)
     490             :         {
     491       33452 :             const xmlChar* xHref = m_aNodePtr->ns->href;
     492       33452 :             aURI = OUString((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8);
     493             :         }
     494       33474 :         return aURI;
     495             :     }
     496             : 
     497             :     /**
     498             :     The node immediately following this node.
     499             :     */
     500       26356 :     Reference< XNode > SAL_CALL CNode::getNextSibling()
     501             :         throw (RuntimeException, std::exception)
     502             :     {
     503       26356 :         ::osl::MutexGuard const g(m_rMutex);
     504             : 
     505       26356 :         if (0 == m_aNodePtr) {
     506           0 :             return 0;
     507             :         }
     508             :         Reference< XNode > const xNode(
     509       52712 :                 GetOwnerDocument().GetCNode(m_aNodePtr->next).get());
     510       52712 :         return xNode;
     511             :     }
     512             : 
     513             :     /**
     514             :     The name of this node, depending on its type; see the table above.
     515             :     */
     516           0 :     OUString SAL_CALL CNode::getNodeName()
     517             :         throw (RuntimeException, std::exception)
     518             :     {
     519             :         /*
     520             :         Interface        nodeName               nodeValue                       attributes
     521             :         --------------------------------------------------------------------------------------
     522             :         Attr             name of attribute      value of attribute              null
     523             :         CDATASection     "#cdata-section"       content of the CDATA Section    null
     524             :         Comment          "#comment"             content of the comment          null
     525             :         Document         "#document"            null                            null
     526             :         DocumentFragment "#document-fragment"   null                            null
     527             :         DocumentType     document type name     null                            null
     528             :         Element          tag name               null                            NamedNodeMap
     529             :         Entity           entity name            null                            null
     530             :         EntityReference  name of entity         null                            null
     531             :                          referenced
     532             :         Notation         notation name          null                            null
     533             :         Processing\      target                 entire content excluding        null
     534             :         Instruction                             the target
     535             :         Text             "#text"                content of the text node        null
     536             :         */
     537           0 :         OUString aName;
     538           0 :         return aName;
     539             :     }
     540             : 
     541             :     /**
     542             :     A code representing the type of the underlying object, as defined above.
     543             :     */
     544       58568 :     NodeType SAL_CALL CNode::getNodeType()
     545             :         throw (RuntimeException, std::exception)
     546             :     {
     547       58568 :         ::osl::MutexGuard const g(m_rMutex);
     548             : 
     549       58568 :         return m_aNodeType;
     550             :     }
     551             : 
     552             :     /**
     553             :     The value of this node, depending on its type; see the table above.
     554             :     */
     555           0 :     OUString SAL_CALL CNode::getNodeValue()
     556             :         throw (RuntimeException, std::exception)
     557             :     {
     558           0 :         OUString aValue;
     559           0 :         return aValue;
     560             :     }
     561             : 
     562             :     /**
     563             :     The Document object associated with this node.
     564             :     */
     565      857300 :     Reference< XDocument > SAL_CALL CNode::getOwnerDocument()
     566             :         throw (RuntimeException, std::exception)
     567             :     {
     568      857300 :         ::osl::MutexGuard const g(m_rMutex);
     569             : 
     570      857300 :         if (0 == m_aNodePtr) {
     571           0 :             return 0;
     572             :         }
     573     1714600 :         Reference< XDocument > const xDoc(& GetOwnerDocument());
     574     1714600 :         return xDoc;
     575             :     }
     576             : 
     577             :     /**
     578             :     The parent of this node.
     579             :     */
     580        6377 :     Reference< XNode > SAL_CALL CNode::getParentNode()
     581             :         throw (RuntimeException, std::exception)
     582             :     {
     583        6377 :         ::osl::MutexGuard const g(m_rMutex);
     584             : 
     585        6377 :         if (0 == m_aNodePtr) {
     586           0 :             return 0;
     587             :         }
     588             :         Reference< XNode > const xNode(
     589       12754 :                 GetOwnerDocument().GetCNode(m_aNodePtr->parent).get());
     590       12754 :         return xNode;
     591             :     }
     592             : 
     593             :     /**
     594             :     The namespace prefix of this node, or null if it is unspecified.
     595             :     */
     596      524928 :     OUString SAL_CALL CNode::getPrefix()
     597             :         throw (RuntimeException, std::exception)
     598             :     {
     599      524928 :         ::osl::MutexGuard const g(m_rMutex);
     600             : 
     601      524928 :         OUString aPrefix;
     602     1049856 :         if (m_aNodePtr != NULL &&
     603     1345806 :             (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
     604      524914 :             m_aNodePtr->ns != NULL)
     605             :         {
     606      285348 :             const xmlChar* xPrefix = m_aNodePtr->ns->prefix;
     607      285348 :             if( xPrefix != NULL )
     608      284460 :                 aPrefix = OUString((sal_Char*)xPrefix, strlen((char*)xPrefix), RTL_TEXTENCODING_UTF8);
     609             :         }
     610      524928 :         return aPrefix;
     611             : 
     612             :     }
     613             : 
     614             :     /**
     615             :     The node immediately preceding this node.
     616             :     */
     617          18 :     Reference< XNode > SAL_CALL CNode::getPreviousSibling()
     618             :         throw (RuntimeException, std::exception)
     619             :     {
     620          18 :         ::osl::MutexGuard const g(m_rMutex);
     621             : 
     622          18 :         if (0 == m_aNodePtr) {
     623           0 :             return 0;
     624             :         }
     625             :         Reference< XNode > const xNode(
     626          36 :                 GetOwnerDocument().GetCNode(m_aNodePtr->prev).get());
     627          36 :         return xNode;
     628             :     }
     629             : 
     630             :     /**
     631             :     Returns whether this node (if it is an element) has any attributes.
     632             :     */
     633       15696 :     sal_Bool SAL_CALL CNode::hasAttributes()
     634             :         throw (RuntimeException, std::exception)
     635             :     {
     636       15696 :         ::osl::MutexGuard const g(m_rMutex);
     637             : 
     638       15696 :         return (m_aNodePtr != NULL && m_aNodePtr->properties != NULL);
     639             :     }
     640             : 
     641             :     /**
     642             :     Returns whether this node has any children.
     643             :     */
     644          72 :     sal_Bool SAL_CALL CNode::hasChildNodes()
     645             :         throw (RuntimeException, std::exception)
     646             :     {
     647          72 :         ::osl::MutexGuard const g(m_rMutex);
     648             : 
     649          72 :         return (m_aNodePtr != NULL && m_aNodePtr->children != NULL);
     650             :     }
     651             : 
     652             :     /**
     653             :     Inserts the node newChild before the existing child node refChild.
     654             :     */
     655          48 :     Reference< XNode > SAL_CALL CNode::insertBefore(
     656             :             const Reference< XNode >& newChild, const Reference< XNode >& refChild)
     657             :         throw (RuntimeException, DOMException, std::exception)
     658             :     {
     659          48 :         if (!newChild.is() || !refChild.is()) { throw RuntimeException(); }
     660             : 
     661          28 :         if (newChild->getOwnerDocument() != getOwnerDocument()) {
     662           0 :             DOMException e;
     663           0 :             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
     664           0 :             throw e;
     665             :         }
     666          28 :         if (refChild->getParentNode() != Reference< XNode >(this)) {
     667          18 :             DOMException e;
     668          18 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     669          18 :             throw e;
     670             :         }
     671             : 
     672          10 :         ::osl::ClearableMutexGuard guard(m_rMutex);
     673             : 
     674          10 :         CNode *const pNewNode(CNode::GetImplementation(newChild));
     675          10 :         CNode *const pRefNode(CNode::GetImplementation(refChild));
     676          10 :         if (!pNewNode || !pRefNode) { throw RuntimeException(); }
     677          10 :         xmlNodePtr const pNewChild(pNewNode->GetNodePtr());
     678          10 :         xmlNodePtr const pRefChild(pRefNode->GetNodePtr());
     679          10 :         if (!pNewChild || !pRefChild) { throw RuntimeException(); }
     680             : 
     681          10 :         if (pNewChild == m_aNodePtr) {
     682           0 :             DOMException e;
     683           0 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     684           0 :             throw e;
     685             :         }
     686             :         // already has parent
     687          10 :         if (pNewChild->parent != NULL)
     688             :         {
     689           0 :             DOMException e;
     690           0 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     691           0 :             throw e;
     692             :         }
     693          10 :         if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
     694           0 :             DOMException e;
     695           0 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     696           0 :             throw e;
     697             :         }
     698             : 
     699             :         // attributes are unordered anyway, so just do appendChild
     700          10 :         if (XML_ATTRIBUTE_NODE == pNewChild->type) {
     701           0 :             guard.clear();
     702           0 :             return appendChild(newChild);
     703             :         }
     704             : 
     705          10 :         xmlNodePtr cur = m_aNodePtr->children;
     706             : 
     707             :         //search child before which to insert
     708          20 :         while (cur != NULL)
     709             :         {
     710          10 :             if (cur == pRefChild) {
     711             :                 // insert before
     712          10 :                 pNewChild->next = cur;
     713          10 :                 pNewChild->prev = cur->prev;
     714          10 :                 cur->prev = pNewChild;
     715          10 :                 if (pNewChild->prev != NULL) {
     716           0 :                     pNewChild->prev->next = pNewChild;
     717             :                 }
     718          10 :                 pNewChild->parent = cur->parent;
     719          10 :                 if (pNewChild->parent->children == cur) {
     720          10 :                     pNewChild->parent->children = pNewChild;
     721             :                 }
     722             :                 // do not update parent->last here!
     723          10 :                 pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
     724          10 :                 break;
     725             :             }
     726           0 :             cur = cur->next;
     727             :         }
     728          10 :         return refChild;
     729             :     }
     730             : 
     731             :     /**
     732             :     Tests whether the DOM implementation implements a specific feature and
     733             :     that feature is supported by this node.
     734             :     */
     735          18 :   sal_Bool SAL_CALL CNode::isSupported(const OUString& /*feature*/, const OUString& /*ver*/)
     736             :         throw (RuntimeException, std::exception)
     737             :     {
     738             :         OSL_ENSURE(false, "CNode::isSupported: not implemented (#i113683#)");
     739          18 :         return sal_False;
     740             :     }
     741             : 
     742             :     /**
     743             :     Puts all Text nodes in the full depth of the sub-tree underneath this
     744             :     Node, including attribute nodes, into a "normal" form where only structure
     745             :     (e.g., elements, comments, processing instructions, CDATA sections, and
     746             :     entity references) separates Text nodes, i.e., there are neither adjacent
     747             :     Text nodes nor empty Text nodes.
     748             :     */
     749          18 :     void SAL_CALL CNode::normalize()
     750             :         throw (RuntimeException, std::exception)
     751             :     {
     752             :         //XXX combine adjacent text nodes and remove empty ones
     753             :         OSL_ENSURE(false, "CNode::normalize: not implemented (#i113683#)");
     754          18 :     }
     755             : 
     756             :     /**
     757             :     Removes the child node indicated by oldChild from the list of children,
     758             :     and returns it.
     759             :     */
     760             :     Reference< XNode > SAL_CALL
     761        6295 :     CNode::removeChild(const Reference< XNode >& xOldChild)
     762             :         throw (RuntimeException, DOMException, std::exception)
     763             :     {
     764        6295 :         if (!xOldChild.is()) {
     765          18 :             throw RuntimeException();
     766             :         }
     767             : 
     768        6277 :         if (xOldChild->getOwnerDocument() != getOwnerDocument()) {
     769           0 :             DOMException e;
     770           0 :             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
     771           0 :             throw e;
     772             :         }
     773        6277 :         if (xOldChild->getParentNode() != Reference< XNode >(this)) {
     774          18 :             DOMException e;
     775          18 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     776          18 :             throw e;
     777             :         }
     778             : 
     779        6259 :         ::osl::ClearableMutexGuard guard(m_rMutex);
     780             : 
     781        6259 :         if (!m_aNodePtr) { throw RuntimeException(); }
     782             : 
     783        6259 :         Reference<XNode> xReturn( xOldChild );
     784             : 
     785       12518 :         ::rtl::Reference<CNode> const pOld(CNode::GetImplementation(xOldChild));
     786        6259 :         if (!pOld.is()) { throw RuntimeException(); }
     787        6259 :         xmlNodePtr const old = pOld->GetNodePtr();
     788        6259 :         if (!old) { throw RuntimeException(); }
     789             : 
     790        6259 :         if( old->type == XML_ATTRIBUTE_NODE )
     791             :         {
     792           0 :             xmlAttrPtr pAttr = reinterpret_cast<xmlAttrPtr>(old);
     793           0 :             xmlRemoveProp( pAttr );
     794           0 :             pOld->invalidate(); // freed by xmlRemoveProp
     795           0 :             xReturn.clear();
     796             :         }
     797             :         else
     798             :         {
     799        6259 :             xmlUnlinkNode(old);
     800        6259 :             pOld->m_bUnlinked = true;
     801             :         }
     802             : 
     803             :         /*DOMNodeRemoved
     804             :          * Fired when a node is being removed from its parent node.
     805             :          * This event is dispatched before the node is removed from the tree.
     806             :          * The target of this event is the node being removed.
     807             :          *   Bubbles: Yes
     808             :          *   Cancelable: No
     809             :          *   Context Info: relatedNode holds the parent node
     810             :          */
     811       12518 :         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
     812        6259 :         Reference< XMutationEvent > event(docevent->createEvent(
     813       12518 :             "DOMNodeRemoved"), UNO_QUERY);
     814        6259 :             event->initMutationEvent("DOMNodeRemoved",
     815             :             sal_True,
     816             :             sal_False,
     817             :             this,
     818        6259 :             OUString(), OUString(), OUString(), (AttrChangeType)0 );
     819             : 
     820             :         // the following dispatch functions use only UNO interfaces
     821             :         // and call event listeners, so release mutex to prevent deadlocks.
     822        6259 :         guard.clear();
     823             : 
     824        6259 :         dispatchEvent(event);
     825             :         // subtree modified for this node
     826        6259 :         dispatchSubtreeModified();
     827             : 
     828       12518 :         return xReturn;
     829             :     }
     830             : 
     831             :     /**
     832             :     Replaces the child node oldChild with newChild in the list of children,
     833             :     and returns the oldChild node.
     834             :     */
     835          58 :     Reference< XNode > SAL_CALL CNode::replaceChild(
     836             :             Reference< XNode > const& xNewChild,
     837             :             Reference< XNode > const& xOldChild)
     838             :         throw (RuntimeException, DOMException, std::exception)
     839             :     {
     840          58 :         if (!xOldChild.is() || !xNewChild.is()) {
     841          20 :             throw RuntimeException();
     842             :         }
     843             : 
     844          38 :         if (xNewChild->getOwnerDocument() != getOwnerDocument()) {
     845           0 :             DOMException e;
     846           0 :             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
     847           0 :             throw e;
     848             :         }
     849          38 :         if (xOldChild->getParentNode() != Reference< XNode >(this)) {
     850          16 :             DOMException e;
     851          16 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     852          16 :             throw e;
     853             :         }
     854             : 
     855          22 :         ::osl::ClearableMutexGuard guard(m_rMutex);
     856             : 
     857             :         ::rtl::Reference<CNode> const pOldNode(
     858          44 :                 CNode::GetImplementation(xOldChild));
     859             :         ::rtl::Reference<CNode> const pNewNode(
     860          44 :                 CNode::GetImplementation(xNewChild));
     861          22 :         if (!pOldNode.is() || !pNewNode.is()) { throw RuntimeException(); }
     862          22 :         xmlNodePtr const pOld = pOldNode->GetNodePtr();
     863          22 :         xmlNodePtr const pNew = pNewNode->GetNodePtr();
     864          22 :         if (!pOld || !pNew) { throw RuntimeException(); }
     865             : 
     866          22 :         if (pNew == m_aNodePtr) {
     867           0 :             DOMException e;
     868           0 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     869           0 :             throw e;
     870             :         }
     871             :         // already has parent
     872          22 :         if (pNew->parent != NULL) {
     873          12 :             DOMException e;
     874          12 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     875          12 :             throw e;
     876             :         }
     877          10 :         if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
     878           0 :             DOMException e;
     879           0 :             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     880           0 :             throw e;
     881             :         }
     882             : 
     883          10 :         if( pOld->type == XML_ATTRIBUTE_NODE )
     884             :         {
     885             :             // can only replace attribute with attribute
     886           0 :             if ( pOld->type != pNew->type )
     887             :             {
     888           0 :                 DOMException e;
     889           0 :                 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
     890           0 :                 throw e;
     891             :             }
     892             : 
     893           0 :             xmlAttrPtr pAttr = (xmlAttrPtr)pOld;
     894           0 :             xmlRemoveProp( pAttr );
     895           0 :             pOldNode->invalidate(); // freed by xmlRemoveProp
     896           0 :             appendChild(xNewChild);
     897             :         }
     898             :         else
     899             :         {
     900             : 
     901          10 :         xmlNodePtr cur = m_aNodePtr->children;
     902             :         //find old node in child list
     903          32 :         while (cur != NULL)
     904             :         {
     905          12 :             if(cur == pOld)
     906             :             {
     907             :                 // exchange nodes
     908          10 :                 pNew->prev = pOld->prev;
     909          10 :                 if (pNew->prev != NULL)
     910           2 :                     pNew->prev->next = pNew;
     911          10 :                 pNew->next = pOld->next;
     912          10 :                 if (pNew->next != NULL)
     913           8 :                     pNew->next->prev = pNew;
     914          10 :                 pNew->parent = pOld->parent;
     915          10 :                 if(pNew->parent->children == pOld)
     916           8 :                     pNew->parent->children = pNew;
     917          10 :                 if(pNew->parent->last == pOld)
     918           2 :                     pNew->parent->last = pNew;
     919          10 :                 pOld->next = NULL;
     920          10 :                 pOld->prev = NULL;
     921          10 :                 pOld->parent = NULL;
     922          10 :                 pOldNode->m_bUnlinked = true;
     923          10 :                 pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
     924             :             }
     925          12 :             cur = cur->next;
     926             :         }
     927             :         }
     928             : 
     929          10 :         guard.clear(); // release for calling event handlers
     930          10 :         dispatchSubtreeModified();
     931             : 
     932          32 :         return xOldChild;
     933             :     }
     934             : 
     935      231120 :     void CNode::dispatchSubtreeModified()
     936             :     {
     937             :         // only uses UNO interfaces => needs no mutex
     938             : 
     939             :         // dispatch DOMSubtreeModified
     940             :         // target is _this_ node
     941      231120 :         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
     942      231120 :         Reference< XMutationEvent > event(docevent->createEvent(
     943      462240 :             "DOMSubtreeModified"), UNO_QUERY);
     944      231120 :         event->initMutationEvent(
     945             :             "DOMSubtreeModified", sal_True,
     946             :             sal_False, Reference< XNode >(),
     947      231120 :             OUString(), OUString(), OUString(), (AttrChangeType)0 );
     948      462240 :         dispatchEvent(event);
     949      231120 :     }
     950             : 
     951             :     /**
     952             :     The value of this node, depending on its type; see the table above.
     953             :     */
     954           8 :     void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/)
     955             :         throw (RuntimeException, DOMException, std::exception)
     956             :     {
     957             :         // use specific node implememntation
     958             :         // if we end up down here, something went wrong
     959           8 :         DOMException e;
     960           8 :         e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
     961           8 :         throw e;
     962             :     }
     963             : 
     964             :     /**
     965             :     The namespace prefix of this node, or null if it is unspecified.
     966             :     */
     967          16 :     void SAL_CALL CNode::setPrefix(const OUString& prefix)
     968             :         throw (RuntimeException, DOMException, std::exception)
     969             :     {
     970          16 :         ::osl::MutexGuard const g(m_rMutex);
     971             : 
     972          32 :         if ((0 == m_aNodePtr) ||
     973          30 :             ((m_aNodePtr->type != XML_ELEMENT_NODE) &&
     974          14 :              (m_aNodePtr->type != XML_ATTRIBUTE_NODE)))
     975             :         {
     976          14 :             DOMException e;
     977          14 :             e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
     978          14 :             throw e;
     979             :         }
     980           4 :         OString o1 = OUStringToOString(prefix, RTL_TEXTENCODING_UTF8);
     981           2 :         xmlChar *pBuf = (xmlChar*)o1.getStr();
     982           2 :         if (m_aNodePtr != NULL && m_aNodePtr->ns != NULL)
     983             :         {
     984           2 :             xmlFree(const_cast<xmlChar *>(m_aNodePtr->ns->prefix));
     985           2 :             m_aNodePtr->ns->prefix = xmlStrdup(pBuf);
     986          16 :         }
     987             : 
     988           2 :     }
     989             : 
     990             :         // --- XEventTarget
     991         910 :     void SAL_CALL CNode::addEventListener(const OUString& eventType,
     992             :         const Reference< css::xml::dom::events::XEventListener >& listener,
     993             :         sal_Bool useCapture)
     994             :         throw (RuntimeException, std::exception)
     995             :     {
     996         910 :         ::osl::MutexGuard const g(m_rMutex);
     997             : 
     998         910 :         CDocument & rDocument(GetOwnerDocument());
     999         910 :         events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
    1000         910 :         rDispatcher.addListener(m_aNodePtr, eventType, listener, useCapture);
    1001         910 :     }
    1002             : 
    1003         910 :     void SAL_CALL CNode::removeEventListener(const OUString& eventType,
    1004             :         const Reference< css::xml::dom::events::XEventListener >& listener,
    1005             :         sal_Bool useCapture)
    1006             :         throw (RuntimeException, std::exception)
    1007             :     {
    1008         910 :         ::osl::MutexGuard const g(m_rMutex);
    1009             : 
    1010         910 :         CDocument & rDocument(GetOwnerDocument());
    1011         910 :         events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
    1012         910 :         rDispatcher.removeListener(m_aNodePtr, eventType, listener, useCapture);
    1013         910 :     }
    1014             : 
    1015      489668 :     sal_Bool SAL_CALL CNode::dispatchEvent(const Reference< XEvent >& evt)
    1016             :         throw(RuntimeException, EventException, std::exception)
    1017             :     {
    1018             :         CDocument * pDocument;
    1019             :         events::CEventDispatcher * pDispatcher;
    1020             :         xmlNodePtr pNode;
    1021             :         {
    1022      489668 :             ::osl::MutexGuard const g(m_rMutex);
    1023             : 
    1024      489668 :             pDocument = & GetOwnerDocument();
    1025      489668 :             pDispatcher = & pDocument->GetEventDispatcher();
    1026      489668 :             pNode = m_aNodePtr;
    1027             :         }
    1028             :         // this calls event listeners, do not call with locked mutex
    1029      489668 :         pDispatcher->dispatchEvent(*pDocument, m_rMutex, pNode, this, evt);
    1030      489668 :         return sal_True;
    1031             :     }
    1032             : 
    1033             :     ::sal_Int64 SAL_CALL
    1034      859168 :     CNode::getSomething(Sequence< ::sal_Int8 > const& rId)
    1035             :         throw (RuntimeException, std::exception)
    1036             :     {
    1037     1718336 :         if ((rId.getLength() == 16) &&
    1038      859168 :             (0 == memcmp(theCNodeUnoTunnelId::get().getSeq().getConstArray(),
    1039     1718336 :                                     rId.getConstArray(), 16)))
    1040             :         {
    1041             :             return ::sal::static_int_cast< sal_Int64 >(
    1042      859168 :                     reinterpret_cast< sal_IntPtr >(this) );
    1043             :         }
    1044           0 :         return 0;
    1045             :     }
    1046         696 : }
    1047             : 
    1048             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10