summaryrefslogtreecommitdiff
path: root/unoxml
diff options
context:
space:
mode:
authorMichael Stahl <mst@openoffice.org>2011-01-19 20:27:26 +0100
committerMichael Stahl <mst@openoffice.org>2011-01-19 20:27:26 +0100
commite94a328aa0b1a0f61018e6978dda626b842f6855 (patch)
tree138379be1300b6a2ec2af02f13b229c847fde7e3 /unoxml
parentdd995cea7b9a262d51b94d536817e5aa2950f1cb (diff)
xmlfix3: #i113682#: unoxml: locking in XPath:
use CDocument mutex in results, and during evaluation. new CXPathAPI member mutex. also, fix lcl_collectNamespaces in case parent nodes declare same prefix.
Diffstat (limited to 'unoxml')
-rw-r--r--unoxml/source/dom/document.hxx3
-rw-r--r--unoxml/source/xpath/nodelist.cxx9
-rw-r--r--unoxml/source/xpath/nodelist.hxx4
-rw-r--r--unoxml/source/xpath/xpathapi.cxx97
-rw-r--r--unoxml/source/xpath/xpathapi.hxx8
-rw-r--r--unoxml/source/xpath/xpathobject.cxx22
-rw-r--r--unoxml/source/xpath/xpathobject.hxx2
7 files changed, 113 insertions, 32 deletions
diff --git a/unoxml/source/dom/document.hxx b/unoxml/source/dom/document.hxx
index 0cde502a53db..92235c08a720 100644
--- a/unoxml/source/dom/document.hxx
+++ b/unoxml/source/dom/document.hxx
@@ -113,6 +113,9 @@ namespace DOM
virtual ~CDocument();
+ // needed by CXPathAPI
+ ::osl::Mutex & GetMutex() { return m_Mutex; }
+
events::CEventDispatcher & GetEventDispatcher();
::rtl::Reference< CElement > GetDocumentElement();
diff --git a/unoxml/source/xpath/nodelist.cxx b/unoxml/source/xpath/nodelist.cxx
index 8e37e70f5590..05add3ca44bc 100644
--- a/unoxml/source/xpath/nodelist.cxx
+++ b/unoxml/source/xpath/nodelist.cxx
@@ -25,15 +25,18 @@
*
************************************************************************/
-#include "nodelist.hxx"
+#include <nodelist.hxx>
+
#include "../dom/document.hxx"
namespace XPath
{
CNodeList::CNodeList(
::rtl::Reference<DOM::CDocument> const& pDocument,
+ ::osl::Mutex & rMutex,
boost::shared_ptr<xmlXPathObject> const& rxpathObj)
: m_pDocument(pDocument)
+ , m_rMutex(rMutex)
, m_pNodeSet(0)
{
if (rxpathObj != NULL && rxpathObj->type == XPATH_NODESET)
@@ -48,6 +51,8 @@ namespace XPath
*/
sal_Int32 SAL_CALL CNodeList::getLength() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
sal_Int32 value = 0;
if (m_pNodeSet != NULL)
value = xmlXPathNodeSetGetLength(m_pNodeSet);
@@ -60,6 +65,8 @@ namespace XPath
Reference< XNode > SAL_CALL CNodeList::item(sal_Int32 index)
throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
if (0 == m_pNodeSet) {
return 0;
}
diff --git a/unoxml/source/xpath/nodelist.hxx b/unoxml/source/xpath/nodelist.hxx
index 2b20c39c1e98..e191fc2a9857 100644
--- a/unoxml/source/xpath/nodelist.hxx
+++ b/unoxml/source/xpath/nodelist.hxx
@@ -59,14 +59,16 @@ namespace XPath
class CNodeList : public cppu::WeakImplHelper1< XNodeList >
{
private:
- /// #i115995# retain context node to keep document alive
+ /// #i115995# keep document alive
::rtl::Reference< DOM::CDocument > const m_pDocument;
+ ::osl::Mutex & m_rMutex;
boost::shared_ptr<xmlXPathObject> m_pXPathObj;
xmlNodeSetPtr m_pNodeSet;
public:
CNodeList(
::rtl::Reference<DOM::CDocument> const& pDocument,
+ ::osl::Mutex & rMutex,
boost::shared_ptr<xmlXPathObject> const& rxpathObj);
/**
The number of nodes in the list.
diff --git a/unoxml/source/xpath/xpathapi.cxx b/unoxml/source/xpath/xpathapi.cxx
index 6fad00f99c8f..d7e1077b5e84 100644
--- a/unoxml/source/xpath/xpathapi.cxx
+++ b/unoxml/source/xpath/xpathapi.cxx
@@ -25,11 +25,12 @@
*
************************************************************************/
-#include "xpathapi.hxx"
+#include <xpathapi.hxx>
#include <stdarg.h>
#include <string.h>
+#include <libxml/tree.h>
#include <libxml/xmlerror.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
@@ -38,6 +39,7 @@
#include <nodelist.hxx>
#include <xpathobject.hxx>
+
#include "../dom/node.hxx"
#include "../dom/document.hxx"
@@ -110,6 +112,8 @@ namespace XPath
const OUString& aURI)
throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_Mutex);
+
m_nsmap.insert(nsmap_t::value_type(aPrefix, aURI));
}
@@ -118,13 +122,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)
{
@@ -142,13 +149,15 @@ namespace XPath
}
}
- // get all ns decls on a node (and parent nodes, if any) and register them
+ // get all ns decls on a node (and parent nodes, if any)
static void lcl_collectNamespaces(
- CXPathAPI *const pAPI,
- Reference< XNode > const& xNamespaceNode)
+ nsmap_t & rNamespaces, Reference< XNode > const& xNamespaceNode)
{
- // get namespace decls from node...
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;
@@ -157,16 +166,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)
{
@@ -215,7 +240,7 @@ namespace XPath
const Reference< XNode >& namespaceNode)
throw (RuntimeException, XPathException)
{
- lcl_collectNamespaces(this, namespaceNode);
+ lcl_collectRegisterNamespaces(*this, namespaceNode);
return selectNodeList(contextNode, expr);
}
@@ -242,7 +267,7 @@ namespace XPath
const Reference< XNode >& namespaceNode )
throw (RuntimeException, XPathException)
{
- lcl_collectNamespaces(this, namespaceNode);
+ lcl_collectRegisterNamespaces(*this, namespaceNode);
return selectSingleNode(contextNode, expr);
}
@@ -313,16 +338,35 @@ 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)
{
+ if (!xContextNode.is()) { throw RuntimeException(); }
+
+ nsmap_t nsmap;
+ extensions_t extensions;
+
+ {
+ ::osl::MutexGuard const g(m_Mutex);
+ nsmap = m_nsmap;
+ extensions = m_extensions;
+ }
+
xmlXPathContextPtr xpathCtx;
xmlXPathObjectPtr xpathObj;
// get the node and document
- DOM::CNode *const pCNode = DOM::CNode::GetImplementation(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;
@@ -349,8 +393,8 @@ namespace XPath
xmlSetGenericErrorFunc(NULL, generic_error_func);
// register namespaces and extension
- _registerNamespaces(xpathCtx, m_nsmap);
- _registerExtensions(xpathCtx, m_extensions);
+ lcl_registerNamespaces(xpathCtx, nsmap);
+ lcl_registerExtensions(xpathCtx, extensions);
/* run the query */
OString o1 = OUStringToOString(expr, RTL_TEXTENCODING_UTF8);
@@ -361,10 +405,8 @@ namespace XPath
throw XPathException();
}
xmlXPathFreeContext(xpathCtx);
- ::rtl::Reference<DOM::CDocument> const pCDoc(
- & pCNode->GetOwnerDocument());
- OSL_ASSERT(pCDoc.is());
- Reference<XXPathObject> const xObj(new CXPathObject(pCDoc, xpathObj));
+ Reference<XXPathObject> const xObj(
+ new CXPathObject(pCDoc, pCDoc->GetMutex(), xpathObj));
return xObj;
}
@@ -377,7 +419,7 @@ namespace XPath
const Reference< XNode >& namespaceNode)
throw (RuntimeException, XPathException)
{
- lcl_collectNamespaces(this, namespaceNode);
+ lcl_collectRegisterNamespaces(*this, namespaceNode);
return eval(contextNode, expr);
}
@@ -390,9 +432,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);
}
/**
@@ -400,13 +445,13 @@ 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 );
}
}
diff --git a/unoxml/source/xpath/xpathapi.hxx b/unoxml/source/xpath/xpathapi.hxx
index 723c15259008..a64eff7444c7 100644
--- a/unoxml/source/xpath/xpathapi.hxx
+++ b/unoxml/source/xpath/xpathapi.hxx
@@ -25,14 +25,16 @@
*
************************************************************************/
-#ifndef _XPATHAPI_HXX
-#define _XPATHAPI_HXX
+#ifndef XPATH_XPATHAPI_HXX
+#define XPATH_XPATHAPI_HXX
#include <map>
#include <vector>
#include <sal/types.h>
+
#include <cppuhelper/implbase2.hxx>
+
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/uno/Sequence.h>
@@ -50,7 +52,6 @@
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
-#include "libxml/tree.h"
using ::rtl::OUString;
using namespace com::sun::star::uno;
@@ -72,6 +73,7 @@ namespace XPath
{
private:
+ ::osl::Mutex m_Mutex;
nsmap_t m_nsmap;
const Reference< ::com::sun::star::lang::XMultiServiceFactory > m_aFactory;
extensions_t m_extensions;
diff --git a/unoxml/source/xpath/xpathobject.cxx b/unoxml/source/xpath/xpathobject.cxx
index 98bebf073d71..ea63bb716736 100644
--- a/unoxml/source/xpath/xpathobject.cxx
+++ b/unoxml/source/xpath/xpathobject.cxx
@@ -66,8 +66,10 @@ namespace XPath
CXPathObject::CXPathObject(
::rtl::Reference<DOM::CDocument> const& pDocument,
+ ::osl::Mutex & rMutex,
xmlXPathObjectPtr const xpathObj)
: m_pDocument(pDocument)
+ , m_rMutex(rMutex)
, m_pXPathObj(xpathObj, xmlXPathFreeObject)
, m_XPathObjectType(lcl_GetType(xpathObj))
{
@@ -87,8 +89,10 @@ namespace XPath
Reference< XNodeList > SAL_CALL
CXPathObject::getNodeList() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
Reference< XNodeList > const xRet(
- new CNodeList(m_pDocument, m_pXPathObj));
+ new CNodeList(m_pDocument, m_rMutex, m_pXPathObj));
return xRet;
}
@@ -97,6 +101,8 @@ namespace XPath
*/
sal_Bool SAL_CALL CXPathObject::getBoolean() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
return (sal_Bool) xmlXPathCastToBoolean(m_pXPathObj.get());
}
@@ -105,6 +111,8 @@ namespace XPath
*/
sal_Int8 SAL_CALL CXPathObject::getByte() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
return (sal_Int8) xmlXPathCastToNumber(m_pXPathObj.get());
}
@@ -113,6 +121,8 @@ namespace XPath
*/
sal_Int16 SAL_CALL CXPathObject::getShort() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
return (sal_Int16) xmlXPathCastToNumber(m_pXPathObj.get());
}
@@ -121,6 +131,8 @@ namespace XPath
*/
sal_Int32 SAL_CALL CXPathObject::getLong() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
return (sal_Int32) xmlXPathCastToNumber(m_pXPathObj.get());
}
@@ -129,6 +141,8 @@ namespace XPath
*/
sal_Int64 SAL_CALL CXPathObject::getHyper() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
return (sal_Int64) xmlXPathCastToNumber(m_pXPathObj.get());
}
@@ -137,6 +151,8 @@ namespace XPath
*/
float SAL_CALL CXPathObject::getFloat() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
return (float) xmlXPathCastToNumber(m_pXPathObj.get());
}
@@ -145,6 +161,8 @@ namespace XPath
*/
double SAL_CALL CXPathObject::getDouble() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
return xmlXPathCastToNumber(m_pXPathObj.get());
}
@@ -153,6 +171,8 @@ namespace XPath
*/
OUString SAL_CALL CXPathObject::getString() throw (RuntimeException)
{
+ ::osl::MutexGuard const g(m_rMutex);
+
const sal_Char* x1 = (sal_Char*) xmlXPathCastToString(m_pXPathObj.get());
return OUString(x1, strlen(x1), RTL_TEXTENCODING_UTF8);
}
diff --git a/unoxml/source/xpath/xpathobject.hxx b/unoxml/source/xpath/xpathobject.hxx
index 7a0bfb1b0cb6..56a8d65996f5 100644
--- a/unoxml/source/xpath/xpathobject.hxx
+++ b/unoxml/source/xpath/xpathobject.hxx
@@ -59,11 +59,13 @@ namespace XPath
{
private:
::rtl::Reference< DOM::CDocument > const m_pDocument;
+ ::osl::Mutex & m_rMutex;
boost::shared_ptr<xmlXPathObject> const m_pXPathObj;
XPathObjectType const m_XPathObjectType;
public:
CXPathObject( ::rtl::Reference<DOM::CDocument> const& pDocument,
+ ::osl::Mutex & rMutex,
xmlXPathObjectPtr const xpathObj);
/**