summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2014-01-08 23:43:03 +0100
committerMichael Stahl <mstahl@redhat.com>2014-01-09 12:08:21 +0100
commit7db6b2f7968d8063b12312737136f09cb7549805 (patch)
tree03a83b72cfce51ee133c01f26818b571a7346392
parentfc1762f96540e18561fbc93c28a36e37ca6e6168 (diff)
fdo#72928: fix deadlocks in librdf_Repository
Refactor to do all calls on parameters before locking the mutex. This requires splitting up some librdf_TypeConverter methods into an extract function and a make function, with an intermediate representation between. Also rename some internal functions to make it clear which are called with Lock and which with NoLock. Change-Id: Iddc42461d95351785578ef6a80fbf5d056356c16
-rw-r--r--unoxml/source/rdf/librdf_repository.cxx473
1 files changed, 324 insertions, 149 deletions
diff --git a/unoxml/source/rdf/librdf_repository.cxx b/unoxml/source/rdf/librdf_repository.cxx
index a595af43bb08..52f3b96e6eaf 100644
--- a/unoxml/source/rdf/librdf_repository.cxx
+++ b/unoxml/source/rdf/librdf_repository.cxx
@@ -30,6 +30,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/bind.hpp>
+#include <boost/optional.hpp>
#include <libxslt/security.h>
@@ -93,7 +94,7 @@ const char s_nsOOo [] = "http://openoffice.org/2004/office/rdfa/";
////////////////////////////////////////////////////////////////////////////
-//FIXME: this approach is not ideal. can we use blind nodes instead?
+//FIXME: this approach is not ideal. can we use blank nodes instead?
bool isInternalContext(librdf_node *i_pNode) throw ()
{
OSL_ENSURE(i_pNode, "isInternalContext: context null");
@@ -176,6 +177,53 @@ static void safe_librdf_free_uri(librdf_uri *const uri)
class librdf_TypeConverter
{
public:
+
+ // some wrapper classes to temporarily hold values of UNO XNodes
+ struct Node
+ {
+ virtual ~Node() {}
+ };
+ struct Resource : public Node { };
+ struct URI : public Resource
+ {
+ OString const value;
+ URI(OString const& i_rValue)
+ : value(i_rValue)
+ { }
+ };
+ struct BlankNode : public Resource
+ {
+ OString const value;
+ BlankNode(OString const& i_rValue)
+ : value(i_rValue)
+ { }
+ };
+ struct Literal : public Node
+ {
+ OString const value;
+ OString const language;
+ ::boost::optional<OString> const type;
+ Literal(OString const& i_rValue, OString const& i_rLanguage,
+ ::boost::optional<OString> const& i_rType)
+ : value(i_rValue)
+ , language(i_rLanguage)
+ , type(i_rType)
+ { }
+ };
+ struct Statement
+ {
+ ::boost::shared_ptr<Resource> const pSubject;
+ ::boost::shared_ptr<URI> const pPredicate;
+ ::boost::shared_ptr<Node> const pObject;
+ Statement(::boost::shared_ptr<Resource> const& i_pSubject,
+ ::boost::shared_ptr<URI> const& i_pPredicate,
+ ::boost::shared_ptr<Node> const& i_pObject)
+ : pSubject(i_pSubject)
+ , pPredicate(i_pPredicate)
+ , pObject(i_pObject)
+ { }
+ };
+
librdf_TypeConverter(
uno::Reference< uno::XComponentContext > const & i_xContext,
librdf_Repository &i_rRep)
@@ -183,17 +231,23 @@ public:
, m_rRep(i_rRep)
{ };
- librdf_world *createWorld() const;
- librdf_storage *createStorage(librdf_world *i_pWorld) const;
- librdf_model *createModel(librdf_world *i_pWorld,
+ librdf_world *createWorld_Lock() const;
+ librdf_storage *createStorage_Lock(librdf_world *i_pWorld) const;
+ librdf_model *createModel_Lock(librdf_world *i_pWorld,
librdf_storage * i_pStorage) const;
- librdf_uri* mkURI( librdf_world* i_pWorld,
- const uno::Reference< rdf::XURI > & i_xURI) const;
- librdf_node* mkResource( librdf_world* i_pWorld,
+ librdf_uri* mkURI_Lock(librdf_world* i_pWorld,
+ const OString & i_rURI) const;
+ librdf_node* mkResource_Lock(librdf_world* i_pWorld,
+ const Resource * i_pResource) const;
+ librdf_node* mkNode_Lock(librdf_world* i_pWorld,
+ const Node * i_pNode) const;
+ librdf_statement* mkStatement_Lock(librdf_world* i_pWorld,
+ Statement const& i_rStatement) const;
+ ::boost::shared_ptr<Resource> extractResource_NoLock(
const uno::Reference< rdf::XResource > & i_xResource) const;
- librdf_node* mkNode( librdf_world* i_pWorld,
+ ::boost::shared_ptr<Node> extractNode_NoLock(
const uno::Reference< rdf::XNode > & i_xNode) const;
- librdf_statement* mkStatement( librdf_world* i_pWorld,
+ Statement extractStatement_NoLock(
const uno::Reference< rdf::XResource > & i_xSubject,
const uno::Reference< rdf::XURI > & i_xPredicate,
const uno::Reference< rdf::XNode > & i_xObject) const;
@@ -207,7 +261,7 @@ public:
const;
private:
- uno::Reference< uno::XComponentContext > m_xContext;
+ uno::Reference< uno::XComponentContext > const m_xContext;
librdf_Repository & m_rRep;
};
@@ -321,10 +375,13 @@ public:
throw (uno::RuntimeException, uno::Exception);
// XNamedGraph forwards ---------------------------------------------
- const NamedGraphMap_t::iterator SAL_CALL clearGraph(
- const uno::Reference< rdf::XURI > & i_xName,
+ const NamedGraphMap_t::iterator clearGraph_NoLock(
+ const OUString & i_rGraphName,
bool i_Internal = false );
- void addStatementGraph(
+ const NamedGraphMap_t::iterator clearGraph_Lock(
+ const OUString & i_rGraphName,
+ bool i_Internal);
+ void addStatementGraph_NoLock(
const uno::Reference< rdf::XResource > & i_xSubject,
const uno::Reference< rdf::XURI > & i_xPredicate,
const uno::Reference< rdf::XNode > & i_xObject,
@@ -332,14 +389,18 @@ public:
bool i_Internal = false );
// throw (uno::RuntimeException, lang::IllegalArgumentException,
// container::NoSuchElementException, rdf::RepositoryException);
- void removeStatementsGraph(
+ void addStatementGraph_Lock(
+ librdf_TypeConverter::Statement const& i_rStatement,
+ OUString const& i_rGraphName,
+ bool i_Internal);
+ void removeStatementsGraph_NoLock(
const uno::Reference< rdf::XResource > & i_xSubject,
const uno::Reference< rdf::XURI > & i_xPredicate,
const uno::Reference< rdf::XNode > & i_xObject,
const uno::Reference< rdf::XURI > & i_xName );
// throw (uno::RuntimeException, lang::IllegalArgumentException,
// container::NoSuchElementException, rdf::RepositoryException);
- uno::Reference< container::XEnumeration > getStatementsGraph(
+ uno::Reference< container::XEnumeration > getStatementsGraph_NoLock(
const uno::Reference< rdf::XResource > & i_xSubject,
const uno::Reference< rdf::XURI > & i_xPredicate,
const uno::Reference< rdf::XNode > & i_xObject,
@@ -352,7 +413,8 @@ public:
private:
- uno::Reference< uno::XComponentContext > m_xContext;
+ /// this is const, no need to lock m_aMutex to access it
+ uno::Reference< uno::XComponentContext > const m_xContext;
/// librdf global data
/** N.B.: The redland documentation gives the impression that you can have
@@ -380,7 +442,7 @@ private:
/// all named graphs
NamedGraphMap_t m_NamedGraphs;
- /// type conversion helper
+ /// type conversion helper - stateless
librdf_TypeConverter m_TypeConverter;
/// set of xml:ids of elements with xhtml:content
@@ -436,7 +498,7 @@ private:
boost::shared_ptr<librdf_node> const m_pContext;
boost::shared_ptr<librdf_stream> const m_pStream;
- librdf_node* getContext() const;
+ librdf_node* getContext_Lock() const;
};
@@ -448,7 +510,7 @@ librdf_GraphResult::hasMoreElements() throw (uno::RuntimeException)
return m_pStream.get() && !librdf_stream_end(m_pStream.get());
}
-librdf_node* librdf_GraphResult::getContext() const
+librdf_node* librdf_GraphResult::getContext_Lock() const
{
if (!m_pStream.get() || librdf_stream_end(m_pStream.get()))
return NULL;
@@ -470,7 +532,7 @@ throw (uno::RuntimeException, container::NoSuchElementException,
{
::osl::MutexGuard g(m_rMutex);
if (!m_pStream.get() || !librdf_stream_end(m_pStream.get())) {
- librdf_node * pCtxt = getContext();
+ librdf_node * pCtxt = getContext_Lock();
librdf_statement *pStmt( librdf_stream_get_object(m_pStream.get()) );
if (!pStmt) {
@@ -543,9 +605,9 @@ private:
::osl::Mutex & m_rMutex;
// not that the redland documentation spells this out explicity, but
// queries must be freed only after all the results are completely read
- boost::shared_ptr<librdf_query> m_pQuery;
- boost::shared_ptr<librdf_query_results> m_pQueryResult;
- uno::Sequence< OUString > m_BindingNames;
+ boost::shared_ptr<librdf_query> const m_pQuery;
+ boost::shared_ptr<librdf_query_results> const m_pQueryResult;
+ uno::Sequence< OUString > const m_BindingNames;
};
@@ -612,6 +674,7 @@ throw (uno::RuntimeException, container::NoSuchElementException,
uno::Sequence< OUString > SAL_CALL
librdf_QuerySelectResult::getBindingNames() throw (uno::RuntimeException)
{
+ // const - no lock needed
return m_BindingNames;
}
@@ -673,9 +736,9 @@ public:
private:
/// weak reference: this is needed to check if m_pRep is valid
- uno::WeakReference< rdf::XRepository > m_wRep;
- librdf_Repository *m_pRep;
- uno::Reference< rdf::XURI > m_xName;
+ uno::WeakReference< rdf::XRepository > const m_wRep;
+ librdf_Repository *const m_pRep;
+ uno::Reference< rdf::XURI > const m_xName;
};
@@ -715,8 +778,9 @@ throw (uno::RuntimeException,
throw rdf::RepositoryException(
"librdf_NamedGraph::clear: repository is gone", *this);
}
+ const OUString contextU( m_xName->getStringValue() );
try {
- m_pRep->clearGraph(m_xName);
+ m_pRep->clearGraph_NoLock(contextU);
} catch (lang::IllegalArgumentException &) {
throw uno::RuntimeException();
}
@@ -734,7 +798,8 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
throw rdf::RepositoryException(
"librdf_NamedGraph::addStatement: repository is gone", *this);
}
- m_pRep->addStatementGraph(i_xSubject, i_xPredicate, i_xObject, m_xName);
+ m_pRep->addStatementGraph_NoLock(
+ i_xSubject, i_xPredicate, i_xObject, m_xName);
}
void SAL_CALL librdf_NamedGraph::removeStatements(
@@ -749,7 +814,8 @@ throw (uno::RuntimeException,
throw rdf::RepositoryException(
"librdf_NamedGraph::removeStatements: repository is gone", *this);
}
- m_pRep->removeStatementsGraph(i_xSubject, i_xPredicate, i_xObject, m_xName);
+ m_pRep->removeStatementsGraph_NoLock(
+ i_xSubject, i_xPredicate, i_xObject, m_xName);
}
uno::Reference< container::XEnumeration > SAL_CALL
@@ -765,7 +831,7 @@ throw (uno::RuntimeException,
throw rdf::RepositoryException(
"librdf_NamedGraph::getStatements: repository is gone", *this);
}
- return m_pRep->getStatementsGraph(
+ return m_pRep->getStatementsGraph_NoLock(
i_xSubject, i_xPredicate, i_xObject, m_xName);
}
@@ -789,7 +855,8 @@ librdf_Repository::librdf_Repository(
::osl::MutexGuard g(m_aMutex);
if (!m_NumInstances++) {
- m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world);
+ m_pWorld.reset(m_TypeConverter.createWorld_Lock(),
+ safe_librdf_free_world);
}
}
@@ -876,7 +943,6 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
container::ElementExistException, rdf::ParseException,
rdf::RepositoryException, io::IOException)
{
- ::osl::MutexGuard g(m_aMutex);
if (!i_xInStream.is()) {
throw lang::IllegalArgumentException(
"librdf_Repository::importGraph: stream is null", *this, 1);
@@ -907,6 +973,16 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
}
const OUString contextU( i_xGraphName->getStringValue() );
+
+ uno::Sequence<sal_Int8> buf;
+ uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY);
+ // UGLY: if only redland could read streams...
+ const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 );
+ // exceptions are propagated
+ i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) );
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
throw container::ElementExistException(
"librdf_Repository::importGraph: graph with given URI exists", *this);
@@ -942,12 +1018,6 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
"librdf_new_parser failed", *this);
}
- uno::Sequence<sal_Int8> buf;
- uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY);
- // UGLY: if only that redland junk could read streams...
- const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 );
- // exceptions are propagated
- i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) );
const boost::shared_ptr<librdf_stream> pStream(
librdf_parser_parse_counted_string_as_stream(pParser.get(),
reinterpret_cast<const unsigned char*>(buf.getConstArray()),
@@ -958,8 +1028,9 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
"librdf_Repository::importGraph: "
"librdf_parser_parse_counted_string_as_stream failed", *this);
}
- m_NamedGraphs.insert(std::make_pair(contextU,
- new librdf_NamedGraph(this, i_xGraphName)));
+ rtl::Reference<librdf_NamedGraph> const pGraph(
+ new librdf_NamedGraph(this, i_xGraphName));
+ m_NamedGraphs.insert(std::make_pair(contextU, pGraph));
if (librdf_model_context_add_statements(m_pModel.get(),
pContext.get(), pStream.get())) {
throw rdf::RepositoryException(
@@ -967,7 +1038,7 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
"librdf_model_context_add_statements failed", *this);
}
- return getGraph(i_xGraphName);
+ return uno::Reference<rdf::XNamedGraph>(pGraph.get());
}
void addChaffWhenEncryptedStorage(const uno::Reference< io::XOutputStream > &rStream, unsigned char* pBuffer, size_t length)
@@ -1027,7 +1098,6 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
container::NoSuchElementException, rdf::RepositoryException,
io::IOException)
{
- ::osl::MutexGuard g(m_aMutex);
if (!i_xOutStream.is()) {
throw lang::IllegalArgumentException(
"librdf_Repository::exportGraph: stream is null", *this, 1);
@@ -1057,6 +1127,9 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
}
const OUString contextU( i_xGraphName->getStringValue() );
+
+ ::osl::ClearableMutexGuard g(m_aMutex); // don't call i_x* with mutex locked
+
if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
throw container::NoSuchElementException(
"librdf_Repository::exportGraph: "
@@ -1155,6 +1228,9 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
"librdf_serializer_serialize_stream_to_counted_string failed",
*this);
}
+
+ g.clear(); // release Mutex before calling i_xOutStream methods //////////
+
addChaffWhenEncryptedStorage(i_xOutStream, pBuf.get(), length);
}
@@ -1176,13 +1252,14 @@ librdf_Repository::getGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
throw (uno::RuntimeException, lang::IllegalArgumentException,
rdf::RepositoryException)
{
- ::osl::MutexGuard g(m_aMutex);
if (!i_xGraphName.is()) {
throw lang::IllegalArgumentException(
"librdf_Repository::getGraph: URI is null", *this, 0);
}
- const NamedGraphMap_t::iterator iter(
- m_NamedGraphs.find(i_xGraphName->getStringValue()) );
+ const OUString contextU( i_xGraphName->getStringValue() );
+
+ ::osl::MutexGuard g(m_aMutex);
+ const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) );
if (iter != m_NamedGraphs.end()) {
return uno::Reference<rdf::XNamedGraph>(iter->second.get());
} else {
@@ -1195,21 +1272,24 @@ librdf_Repository::createGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
throw (uno::RuntimeException, lang::IllegalArgumentException,
container::ElementExistException, rdf::RepositoryException)
{
- ::osl::MutexGuard g(m_aMutex);
if (!i_xGraphName.is()) {
throw lang::IllegalArgumentException(
"librdf_Repository::createGraph: URI is null", *this, 0);
}
- if (i_xGraphName->getStringValue().matchAsciiL(s_nsOOo, sizeof(s_nsOOo)-1))
+
+ const OUString contextU( i_xGraphName->getStringValue() );
+ if (contextU.matchAsciiL(s_nsOOo, sizeof(s_nsOOo)-1))
{
throw lang::IllegalArgumentException(
"librdf_Repository::createGraph: URI is reserved", *this, 0);
}
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
// NB: librdf does not have a concept of graphs as such;
// a librdf named graph exists iff the model contains a statement with
// the graph name as context
- const OUString contextU( i_xGraphName->getStringValue() );
+
if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
throw container::ElementExistException(
"librdf_Repository::createGraph: graph with given URI exists", *this);
@@ -1226,8 +1306,15 @@ librdf_Repository::destroyGraph(
throw (uno::RuntimeException, lang::IllegalArgumentException,
container::NoSuchElementException, rdf::RepositoryException)
{
- ::osl::MutexGuard g(m_aMutex);
- const NamedGraphMap_t::iterator iter( clearGraph(i_xGraphName) );
+ if (!i_xGraphName.is()) {
+ throw lang::IllegalArgumentException(
+ "librdf_Repository::destroyGraph: URI is null", *this, 0);
+ }
+ const OUString contextU( i_xGraphName->getStringValue() );
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
+ const NamedGraphMap_t::iterator iter( clearGraph_Lock(contextU, false) );
m_NamedGraphs.erase(iter);
}
@@ -1254,10 +1341,14 @@ throw (uno::RuntimeException, rdf::RepositoryException)
::boost::shared_ptr<librdf_node>());
}
- ::osl::MutexGuard g(m_aMutex);
+ librdf_TypeConverter::Statement const stmt(
+ m_TypeConverter.extractStatement_NoLock(
+ i_xSubject, i_xPredicate, i_xObject));
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
const boost::shared_ptr<librdf_statement> pStatement(
- m_TypeConverter.mkStatement(m_pWorld.get(),
- i_xSubject, i_xPredicate, i_xObject),
+ m_TypeConverter.mkStatement_Lock(m_pWorld.get(), stmt),
safe_librdf_free_statement);
OSL_ENSURE(pStatement, "mkStatement failed");
@@ -1456,18 +1547,7 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
"ensureMetadataReference did not", *this);
}
OUString const sXmlId(mdref.First + "#" + mdref.Second);
- uno::Reference<rdf::XURI> xXmlId;
- try {
- xXmlId.set( rdf::URI::create(m_xContext,
- OUString::createFromAscii(s_nsOOo) + sXmlId),
- uno::UNO_QUERY_THROW);
- } catch (const lang::IllegalArgumentException & iae) {
- throw lang::WrappedTargetRuntimeException(
- "librdf_Repository::setStatementRDFa: "
- "cannot create URI for XML ID", *this, uno::makeAny(iae));
- }
-
- ::osl::MutexGuard g(m_aMutex);
+ OUString const sContext(OUString::createFromAscii(s_nsOOo) + sXmlId);
OUString const content( (i_rRDFaContent.isEmpty())
? xTextRange->getString()
: i_rRDFaContent );
@@ -1486,15 +1566,37 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
"librdf_Repository::setStatementRDFa: "
"cannot create literal", *this, uno::makeAny(iae));
}
- removeStatementRDFa(i_xObject);
+
+ ::boost::shared_ptr<librdf_TypeConverter::Resource> const pSubject(
+ m_TypeConverter.extractResource_NoLock(i_xSubject));
+ ::boost::shared_ptr<librdf_TypeConverter::Node> const pContent(
+ m_TypeConverter.extractNode_NoLock(xContent));
+ ::std::vector< ::boost::shared_ptr<librdf_TypeConverter::Resource> >
+ predicates;
+ ::std::transform(i_rPredicates.begin(), i_rPredicates.end(),
+ ::std::back_inserter(predicates),
+ ::boost::bind(&librdf_TypeConverter::extractResource_NoLock,
+ m_TypeConverter, _1));
+
+ removeStatementRDFa(i_xObject); // not atomic with insertion?
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
if (i_rRDFaContent.isEmpty()) {
m_RDFaXHTMLContentSet.erase(sXmlId);
} else {
m_RDFaXHTMLContentSet.insert(sXmlId);
}
- ::std::for_each(i_rPredicates.begin(), i_rPredicates.end(),
- ::boost::bind( &librdf_Repository::addStatementGraph,
- this, i_xSubject, _1, xContent, xXmlId, true));
+ for (::std::vector< ::boost::shared_ptr<librdf_TypeConverter::Resource> >
+ ::iterator iter = predicates.begin(); iter != predicates.end();
+ ++iter)
+ {
+ addStatementGraph_Lock(
+ librdf_TypeConverter::Statement(pSubject,
+ ::boost::dynamic_pointer_cast<librdf_TypeConverter::URI>(*iter),
+ pContent),
+ sContext, true);
+ }
}
void SAL_CALL librdf_Repository::removeStatementRDFa(
@@ -1512,20 +1614,11 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
return; // nothing to do...
}
- uno::Reference<rdf::XURI> xXmlId;
- try {
- xXmlId.set( rdf::URI::create(m_xContext,
- OUString::createFromAscii(s_nsOOo)
- + mdref.First + "#"
- + mdref.Second),
- uno::UNO_QUERY_THROW);
- } catch (const lang::IllegalArgumentException & iae) {
- throw lang::WrappedTargetRuntimeException(
- "librdf_Repository::removeStatementRDFa: "
- "cannot create URI for XML ID", *this, uno::makeAny(iae));
- }
- // clearGraph does locking, not needed here
- clearGraph(xXmlId, true);
+
+ OUString const sXmlId(
+ OUString::createFromAscii(s_nsOOo) + mdref.First + "#" + mdref.Second);
+
+ clearGraph_NoLock(sXmlId, true);
}
beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
@@ -1554,10 +1647,9 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
"cannot create URI for XML ID", *this, uno::makeAny(iae));
}
- ::osl::MutexGuard g(m_aMutex);
::comphelper::SequenceAsVector< rdf::Statement > ret;
const uno::Reference<container::XEnumeration> xIter(
- getStatementsGraph(0, 0, 0, xXmlId, true) );
+ getStatementsGraph_NoLock(0, 0, 0, xXmlId, true) );
OSL_ENSURE(xIter.is(), "getStatementRDFa: no result?");
if (!xIter.is()) throw uno::RuntimeException();
while (xIter->hasMoreElements()) {
@@ -1568,6 +1660,9 @@ throw (uno::RuntimeException, lang::IllegalArgumentException,
ret.push_back(stmt);
}
}
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >(
ret.getAsConstList(), 0 != m_RDFaXHTMLContentSet.count(sXmlId));
}
@@ -1608,10 +1703,14 @@ throw (uno::RuntimeException, rdf::RepositoryException)
::boost::shared_ptr<librdf_node>());
}
- ::osl::MutexGuard g(m_aMutex);
+ librdf_TypeConverter::Statement const stmt(
+ m_TypeConverter.extractStatement_NoLock(
+ i_xSubject, i_xPredicate, i_xObject));
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
const boost::shared_ptr<librdf_statement> pStatement(
- m_TypeConverter.mkStatement(m_pWorld.get(),
- i_xSubject, i_xPredicate, i_xObject),
+ m_TypeConverter.mkStatement_Lock(m_pWorld.get(), stmt),
safe_librdf_free_statement);
OSL_ENSURE(pStatement, "mkStatement failed");
@@ -1645,31 +1744,34 @@ throw (uno::RuntimeException, uno::Exception)
::osl::MutexGuard g(m_aMutex);
// m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world);
- m_pStorage.reset(m_TypeConverter.createStorage(m_pWorld.get()),
+ m_pStorage.reset(m_TypeConverter.createStorage_Lock(m_pWorld.get()),
safe_librdf_free_storage);
- m_pModel.reset(m_TypeConverter.createModel(
+ m_pModel.reset(m_TypeConverter.createModel_Lock(
m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model);
}
-const NamedGraphMap_t::iterator SAL_CALL librdf_Repository::clearGraph(
- const uno::Reference< rdf::XURI > & i_xGraphName, bool i_Internal)
+const NamedGraphMap_t::iterator librdf_Repository::clearGraph_NoLock(
+ OUString const& i_rGraphName, bool i_Internal)
// throw (uno::RuntimeException, container::NoSuchElementException,
// rdf::RepositoryException)
{
- if (!i_xGraphName.is()) {
- throw lang::IllegalArgumentException(
- "librdf_Repository::clearGraph: URI is null", *this, 0);
- }
::osl::MutexGuard g(m_aMutex);
- const OUString contextU( i_xGraphName->getStringValue() );
- const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) );
+
+ return clearGraph_Lock(i_rGraphName, i_Internal);
+}
+
+const NamedGraphMap_t::iterator librdf_Repository::clearGraph_Lock(
+ OUString const& i_rGraphName, bool i_Internal)
+{
+ // internal: must be called with mutex locked!
+ const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(i_rGraphName) );
if (!i_Internal && iter == m_NamedGraphs.end()) {
throw container::NoSuchElementException(
"librdf_Repository::clearGraph: "
"no graph with given URI exists", *this);
}
const OString context(
- OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
+ OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
const boost::shared_ptr<librdf_node> pContext(
librdf_new_node_from_uri_string(m_pWorld.get(),
@@ -1689,7 +1791,7 @@ const NamedGraphMap_t::iterator SAL_CALL librdf_Repository::clearGraph(
return iter;
}
-void librdf_Repository::addStatementGraph(
+void librdf_Repository::addStatementGraph_NoLock(
const uno::Reference< rdf::XResource > & i_xSubject,
const uno::Reference< rdf::XURI > & i_xPredicate,
const uno::Reference< rdf::XNode > & i_xObject,
@@ -1712,15 +1814,31 @@ void librdf_Repository::addStatementGraph(
"librdf_Repository::addStatement: Object is null", *this, 2);
}
- ::osl::MutexGuard g(m_aMutex);
+ librdf_TypeConverter::Statement const stmt(
+ m_TypeConverter.extractStatement_NoLock(
+ i_xSubject, i_xPredicate, i_xObject));
+
const OUString contextU( i_xGraphName->getStringValue() );
- if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) {
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
+ addStatementGraph_Lock(stmt, contextU, i_Internal);
+}
+
+void librdf_Repository::addStatementGraph_Lock(
+ librdf_TypeConverter::Statement const& i_rStatement,
+ OUString const& i_rGraphName,
+ bool i_Internal)
+{
+ if (!i_Internal
+ && (m_NamedGraphs.find(i_rGraphName) == m_NamedGraphs.end()))
+ {
throw container::NoSuchElementException(
"librdf_Repository::addStatement: "
"no graph with given URI exists", *this);
}
const OString context(
- OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
+ OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
const boost::shared_ptr<librdf_node> pContext(
librdf_new_node_from_uri_string(m_pWorld.get(),
@@ -1732,8 +1850,7 @@ void librdf_Repository::addStatementGraph(
"librdf_new_node_from_uri_string failed", *this);
}
const boost::shared_ptr<librdf_statement> pStatement(
- m_TypeConverter.mkStatement(m_pWorld.get(),
- i_xSubject, i_xPredicate, i_xObject),
+ m_TypeConverter.mkStatement_Lock(m_pWorld.get(), i_rStatement),
safe_librdf_free_statement);
OSL_ENSURE(pStatement, "mkStatement failed");
@@ -1757,7 +1874,7 @@ void librdf_Repository::addStatementGraph(
}
}
-void librdf_Repository::removeStatementsGraph(
+void librdf_Repository::removeStatementsGraph_NoLock(
const uno::Reference< rdf::XResource > & i_xSubject,
const uno::Reference< rdf::XURI > & i_xPredicate,
const uno::Reference< rdf::XNode > & i_xObject,
@@ -1772,8 +1889,13 @@ void librdf_Repository::removeStatementsGraph(
return;
}
- ::osl::MutexGuard g(m_aMutex);
+ librdf_TypeConverter::Statement const stmt(
+ m_TypeConverter.extractStatement_NoLock(
+ i_xSubject, i_xPredicate, i_xObject));
const OUString contextU( i_xGraphName->getStringValue() );
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
throw container::NoSuchElementException(
"librdf_Repository::removeStatements: "
@@ -1792,8 +1914,7 @@ void librdf_Repository::removeStatementsGraph(
"librdf_new_node_from_uri_string failed", *this);
}
const boost::shared_ptr<librdf_statement> pStatement(
- m_TypeConverter.mkStatement(m_pWorld.get(),
- i_xSubject, i_xPredicate, i_xObject),
+ m_TypeConverter.mkStatement_Lock(m_pWorld.get(), stmt),
safe_librdf_free_statement);
OSL_ENSURE(pStatement, "mkStatement failed");
@@ -1826,7 +1947,7 @@ void librdf_Repository::removeStatementsGraph(
}
uno::Reference< container::XEnumeration >
-librdf_Repository::getStatementsGraph(
+librdf_Repository::getStatementsGraph_NoLock(
const uno::Reference< rdf::XResource > & i_xSubject,
const uno::Reference< rdf::XURI > & i_xPredicate,
const uno::Reference< rdf::XNode > & i_xObject,
@@ -1848,8 +1969,13 @@ librdf_Repository::getStatementsGraph(
::boost::shared_ptr<librdf_node>());
}
- ::osl::MutexGuard g(m_aMutex);
+ librdf_TypeConverter::Statement const stmt(
+ m_TypeConverter.extractStatement_NoLock(
+ i_xSubject, i_xPredicate, i_xObject));
const OUString contextU( i_xGraphName->getStringValue() );
+
+ ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked //////
+
if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) {
throw container::NoSuchElementException(
"librdf_Repository::getStatements: "
@@ -1868,8 +1994,7 @@ librdf_Repository::getStatementsGraph(
"librdf_new_node_from_uri_string failed", *this);
}
const boost::shared_ptr<librdf_statement> pStatement(
- m_TypeConverter.mkStatement(m_pWorld.get(),
- i_xSubject, i_xPredicate, i_xObject),
+ m_TypeConverter.mkStatement_Lock(m_pWorld.get(), stmt),
safe_librdf_free_statement);
OSL_ENSURE(pStatement, "mkStatement failed");
@@ -1898,7 +2023,7 @@ void librdf_raptor_init(void* /*user_data*/, raptor_world* pRaptorWorld)
RAPTOR_WORLD_FLAG_LIBXML_GENERIC_ERROR_SAVE, 0);
}
-librdf_world *librdf_TypeConverter::createWorld() const
+librdf_world *librdf_TypeConverter::createWorld_Lock() const
{
// create and initialize world
librdf_world *pWorld( librdf_new_world() );
@@ -1922,7 +2047,7 @@ librdf_world *librdf_TypeConverter::createWorld() const
}
librdf_storage *
-librdf_TypeConverter::createStorage(librdf_world *i_pWorld) const
+librdf_TypeConverter::createStorage_Lock(librdf_world *i_pWorld) const
{
librdf_storage *pStorage(
// librdf_new_storage(i_pWorld, "memory", NULL, "contexts='yes'") );
@@ -1936,7 +2061,7 @@ librdf_TypeConverter::createStorage(librdf_world *i_pWorld) const
return pStorage;
}
-librdf_model *librdf_TypeConverter::createModel(
+librdf_model *librdf_TypeConverter::createModel_Lock(
librdf_world *i_pWorld, librdf_storage * i_pStorage) const
{
librdf_model *pRepository( librdf_new_model(i_pWorld, i_pStorage, NULL) );
@@ -1964,14 +2089,11 @@ librdf_model *librdf_TypeConverter::createModel(
}
// this does NOT create a node, only URI
-librdf_uri* librdf_TypeConverter::mkURI( librdf_world* i_pWorld,
- const uno::Reference< rdf::XURI > & i_xURI) const
+librdf_uri* librdf_TypeConverter::mkURI_Lock( librdf_world* i_pWorld,
+ OString const& i_rURI) const
{
- const OString uri(
- OUStringToOString(i_xURI->getStringValue(),
- RTL_TEXTENCODING_UTF8) );
librdf_uri *pURI( librdf_new_uri(i_pWorld,
- reinterpret_cast<const unsigned char *>(uri.getStr())));
+ reinterpret_cast<const unsigned char *>(i_rURI.getStr())));
if (!pURI) {
throw uno::RuntimeException(
"librdf_TypeConverter::mkURI: librdf_new_uri failed", 0);
@@ -1979,8 +2101,9 @@ librdf_uri* librdf_TypeConverter::mkURI( librdf_world* i_pWorld,
return pURI;
}
-// create blank or URI node
-librdf_node* librdf_TypeConverter::mkResource( librdf_world* i_pWorld,
+// extract blank or URI node - call without Mutex locked
+::boost::shared_ptr<librdf_TypeConverter::Resource>
+librdf_TypeConverter::extractResource_NoLock(
const uno::Reference< rdf::XResource > & i_xResource) const
{
if (!i_xResource.is()) return 0;
@@ -1989,9 +2112,27 @@ librdf_node* librdf_TypeConverter::mkResource( librdf_world* i_pWorld,
const OString label(
OUStringToOString(xBlankNode->getStringValue(),
RTL_TEXTENCODING_UTF8) );
+ return ::boost::shared_ptr<Resource>(new BlankNode(label));
+ } else { // assumption: everything else is URI
+ const OString uri(
+ OUStringToOString(i_xResource->getStringValue(),
+ RTL_TEXTENCODING_UTF8) );
+ return ::boost::shared_ptr<Resource>(new URI(uri));
+ }
+}
+
+// create blank or URI node
+librdf_node* librdf_TypeConverter::mkResource_Lock( librdf_world* i_pWorld,
+ Resource const*const i_pResource) const
+{
+ if (!i_pResource) return 0;
+ BlankNode const*const pBlankNode(
+ dynamic_cast<BlankNode const*>(i_pResource));
+ if (pBlankNode) {
librdf_node *pNode(
librdf_new_node_from_blank_identifier(i_pWorld,
- reinterpret_cast<const unsigned char*> (label.getStr())));
+ reinterpret_cast<const unsigned char*>(
+ pBlankNode->value.getStr())));
if (!pNode) {
throw uno::RuntimeException(
"librdf_TypeConverter::mkResource: "
@@ -1999,12 +2140,11 @@ librdf_node* librdf_TypeConverter::mkResource( librdf_world* i_pWorld,
}
return pNode;
} else { // assumption: everything else is URI
- const OString uri(
- OUStringToOString(i_xResource->getStringValue(),
- RTL_TEXTENCODING_UTF8) );
+ URI const*const pURI(dynamic_cast<URI const*>(i_pResource));
+ assert(pURI);
librdf_node *pNode(
librdf_new_node_from_uri_string(i_pWorld,
- reinterpret_cast<const unsigned char*> (uri.getStr())));
+ reinterpret_cast<const unsigned char*>(pURI->value.getStr())));
if (!pNode) {
throw uno::RuntimeException(
"librdf_TypeConverter::mkResource: "
@@ -2014,14 +2154,15 @@ librdf_node* librdf_TypeConverter::mkResource( librdf_world* i_pWorld,
}
}
-// create blank or URI or literal node
-librdf_node* librdf_TypeConverter::mkNode( librdf_world* i_pWorld,
+// extract blank or URI or literal node - call without Mutex locked
+::boost::shared_ptr<librdf_TypeConverter::Node>
+librdf_TypeConverter::extractNode_NoLock(
const uno::Reference< rdf::XNode > & i_xNode) const
{
if (!i_xNode.is()) return 0;
uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
if (xResource.is()) {
- return mkResource(i_pWorld, xResource);
+ return extractResource_NoLock(xResource);
}
uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
OSL_ENSURE(xLiteral.is(),
@@ -2034,25 +2175,46 @@ librdf_node* librdf_TypeConverter::mkNode( librdf_world* i_pWorld,
OUStringToOString(xLiteral->getLanguage(),
RTL_TEXTENCODING_UTF8) );
const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
+ boost::optional<OString> type;
+ if (xType.is())
+ {
+ type =
+ OUStringToOString(xType->getStringValue(), RTL_TEXTENCODING_UTF8);
+ }
+ return ::boost::shared_ptr<Node>(new Literal(val, lang, type));
+}
+
+// create blank or URI or literal node
+librdf_node* librdf_TypeConverter::mkNode_Lock( librdf_world* i_pWorld,
+ Node const*const i_pNode) const
+{
+ if (!i_pNode) return 0;
+ Resource const*const pResource(dynamic_cast<Resource const*>(i_pNode));
+ if (pResource) {
+ return mkResource_Lock(i_pWorld, pResource);
+ }
+
+ Literal const*const pLiteral(dynamic_cast<Literal const*>(i_pNode));
+ assert(pLiteral);
librdf_node * ret(0);
- if (lang.isEmpty()) {
- if (!xType.is()) {
+ if (pLiteral->language.isEmpty()) {
+ if (!pLiteral->type) {
ret = librdf_new_node_from_literal(i_pWorld,
- reinterpret_cast<const unsigned char*> (val.getStr()),
- NULL, 0);
+ reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
+ , NULL, 0);
} else {
const boost::shared_ptr<librdf_uri> pDatatype(
- mkURI(i_pWorld, xType), safe_librdf_free_uri);
+ mkURI_Lock(i_pWorld, *pLiteral->type),
+ safe_librdf_free_uri);
ret = librdf_new_node_from_typed_literal(i_pWorld,
- reinterpret_cast<const unsigned char*> (val.getStr()),
- NULL, pDatatype.get());
+ reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
+ , NULL, pDatatype.get());
}
} else {
- if (!xType.is()) {
+ if (!pLiteral->type) {
ret = librdf_new_node_from_literal(i_pWorld,
- reinterpret_cast<const unsigned char*> (val.getStr()),
- (lang.getStr()), 0);
-
+ reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
+ , pLiteral->language.getStr(), 0);
} else {
OSL_FAIL("mkNode: invalid literal");
return 0;
@@ -2065,20 +2227,33 @@ librdf_node* librdf_TypeConverter::mkNode( librdf_world* i_pWorld,
return ret;
}
-librdf_statement* librdf_TypeConverter::mkStatement( librdf_world* i_pWorld,
+// extract statement - call without Mutex locked
+librdf_TypeConverter::Statement librdf_TypeConverter::extractStatement_NoLock(
const uno::Reference< rdf::XResource > & i_xSubject,
const uno::Reference< rdf::XURI > & i_xPredicate,
const uno::Reference< rdf::XNode > & i_xObject) const
{
- librdf_node* pSubject( mkResource(i_pWorld, i_xSubject) );
+ ::boost::shared_ptr<Resource> const pSubject(
+ extractResource_NoLock(i_xSubject));
+ const uno::Reference<rdf::XResource> xPredicate(i_xPredicate,
+ uno::UNO_QUERY);
+ ::boost::shared_ptr<URI> const pPredicate(
+ ::boost::dynamic_pointer_cast<URI>(extractResource_NoLock(xPredicate)));
+ ::boost::shared_ptr<Node> const pObject(extractNode_NoLock(i_xObject));
+ return Statement(pSubject, pPredicate, pObject);
+}
+
+librdf_statement* librdf_TypeConverter::mkStatement_Lock(librdf_world* i_pWorld,
+ Statement const& i_rStatement) const
+{
+ librdf_node *const pSubject(
+ mkResource_Lock(i_pWorld, i_rStatement.pSubject.get()) );
librdf_node* pPredicate(0);
librdf_node* pObject(0);
try {
- const uno::Reference<rdf::XResource> xPredicate(i_xPredicate,
- uno::UNO_QUERY);
- pPredicate = mkResource(i_pWorld, xPredicate);
+ pPredicate = mkResource_Lock(i_pWorld, i_rStatement.pPredicate.get());
try {
- pObject = mkNode(i_pWorld, i_xObject);
+ pObject = mkNode_Lock(i_pWorld, i_rStatement.pObject.get());
} catch (...) {
safe_librdf_free_node(pPredicate);
throw;