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