summaryrefslogtreecommitdiff
path: root/unoxml/source/xpath/xpathapi.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'unoxml/source/xpath/xpathapi.cxx')
-rw-r--r--unoxml/source/xpath/xpathapi.cxx133
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 );
}
}