diff options
Diffstat (limited to 'unoxml/source/xpath/xpathapi.cxx')
-rw-r--r-- | unoxml/source/xpath/xpathapi.cxx | 133 |
1 files changed, 94 insertions, 39 deletions
diff --git a/unoxml/source/xpath/xpathapi.cxx b/unoxml/source/xpath/xpathapi.cxx index ee729a9451e3..dac4b2e2ca9d 100644 --- a/unoxml/source/xpath/xpathapi.cxx +++ b/unoxml/source/xpath/xpathapi.cxx @@ -26,19 +26,26 @@ * ************************************************************************/ -#include "xpathapi.hxx" -#include "nodelist.hxx" -#include "xpathobject.hxx" -#include "../dom/node.hxx" +#include <xpathapi.hxx> -#include <rtl/ustrbuf.hxx> +#include <stdarg.h> +#include <string.h> +#include <libxml/tree.h> #include <libxml/xmlerror.h> #include <libxml/xpath.h> #include <libxml/xpathInternals.h> -#include <stdarg.h> -#include <string.h> +#include <rtl/ustrbuf.hxx> + +#include <nodelist.hxx> +#include <xpathobject.hxx> + +#include "../dom/node.hxx" +#include "../dom/document.hxx" + + +using ::com::sun::star::lang::XMultiServiceFactory; namespace XPath @@ -106,6 +113,8 @@ namespace XPath const OUString& aURI) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_nsmap.insert(nsmap_t::value_type(aPrefix, aURI)); } @@ -114,13 +123,16 @@ namespace XPath const OUString& aURI) throw (RuntimeException) { - if ((m_nsmap.find(aPrefix))->second.equals(aURI)) + ::osl::MutexGuard const g(m_Mutex); + + if ((m_nsmap.find(aPrefix))->second.equals(aURI)) { m_nsmap.erase(aPrefix); + } } // register all namespaces stored in the namespace list for this object // with the current xpath evaluation context - static void _registerNamespaces( + static void lcl_registerNamespaces( xmlXPathContextPtr ctx, const nsmap_t& nsmap) { @@ -138,13 +150,16 @@ namespace XPath } } - // get all ns decls on a node (and parent nodes, if any) and register them - static void _collectNamespaces( - CXPathAPI* pAPI, - const Reference< XNode >& namespaceNode) + // get all ns decls on a node (and parent nodes, if any) + static void lcl_collectNamespaces( + nsmap_t & rNamespaces, Reference< XNode > const& xNamespaceNode) { - // get namespace decls from node... - xmlNodePtr pNode = DOM::CNode::getNodePtr(namespaceNode); + DOM::CNode *const pCNode(DOM::CNode::GetImplementation(xNamespaceNode)); + if (!pCNode) { throw RuntimeException(); } + + ::osl::MutexGuard const g(pCNode->GetOwnerDocument().GetMutex()); + + xmlNodePtr pNode = pCNode->GetNodePtr(); while (pNode != 0) { xmlNsPtr curDef = pNode->nsDef; while (curDef != 0) { @@ -152,16 +167,32 @@ namespace XPath OUString aURI((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8); const xmlChar* xPre = curDef->prefix; OUString aPrefix((sal_Char*)xPre, strlen((char*)xPre), RTL_TEXTENCODING_UTF8); - pAPI->registerNS(aPrefix, aURI); + // we could already have this prefix from a child node + if (rNamespaces.find(aPrefix) == rNamespaces.end()) + { + rNamespaces.insert(::std::make_pair(aPrefix, aURI)); + } curDef = curDef->next; } pNode = pNode->parent; } } + static void lcl_collectRegisterNamespaces( + CXPathAPI & rAPI, Reference< XNode > const& xNamespaceNode) + { + nsmap_t namespaces; + lcl_collectNamespaces(namespaces, xNamespaceNode); + for (nsmap_t::const_iterator iter = namespaces.begin(); + iter != namespaces.end(); ++iter) + { + rAPI.registerNS(iter->first, iter->second); + } + } + // register function and variable lookup functions with the current // xpath evaluation context - static void _registerExtensions( + static void lcl_registerExtensions( xmlXPathContextPtr ctx, const extensions_t& extensions) { @@ -210,7 +241,7 @@ namespace XPath const Reference< XNode >& namespaceNode) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return selectNodeList(contextNode, expr); } @@ -237,7 +268,7 @@ namespace XPath const Reference< XNode >& namespaceNode ) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return selectSingleNode(contextNode, expr); } @@ -308,15 +339,34 @@ namespace XPath * the context Node */ Reference< XXPathObject > SAL_CALL CXPathAPI::eval( - const Reference< XNode >& contextNode, + Reference< XNode > const& xContextNode, const OUString& expr) throw (RuntimeException, XPathException) { - xmlXPathContextPtr xpathCtx; - xmlXPathObjectPtr xpathObj; + if (!xContextNode.is()) { throw RuntimeException(); } + + nsmap_t nsmap; + extensions_t extensions; + + { + ::osl::MutexGuard const g(m_Mutex); + nsmap = m_nsmap; + extensions = m_extensions; + } // get the node and document - xmlNodePtr pNode = DOM::CNode::getNodePtr(contextNode); + ::rtl::Reference<DOM::CDocument> const pCDoc( + dynamic_cast<DOM::CDocument*>( DOM::CNode::GetImplementation( + xContextNode->getOwnerDocument()))); + if (!pCDoc.is()) { throw RuntimeException(); } + + DOM::CNode *const pCNode = DOM::CNode::GetImplementation(xContextNode); + if (!pCNode) { throw RuntimeException(); } + + ::osl::MutexGuard const g(pCDoc->GetMutex()); // lock the document! + + xmlNodePtr const pNode = pCNode->GetNodePtr(); + if (!pNode) { throw RuntimeException(); } xmlDocPtr pDoc = pNode->doc; /* NB: workaround for #i87252#: @@ -331,8 +381,9 @@ namespace XPath } /* Create xpath evaluation context */ - xpathCtx = xmlXPathNewContext(pDoc); - if (xpathCtx == NULL) throw XPathException(); + ::boost::shared_ptr<xmlXPathContext> const xpathCtx( + xmlXPathNewContext(pDoc), xmlXPathFreeContext); + if (xpathCtx == NULL) { throw XPathException(); } // set context node xpathCtx->node = pNode; @@ -341,20 +392,21 @@ namespace XPath xmlSetGenericErrorFunc(NULL, generic_error_func); // register namespaces and extension - _registerNamespaces(xpathCtx, m_nsmap); - _registerExtensions(xpathCtx, m_extensions); + lcl_registerNamespaces(xpathCtx.get(), nsmap); + lcl_registerExtensions(xpathCtx.get(), extensions); /* run the query */ OString o1 = OUStringToOString(expr, RTL_TEXTENCODING_UTF8); xmlChar *xStr = (xmlChar*)o1.getStr(); - if ((xpathObj = xmlXPathEval(xStr, xpathCtx)) == NULL) { + ::boost::shared_ptr<xmlXPathObject> const xpathObj( + xmlXPathEval(xStr, xpathCtx.get()), xmlXPathFreeObject); + if (0 == xpathObj) { // OSL_ENSURE(xpathCtx->lastError == NULL, xpathCtx->lastError->message); - xmlXPathFreeContext(xpathCtx); throw XPathException(); } - xmlXPathFreeContext(xpathCtx); - Reference< XXPathObject > aObj(new CXPathObject(xpathObj, contextNode)); - return aObj; + Reference<XXPathObject> const xObj( + new CXPathObject(pCDoc, pCDoc->GetMutex(), xpathObj)); + return xObj; } /** @@ -366,7 +418,7 @@ namespace XPath const Reference< XNode >& namespaceNode) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return eval(contextNode, expr); } @@ -379,9 +431,12 @@ namespace XPath const OUString& aName) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // get extension from service manager - Reference< XXPathExtension > aExtension(m_aFactory->createInstance(aName), UNO_QUERY_THROW); - m_extensions.push_back( aExtension ); + Reference< XXPathExtension > const xExtension( + m_aFactory->createInstance(aName), UNO_QUERY_THROW); + m_extensions.push_back(xExtension); } /** @@ -389,14 +444,14 @@ namespace XPath * XPathAPI instance */ void SAL_CALL CXPathAPI::registerExtensionInstance( - const Reference< XXPathExtension>& aExtension) + Reference< XXPathExtension> const& xExtension) throw (RuntimeException) { - if (aExtension.is()) { - m_extensions.push_back( aExtension ); - } else { + if (!xExtension.is()) { throw RuntimeException(); } + ::osl::MutexGuard const g(m_Mutex); + m_extensions.push_back( xExtension ); } } |