Index: configure.in =================================================================== --- configure.in (Revision 277995) +++ configure.in (Arbeitskopie) @@ -528,6 +528,9 @@ AC_ARG_WITH(system-lpsolve, [ --with-system-lpsolve Use lpsolve already on system ],,) +AC_ARG_WITH(system-redland, +[ --with-system-redland Use redland library already on system +],,) AC_ARG_WITH(system-mozilla, [ --with-system-mozilla Use mozilla already on system. Note that some components cannot be built against a contemporary @@ -4889,16 +4892,12 @@ dnl Check for system redland dnl =================================================================== AC_MSG_CHECKING([which redland library to use]) -dnl if test -n "$with_system_redland" -o -n "$with_system_libs" && \ -dnl test "$with_system_redland" != "no"; then -dnl mst: NOTE: right now we need patches against redland -dnl so we only enable system redland if explicitly requested -dnl if next version includes patches, insert version check here -if test -n "$with_system_redland" && \ +if test -n "$with_system_redland" -o -n "$with_system_libs" && \ test "$with_system_redland" != "no"; then AC_MSG_RESULT([external]) SYSTEM_REDLAND=YES - PKG_CHECK_MODULES(REDLAND, redland) + dnl versions before 1.0.8 write RDF/XML that is useless for ODF (@xml:base) + PKG_CHECK_MODULES(REDLAND, redland >= 1.0.8) else AC_MSG_RESULT([internal]) BUILD_TYPE="$BUILD_TYPE REDLAND" Index: redland/redland/makefile.mk =================================================================== --- redland/redland/makefile.mk (Revision 278035) +++ redland/redland/makefile.mk (Arbeitskopie) @@ -62,9 +62,6 @@ PATCH_FILES=$(OOO_PATCH_FILES) \ - $(TARFILE_NAME).patch.free_null \ - $(TARFILE_NAME).patch.storage_hashes_context_serialize_get_statement \ - $(TARFILE_NAME).patch.storage_hashes_list_duplicates \ .IF "$(OS)"=="OS2" Index: redland/README =================================================================== --- redland/README (Revision 278035) +++ redland/README (Arbeitskopie) @@ -22,7 +22,8 @@ Patches: There are several patches, most of which contain only hacks to get it to build with OOo build system. -There are also 3 patches that fix bugs in redland and are of general interest: +There used to be also 3 patches here that fix bugs in redland and ought to be +of general interest: - redland-1.0.8.patch.free_null: redland destructor functions don't check if argument is NULL - redland-1.0.8.patch.storage_hashes_context_serialize_get_statement: @@ -31,4 +32,7 @@ - redland-1.0.8.patch.storage_hashes_list_duplicates: hashes, list storage: if contexts are enabled, then it is possible to add duplicate statements +Attempts to upstream these patches failed for reasons upstream kept to +themselves. Now these patches are replaced with workarounds in unoxml. +Note to future maintainers: work around redland bugs in client code. Index: unoxml/source/rdf/librdf_repository.cxx =================================================================== --- unoxml/source/rdf/librdf_repository.cxx (Revision 277995) +++ unoxml/source/rdf/librdf_repository.cxx (Arbeitskopie) @@ -128,6 +128,56 @@ //////////////////////////////////////////////////////////////////////////// +// n.b.: librdf destructor functions dereference null pointers! +// so they need to be wrapped to be usable with boost::shared_ptr. +static void safe_librdf_free_world(librdf_world *const world) +{ + if (world) { librdf_free_world(world); } +} +static void safe_librdf_free_model(librdf_model *const model) +{ + if (model) { librdf_free_model(model); } +} +static void safe_librdf_free_node(librdf_node* node) +{ + if (node) { librdf_free_node(node); } +} +static void safe_librdf_free_parser(librdf_parser *const parser) +{ + if (parser) { librdf_free_parser(parser); } +} +static void safe_librdf_free_query(librdf_query *const query) +{ + if (query) { librdf_free_query(query); } +} +static void +safe_librdf_free_query_results(librdf_query_results *const query_results) +{ + if (query_results) { librdf_free_query_results(query_results); } +} +static void safe_librdf_free_serializer(librdf_serializer *const serializer) +{ + if (serializer) { librdf_free_serializer(serializer); } +} +static void safe_librdf_free_statement(librdf_statement *const statement) +{ + if (statement) { librdf_free_statement(statement); } +} +static void safe_librdf_free_storage(librdf_storage *const storage) +{ + if (storage) { librdf_free_storage(storage); } +} +static void safe_librdf_free_stream(librdf_stream *const stream) +{ + if (stream) { librdf_free_stream(stream); } +} +static void safe_librdf_free_uri(librdf_uri *const uri) +{ + if (uri) { librdf_free_uri(uri); } +} + +//////////////////////////////////////////////////////////////////////////// + #if 0 class librdf_Statement: public ::cppu::WeakImplHelper1< @@ -425,11 +475,13 @@ librdf_GraphResult(librdf_Repository *i_pRepository, ::osl::Mutex & i_rMutex, boost::shared_ptr const& i_pStream, + boost::shared_ptr const& i_pContext, boost::shared_ptr const& i_pQuery = boost::shared_ptr() ) : m_xRep(i_pRepository) , m_rMutex(i_rMutex) , m_pQuery(i_pQuery) + , m_pContext(i_pContext) , m_pStream(i_pStream) { }; @@ -452,8 +504,11 @@ // the query (in case this is a result of a graph query) // 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 m_pQuery; - boost::shared_ptr m_pStream; + boost::shared_ptr const m_pQuery; + boost::shared_ptr const m_pContext; + boost::shared_ptr const m_pStream; + + librdf_node* getContext() const; }; @@ -465,6 +520,17 @@ return m_pStream.get() && !librdf_stream_end(m_pStream.get()); } +librdf_node* librdf_GraphResult::getContext() const +{ + if (!m_pStream.get() || librdf_stream_end(m_pStream.get())) + return NULL; + librdf_node *pCtxt( static_cast + (librdf_stream_get_context(m_pStream.get())) ); + if (pCtxt) + return pCtxt; + return m_pContext.get(); +} + ::com::sun::star::uno::Any SAL_CALL librdf_GraphResult::nextElement() throw (uno::RuntimeException, container::NoSuchElementException, @@ -472,8 +538,8 @@ { ::osl::MutexGuard g(m_rMutex); if (!m_pStream.get() || !librdf_stream_end(m_pStream.get())) { - librdf_node *pCtxt( static_cast - (librdf_stream_get_context(m_pStream.get())) ); + librdf_node * pCtxt = getContext(); + librdf_statement *pStmt( librdf_stream_get_object(m_pStream.get()) ); if (!pStmt) { rdf::QueryException e(::rtl::OUString::createFromAscii( @@ -568,7 +634,7 @@ void operator() (librdf_node** io_pArray) const throw () { - std::for_each(io_pArray, io_pArray + m_Count, librdf_free_node); + std::for_each(io_pArray, io_pArray + m_Count, safe_librdf_free_node); delete[] io_pArray; } }; @@ -781,9 +847,9 @@ librdf_Repository::librdf_Repository( uno::Reference< uno::XComponentContext > const & i_xContext) : /*BaseMutex(),*/ m_xContext(i_xContext) -// m_pWorld (static_cast(0), librdf_free_world ), - , m_pStorage(static_cast(0), librdf_free_storage) - , m_pModel (static_cast(0), librdf_free_model ) +// m_pWorld (static_cast(0), safe_librdf_free_world ), + , m_pStorage(static_cast(0), safe_librdf_free_storage) + , m_pModel (static_cast(0), safe_librdf_free_model ) , m_NamedGraphs() , m_TypeConverter(i_xContext, *this) { @@ -791,7 +857,7 @@ ::osl::MutexGuard g(m_aMutex); if (!m_NumInstances++) { - m_pWorld.reset(m_TypeConverter.createWorld(), librdf_free_world); + m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world); } } @@ -844,7 +910,7 @@ ::osl::MutexGuard g(m_aMutex); const boost::shared_ptr pNode( librdf_new_node_from_blank_identifier(m_pWorld.get(), NULL), - librdf_free_node); + safe_librdf_free_node); if (!pNode) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::createBlankNode: " @@ -933,7 +999,7 @@ const boost::shared_ptr pContext( librdf_new_node_from_uri_string(m_pWorld.get(), reinterpret_cast (context.getStr())), - librdf_free_node); + safe_librdf_free_node); if (!pContext) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::importGraph: " @@ -945,7 +1011,7 @@ const boost::shared_ptr pBaseURI( librdf_new_uri(m_pWorld.get(), reinterpret_cast (baseURI.getStr())), - librdf_free_uri); + safe_librdf_free_uri); if (!pBaseURI) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::importGraph: " @@ -954,7 +1020,7 @@ const boost::shared_ptr pParser( librdf_new_parser(m_pWorld.get(), "rdfxml", NULL, NULL), - librdf_free_parser); + safe_librdf_free_parser); if (!pParser) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::importGraph: " @@ -971,7 +1037,7 @@ librdf_parser_parse_counted_string_as_stream(pParser.get(), reinterpret_cast(buf.getConstArray()), buf.getLength(), pBaseURI.get()), - librdf_free_stream); + safe_librdf_free_stream); if (!pStream) { throw rdf::ParseException(::rtl::OUString::createFromAscii( "librdf_Repository::importGraph: " @@ -1040,7 +1106,7 @@ const boost::shared_ptr pContext( librdf_new_node_from_uri_string(m_pWorld.get(), reinterpret_cast (context.getStr())), - librdf_free_node); + safe_librdf_free_node); if (!pContext) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::exportGraph: " @@ -1051,7 +1117,7 @@ const boost::shared_ptr pBaseURI( librdf_new_uri(m_pWorld.get(), reinterpret_cast (baseURI.getStr())), - librdf_free_uri); + safe_librdf_free_uri); if (!pBaseURI) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::exportGraph: " @@ -1060,7 +1126,7 @@ const boost::shared_ptr pStream( librdf_model_context_as_stream(m_pModel.get(), pContext.get()), - librdf_free_stream); + safe_librdf_free_stream); if (!pStream) { throw rdf::RepositoryException(::rtl::OUString::createFromAscii( "librdf_Repository::exportGraph: " @@ -1070,7 +1136,7 @@ const char *format("rdfxml-abbrev"); const boost::shared_ptr pSerializer( librdf_new_serializer(m_pWorld.get(), format, NULL, NULL), - librdf_free_serializer); + safe_librdf_free_serializer); if (!pSerializer) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::exportGraph: " @@ -1080,19 +1146,19 @@ const boost::shared_ptr pRelativeURI( librdf_new_uri(m_pWorld.get(), reinterpret_cast ("http://feature.librdf.org/raptor-relativeURIs")), - librdf_free_uri); + safe_librdf_free_uri); const boost::shared_ptr pWriteBaseURI( librdf_new_uri(m_pWorld.get(), reinterpret_cast ("http://feature.librdf.org/raptor-writeBaseURI")), - librdf_free_uri); + safe_librdf_free_uri); const boost::shared_ptr p0( librdf_new_node_from_literal(m_pWorld.get(), reinterpret_cast ("0"), NULL, 0), - librdf_free_node); + safe_librdf_free_node); const boost::shared_ptr p1( librdf_new_node_from_literal(m_pWorld.get(), reinterpret_cast ("1"), NULL, 0), - librdf_free_node); + safe_librdf_free_node); if (!pWriteBaseURI || !pRelativeURI || !p0 || !p1) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::exportGraph: " @@ -1228,26 +1294,28 @@ isMetadatableWithoutMetadata(i_xObject)) { return new librdf_GraphResult(this, m_aMutex, - ::boost::shared_ptr()); + ::boost::shared_ptr(), + ::boost::shared_ptr()); } ::osl::MutexGuard g(m_aMutex); const boost::shared_ptr pStatement( m_TypeConverter.mkStatement(m_pWorld.get(), i_xSubject, i_xPredicate, i_xObject), - librdf_free_statement); + safe_librdf_free_statement); OSL_ENSURE(pStatement, "mkStatement failed"); const boost::shared_ptr pStream( librdf_model_find_statements(m_pModel.get(), pStatement.get()), - librdf_free_stream); + safe_librdf_free_stream); if (!pStream) { throw rdf::RepositoryException(::rtl::OUString::createFromAscii( "librdf_Repository::getStatements: " "librdf_model_find_statements failed"), *this); } - return new librdf_GraphResult(this, m_aMutex, pStream); + return new librdf_GraphResult(this, m_aMutex, pStream, + ::boost::shared_ptr()); } @@ -1261,7 +1329,7 @@ const boost::shared_ptr pQuery( librdf_new_query(m_pWorld.get(), s_sparql, NULL, reinterpret_cast (query.getStr()), NULL), - librdf_free_query); + safe_librdf_free_query); if (!pQuery) { throw rdf::QueryException(::rtl::OUString::createFromAscii( "librdf_Repository::querySelect: " @@ -1269,7 +1337,7 @@ } const boost::shared_ptr pResults( librdf_model_query_execute(m_pModel.get(), pQuery.get()), - librdf_free_query_results); + safe_librdf_free_query_results); if (!pResults || !librdf_query_results_is_bindings(pResults.get())) { throw rdf::QueryException(::rtl::OUString::createFromAscii( "librdf_Repository::querySelect: " @@ -1311,7 +1379,7 @@ const boost::shared_ptr pQuery( librdf_new_query(m_pWorld.get(), s_sparql, NULL, reinterpret_cast (query.getStr()), NULL), - librdf_free_query); + safe_librdf_free_query); if (!pQuery) { throw rdf::QueryException(::rtl::OUString::createFromAscii( "librdf_Repository::queryConstruct: " @@ -1319,7 +1387,7 @@ } const boost::shared_ptr pResults( librdf_model_query_execute(m_pModel.get(), pQuery.get()), - librdf_free_query_results); + safe_librdf_free_query_results); if (!pResults || !librdf_query_results_is_graph(pResults.get())) { throw rdf::QueryException(::rtl::OUString::createFromAscii( "librdf_Repository::queryConstruct: " @@ -1327,14 +1395,15 @@ } const boost::shared_ptr pStream( librdf_query_results_as_stream(pResults.get()), - librdf_free_stream); + safe_librdf_free_stream); if (!pStream) { throw rdf::QueryException(::rtl::OUString::createFromAscii( "librdf_Repository::queryConstruct: " "librdf_query_results_as_stream failed"), *this); } - return new librdf_GraphResult(this, m_aMutex, pStream, pQuery); + return new librdf_GraphResult(this, m_aMutex, pStream, + ::boost::shared_ptr(), pQuery); } ::sal_Bool SAL_CALL @@ -1348,7 +1417,7 @@ const boost::shared_ptr pQuery( librdf_new_query(m_pWorld.get(), s_sparql, NULL, reinterpret_cast (query.getStr()), NULL), - librdf_free_query); + safe_librdf_free_query); if (!pQuery) { throw rdf::QueryException(::rtl::OUString::createFromAscii( "librdf_Repository::queryAsk: " @@ -1356,7 +1425,7 @@ } const boost::shared_ptr pResults( librdf_model_query_execute(m_pModel.get(), pQuery.get()), - librdf_free_query_results); + safe_librdf_free_query_results); if (!pResults || !librdf_query_results_is_boolean(pResults.get())) { throw rdf::QueryException(::rtl::OUString::createFromAscii( "librdf_Repository::queryAsk: " @@ -1611,19 +1680,20 @@ isMetadatableWithoutMetadata(i_xObject)) { return new librdf_GraphResult(this, m_aMutex, - ::boost::shared_ptr()); + ::boost::shared_ptr(), + ::boost::shared_ptr()); } ::osl::MutexGuard g(m_aMutex); const boost::shared_ptr pStatement( m_TypeConverter.mkStatement(m_pWorld.get(), i_xSubject, i_xPredicate, i_xObject), - librdf_free_statement); + safe_librdf_free_statement); OSL_ENSURE(pStatement, "mkStatement failed"); const boost::shared_ptr pStream( librdf_model_find_statements(m_pModel.get(), pStatement.get()), - librdf_free_stream); + safe_librdf_free_stream); if (!pStream) { throw rdf::RepositoryException(::rtl::OUString::createFromAscii( "librdf_Repository::getStatementsRDFa: " @@ -1637,7 +1707,8 @@ "librdf_stream_add_map failed"), *this); } - return new librdf_GraphResult(this, m_aMutex, pStream); + return new librdf_GraphResult(this, m_aMutex, pStream, + ::boost::shared_ptr()); } // ::com::sun::star::lang::XInitialization: @@ -1649,11 +1720,11 @@ ::osl::MutexGuard g(m_aMutex); -// m_pWorld.reset(m_TypeConverter.createWorld(), librdf_free_world); +// m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world); m_pStorage.reset(m_TypeConverter.createStorage(m_pWorld.get()), - librdf_free_storage); + safe_librdf_free_storage); m_pModel.reset(m_TypeConverter.createModel( - m_pWorld.get(), m_pStorage.get()), librdf_free_model); + m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model); } const NamedGraphMap_t::iterator SAL_CALL librdf_Repository::clearGraph( @@ -1680,7 +1751,7 @@ const boost::shared_ptr pContext( librdf_new_node_from_uri_string(m_pWorld.get(), reinterpret_cast (context.getStr())), - librdf_free_node); + safe_librdf_free_node); if (!pContext) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::clearGraph: " @@ -1731,7 +1802,7 @@ const boost::shared_ptr pContext( librdf_new_node_from_uri_string(m_pWorld.get(), reinterpret_cast (context.getStr())), - librdf_free_node); + safe_librdf_free_node); if (!pContext) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::addStatement: " @@ -1740,8 +1811,21 @@ const boost::shared_ptr pStatement( m_TypeConverter.mkStatement(m_pWorld.get(), i_xSubject, i_xPredicate, i_xObject), - librdf_free_statement); + safe_librdf_free_statement); OSL_ENSURE(pStatement, "mkStatement failed"); + + // Test for duplicate statement + // librdf_model_add_statement disallows duplicates while + // librdf_model_context_add_statement allows duplicates + { + const boost::shared_ptr pStream( + librdf_model_find_statements_in_context(m_pModel.get(), + pStatement.get(), pContext.get()), + safe_librdf_free_stream); + if (pStream && !librdf_stream_end(pStream.get())) + return; + } + if (librdf_model_context_add_statement(m_pModel.get(), pContext.get(), pStatement.get())) { throw rdf::RepositoryException(::rtl::OUString::createFromAscii( @@ -1779,7 +1863,7 @@ const boost::shared_ptr pContext( librdf_new_node_from_uri_string(m_pWorld.get(), reinterpret_cast (context.getStr())), - librdf_free_node); + safe_librdf_free_node); if (!pContext) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::removeStatements: " @@ -1788,13 +1872,13 @@ const boost::shared_ptr pStatement( m_TypeConverter.mkStatement(m_pWorld.get(), i_xSubject, i_xPredicate, i_xObject), - librdf_free_statement); + safe_librdf_free_statement); OSL_ENSURE(pStatement, "mkStatement failed"); const boost::shared_ptr pStream( librdf_model_find_statements_in_context(m_pModel.get(), pStatement.get(), pContext.get()), - librdf_free_stream); + safe_librdf_free_stream); if (!pStream) { throw rdf::RepositoryException(::rtl::OUString::createFromAscii( "librdf_Repository::removeStatements: " @@ -1838,7 +1922,8 @@ isMetadatableWithoutMetadata(i_xObject)) { return new librdf_GraphResult(this, m_aMutex, - ::boost::shared_ptr()); + ::boost::shared_ptr(), + ::boost::shared_ptr()); } ::osl::MutexGuard g(m_aMutex); @@ -1855,7 +1940,7 @@ const boost::shared_ptr pContext( librdf_new_node_from_uri_string(m_pWorld.get(), reinterpret_cast (context.getStr())), - librdf_free_node); + safe_librdf_free_node); if (!pContext) { throw uno::RuntimeException(::rtl::OUString::createFromAscii( "librdf_Repository::getStatements: " @@ -1864,20 +1949,22 @@ const boost::shared_ptr pStatement( m_TypeConverter.mkStatement(m_pWorld.get(), i_xSubject, i_xPredicate, i_xObject), - librdf_free_statement); + safe_librdf_free_statement); OSL_ENSURE(pStatement, "mkStatement failed"); const boost::shared_ptr pStream( librdf_model_find_statements_in_context(m_pModel.get(), pStatement.get(), pContext.get()), - librdf_free_stream); + safe_librdf_free_stream); if (!pStream) { throw rdf::RepositoryException(::rtl::OUString::createFromAscii( "librdf_Repository::getStatements: " "librdf_model_find_statements_in_context failed"), *this); } - return new librdf_GraphResult(this, m_aMutex, pStream); + // librdf_model_find_statements_in_context is buggy and does not put + // the context into result statements; pass it to librdf_GraphResult here + return new librdf_GraphResult(this, m_aMutex, pStream, pContext); } librdf_world *librdf_TypeConverter::createWorld() const @@ -1929,8 +2016,8 @@ prtNode(contexts); std::cout << std::endl; // librdf_model_set_feature(repository, LIBRDF_FEATURE_CONTEXTS, ...); - librdf_free_node(contexts); - librdf_free_uri(ctxt); + safe_librdf_free_node(contexts); + safe_librdf_free_uri(ctxt); } #endif return pRepository; @@ -2015,7 +2102,7 @@ NULL, 0); } else { const boost::shared_ptr pDatatype( - mkURI(i_pWorld, xType), librdf_free_uri); + mkURI(i_pWorld, xType), safe_librdf_free_uri); ret = librdf_new_node_from_typed_literal(i_pWorld, reinterpret_cast (val.getStr()), NULL, pDatatype.get()); @@ -2054,11 +2141,11 @@ try { pObject = mkNode(i_pWorld, i_xObject); } catch (...) { - librdf_free_node(pPredicate); + safe_librdf_free_node(pPredicate); throw; } } catch (...) { - librdf_free_node(pSubject); + safe_librdf_free_node(pSubject); throw; } // NB: this takes ownership of the nodes! (which is really ugly)