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