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

Generated by: LCOV version 1.10