/src/libreoffice/unoxml/source/rdf/librdf_repository.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <string.h> |
21 | | |
22 | | #include <map> |
23 | | #include <memory> |
24 | | #include <mutex> |
25 | | #include <set> |
26 | | #include <string_view> |
27 | | #include <iterator> |
28 | | #include <algorithm> |
29 | | #include <atomic> |
30 | | |
31 | | #include <optional> |
32 | | |
33 | | #include <libxslt/security.h> |
34 | | |
35 | | #include <redland.h> |
36 | | |
37 | | #include <com/sun/star/container/ElementExistException.hpp> |
38 | | #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp> |
39 | | #include <com/sun/star/lang/XServiceInfo.hpp> |
40 | | #include <com/sun/star/lang/XInitialization.hpp> |
41 | | #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> |
42 | | #include <com/sun/star/lang/IllegalArgumentException.hpp> |
43 | | #include <com/sun/star/io/XSeekable.hpp> |
44 | | #include <com/sun/star/text/XTextRange.hpp> |
45 | | #include <com/sun/star/rdf/ParseException.hpp> |
46 | | #include <com/sun/star/rdf/QueryException.hpp> |
47 | | #include <com/sun/star/rdf/RepositoryException.hpp> |
48 | | #include <com/sun/star/rdf/XDocumentRepository.hpp> |
49 | | #include <com/sun/star/rdf/XLiteral.hpp> |
50 | | #include <com/sun/star/rdf/FileFormat.hpp> |
51 | | #include <com/sun/star/rdf/BlankNode.hpp> |
52 | | #include <com/sun/star/rdf/URI.hpp> |
53 | | #include <com/sun/star/rdf/Literal.hpp> |
54 | | |
55 | | #include <rtl/ref.hxx> |
56 | | #include <rtl/ustrbuf.hxx> |
57 | | #include <rtl/ustring.hxx> |
58 | | #include <osl/diagnose.h> |
59 | | #include <cppuhelper/exc_hlp.hxx> |
60 | | #include <cppuhelper/implbase.hxx> |
61 | | #include <cppuhelper/supportsservice.hxx> |
62 | | #include <unotools/weakref.hxx> |
63 | | |
64 | | #include <comphelper/sequence.hxx> |
65 | | #include <comphelper/xmltools.hxx> |
66 | | |
67 | | #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp> |
68 | | #include <utility> |
69 | | |
70 | | /** |
71 | | Implementation of the service com.sun.star.rdf.Repository. |
72 | | |
73 | | This implementation uses the Redland RDF library (librdf). |
74 | | |
75 | | There are several classes involved: |
76 | | librdf_TypeConverter: helper class to convert data types redland <-> uno |
77 | | librdf_Repository: the main repository, does almost all the work |
78 | | librdf_NamedGraph: the XNamedGraph, forwards everything to repository |
79 | | librdf_GraphResult: an XEnumeration<Statement> |
80 | | librdf_QuerySelectResult: an XEnumeration<sequence<XNode>> |
81 | | |
82 | | */ |
83 | | |
84 | | /// anonymous implementation namespace |
85 | | namespace { |
86 | | |
87 | | class librdf_NamedGraph; |
88 | | class librdf_Repository; |
89 | | |
90 | | using namespace ::com::sun::star; |
91 | | |
92 | | typedef std::map< OUString, ::rtl::Reference<librdf_NamedGraph> > |
93 | | NamedGraphMap_t; |
94 | | |
95 | | const char s_sparql [] = "sparql"; |
96 | | const char s_nsOOo [] = "http://openoffice.org/2004/office/rdfa/"; |
97 | | |
98 | | |
99 | | //FIXME: this approach is not ideal. can we use blank nodes instead? |
100 | | bool isInternalContext(librdf_node *i_pNode) noexcept |
101 | 0 | { |
102 | 0 | OSL_ENSURE(i_pNode, "isInternalContext: context null"); |
103 | 0 | OSL_ENSURE(librdf_node_is_resource(i_pNode), |
104 | 0 | "isInternalContext: context not resource"); |
105 | 0 | if (i_pNode) { |
106 | 0 | librdf_uri *pURI(librdf_node_get_uri(i_pNode)); |
107 | 0 | OSL_ENSURE(pURI, "isInternalContext: URI null"); |
108 | 0 | if (pURI) { |
109 | 0 | unsigned char *pContextURI(librdf_uri_as_string(pURI)); |
110 | 0 | assert(pContextURI && "isInternalContext: URI string null"); |
111 | | // if prefix matches reserved uri, it is RDFa context |
112 | 0 | if (!strncmp(reinterpret_cast<char *>(pContextURI), |
113 | 0 | s_nsOOo, sizeof(s_nsOOo)-1)) { |
114 | 0 | return true; |
115 | 0 | } |
116 | 0 | } |
117 | 0 | return false; |
118 | 0 | } |
119 | 0 | return true; |
120 | 0 | } |
121 | | |
122 | | |
123 | | // n.b.: librdf destructor functions dereference null pointers! |
124 | | // so they need to be wrapped to be usable with std::shared_ptr. |
125 | | void safe_librdf_free_world(librdf_world *const world) |
126 | 0 | { |
127 | 0 | if (world) { librdf_free_world(world); } |
128 | 0 | } |
129 | | void safe_librdf_free_model(librdf_model *const model) |
130 | 13.4k | { |
131 | 13.4k | if (model) { librdf_free_model(model); } |
132 | 13.4k | } |
133 | | void safe_librdf_free_node(librdf_node* node) |
134 | 13.4k | { |
135 | 13.4k | if (node) { librdf_free_node(node); } |
136 | 13.4k | } |
137 | | void safe_librdf_free_parser(librdf_parser *const parser) |
138 | 0 | { |
139 | 0 | if (parser) { librdf_free_parser(parser); } |
140 | 0 | } |
141 | | void safe_librdf_free_query(librdf_query *const query) |
142 | 0 | { |
143 | 0 | if (query) { librdf_free_query(query); } |
144 | 0 | } |
145 | | void |
146 | | safe_librdf_free_query_results(librdf_query_results *const query_results) |
147 | 0 | { |
148 | 0 | if (query_results) { librdf_free_query_results(query_results); } |
149 | 0 | } |
150 | | void safe_librdf_free_serializer(librdf_serializer *const serializer) |
151 | 0 | { |
152 | 0 | if (serializer) { librdf_free_serializer(serializer); } |
153 | 0 | } |
154 | | void safe_librdf_free_statement(librdf_statement *const statement) |
155 | 13.4k | { |
156 | 13.4k | if (statement) { librdf_free_statement(statement); } |
157 | 13.4k | } |
158 | | void safe_librdf_free_storage(librdf_storage *const storage) |
159 | 13.4k | { |
160 | 13.4k | if (storage) { librdf_free_storage(storage); } |
161 | 13.4k | } |
162 | | void safe_librdf_free_stream(librdf_stream *const stream) |
163 | 13.4k | { |
164 | 13.4k | if (stream) { librdf_free_stream(stream); } |
165 | 13.4k | } |
166 | | void safe_librdf_free_uri(librdf_uri *const uri) |
167 | 0 | { |
168 | 0 | if (uri) { librdf_free_uri(uri); } |
169 | 0 | } |
170 | | |
171 | | |
172 | | /** converts between librdf types and UNO API types. |
173 | | */ |
174 | | class librdf_TypeConverter |
175 | | { |
176 | | public: |
177 | | |
178 | | // some wrapper classes to temporarily hold values of UNO XNodes |
179 | | struct Node |
180 | | { |
181 | 33.6k | virtual ~Node() {} |
182 | | }; |
183 | | struct Resource : public Node { }; |
184 | | struct URI : public Resource |
185 | | { |
186 | | OString const value; |
187 | | explicit URI(OString i_Value) |
188 | 33.6k | : value(std::move(i_Value)) |
189 | 33.6k | { } |
190 | | }; |
191 | | struct BlankNode : public Resource |
192 | | { |
193 | | OString const value; |
194 | | explicit BlankNode(OString i_Value) |
195 | 0 | : value(std::move(i_Value)) |
196 | 0 | { } |
197 | | }; |
198 | | struct Literal : public Node |
199 | | { |
200 | | OString const value; |
201 | | OString const language; |
202 | | ::std::optional<OString> const type; |
203 | | Literal(OString i_rValue, OString i_Language, |
204 | | ::std::optional<OString> i_Type) |
205 | 0 | : value(std::move(i_rValue)) |
206 | 0 | , language(std::move(i_Language)) |
207 | 0 | , type(std::move(i_Type)) |
208 | 0 | { } |
209 | | }; |
210 | | struct Statement |
211 | | { |
212 | | std::shared_ptr<Resource> const pSubject; |
213 | | std::shared_ptr<URI> const pPredicate; |
214 | | std::shared_ptr<Node> const pObject; |
215 | | Statement(std::shared_ptr<Resource> i_pSubject, |
216 | | std::shared_ptr<URI> i_pPredicate, |
217 | | std::shared_ptr<Node> i_pObject) |
218 | 13.4k | : pSubject(std::move(i_pSubject)) |
219 | 13.4k | , pPredicate(std::move(i_pPredicate)) |
220 | 13.4k | , pObject(std::move(i_pObject)) |
221 | 13.4k | { } |
222 | | }; |
223 | | |
224 | | librdf_TypeConverter( |
225 | | uno::Reference< uno::XComponentContext > i_xContext, |
226 | | librdf_Repository &i_rRep) |
227 | 6.73k | : m_xContext(std::move(i_xContext)) |
228 | 6.73k | , m_rRep(i_rRep) |
229 | 6.73k | { }; |
230 | | |
231 | | librdf_world *createWorld_Lock() const; |
232 | | librdf_storage *createStorage_Lock(librdf_world *i_pWorld) const; |
233 | | librdf_model *createModel_Lock(librdf_world *i_pWorld, |
234 | | librdf_storage * i_pStorage) const; |
235 | | static librdf_uri* mkURI_Lock(librdf_world* i_pWorld, |
236 | | const OString & i_rURI); |
237 | | static librdf_node* mkResource_Lock(librdf_world* i_pWorld, |
238 | | const Resource * i_pResource); |
239 | | static librdf_node* mkNode_Lock(librdf_world* i_pWorld, |
240 | | const Node * i_pNode); |
241 | | static librdf_statement* mkStatement_Lock(librdf_world* i_pWorld, |
242 | | Statement const& i_rStatement); |
243 | | static std::shared_ptr<Resource> extractResource_NoLock( |
244 | | const uno::Reference< rdf::XResource > & i_xResource); |
245 | | static void extractResourceToCacheKey_NoLock( |
246 | | const uno::Reference< rdf::XResource > & i_xResource, |
247 | | OUStringBuffer& rBuf); |
248 | | static std::shared_ptr<Node> extractNode_NoLock( |
249 | | const uno::Reference< rdf::XNode > & i_xNode); |
250 | | static void extractNodeToCacheKey_NoLock( |
251 | | const uno::Reference< rdf::XNode > & i_xNode, |
252 | | OUStringBuffer& rBuffer); |
253 | | static Statement extractStatement_NoLock( |
254 | | const uno::Reference< rdf::XResource > & i_xSubject, |
255 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
256 | | const uno::Reference< rdf::XNode > & i_xObject); |
257 | | uno::Reference<rdf::XURI> convertToXURI(librdf_uri* i_pURI) const; |
258 | | uno::Reference<rdf::XURI> convertToXURI(librdf_node* i_pURI) const; |
259 | | uno::Reference<rdf::XResource> |
260 | | convertToXResource(librdf_node* i_pNode) const; |
261 | | uno::Reference<rdf::XNode> convertToXNode(librdf_node* i_pNode) const; |
262 | | rdf::Statement |
263 | | convertToStatement(librdf_statement* i_pStmt, librdf_node* i_pContext) |
264 | | const; |
265 | | |
266 | | private: |
267 | | uno::Reference< uno::XComponentContext > const m_xContext; |
268 | | librdf_Repository & m_rRep; |
269 | | }; |
270 | | |
271 | | |
272 | | /** implements the repository service. |
273 | | */ |
274 | | class librdf_Repository: |
275 | | // private ::cppu::BaseMutex, |
276 | | public ::cppu::WeakImplHelper< |
277 | | lang::XServiceInfo, |
278 | | rdf::XDocumentRepository, |
279 | | lang::XInitialization> |
280 | | { |
281 | | public: |
282 | | |
283 | | explicit librdf_Repository( |
284 | | uno::Reference< uno::XComponentContext > const & i_xContext); |
285 | | virtual ~librdf_Repository() override; |
286 | | |
287 | | // css::lang::XServiceInfo: |
288 | | virtual OUString SAL_CALL getImplementationName() override; |
289 | | virtual sal_Bool SAL_CALL supportsService( |
290 | | const OUString & ServiceName) override; |
291 | | virtual uno::Sequence< OUString > SAL_CALL |
292 | | getSupportedServiceNames() override; |
293 | | |
294 | | // css::rdf::XRepository: |
295 | | virtual uno::Reference< rdf::XBlankNode > SAL_CALL createBlankNode() override; |
296 | | virtual uno::Reference<rdf::XNamedGraph> SAL_CALL importGraph( |
297 | | ::sal_Int16 i_Format, |
298 | | const uno::Reference< io::XInputStream > & i_xInStream, |
299 | | const uno::Reference< rdf::XURI > & i_xGraphName, |
300 | | const uno::Reference< rdf::XURI > & i_xBaseURI) override; |
301 | | virtual void SAL_CALL exportGraph(::sal_Int16 i_Format, |
302 | | const uno::Reference< io::XOutputStream > & i_xOutStream, |
303 | | const uno::Reference< rdf::XURI > & i_xGraphName, |
304 | | const uno::Reference< rdf::XURI > & i_xBaseURI) override; |
305 | | virtual uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL |
306 | | getGraphNames() override; |
307 | | virtual uno::Reference< rdf::XNamedGraph > SAL_CALL getGraph( |
308 | | const uno::Reference< rdf::XURI > & i_xGraphName) override; |
309 | | virtual uno::Reference< rdf::XNamedGraph > SAL_CALL createGraph( |
310 | | const uno::Reference< rdf::XURI > & i_xGraphName) override; |
311 | | virtual void SAL_CALL destroyGraph( |
312 | | const uno::Reference< rdf::XURI > & i_xGraphName) override; |
313 | | virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements( |
314 | | const uno::Reference< rdf::XResource > & i_xSubject, |
315 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
316 | | const uno::Reference< rdf::XNode > & i_xObject) override; |
317 | | virtual uno::Reference< rdf::XQuerySelectResult > SAL_CALL |
318 | | querySelect(const OUString & i_rQuery) override; |
319 | | virtual uno::Reference< container::XEnumeration > SAL_CALL |
320 | | queryConstruct(const OUString & i_rQuery) override; |
321 | | virtual sal_Bool SAL_CALL queryAsk(const OUString & i_rQuery) override; |
322 | | |
323 | | // css::rdf::XDocumentRepository: |
324 | | virtual void SAL_CALL setStatementRDFa( |
325 | | const uno::Reference< rdf::XResource > & i_xSubject, |
326 | | const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates, |
327 | | const uno::Reference< rdf::XMetadatable > & i_xObject, |
328 | | const OUString & i_rRDFaContent, |
329 | | const uno::Reference< rdf::XURI > & i_xRDFaDatatype) override; |
330 | | virtual void SAL_CALL removeStatementRDFa( |
331 | | const uno::Reference< rdf::XMetadatable > & i_xElement) override; |
332 | | virtual beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL |
333 | | getStatementRDFa(uno::Reference< rdf::XMetadatable > const& i_xElement) override; |
334 | | virtual uno::Reference< container::XEnumeration > SAL_CALL |
335 | | getStatementsRDFa( |
336 | | const uno::Reference< rdf::XResource > & i_xSubject, |
337 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
338 | | const uno::Reference< rdf::XNode > & i_xObject) override; |
339 | | |
340 | | // css::lang::XInitialization: |
341 | | virtual void SAL_CALL initialize( |
342 | | const uno::Sequence< css::uno::Any > & i_rArguments) override; |
343 | | |
344 | | // XNamedGraph forwards --------------------------------------------- |
345 | | NamedGraphMap_t::iterator clearGraph_NoLock( |
346 | | const OUString & i_rGraphName, |
347 | | bool i_Internal = false ); |
348 | | NamedGraphMap_t::iterator clearGraph_Lock( |
349 | | const OUString & i_rGraphName, |
350 | | bool i_Internal); |
351 | | void addStatementGraph_NoLock( |
352 | | const uno::Reference< rdf::XResource > & i_xSubject, |
353 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
354 | | const uno::Reference< rdf::XNode > & i_xObject, |
355 | | const uno::Reference< rdf::XURI > & i_xName ); |
356 | | // throw (uno::RuntimeException, lang::IllegalArgumentException, |
357 | | // container::NoSuchElementException, rdf::RepositoryException); |
358 | | void addStatementGraph_Lock( |
359 | | librdf_TypeConverter::Statement const& i_rStatement, |
360 | | OUString const& i_rGraphName, |
361 | | bool i_Internal); |
362 | | void removeStatementsGraph_NoLock( |
363 | | const uno::Reference< rdf::XResource > & i_xSubject, |
364 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
365 | | const uno::Reference< rdf::XNode > & i_xObject, |
366 | | const uno::Reference< rdf::XURI > & i_xName ); |
367 | | // throw (uno::RuntimeException, lang::IllegalArgumentException, |
368 | | // container::NoSuchElementException, rdf::RepositoryException); |
369 | | std::vector<rdf::Statement> getStatementsGraph_NoLock( |
370 | | const uno::Reference< rdf::XResource > & i_xSubject, |
371 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
372 | | const uno::Reference< rdf::XNode > & i_xObject, |
373 | | const uno::Reference< rdf::XURI > & i_xName, |
374 | | bool i_Internal = false ); |
375 | | // throw (uno::RuntimeException, lang::IllegalArgumentException, |
376 | | // container::NoSuchElementException, rdf::RepositoryException); |
377 | | |
378 | 0 | const librdf_TypeConverter& getTypeConverter() const { return m_TypeConverter; }; |
379 | | |
380 | | private: |
381 | | |
382 | | librdf_Repository(librdf_Repository const&) = delete; |
383 | | librdf_Repository& operator=(librdf_Repository const&) = delete; |
384 | | |
385 | | /// this is const, no need to lock m_aMutex to access it |
386 | | uno::Reference< uno::XComponentContext > const m_xContext; |
387 | | |
388 | | /// librdf global data |
389 | | /** N.B.: The redland documentation gives the impression that you can have |
390 | | as many librdf_worlds as you like. This is true in the same sense |
391 | | that you can physically be in as many places as you like. |
392 | | Well, you can, just not at the same time. |
393 | | The ugly truth is that destroying a librdf_world kills a bunch |
394 | | of static variables; other librdf_worlds become very unhappy |
395 | | when they access these. |
396 | | And of course this is not documented anywhere that I could find. |
397 | | So we allocate a single world, and refcount that. |
398 | | */ |
399 | | static std::shared_ptr<librdf_world> m_pWorld; |
400 | | /// refcount |
401 | | static sal_uInt32 m_NumInstances; |
402 | | /// mutex for m_pWorld - redland is not as threadsafe as is often claimed |
403 | | static std::mutex m_aMutex; |
404 | | |
405 | | // NB: sequence of the shared pointers is important! |
406 | | /// librdf repository storage |
407 | | std::shared_ptr<librdf_storage> m_pStorage; |
408 | | /// librdf repository model |
409 | | std::shared_ptr<librdf_model> m_pModel; |
410 | | |
411 | | /// all named graphs |
412 | | NamedGraphMap_t m_NamedGraphs; |
413 | | |
414 | | /// type conversion helper - stateless |
415 | | librdf_TypeConverter m_TypeConverter; |
416 | | |
417 | | /// set of xml:ids of elements with xhtml:content |
418 | | ::std::set< OUString > m_RDFaXHTMLContentSet; |
419 | | }; |
420 | | |
421 | | |
422 | | /** result of operations that return a graph, i.e., |
423 | | an XEnumeration of statements. |
424 | | */ |
425 | | class librdf_GraphResult: |
426 | | public ::cppu::WeakImplHelper< |
427 | | container::XEnumeration> |
428 | | { |
429 | | public: |
430 | | |
431 | | librdf_GraphResult(librdf_Repository *i_pRepository, |
432 | | std::mutex & i_rMutex, |
433 | | std::shared_ptr<librdf_stream> i_pStream, |
434 | | std::shared_ptr<librdf_node> i_pContext, |
435 | | std::shared_ptr<librdf_query> i_pQuery = |
436 | | std::shared_ptr<librdf_query>() ) |
437 | 24 | : m_xRep(i_pRepository) |
438 | 24 | , m_rMutex(i_rMutex) |
439 | 24 | , m_pQuery(std::move(i_pQuery)) |
440 | 24 | , m_pContext(std::move(i_pContext)) |
441 | 24 | , m_pStream(std::move(i_pStream)) |
442 | 24 | { }; |
443 | | |
444 | | virtual ~librdf_GraphResult() override |
445 | 24 | { |
446 | 24 | std::scoped_lock g(m_rMutex); // lock mutex when destroying members |
447 | 24 | const_cast<std::shared_ptr<librdf_stream>& >(m_pStream).reset(); |
448 | 24 | const_cast<std::shared_ptr<librdf_node>& >(m_pContext).reset(); |
449 | 24 | const_cast<std::shared_ptr<librdf_query>& >(m_pQuery).reset(); |
450 | 24 | } |
451 | | |
452 | | // css::container::XEnumeration: |
453 | | virtual sal_Bool SAL_CALL hasMoreElements() override; |
454 | | virtual uno::Any SAL_CALL nextElement() override; |
455 | | |
456 | | private: |
457 | | |
458 | | librdf_GraphResult(librdf_GraphResult const&) = delete; |
459 | | librdf_GraphResult& operator=(librdf_GraphResult const&) = delete; |
460 | | |
461 | | // NB: this is not a weak pointer: streams _must_ be deleted before the |
462 | | // storage they point into, so we keep the repository alive here |
463 | | // also, sequence is important: the stream must be destroyed first. |
464 | | ::rtl::Reference< librdf_Repository > m_xRep; |
465 | | // needed for synchronizing access to librdf (it doesn't do win32 threading) |
466 | | std::mutex & m_rMutex; |
467 | | // the query (in case this is a result of a graph query) |
468 | | // not that the redland documentation spells this out explicitly, but |
469 | | // queries must be freed only after all the results are completely read |
470 | | std::shared_ptr<librdf_query> const m_pQuery; |
471 | | std::shared_ptr<librdf_node> const m_pContext; |
472 | | std::shared_ptr<librdf_stream> const m_pStream; |
473 | | |
474 | | librdf_node* getContext_Lock() const; |
475 | | }; |
476 | | |
477 | | |
478 | | // css::container::XEnumeration: |
479 | | sal_Bool SAL_CALL |
480 | | librdf_GraphResult::hasMoreElements() |
481 | 24 | { |
482 | 24 | std::scoped_lock g(m_rMutex); |
483 | 24 | return m_pStream && !librdf_stream_end(m_pStream.get()); |
484 | 24 | } |
485 | | |
486 | | librdf_node* librdf_GraphResult::getContext_Lock() const |
487 | 0 | { |
488 | 0 | if (!m_pStream || librdf_stream_end(m_pStream.get())) |
489 | 0 | return nullptr; |
490 | 0 | librdf_node *pCtxt( |
491 | 0 | #if LIBRDF_VERSION >= 10012 |
492 | 0 | librdf_stream_get_context2(m_pStream.get()) ); |
493 | | #else |
494 | | static_cast<librdf_node *>(librdf_stream_get_context(m_pStream.get())) ); |
495 | | #endif |
496 | 0 | if (pCtxt) |
497 | 0 | return pCtxt; |
498 | 0 | return m_pContext.get(); |
499 | 0 | } |
500 | | |
501 | | css::uno::Any SAL_CALL |
502 | | librdf_GraphResult::nextElement() |
503 | 0 | { |
504 | 0 | std::scoped_lock g(m_rMutex); |
505 | 0 | if (m_pStream && librdf_stream_end(m_pStream.get())) { |
506 | 0 | throw container::NoSuchElementException(); |
507 | 0 | } |
508 | 0 | librdf_node * pCtxt = getContext_Lock(); |
509 | |
|
510 | 0 | librdf_statement *pStmt( librdf_stream_get_object(m_pStream.get()) ); |
511 | 0 | if (!pStmt) { |
512 | 0 | rdf::QueryException e( |
513 | 0 | u"librdf_GraphResult::nextElement: " |
514 | 0 | "librdf_stream_get_object failed"_ustr, *this); |
515 | 0 | throw lang::WrappedTargetException( |
516 | 0 | u"librdf_GraphResult::nextElement: " |
517 | 0 | "librdf_stream_get_object failed"_ustr, *this, |
518 | 0 | uno::Any(e)); |
519 | 0 | } |
520 | | // NB: pCtxt may be null here if this is result of a graph query |
521 | 0 | if (pCtxt && isInternalContext(pCtxt)) { |
522 | 0 | pCtxt = nullptr; // XML ID context is implementation detail! |
523 | 0 | } |
524 | 0 | rdf::Statement Stmt( |
525 | 0 | m_xRep->getTypeConverter().convertToStatement(pStmt, pCtxt) ); |
526 | | // NB: this will invalidate current item. |
527 | 0 | librdf_stream_next(m_pStream.get()); |
528 | 0 | return uno::Any(Stmt); |
529 | 0 | } |
530 | | |
531 | | |
532 | | /** result of operations that return a graph, i.e., |
533 | | an XEnumeration of statements. |
534 | | */ |
535 | | class librdf_GraphResult2: |
536 | | public ::cppu::WeakImplHelper< |
537 | | container::XEnumeration> |
538 | | { |
539 | | public: |
540 | | |
541 | | librdf_GraphResult2(std::vector<rdf::Statement> statements) |
542 | 7.81k | : m_vStatements(std::move(statements)) |
543 | 7.81k | { }; |
544 | | |
545 | | // css::container::XEnumeration: |
546 | | virtual sal_Bool SAL_CALL hasMoreElements() override; |
547 | | virtual uno::Any SAL_CALL nextElement() override; |
548 | | |
549 | | private: |
550 | | |
551 | | std::vector<rdf::Statement> m_vStatements; |
552 | | std::atomic<std::size_t> m_nIndex = 0; |
553 | | }; |
554 | | |
555 | | |
556 | | // css::container::XEnumeration: |
557 | | sal_Bool SAL_CALL |
558 | | librdf_GraphResult2::hasMoreElements() |
559 | 7.81k | { |
560 | 7.81k | return m_nIndex < m_vStatements.size(); |
561 | 7.81k | } |
562 | | |
563 | | css::uno::Any SAL_CALL |
564 | | librdf_GraphResult2::nextElement() |
565 | 0 | { |
566 | 0 | std::size_t const n = m_nIndex++; |
567 | 0 | if (m_vStatements.size() <= n) |
568 | 0 | { |
569 | 0 | m_nIndex = m_vStatements.size(); // avoid overflow |
570 | 0 | throw container::NoSuchElementException(); |
571 | 0 | } |
572 | 0 | return uno::Any(m_vStatements[n]); |
573 | 0 | } |
574 | | |
575 | | /** result of tuple queries ("SELECT"). |
576 | | */ |
577 | | class librdf_QuerySelectResult: |
578 | | public ::cppu::WeakImplHelper< |
579 | | rdf::XQuerySelectResult> |
580 | | { |
581 | | public: |
582 | | |
583 | | librdf_QuerySelectResult(librdf_Repository *i_pRepository, |
584 | | std::mutex & i_rMutex, |
585 | | std::shared_ptr<librdf_query> i_pQuery, |
586 | | std::shared_ptr<librdf_query_results> i_pQueryResult, |
587 | | uno::Sequence< OUString > const& i_rBindingNames ) |
588 | 0 | : m_xRep(i_pRepository) |
589 | 0 | , m_rMutex(i_rMutex) |
590 | 0 | , m_pQuery(std::move(i_pQuery)) |
591 | 0 | , m_pQueryResult(std::move(i_pQueryResult)) |
592 | 0 | , m_BindingNames(i_rBindingNames) |
593 | 0 | { }; |
594 | | |
595 | | virtual ~librdf_QuerySelectResult() override |
596 | 0 | { |
597 | 0 | std::scoped_lock g(m_rMutex); // lock mutex when destroying members |
598 | 0 | const_cast<std::shared_ptr<librdf_query_results>& >(m_pQueryResult) |
599 | 0 | .reset(); |
600 | 0 | const_cast<std::shared_ptr<librdf_query>& >(m_pQuery).reset(); |
601 | 0 | } |
602 | | |
603 | | // css::container::XEnumeration: |
604 | | virtual sal_Bool SAL_CALL hasMoreElements() override; |
605 | | virtual uno::Any SAL_CALL nextElement() override; |
606 | | |
607 | | // css::rdf::XQuerySelectResult: |
608 | | virtual uno::Sequence< OUString > SAL_CALL getBindingNames() override; |
609 | | |
610 | | private: |
611 | | |
612 | | librdf_QuerySelectResult(librdf_QuerySelectResult const&) = delete; |
613 | | librdf_QuerySelectResult& operator=(librdf_QuerySelectResult const&) = delete; |
614 | | |
615 | | // NB: this is not a weak pointer: streams _must_ be deleted before the |
616 | | // storage they point into, so we keep the repository alive here |
617 | | // also, sequence is important: the stream must be destroyed first. |
618 | | ::rtl::Reference< librdf_Repository > m_xRep; |
619 | | // needed for synchronizing access to librdf (it doesn't do win32 threading) |
620 | | std::mutex & m_rMutex; |
621 | | // not that the redland documentation spells this out explicitly, but |
622 | | // queries must be freed only after all the results are completely read |
623 | | std::shared_ptr<librdf_query> const m_pQuery; |
624 | | std::shared_ptr<librdf_query_results> const m_pQueryResult; |
625 | | uno::Sequence< OUString > const m_BindingNames; |
626 | | }; |
627 | | |
628 | | |
629 | | // css::container::XEnumeration: |
630 | | sal_Bool SAL_CALL |
631 | | librdf_QuerySelectResult::hasMoreElements() |
632 | 0 | { |
633 | 0 | std::scoped_lock g(m_rMutex); |
634 | 0 | return !librdf_query_results_finished(m_pQueryResult.get()); |
635 | 0 | } |
636 | | |
637 | | class NodeArray : private std::vector<librdf_node*> |
638 | | { |
639 | | public: |
640 | 0 | NodeArray(int cnt) : std::vector<librdf_node*>(cnt) {} |
641 | | |
642 | | ~NodeArray() noexcept |
643 | 0 | { |
644 | 0 | std::for_each(begin(), end(), safe_librdf_free_node); |
645 | 0 | } |
646 | | |
647 | | using std::vector<librdf_node*>::data; |
648 | | using std::vector<librdf_node*>::operator[]; |
649 | | }; |
650 | | |
651 | | css::uno::Any SAL_CALL |
652 | | librdf_QuerySelectResult::nextElement() |
653 | 0 | { |
654 | 0 | std::scoped_lock g(m_rMutex); |
655 | 0 | if (librdf_query_results_finished(m_pQueryResult.get())) { |
656 | 0 | throw container::NoSuchElementException(); |
657 | 0 | } |
658 | 0 | sal_Int32 count(m_BindingNames.getLength()); |
659 | 0 | OSL_ENSURE(count >= 0, "negative length?"); |
660 | 0 | NodeArray aNodes(count); |
661 | 0 | if (librdf_query_results_get_bindings(m_pQueryResult.get(), nullptr, |
662 | 0 | aNodes.data())) |
663 | 0 | { |
664 | 0 | rdf::QueryException e( |
665 | 0 | u"librdf_QuerySelectResult::nextElement: " |
666 | 0 | "librdf_query_results_get_bindings failed"_ustr, *this); |
667 | 0 | throw lang::WrappedTargetException( |
668 | 0 | u"librdf_QuerySelectResult::nextElement: " |
669 | 0 | "librdf_query_results_get_bindings failed"_ustr, *this, |
670 | 0 | uno::Any(e)); |
671 | 0 | } |
672 | 0 | uno::Sequence< uno::Reference< rdf::XNode > > ret(count); |
673 | 0 | auto retRange = asNonConstRange(ret); |
674 | 0 | for (int i = 0; i < count; ++i) { |
675 | 0 | retRange[i] = m_xRep->getTypeConverter().convertToXNode(aNodes[i]); |
676 | 0 | } |
677 | | // NB: this will invalidate current item. |
678 | 0 | librdf_query_results_next(m_pQueryResult.get()); |
679 | 0 | return uno::Any(ret); |
680 | 0 | } |
681 | | |
682 | | // css::rdf::XQuerySelectResult: |
683 | | uno::Sequence< OUString > SAL_CALL |
684 | | librdf_QuerySelectResult::getBindingNames() |
685 | 0 | { |
686 | | // const - no lock needed |
687 | 0 | return m_BindingNames; |
688 | 0 | } |
689 | | |
690 | | |
691 | | /** represents a named graph, and forwards all the work to repository. |
692 | | */ |
693 | | class librdf_NamedGraph: |
694 | | public ::cppu::WeakImplHelper< |
695 | | rdf::XNamedGraph> |
696 | | { |
697 | | public: |
698 | | librdf_NamedGraph(librdf_Repository * i_pRep, |
699 | | uno::Reference<rdf::XURI> i_xName) |
700 | 6.73k | : m_wRep(i_pRep) |
701 | 6.73k | , m_xName(std::move(i_xName)) |
702 | 6.73k | { }; |
703 | | |
704 | | // css::rdf::XNode: |
705 | | virtual OUString SAL_CALL getStringValue() override; |
706 | | |
707 | | // css::rdf::XURI: |
708 | | virtual OUString SAL_CALL getNamespace() override; |
709 | | virtual OUString SAL_CALL getLocalName() override; |
710 | | |
711 | | // css::rdf::XNamedGraph: |
712 | | virtual uno::Reference<rdf::XURI> SAL_CALL getName() override; |
713 | | virtual void SAL_CALL clear() override; |
714 | | virtual void SAL_CALL addStatement( |
715 | | const uno::Reference< rdf::XResource > & i_xSubject, |
716 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
717 | | const uno::Reference< rdf::XNode > & i_xObject) override; |
718 | | virtual void SAL_CALL removeStatements( |
719 | | const uno::Reference< rdf::XResource > & i_xSubject, |
720 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
721 | | const uno::Reference< rdf::XNode > & i_xObject) override; |
722 | | virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements( |
723 | | const uno::Reference< rdf::XResource > & i_xSubject, |
724 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
725 | | const uno::Reference< rdf::XNode > & i_xObject) override; |
726 | | |
727 | | private: |
728 | | |
729 | | librdf_NamedGraph(librdf_NamedGraph const&) = delete; |
730 | | librdf_NamedGraph& operator=(librdf_NamedGraph const&) = delete; |
731 | | |
732 | | static OUString createCacheKey_NoLock( |
733 | | const uno::Reference< rdf::XResource > & i_xSubject, |
734 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
735 | | const uno::Reference< rdf::XNode > & i_xObject); |
736 | | |
737 | | /// weak reference: this is needed to check if m_pRep is valid |
738 | | unotools::WeakReference< librdf_Repository > const m_wRep; |
739 | | uno::Reference< rdf::XURI > const m_xName; |
740 | | |
741 | | /// Querying is rather slow, so cache the results. |
742 | | std::map<OUString, std::vector<rdf::Statement>> m_aStatementsCache; |
743 | | std::mutex m_CacheMutex; |
744 | | }; |
745 | | |
746 | | |
747 | | // css::rdf::XNode: |
748 | | OUString SAL_CALL librdf_NamedGraph::getStringValue() |
749 | 0 | { |
750 | 0 | return m_xName->getStringValue(); |
751 | 0 | } |
752 | | |
753 | | // css::rdf::XURI: |
754 | | OUString SAL_CALL librdf_NamedGraph::getNamespace() |
755 | 0 | { |
756 | 0 | return m_xName->getNamespace(); |
757 | 0 | } |
758 | | |
759 | | OUString SAL_CALL librdf_NamedGraph::getLocalName() |
760 | 0 | { |
761 | 0 | return m_xName->getLocalName(); |
762 | 0 | } |
763 | | |
764 | | // css::rdf::XNamedGraph: |
765 | | uno::Reference< rdf::XURI > SAL_CALL librdf_NamedGraph::getName() |
766 | 0 | { |
767 | 0 | return m_xName; |
768 | 0 | } |
769 | | |
770 | | void SAL_CALL librdf_NamedGraph::clear() |
771 | 0 | { |
772 | 0 | rtl::Reference< librdf_Repository > xRep( m_wRep ); |
773 | 0 | if (!xRep.is()) { |
774 | 0 | throw rdf::RepositoryException( |
775 | 0 | u"librdf_NamedGraph::clear: repository is gone"_ustr, *this); |
776 | 0 | } |
777 | 0 | const OUString contextU( m_xName->getStringValue() ); |
778 | 0 | try { |
779 | 0 | xRep->clearGraph_NoLock(contextU); |
780 | 0 | } catch (lang::IllegalArgumentException & ex) { |
781 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
782 | 0 | throw lang::WrappedTargetRuntimeException( ex.Message, |
783 | 0 | *this, anyEx ); |
784 | 0 | } |
785 | 0 | std::unique_lock g(m_CacheMutex); |
786 | 0 | m_aStatementsCache.clear(); |
787 | 0 | } |
788 | | |
789 | | void SAL_CALL librdf_NamedGraph::addStatement( |
790 | | const uno::Reference< rdf::XResource > & i_xSubject, |
791 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
792 | | const uno::Reference< rdf::XNode > & i_xObject) |
793 | 6.73k | { |
794 | 6.73k | rtl::Reference< librdf_Repository > xRep( m_wRep ); |
795 | 6.73k | if (!xRep.is()) { |
796 | 0 | throw rdf::RepositoryException( |
797 | 0 | u"librdf_NamedGraph::addStatement: repository is gone"_ustr, *this); |
798 | 0 | } |
799 | 6.73k | { |
800 | 6.73k | std::unique_lock g(m_CacheMutex); |
801 | 6.73k | m_aStatementsCache.clear(); |
802 | 6.73k | } |
803 | 6.73k | xRep->addStatementGraph_NoLock( |
804 | 6.73k | i_xSubject, i_xPredicate, i_xObject, m_xName); |
805 | 6.73k | } |
806 | | |
807 | | void SAL_CALL librdf_NamedGraph::removeStatements( |
808 | | const uno::Reference< rdf::XResource > & i_xSubject, |
809 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
810 | | const uno::Reference< rdf::XNode > & i_xObject) |
811 | 0 | { |
812 | 0 | rtl::Reference< librdf_Repository > xRep( m_wRep ); |
813 | 0 | if (!xRep.is()) { |
814 | 0 | throw rdf::RepositoryException( |
815 | 0 | u"librdf_NamedGraph::removeStatements: repository is gone"_ustr, *this); |
816 | 0 | } |
817 | 0 | { |
818 | 0 | std::unique_lock g(m_CacheMutex); |
819 | 0 | m_aStatementsCache.clear(); |
820 | 0 | } |
821 | 0 | xRep->removeStatementsGraph_NoLock( |
822 | 0 | i_xSubject, i_xPredicate, i_xObject, m_xName); |
823 | 0 | } |
824 | | |
825 | | OUString librdf_NamedGraph::createCacheKey_NoLock( |
826 | | const uno::Reference< rdf::XResource > & i_xSubject, |
827 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
828 | | const uno::Reference< rdf::XNode > & i_xObject) |
829 | 7.81k | { |
830 | 7.81k | OUStringBuffer cacheKey(256); |
831 | 7.81k | librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xSubject, cacheKey); |
832 | 7.81k | cacheKey.append("\t"); |
833 | 7.81k | librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xPredicate, cacheKey); |
834 | 7.81k | cacheKey.append("\t"); |
835 | 7.81k | librdf_TypeConverter::extractNodeToCacheKey_NoLock(i_xObject, cacheKey); |
836 | 7.81k | return cacheKey.makeStringAndClear(); |
837 | 7.81k | } |
838 | | |
839 | | uno::Reference< container::XEnumeration > SAL_CALL |
840 | | librdf_NamedGraph::getStatements( |
841 | | const uno::Reference< rdf::XResource > & i_xSubject, |
842 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
843 | | const uno::Reference< rdf::XNode > & i_xObject) |
844 | 7.81k | { |
845 | 7.81k | OUString cacheKey = createCacheKey_NoLock(i_xSubject, i_xPredicate, i_xObject); |
846 | 7.81k | { |
847 | 7.81k | std::unique_lock g(m_CacheMutex); |
848 | 7.81k | auto it = m_aStatementsCache.find(cacheKey); |
849 | 7.81k | if (it != m_aStatementsCache.end()) { |
850 | 1.07k | return new librdf_GraphResult2(it->second); |
851 | 1.07k | } |
852 | 7.81k | } |
853 | | |
854 | 6.73k | rtl::Reference< librdf_Repository > xRep( m_wRep ); |
855 | 6.73k | if (!xRep.is()) { |
856 | 0 | throw rdf::RepositoryException( |
857 | 0 | u"librdf_NamedGraph::getStatements: repository is gone"_ustr, *this); |
858 | 0 | } |
859 | 6.73k | std::vector<rdf::Statement> vStatements = xRep->getStatementsGraph_NoLock( |
860 | 6.73k | i_xSubject, i_xPredicate, i_xObject, m_xName); |
861 | | |
862 | 6.73k | { |
863 | 6.73k | std::unique_lock g(m_CacheMutex); |
864 | 6.73k | m_aStatementsCache.emplace(cacheKey, vStatements); |
865 | 6.73k | } |
866 | 6.73k | return new librdf_GraphResult2(std::move(vStatements)); |
867 | 6.73k | } |
868 | | |
869 | | |
870 | | std::shared_ptr<librdf_world> librdf_Repository::m_pWorld; |
871 | | sal_uInt32 librdf_Repository::m_NumInstances = 0; |
872 | | std::mutex librdf_Repository::m_aMutex; |
873 | | |
874 | | librdf_Repository::librdf_Repository( |
875 | | uno::Reference< uno::XComponentContext > const & i_xContext) |
876 | 6.73k | : /*BaseMutex(),*/ m_xContext(i_xContext) |
877 | | // m_pWorld (static_cast<librdf_world *>(0), safe_librdf_free_world ), |
878 | 6.73k | , m_pStorage(static_cast<librdf_storage*>(nullptr), safe_librdf_free_storage) |
879 | 6.73k | , m_pModel (static_cast<librdf_model *>(nullptr), safe_librdf_free_model ) |
880 | 6.73k | , m_TypeConverter(i_xContext, *this) |
881 | 6.73k | { |
882 | 6.73k | OSL_ENSURE(i_xContext.is(), "librdf_Repository: null context"); |
883 | | |
884 | 6.73k | std::scoped_lock g(m_aMutex); |
885 | 6.73k | if (!m_NumInstances++) { |
886 | 2 | m_pWorld.reset(m_TypeConverter.createWorld_Lock(), |
887 | 2 | safe_librdf_free_world); |
888 | 2 | } |
889 | 6.73k | } |
890 | | |
891 | | librdf_Repository::~librdf_Repository() |
892 | 6.73k | { |
893 | 6.73k | std::scoped_lock g(m_aMutex); |
894 | | |
895 | | // must destroy these before world! |
896 | 6.73k | m_pModel.reset(); |
897 | 6.73k | m_pStorage.reset(); |
898 | | |
899 | | // FIXME: so it turns out that calling librdf_free_world will |
900 | | // (via raptor_sax2_finish) call xmlCleanupParser, which will |
901 | | // free libxml2's globals! ARRRGH!!! => never call librdf_free_world |
902 | | #if 0 |
903 | | if (!--m_NumInstances) { |
904 | | m_pWorld.reset(); |
905 | | } |
906 | | #endif |
907 | 6.73k | } |
908 | | |
909 | | // com.sun.star.uno.XServiceInfo: |
910 | | OUString SAL_CALL librdf_Repository::getImplementationName() |
911 | 0 | { |
912 | 0 | return u"librdf_Repository"_ustr; |
913 | 0 | } |
914 | | |
915 | | sal_Bool SAL_CALL librdf_Repository::supportsService( |
916 | | OUString const & serviceName) |
917 | 0 | { |
918 | 0 | return cppu::supportsService(this, serviceName); |
919 | 0 | } |
920 | | |
921 | | uno::Sequence< OUString > SAL_CALL |
922 | | librdf_Repository::getSupportedServiceNames() |
923 | 0 | { |
924 | 0 | return { u"com.sun.star.rdf.Repository"_ustr }; |
925 | 0 | } |
926 | | |
927 | | // css::rdf::XRepository: |
928 | | uno::Reference< rdf::XBlankNode > SAL_CALL librdf_Repository::createBlankNode() |
929 | 0 | { |
930 | 0 | std::scoped_lock g(m_aMutex); |
931 | 0 | const std::shared_ptr<librdf_node> pNode( |
932 | 0 | librdf_new_node_from_blank_identifier(m_pWorld.get(), nullptr), |
933 | 0 | safe_librdf_free_node); |
934 | 0 | if (!pNode) { |
935 | 0 | throw uno::RuntimeException( |
936 | 0 | u"librdf_Repository::createBlankNode: " |
937 | 0 | "librdf_new_node_from_blank_identifier failed"_ustr, *this); |
938 | 0 | } |
939 | 0 | const unsigned char * id (librdf_node_get_blank_identifier(pNode.get())); |
940 | 0 | if (!id) { |
941 | 0 | throw uno::RuntimeException( |
942 | 0 | u"librdf_Repository::createBlankNode: " |
943 | 0 | "librdf_node_get_blank_identifier failed"_ustr, *this); |
944 | 0 | } |
945 | 0 | const OUString nodeID(OUString::createFromAscii( |
946 | 0 | reinterpret_cast<const char *>(id))); |
947 | 0 | try { |
948 | 0 | return rdf::BlankNode::create(m_xContext, nodeID); |
949 | 0 | } catch (const lang::IllegalArgumentException &) { |
950 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
951 | 0 | throw lang::WrappedTargetRuntimeException( |
952 | 0 | u"librdf_Repository::createBlankNode: " |
953 | 0 | "illegal blank node label"_ustr, *this, anyEx); |
954 | 0 | } |
955 | 0 | } |
956 | | |
957 | | //void SAL_CALL |
958 | | uno::Reference<rdf::XNamedGraph> SAL_CALL |
959 | | librdf_Repository::importGraph(::sal_Int16 i_Format, |
960 | | const uno::Reference< io::XInputStream > & i_xInStream, |
961 | | const uno::Reference< rdf::XURI > & i_xGraphName, |
962 | | const uno::Reference< rdf::XURI > & i_xBaseURI) |
963 | 0 | { |
964 | 0 | if (!i_xInStream.is()) { |
965 | 0 | throw lang::IllegalArgumentException( |
966 | 0 | u"librdf_Repository::importGraph: stream is null"_ustr, *this, 1); |
967 | 0 | } |
968 | | //FIXME: other formats |
969 | 0 | if (i_Format != rdf::FileFormat::RDF_XML) { |
970 | 0 | throw datatransfer::UnsupportedFlavorException( |
971 | 0 | u"librdf_Repository::importGraph: file format not supported"_ustr, *this); |
972 | 0 | } |
973 | 0 | if (!i_xGraphName.is()) { |
974 | 0 | throw lang::IllegalArgumentException( |
975 | 0 | u"librdf_Repository::importGraph: graph name is null"_ustr, *this, 2); |
976 | 0 | } |
977 | 0 | if (i_xGraphName->getStringValue().startsWith(s_nsOOo)) |
978 | 0 | { |
979 | 0 | throw lang::IllegalArgumentException( |
980 | 0 | u"librdf_Repository::importGraph: URI is reserved"_ustr, *this, 0); |
981 | 0 | } |
982 | 0 | if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI? |
983 | 0 | throw lang::IllegalArgumentException( |
984 | 0 | u"librdf_Repository::importGraph: base URI is null"_ustr, *this, 3); |
985 | 0 | } |
986 | 0 | OSL_ENSURE(i_xBaseURI.is(), "no base uri"); |
987 | 0 | const OUString baseURIU( i_xBaseURI->getStringValue() ); |
988 | 0 | if (baseURIU.indexOf('#') >= 0) { |
989 | 0 | throw lang::IllegalArgumentException( |
990 | 0 | u"librdf_Repository::importGraph: base URI is not absolute"_ustr, *this, 3); |
991 | 0 | } |
992 | | |
993 | 0 | const OUString contextU( i_xGraphName->getStringValue() ); |
994 | |
|
995 | 0 | uno::Sequence<sal_Int8> buf; |
996 | 0 | uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY); |
997 | | // UGLY: if only redland could read streams... |
998 | 0 | const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 ); |
999 | | // exceptions are propagated |
1000 | 0 | i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) ); |
1001 | |
|
1002 | 0 | if (buf.getLength() == 0) { |
1003 | 0 | throw rdf::ParseException( |
1004 | 0 | u"librdf_Repository::importGraph: stream is empty"_ustr, *this); |
1005 | 0 | } |
1006 | | |
1007 | 0 | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1008 | |
|
1009 | 0 | if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) { |
1010 | 0 | throw container::ElementExistException( |
1011 | 0 | u"librdf_Repository::importGraph: graph with given URI exists"_ustr, *this); |
1012 | 0 | } |
1013 | 0 | const OString context( |
1014 | 0 | OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); |
1015 | |
|
1016 | 0 | const std::shared_ptr<librdf_node> pContext( |
1017 | 0 | librdf_new_node_from_uri_string(m_pWorld.get(), |
1018 | 0 | reinterpret_cast<const unsigned char*> (context.getStr())), |
1019 | 0 | safe_librdf_free_node); |
1020 | 0 | if (!pContext) { |
1021 | 0 | throw uno::RuntimeException( |
1022 | 0 | u"librdf_Repository::importGraph: librdf_new_node_from_uri_string failed"_ustr, *this); |
1023 | 0 | } |
1024 | | |
1025 | 0 | const OString baseURI( |
1026 | 0 | OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) ); |
1027 | 0 | const std::shared_ptr<librdf_uri> pBaseURI( |
1028 | 0 | librdf_new_uri(m_pWorld.get(), |
1029 | 0 | reinterpret_cast<const unsigned char*> (baseURI.getStr())), |
1030 | 0 | safe_librdf_free_uri); |
1031 | 0 | if (!pBaseURI) { |
1032 | 0 | throw uno::RuntimeException( u"librdf_Repository::importGraph: librdf_new_uri failed"_ustr, *this); |
1033 | 0 | } |
1034 | | |
1035 | 0 | const std::shared_ptr<librdf_parser> pParser( |
1036 | 0 | librdf_new_parser(m_pWorld.get(), "rdfxml", nullptr, nullptr), |
1037 | 0 | safe_librdf_free_parser); |
1038 | 0 | if (!pParser) { |
1039 | 0 | throw uno::RuntimeException( |
1040 | 0 | u"librdf_Repository::importGraph: " |
1041 | 0 | "librdf_new_parser failed"_ustr, *this); |
1042 | 0 | } |
1043 | | |
1044 | 0 | const std::shared_ptr<librdf_stream> pStream( |
1045 | 0 | librdf_parser_parse_counted_string_as_stream(pParser.get(), |
1046 | 0 | reinterpret_cast<const unsigned char*>(buf.getConstArray()), |
1047 | 0 | buf.getLength(), pBaseURI.get()), |
1048 | 0 | safe_librdf_free_stream); |
1049 | 0 | if (!pStream) { |
1050 | 0 | throw rdf::ParseException( |
1051 | 0 | u"librdf_Repository::importGraph: " |
1052 | 0 | "librdf_parser_parse_counted_string_as_stream failed"_ustr, *this); |
1053 | 0 | } |
1054 | 0 | rtl::Reference<librdf_NamedGraph> const pGraph( |
1055 | 0 | new librdf_NamedGraph(this, i_xGraphName)); |
1056 | 0 | m_NamedGraphs.insert(std::make_pair(contextU, pGraph)); |
1057 | 0 | if (librdf_model_context_add_statements(m_pModel.get(), |
1058 | 0 | pContext.get(), pStream.get())) { |
1059 | 0 | throw rdf::RepositoryException( |
1060 | 0 | u"librdf_Repository::importGraph: " |
1061 | 0 | "librdf_model_context_add_statements failed"_ustr, *this); |
1062 | 0 | } |
1063 | | |
1064 | 0 | return pGraph; |
1065 | 0 | } |
1066 | | |
1067 | | void addChaffWhenEncryptedStorage(const uno::Reference< io::XOutputStream > &rStream, unsigned char* pBuffer, size_t length) |
1068 | 0 | { |
1069 | 0 | if (!length) |
1070 | 0 | return; |
1071 | | |
1072 | 0 | uno::Reference< embed::XEncryptionProtectedSource2 > xEncr(rStream, |
1073 | 0 | uno::UNO_QUERY); |
1074 | |
|
1075 | 0 | bool bAddChaff = xEncr.is() && xEncr->hasEncryptionData(); |
1076 | | |
1077 | | // exceptions are propagated |
1078 | 0 | if (!bAddChaff) |
1079 | 0 | { |
1080 | 0 | const uno::Sequence<sal_Int8> buf( |
1081 | 0 | reinterpret_cast<sal_Int8*>(pBuffer), length); |
1082 | 0 | rStream->writeBytes(buf); |
1083 | 0 | } |
1084 | 0 | else |
1085 | 0 | { |
1086 | 0 | unsigned char *postcomment = |
1087 | 0 | reinterpret_cast<unsigned char*>(strchr(reinterpret_cast<char*>(pBuffer), '\n')); |
1088 | 0 | if (postcomment != nullptr) |
1089 | 0 | { |
1090 | 0 | ++postcomment; |
1091 | |
|
1092 | 0 | size_t preamblelen = postcomment - pBuffer; |
1093 | |
|
1094 | 0 | uno::Sequence<sal_Int8> buf( |
1095 | 0 | reinterpret_cast<sal_Int8*>(pBuffer), preamblelen); |
1096 | 0 | rStream->writeBytes(buf); |
1097 | |
|
1098 | 0 | OString aComment = |
1099 | 0 | "<!--" + |
1100 | 0 | comphelper::xml::makeXMLChaff() + |
1101 | 0 | "-->"; |
1102 | |
|
1103 | 0 | buf = uno::Sequence<sal_Int8>( |
1104 | 0 | reinterpret_cast<const sal_Int8*>(aComment.getStr()), aComment.getLength()); |
1105 | 0 | rStream->writeBytes(buf); |
1106 | |
|
1107 | 0 | buf = uno::Sequence<sal_Int8>( |
1108 | 0 | reinterpret_cast<sal_Int8*>(postcomment), length-preamblelen); |
1109 | 0 | rStream->writeBytes(buf); |
1110 | 0 | } |
1111 | 0 | } |
1112 | 0 | } |
1113 | | |
1114 | | void SAL_CALL |
1115 | | librdf_Repository::exportGraph(::sal_Int16 i_Format, |
1116 | | const uno::Reference< io::XOutputStream > & i_xOutStream, |
1117 | | const uno::Reference< rdf::XURI > & i_xGraphName, |
1118 | | const uno::Reference< rdf::XURI > & i_xBaseURI) |
1119 | 0 | { |
1120 | 0 | if (!i_xOutStream.is()) { |
1121 | 0 | throw lang::IllegalArgumentException( |
1122 | 0 | u"librdf_Repository::exportGraph: stream is null"_ustr, *this, 1); |
1123 | 0 | } |
1124 | | // FIXME: other formats |
1125 | 0 | if (i_Format != rdf::FileFormat::RDF_XML) { |
1126 | 0 | throw datatransfer::UnsupportedFlavorException( |
1127 | 0 | u"librdf_Repository::exportGraph: " |
1128 | 0 | "file format not supported"_ustr, *this); |
1129 | 0 | } |
1130 | 0 | if (!i_xGraphName.is()) { |
1131 | 0 | throw lang::IllegalArgumentException( |
1132 | 0 | u"librdf_Repository::exportGraph: " |
1133 | 0 | "graph name is null"_ustr, *this, 2); |
1134 | 0 | } |
1135 | 0 | if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI? |
1136 | 0 | throw lang::IllegalArgumentException( |
1137 | 0 | u"librdf_Repository::exportGraph: " |
1138 | 0 | "base URI is null"_ustr, *this, 3); |
1139 | 0 | } |
1140 | 0 | OSL_ENSURE(i_xBaseURI.is(), "no base uri"); |
1141 | 0 | const OUString baseURIU( i_xBaseURI->getStringValue() ); |
1142 | 0 | if (baseURIU.indexOf('#') >= 0) { |
1143 | 0 | throw lang::IllegalArgumentException( |
1144 | 0 | u"librdf_Repository::exportGraph: " |
1145 | 0 | "base URI is not absolute"_ustr, *this, 3); |
1146 | 0 | } |
1147 | | |
1148 | 0 | const OUString contextU( i_xGraphName->getStringValue() ); |
1149 | |
|
1150 | 0 | std::unique_lock g(m_aMutex); // don't call i_x* with mutex locked |
1151 | |
|
1152 | 0 | if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) { |
1153 | 0 | throw container::NoSuchElementException( |
1154 | 0 | u"librdf_Repository::exportGraph: " |
1155 | 0 | "no graph with given URI exists"_ustr, *this); |
1156 | 0 | } |
1157 | 0 | const OString context( |
1158 | 0 | OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); |
1159 | |
|
1160 | 0 | const std::shared_ptr<librdf_node> pContext( |
1161 | 0 | librdf_new_node_from_uri_string(m_pWorld.get(), |
1162 | 0 | reinterpret_cast<const unsigned char*> (context.getStr())), |
1163 | 0 | safe_librdf_free_node); |
1164 | 0 | if (!pContext) { |
1165 | 0 | throw uno::RuntimeException( |
1166 | 0 | u"librdf_Repository::exportGraph: " |
1167 | 0 | "librdf_new_node_from_uri_string failed"_ustr, *this); |
1168 | 0 | } |
1169 | 0 | const OString baseURI( |
1170 | 0 | OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) ); |
1171 | 0 | const std::shared_ptr<librdf_uri> pBaseURI( |
1172 | 0 | librdf_new_uri(m_pWorld.get(), |
1173 | 0 | reinterpret_cast<const unsigned char*> (baseURI.getStr())), |
1174 | 0 | safe_librdf_free_uri); |
1175 | 0 | if (!pBaseURI) { |
1176 | 0 | throw uno::RuntimeException( |
1177 | 0 | u"librdf_Repository::exportGraph: " |
1178 | 0 | "librdf_new_uri failed"_ustr, *this); |
1179 | 0 | } |
1180 | | |
1181 | 0 | const std::shared_ptr<librdf_stream> pStream( |
1182 | 0 | librdf_model_context_as_stream(m_pModel.get(), pContext.get()), |
1183 | 0 | safe_librdf_free_stream); |
1184 | 0 | if (!pStream) { |
1185 | 0 | throw rdf::RepositoryException( |
1186 | 0 | u"librdf_Repository::exportGraph: " |
1187 | 0 | "librdf_model_context_as_stream failed"_ustr, *this); |
1188 | 0 | } |
1189 | 0 | const char * const format("rdfxml"); |
1190 | | // #i116443#: abbrev breaks when certain URIs are used as data types |
1191 | | // const char *format("rdfxml-abbrev"); |
1192 | 0 | const std::shared_ptr<librdf_serializer> pSerializer( |
1193 | 0 | librdf_new_serializer(m_pWorld.get(), format, nullptr, nullptr), |
1194 | 0 | safe_librdf_free_serializer); |
1195 | 0 | if (!pSerializer) { |
1196 | 0 | throw uno::RuntimeException( |
1197 | 0 | u"librdf_Repository::exportGraph: " |
1198 | 0 | "librdf_new_serializer failed"_ustr, *this); |
1199 | 0 | } |
1200 | | |
1201 | 0 | const std::shared_ptr<librdf_uri> pRelativeURI( |
1202 | 0 | librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*> |
1203 | 0 | ("http://feature.librdf.org/raptor-relativeURIs")), |
1204 | 0 | safe_librdf_free_uri); |
1205 | 0 | const std::shared_ptr<librdf_uri> pWriteBaseURI( |
1206 | 0 | librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*> |
1207 | 0 | ("http://feature.librdf.org/raptor-writeBaseURI")), |
1208 | 0 | safe_librdf_free_uri); |
1209 | 0 | const std::shared_ptr<librdf_node> p0( |
1210 | 0 | librdf_new_node_from_literal(m_pWorld.get(), |
1211 | 0 | reinterpret_cast<const unsigned char*> ("0"), nullptr, 0), |
1212 | 0 | safe_librdf_free_node); |
1213 | 0 | const std::shared_ptr<librdf_node> p1( |
1214 | 0 | librdf_new_node_from_literal(m_pWorld.get(), |
1215 | 0 | reinterpret_cast<const unsigned char*> ("1"), nullptr, 0), |
1216 | 0 | safe_librdf_free_node); |
1217 | 0 | if (!pWriteBaseURI || !pRelativeURI || !p0 || !p1) { |
1218 | 0 | throw uno::RuntimeException( |
1219 | 0 | u"librdf_Repository::exportGraph: " |
1220 | 0 | "librdf_new_uri or librdf_new_node_from_literal failed"_ustr, *this); |
1221 | 0 | } |
1222 | | |
1223 | | // make URIs relative to base URI |
1224 | 0 | if (librdf_serializer_set_feature(pSerializer.get(), |
1225 | 0 | pRelativeURI.get(), p1.get())) |
1226 | 0 | { |
1227 | 0 | throw uno::RuntimeException( |
1228 | 0 | u"librdf_Repository::exportGraph: " |
1229 | 0 | "librdf_serializer_set_feature relativeURIs failed"_ustr, *this); |
1230 | 0 | } |
1231 | | // but do not write the base URI to the file! |
1232 | 0 | if (librdf_serializer_set_feature(pSerializer.get(), |
1233 | 0 | pWriteBaseURI.get(), p0.get())) |
1234 | 0 | { |
1235 | 0 | throw uno::RuntimeException( |
1236 | 0 | u"librdf_Repository::exportGraph: " |
1237 | 0 | "librdf_serializer_set_feature writeBaseURI failed"_ustr, *this); |
1238 | 0 | } |
1239 | | |
1240 | 0 | size_t length; |
1241 | 0 | const std::shared_ptr<unsigned char> pBuf( |
1242 | 0 | librdf_serializer_serialize_stream_to_counted_string( |
1243 | 0 | pSerializer.get(), pBaseURI.get(), pStream.get(), &length), free); |
1244 | 0 | if (!pBuf) { |
1245 | 0 | throw rdf::RepositoryException( |
1246 | 0 | u"librdf_Repository::exportGraph: " |
1247 | 0 | "librdf_serializer_serialize_stream_to_counted_string failed"_ustr, |
1248 | 0 | *this); |
1249 | 0 | } |
1250 | | |
1251 | 0 | g.unlock(); // release Mutex before calling i_xOutStream methods |
1252 | |
|
1253 | 0 | addChaffWhenEncryptedStorage(i_xOutStream, pBuf.get(), length); |
1254 | 0 | } |
1255 | | |
1256 | | uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL |
1257 | | librdf_Repository::getGraphNames() |
1258 | 0 | { |
1259 | 0 | std::scoped_lock g(m_aMutex); |
1260 | 0 | ::std::vector< uno::Reference<rdf::XURI> > ret; |
1261 | 0 | std::transform(m_NamedGraphs.begin(), m_NamedGraphs.end(), |
1262 | 0 | std::back_inserter(ret), |
1263 | 0 | [](std::pair<OUString, ::rtl::Reference<librdf_NamedGraph>> const& it) |
1264 | 0 | { return it.second->getName(); }); |
1265 | 0 | return comphelper::containerToSequence(ret); |
1266 | 0 | } |
1267 | | |
1268 | | uno::Reference< rdf::XNamedGraph > SAL_CALL |
1269 | | librdf_Repository::getGraph(const uno::Reference< rdf::XURI > & i_xGraphName) |
1270 | 6.73k | { |
1271 | 6.73k | if (!i_xGraphName.is()) { |
1272 | 0 | throw lang::IllegalArgumentException( |
1273 | 0 | u"librdf_Repository::getGraph: URI is null"_ustr, *this, 0); |
1274 | 0 | } |
1275 | 6.73k | const OUString contextU( i_xGraphName->getStringValue() ); |
1276 | | |
1277 | 6.73k | std::scoped_lock g(m_aMutex); |
1278 | 6.73k | const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) ); |
1279 | 6.73k | if (iter != m_NamedGraphs.end()) { |
1280 | 0 | return iter->second; |
1281 | 6.73k | } else { |
1282 | 6.73k | return nullptr; |
1283 | 6.73k | } |
1284 | 6.73k | } |
1285 | | |
1286 | | uno::Reference< rdf::XNamedGraph > SAL_CALL |
1287 | | librdf_Repository::createGraph(const uno::Reference< rdf::XURI > & i_xGraphName) |
1288 | 6.73k | { |
1289 | 6.73k | if (!i_xGraphName.is()) { |
1290 | 0 | throw lang::IllegalArgumentException( |
1291 | 0 | u"librdf_Repository::createGraph: URI is null"_ustr, *this, 0); |
1292 | 0 | } |
1293 | | |
1294 | 6.73k | const OUString contextU( i_xGraphName->getStringValue() ); |
1295 | 6.73k | if (contextU.startsWith(s_nsOOo)) |
1296 | 0 | { |
1297 | 0 | throw lang::IllegalArgumentException( |
1298 | 0 | u"librdf_Repository::createGraph: URI is reserved"_ustr, *this, 0); |
1299 | 0 | } |
1300 | | |
1301 | 6.73k | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1302 | | |
1303 | | // NB: librdf does not have a concept of graphs as such; |
1304 | | // a librdf named graph exists iff the model contains a statement with |
1305 | | // the graph name as context |
1306 | | |
1307 | 6.73k | if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) { |
1308 | 0 | throw container::ElementExistException( |
1309 | 0 | u"librdf_Repository::createGraph: graph with given URI exists"_ustr, *this); |
1310 | 0 | } |
1311 | 6.73k | m_NamedGraphs.insert(std::make_pair(contextU, |
1312 | 6.73k | new librdf_NamedGraph(this, i_xGraphName))); |
1313 | 6.73k | return m_NamedGraphs.find(contextU)->second; |
1314 | 6.73k | } |
1315 | | |
1316 | | void SAL_CALL |
1317 | | librdf_Repository::destroyGraph( |
1318 | | const uno::Reference< rdf::XURI > & i_xGraphName) |
1319 | 0 | { |
1320 | 0 | if (!i_xGraphName.is()) { |
1321 | 0 | throw lang::IllegalArgumentException( |
1322 | 0 | u"librdf_Repository::destroyGraph: URI is null"_ustr, *this, 0); |
1323 | 0 | } |
1324 | 0 | const OUString contextU( i_xGraphName->getStringValue() ); |
1325 | |
|
1326 | 0 | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1327 | |
|
1328 | 0 | const NamedGraphMap_t::iterator iter( clearGraph_Lock(contextU, false) ); |
1329 | 0 | m_NamedGraphs.erase(iter); |
1330 | 0 | } |
1331 | | |
1332 | | bool isMetadatableWithoutMetadata( |
1333 | | uno::Reference<uno::XInterface> const & i_xNode) |
1334 | 20.2k | { |
1335 | 20.2k | const uno::Reference<rdf::XMetadatable> xMeta( i_xNode, uno::UNO_QUERY ); |
1336 | 20.2k | return (xMeta.is() && xMeta->getMetadataReference().Second.isEmpty()); |
1337 | 20.2k | } |
1338 | | |
1339 | | uno::Reference< container::XEnumeration > SAL_CALL |
1340 | | librdf_Repository::getStatements( |
1341 | | const uno::Reference< rdf::XResource > & i_xSubject, |
1342 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
1343 | | const uno::Reference< rdf::XNode > & i_xObject) |
1344 | 24 | { |
1345 | 24 | if (isMetadatableWithoutMetadata(i_xSubject) || |
1346 | 0 | isMetadatableWithoutMetadata(i_xPredicate) || |
1347 | 0 | isMetadatableWithoutMetadata(i_xObject)) |
1348 | 24 | { |
1349 | 24 | return new librdf_GraphResult(this, m_aMutex, |
1350 | 24 | std::shared_ptr<librdf_stream>(), |
1351 | 24 | std::shared_ptr<librdf_node>()); |
1352 | 24 | } |
1353 | | |
1354 | 0 | librdf_TypeConverter::Statement const stmt( |
1355 | 0 | librdf_TypeConverter::extractStatement_NoLock( |
1356 | 0 | i_xSubject, i_xPredicate, i_xObject)); |
1357 | |
|
1358 | 0 | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1359 | |
|
1360 | 0 | const std::shared_ptr<librdf_statement> pStatement( |
1361 | 0 | librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt), |
1362 | 0 | safe_librdf_free_statement); |
1363 | 0 | OSL_ENSURE(pStatement, "mkStatement failed"); |
1364 | |
|
1365 | 0 | std::shared_ptr<librdf_stream> pStream( |
1366 | 0 | librdf_model_find_statements(m_pModel.get(), pStatement.get()), |
1367 | 0 | safe_librdf_free_stream); |
1368 | 0 | if (!pStream) { |
1369 | 0 | throw rdf::RepositoryException( |
1370 | 0 | u"librdf_Repository::getStatements: " |
1371 | 0 | "librdf_model_find_statements failed"_ustr, *this); |
1372 | 0 | } |
1373 | | |
1374 | 0 | return new librdf_GraphResult(this, m_aMutex, std::move(pStream), |
1375 | 0 | std::shared_ptr<librdf_node>()); |
1376 | 0 | } |
1377 | | |
1378 | | |
1379 | | uno::Reference< rdf::XQuerySelectResult > SAL_CALL |
1380 | | librdf_Repository::querySelect(const OUString & i_rQuery) |
1381 | 0 | { |
1382 | 0 | std::scoped_lock g(m_aMutex); |
1383 | 0 | const OString query( |
1384 | 0 | OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) ); |
1385 | 0 | std::shared_ptr<librdf_query> pQuery( |
1386 | 0 | librdf_new_query(m_pWorld.get(), s_sparql, nullptr, |
1387 | 0 | reinterpret_cast<const unsigned char*> (query.getStr()), nullptr), |
1388 | 0 | safe_librdf_free_query); |
1389 | 0 | if (!pQuery) { |
1390 | 0 | throw rdf::QueryException( |
1391 | 0 | u"librdf_Repository::querySelect: " |
1392 | 0 | "librdf_new_query failed"_ustr, *this); |
1393 | 0 | } |
1394 | 0 | std::shared_ptr<librdf_query_results> pResults( |
1395 | 0 | librdf_model_query_execute(m_pModel.get(), pQuery.get()), |
1396 | 0 | safe_librdf_free_query_results); |
1397 | 0 | if (!pResults || !librdf_query_results_is_bindings(pResults.get())) { |
1398 | 0 | throw rdf::QueryException( |
1399 | 0 | u"librdf_Repository::querySelect: " |
1400 | 0 | "query result is null or not bindings"_ustr, *this); |
1401 | 0 | } |
1402 | | |
1403 | 0 | const int count( librdf_query_results_get_bindings_count(pResults.get()) ); |
1404 | 0 | if (count < 0) { |
1405 | 0 | throw rdf::QueryException( |
1406 | 0 | u"librdf_Repository::querySelect: " |
1407 | 0 | "librdf_query_results_get_bindings_count failed"_ustr, *this); |
1408 | 0 | } |
1409 | 0 | uno::Sequence< OUString > names(count); |
1410 | 0 | auto namesRange = asNonConstRange(names); |
1411 | 0 | for (int i = 0; i < count; ++i) { |
1412 | 0 | const char* name( librdf_query_results_get_binding_name( |
1413 | 0 | pResults.get(), i) ); |
1414 | 0 | if (!name) { |
1415 | 0 | throw rdf::QueryException( |
1416 | 0 | u"librdf_Repository::querySelect: binding is null"_ustr, *this); |
1417 | 0 | } |
1418 | | |
1419 | 0 | namesRange[i] = OUString::createFromAscii(name); |
1420 | 0 | } |
1421 | | |
1422 | 0 | return new librdf_QuerySelectResult(this, m_aMutex, |
1423 | 0 | std::move(pQuery), std::move(pResults), names); |
1424 | 0 | } |
1425 | | |
1426 | | uno::Reference< container::XEnumeration > SAL_CALL |
1427 | | librdf_Repository::queryConstruct(const OUString & i_rQuery) |
1428 | 0 | { |
1429 | 0 | std::scoped_lock g(m_aMutex); |
1430 | 0 | const OString query( |
1431 | 0 | OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) ); |
1432 | 0 | std::shared_ptr<librdf_query> pQuery( |
1433 | 0 | librdf_new_query(m_pWorld.get(), s_sparql, nullptr, |
1434 | 0 | reinterpret_cast<const unsigned char*> (query.getStr()), nullptr), |
1435 | 0 | safe_librdf_free_query); |
1436 | 0 | if (!pQuery) { |
1437 | 0 | throw rdf::QueryException( |
1438 | 0 | u"librdf_Repository::queryConstruct: " |
1439 | 0 | "librdf_new_query failed"_ustr, *this); |
1440 | 0 | } |
1441 | 0 | const std::shared_ptr<librdf_query_results> pResults( |
1442 | 0 | librdf_model_query_execute(m_pModel.get(), pQuery.get()), |
1443 | 0 | safe_librdf_free_query_results); |
1444 | 0 | if (!pResults || !librdf_query_results_is_graph(pResults.get())) { |
1445 | 0 | throw rdf::QueryException( |
1446 | 0 | u"librdf_Repository::queryConstruct: " |
1447 | 0 | "query result is null or not graph"_ustr, *this); |
1448 | 0 | } |
1449 | 0 | std::shared_ptr<librdf_stream> pStream( |
1450 | 0 | librdf_query_results_as_stream(pResults.get()), |
1451 | 0 | safe_librdf_free_stream); |
1452 | 0 | if (!pStream) { |
1453 | 0 | throw rdf::QueryException( |
1454 | 0 | u"librdf_Repository::queryConstruct: " |
1455 | 0 | "librdf_query_results_as_stream failed"_ustr, *this); |
1456 | 0 | } |
1457 | | |
1458 | 0 | return new librdf_GraphResult(this, m_aMutex, std::move(pStream), |
1459 | 0 | std::shared_ptr<librdf_node>(), |
1460 | 0 | std::move(pQuery)); |
1461 | 0 | } |
1462 | | |
1463 | | sal_Bool SAL_CALL |
1464 | | librdf_Repository::queryAsk(const OUString & i_rQuery) |
1465 | 0 | { |
1466 | 0 | std::scoped_lock g(m_aMutex); |
1467 | |
|
1468 | 0 | const OString query( |
1469 | 0 | OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) ); |
1470 | 0 | const std::shared_ptr<librdf_query> pQuery( |
1471 | 0 | librdf_new_query(m_pWorld.get(), s_sparql, nullptr, |
1472 | 0 | reinterpret_cast<const unsigned char*> (query.getStr()), nullptr), |
1473 | 0 | safe_librdf_free_query); |
1474 | 0 | if (!pQuery) { |
1475 | 0 | throw rdf::QueryException( |
1476 | 0 | u"librdf_Repository::queryAsk: " |
1477 | 0 | "librdf_new_query failed"_ustr, *this); |
1478 | 0 | } |
1479 | 0 | const std::shared_ptr<librdf_query_results> pResults( |
1480 | 0 | librdf_model_query_execute(m_pModel.get(), pQuery.get()), |
1481 | 0 | safe_librdf_free_query_results); |
1482 | 0 | if (!pResults || !librdf_query_results_is_boolean(pResults.get())) { |
1483 | 0 | throw rdf::QueryException( |
1484 | 0 | u"librdf_Repository::queryAsk: " |
1485 | 0 | "query result is null or not boolean"_ustr, *this); |
1486 | 0 | } |
1487 | 0 | return bool(librdf_query_results_get_boolean(pResults.get())); |
1488 | 0 | } |
1489 | | |
1490 | | // css::rdf::XDocumentRepository: |
1491 | | void SAL_CALL librdf_Repository::setStatementRDFa( |
1492 | | const uno::Reference< rdf::XResource > & i_xSubject, |
1493 | | const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates, |
1494 | | const uno::Reference< rdf::XMetadatable > & i_xObject, |
1495 | | const OUString & i_rRDFaContent, |
1496 | | const uno::Reference< rdf::XURI > & i_xRDFaDatatype) |
1497 | 0 | { |
1498 | 0 | if (!i_xSubject.is()) { |
1499 | 0 | throw lang::IllegalArgumentException( |
1500 | 0 | u"librdf_Repository::setStatementRDFa: Subject is null"_ustr, *this, 0); |
1501 | 0 | } |
1502 | 0 | if (!i_rPredicates.hasElements()) { |
1503 | 0 | throw lang::IllegalArgumentException( |
1504 | 0 | u"librdf_Repository::setStatementRDFa: no Predicates"_ustr, |
1505 | 0 | *this, 1); |
1506 | 0 | } |
1507 | 0 | if (std::any_of(i_rPredicates.begin(), i_rPredicates.end(), |
1508 | 0 | [](const uno::Reference< rdf::XURI >& rPredicate) { return !rPredicate.is(); })) { |
1509 | 0 | throw lang::IllegalArgumentException( |
1510 | 0 | u"librdf_Repository::setStatementRDFa: Predicate is null"_ustr, *this, 1); |
1511 | 0 | } |
1512 | 0 | if (!i_xObject.is()) { |
1513 | 0 | throw lang::IllegalArgumentException( |
1514 | 0 | u"librdf_Repository::setStatementRDFa: Object is null"_ustr, *this, 2); |
1515 | 0 | } |
1516 | 0 | const uno::Reference<lang::XServiceInfo> xService(i_xObject, |
1517 | 0 | uno::UNO_QUERY_THROW); |
1518 | 0 | uno::Reference<text::XTextRange> xTextRange; |
1519 | 0 | if (xService->supportsService(u"com.sun.star.table.Cell"_ustr) || |
1520 | 0 | xService->supportsService(u"com.sun.star.text.CellProperties"_ustr) || // for writer |
1521 | 0 | xService->supportsService(u"com.sun.star.text.Paragraph"_ustr)) |
1522 | 0 | { |
1523 | 0 | xTextRange.set(i_xObject, uno::UNO_QUERY_THROW); |
1524 | 0 | } |
1525 | 0 | else if (xService->supportsService(u"com.sun.star.text.Bookmark"_ustr) || |
1526 | 0 | xService->supportsService(u"com.sun.star.text.InContentMetadata"_ustr)) |
1527 | 0 | { |
1528 | 0 | const uno::Reference<text::XTextContent> xTextContent(i_xObject, |
1529 | 0 | uno::UNO_QUERY_THROW); |
1530 | 0 | xTextRange = xTextContent->getAnchor(); |
1531 | 0 | } |
1532 | 0 | if (!xTextRange.is()) { |
1533 | 0 | throw lang::IllegalArgumentException( |
1534 | 0 | u"librdf_Repository::setStatementRDFa: " |
1535 | 0 | "Object does not support RDFa"_ustr, *this, 2); |
1536 | 0 | } |
1537 | | // ensure that the metadatable has an XML ID |
1538 | 0 | i_xObject->ensureMetadataReference(); |
1539 | 0 | const beans::StringPair mdref( i_xObject->getMetadataReference() ); |
1540 | 0 | if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) { |
1541 | 0 | throw uno::RuntimeException( |
1542 | 0 | u"librdf_Repository::setStatementRDFa: " |
1543 | 0 | "ensureMetadataReference did not"_ustr, *this); |
1544 | 0 | } |
1545 | 0 | OUString const sXmlId(mdref.First + "#" + mdref.Second); |
1546 | 0 | OUString const sContext(s_nsOOo + sXmlId); |
1547 | 0 | OUString const content( (i_rRDFaContent.isEmpty()) |
1548 | 0 | ? xTextRange->getString() |
1549 | 0 | : i_rRDFaContent ); |
1550 | 0 | uno::Reference<rdf::XNode> xContent; |
1551 | 0 | try { |
1552 | 0 | if (i_xRDFaDatatype.is()) { |
1553 | 0 | xContent.set(rdf::Literal::createWithType(m_xContext, |
1554 | 0 | content, i_xRDFaDatatype), |
1555 | 0 | uno::UNO_QUERY_THROW); |
1556 | 0 | } else { |
1557 | 0 | xContent.set(rdf::Literal::create(m_xContext, content), |
1558 | 0 | uno::UNO_QUERY_THROW); |
1559 | 0 | } |
1560 | 0 | } catch (const lang::IllegalArgumentException &) { |
1561 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
1562 | 0 | throw lang::WrappedTargetRuntimeException( |
1563 | 0 | u"librdf_Repository::setStatementRDFa: " |
1564 | 0 | "cannot create literal"_ustr, *this, anyEx); |
1565 | 0 | } |
1566 | | |
1567 | 0 | std::shared_ptr<librdf_TypeConverter::Resource> const pSubject( |
1568 | 0 | librdf_TypeConverter::extractResource_NoLock(i_xSubject)); |
1569 | 0 | std::shared_ptr<librdf_TypeConverter::Node> const pContent( |
1570 | 0 | librdf_TypeConverter::extractNode_NoLock(xContent)); |
1571 | 0 | ::std::vector< std::shared_ptr<librdf_TypeConverter::Resource> > |
1572 | 0 | predicates; |
1573 | 0 | ::std::transform(i_rPredicates.begin(), i_rPredicates.end(), |
1574 | 0 | ::std::back_inserter(predicates), |
1575 | 0 | [](uno::Reference<rdf::XURI> const& xURI) |
1576 | 0 | { return librdf_TypeConverter::extractResource_NoLock(xURI); }); |
1577 | |
|
1578 | 0 | removeStatementRDFa(i_xObject); // not atomic with insertion? |
1579 | |
|
1580 | 0 | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1581 | |
|
1582 | 0 | if (i_rRDFaContent.isEmpty()) { |
1583 | 0 | m_RDFaXHTMLContentSet.erase(sXmlId); |
1584 | 0 | } else { |
1585 | 0 | m_RDFaXHTMLContentSet.insert(sXmlId); |
1586 | 0 | } |
1587 | 0 | try |
1588 | 0 | { |
1589 | 0 | for (const auto& rPredicatePtr : predicates) |
1590 | 0 | { |
1591 | 0 | addStatementGraph_Lock( |
1592 | 0 | librdf_TypeConverter::Statement(pSubject, |
1593 | 0 | std::dynamic_pointer_cast<librdf_TypeConverter::URI>(rPredicatePtr), |
1594 | 0 | pContent), |
1595 | 0 | sContext, true); |
1596 | 0 | } |
1597 | 0 | } |
1598 | 0 | catch (const container::NoSuchElementException&) |
1599 | 0 | { |
1600 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
1601 | 0 | throw lang::WrappedTargetRuntimeException( |
1602 | 0 | u"librdf_Repository::setStatementRDFa: " |
1603 | 0 | "cannot addStatementGraph"_ustr, *this, anyEx); |
1604 | 0 | } |
1605 | 0 | } |
1606 | | |
1607 | | void SAL_CALL librdf_Repository::removeStatementRDFa( |
1608 | | const uno::Reference< rdf::XMetadatable > & i_xElement) |
1609 | 0 | { |
1610 | 0 | if (!i_xElement.is()) { |
1611 | 0 | throw lang::IllegalArgumentException( |
1612 | 0 | u"librdf_Repository::removeStatementRDFa: Element is null"_ustr, |
1613 | 0 | *this, 0); |
1614 | 0 | } |
1615 | | |
1616 | 0 | const beans::StringPair mdref( i_xElement->getMetadataReference() ); |
1617 | 0 | if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) { |
1618 | 0 | return; // nothing to do... |
1619 | 0 | } |
1620 | | |
1621 | 0 | OUString const sXmlId(s_nsOOo + mdref.First + "#" + mdref.Second); |
1622 | |
|
1623 | 0 | clearGraph_NoLock(sXmlId, true); |
1624 | 0 | } |
1625 | | |
1626 | | beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL |
1627 | | librdf_Repository::getStatementRDFa( |
1628 | | const uno::Reference< rdf::XMetadatable > & i_xElement) |
1629 | 0 | { |
1630 | 0 | if (!i_xElement.is()) { |
1631 | 0 | throw lang::IllegalArgumentException( |
1632 | 0 | u"librdf_Repository::getStatementRDFa: Element is null"_ustr, *this, 0); |
1633 | 0 | } |
1634 | 0 | const beans::StringPair mdref( i_xElement->getMetadataReference() ); |
1635 | 0 | if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) { |
1636 | 0 | return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >(); |
1637 | 0 | } |
1638 | 0 | OUString const sXmlId(mdref.First + "#" + mdref.Second); |
1639 | 0 | uno::Reference<rdf::XURI> xXmlId; |
1640 | 0 | try { |
1641 | 0 | xXmlId.set( rdf::URI::create(m_xContext, s_nsOOo + sXmlId), |
1642 | 0 | uno::UNO_SET_THROW); |
1643 | 0 | } catch (const lang::IllegalArgumentException &) { |
1644 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
1645 | 0 | throw lang::WrappedTargetRuntimeException( |
1646 | 0 | u"librdf_Repository::getStatementRDFa: " |
1647 | 0 | "cannot create URI for XML ID"_ustr, *this, anyEx); |
1648 | 0 | } |
1649 | | |
1650 | 0 | ::std::vector< rdf::Statement > ret; |
1651 | 0 | try |
1652 | 0 | { |
1653 | 0 | ret = getStatementsGraph_NoLock(nullptr, nullptr, nullptr, xXmlId, true); |
1654 | 0 | } |
1655 | 0 | catch (const container::NoSuchElementException&) |
1656 | 0 | { |
1657 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
1658 | 0 | throw lang::WrappedTargetRuntimeException( |
1659 | 0 | u"librdf_Repository::getStatementRDFa: " |
1660 | 0 | "cannot getStatementsGraph"_ustr, *this, anyEx); |
1661 | 0 | } |
1662 | | |
1663 | 0 | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1664 | |
|
1665 | 0 | return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >( |
1666 | 0 | comphelper::containerToSequence(ret), 0 != m_RDFaXHTMLContentSet.count(sXmlId)); |
1667 | 0 | } |
1668 | | |
1669 | | extern "C" |
1670 | | librdf_statement *rdfa_context_stream_map_handler( |
1671 | | librdf_stream *i_pStream, void *, librdf_statement *i_pStatement) |
1672 | 0 | { |
1673 | 0 | OSL_ENSURE(i_pStream, "rdfa_context_stream_map_handler: stream null"); |
1674 | 0 | if (i_pStream) { |
1675 | 0 | librdf_node *pCtxt( |
1676 | 0 | #if LIBRDF_VERSION >= 10012 |
1677 | 0 | librdf_stream_get_context2(i_pStream) ); |
1678 | | #else |
1679 | | static_cast<librdf_node *>(librdf_stream_get_context(i_pStream)) ); |
1680 | | #endif |
1681 | 0 | OSL_ENSURE(pCtxt, "rdfa_context_stream_map_handler: context null"); |
1682 | 0 | if (pCtxt && isInternalContext(pCtxt)) { |
1683 | 0 | return i_pStatement; |
1684 | 0 | } |
1685 | 0 | } |
1686 | 0 | return nullptr; |
1687 | 0 | }; |
1688 | | |
1689 | | uno::Reference< container::XEnumeration > SAL_CALL |
1690 | | librdf_Repository::getStatementsRDFa( |
1691 | | const uno::Reference< rdf::XResource > & i_xSubject, |
1692 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
1693 | | const uno::Reference< rdf::XNode > & i_xObject) |
1694 | 0 | { |
1695 | 0 | if (isMetadatableWithoutMetadata(i_xSubject) || |
1696 | 0 | isMetadatableWithoutMetadata(i_xPredicate) || |
1697 | 0 | isMetadatableWithoutMetadata(i_xObject)) |
1698 | 0 | { |
1699 | 0 | return new librdf_GraphResult(this, m_aMutex, |
1700 | 0 | std::shared_ptr<librdf_stream>(), |
1701 | 0 | std::shared_ptr<librdf_node>()); |
1702 | 0 | } |
1703 | | |
1704 | 0 | librdf_TypeConverter::Statement const stmt( |
1705 | 0 | librdf_TypeConverter::extractStatement_NoLock( |
1706 | 0 | i_xSubject, i_xPredicate, i_xObject)); |
1707 | |
|
1708 | 0 | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1709 | |
|
1710 | 0 | const std::shared_ptr<librdf_statement> pStatement( |
1711 | 0 | librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt), |
1712 | 0 | safe_librdf_free_statement); |
1713 | 0 | OSL_ENSURE(pStatement, "mkStatement failed"); |
1714 | |
|
1715 | 0 | std::shared_ptr<librdf_stream> pStream( |
1716 | 0 | librdf_model_find_statements(m_pModel.get(), pStatement.get()), |
1717 | 0 | safe_librdf_free_stream); |
1718 | 0 | if (!pStream) { |
1719 | 0 | throw rdf::RepositoryException( |
1720 | 0 | u"librdf_Repository::getStatementsRDFa: " |
1721 | 0 | "librdf_model_find_statements failed"_ustr, *this); |
1722 | 0 | } |
1723 | | |
1724 | 0 | if (librdf_stream_add_map(pStream.get(), rdfa_context_stream_map_handler, |
1725 | 0 | nullptr, nullptr)) { |
1726 | 0 | throw rdf::RepositoryException( |
1727 | 0 | u"librdf_Repository::getStatementsRDFa: " |
1728 | 0 | "librdf_stream_add_map failed"_ustr, *this); |
1729 | 0 | } |
1730 | | |
1731 | 0 | return new librdf_GraphResult(this, m_aMutex, std::move(pStream), |
1732 | 0 | std::shared_ptr<librdf_node>()); |
1733 | 0 | } |
1734 | | |
1735 | | // css::lang::XInitialization: |
1736 | | void SAL_CALL librdf_Repository::initialize( |
1737 | | const uno::Sequence< css::uno::Any > &) |
1738 | 6.73k | { |
1739 | 6.73k | std::scoped_lock g(m_aMutex); |
1740 | | |
1741 | | // m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world); |
1742 | 6.73k | m_pStorage.reset(m_TypeConverter.createStorage_Lock(m_pWorld.get()), |
1743 | 6.73k | safe_librdf_free_storage); |
1744 | 6.73k | m_pModel.reset(m_TypeConverter.createModel_Lock( |
1745 | 6.73k | m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model); |
1746 | 6.73k | } |
1747 | | |
1748 | | NamedGraphMap_t::iterator librdf_Repository::clearGraph_NoLock( |
1749 | | OUString const& i_rGraphName, bool i_Internal) |
1750 | | // throw (uno::RuntimeException, container::NoSuchElementException, |
1751 | | // rdf::RepositoryException) |
1752 | 0 | { |
1753 | 0 | std::scoped_lock g(m_aMutex); |
1754 | |
|
1755 | 0 | return clearGraph_Lock(i_rGraphName, i_Internal); |
1756 | 0 | } |
1757 | | |
1758 | | NamedGraphMap_t::iterator librdf_Repository::clearGraph_Lock( |
1759 | | OUString const& i_rGraphName, bool i_Internal) |
1760 | 0 | { |
1761 | | // internal: must be called with mutex locked! |
1762 | 0 | const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(i_rGraphName) ); |
1763 | 0 | if (!i_Internal && iter == m_NamedGraphs.end()) { |
1764 | 0 | throw container::NoSuchElementException( |
1765 | 0 | u"librdf_Repository::clearGraph: " |
1766 | 0 | "no graph with given URI exists"_ustr, *this); |
1767 | 0 | } |
1768 | 0 | const OString context( |
1769 | 0 | OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) ); |
1770 | |
|
1771 | 0 | const std::shared_ptr<librdf_node> pContext( |
1772 | 0 | librdf_new_node_from_uri_string(m_pWorld.get(), |
1773 | 0 | reinterpret_cast<const unsigned char*> (context.getStr())), |
1774 | 0 | safe_librdf_free_node); |
1775 | 0 | if (!pContext) { |
1776 | 0 | throw uno::RuntimeException( |
1777 | 0 | u"librdf_Repository::clearGraph: " |
1778 | 0 | "librdf_new_node_from_uri_string failed"_ustr, *this); |
1779 | 0 | } |
1780 | 0 | if (librdf_model_context_remove_statements(m_pModel.get(), pContext.get())) |
1781 | 0 | { |
1782 | 0 | throw rdf::RepositoryException( |
1783 | 0 | u"librdf_Repository::clearGraph: " |
1784 | 0 | "librdf_model_context_remove_statements failed"_ustr, *this); |
1785 | 0 | } |
1786 | 0 | return iter; |
1787 | 0 | } |
1788 | | |
1789 | | void librdf_Repository::addStatementGraph_NoLock( |
1790 | | const uno::Reference< rdf::XResource > & i_xSubject, |
1791 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
1792 | | const uno::Reference< rdf::XNode > & i_xObject, |
1793 | | const uno::Reference< rdf::XURI > & i_xGraphName) |
1794 | | //throw (uno::RuntimeException, lang::IllegalArgumentException, |
1795 | | // container::NoSuchElementException, rdf::RepositoryException) |
1796 | 6.73k | { |
1797 | 6.73k | if (!i_xSubject.is()) { |
1798 | 0 | throw lang::IllegalArgumentException( |
1799 | 0 | u"librdf_Repository::addStatement: Subject is null"_ustr, *this, 0); |
1800 | 0 | } |
1801 | 6.73k | if (!i_xPredicate.is()) { |
1802 | 0 | throw lang::IllegalArgumentException( |
1803 | 0 | u"librdf_Repository::addStatement: Predicate is null"_ustr, |
1804 | 0 | *this, 1); |
1805 | 0 | } |
1806 | 6.73k | if (!i_xObject.is()) { |
1807 | 0 | throw lang::IllegalArgumentException( |
1808 | 0 | u"librdf_Repository::addStatement: Object is null"_ustr, *this, 2); |
1809 | 0 | } |
1810 | | |
1811 | 6.73k | librdf_TypeConverter::Statement const stmt( |
1812 | 6.73k | librdf_TypeConverter::extractStatement_NoLock( |
1813 | 6.73k | i_xSubject, i_xPredicate, i_xObject)); |
1814 | | |
1815 | 6.73k | const OUString contextU( i_xGraphName->getStringValue() ); |
1816 | | |
1817 | 6.73k | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1818 | | |
1819 | 6.73k | addStatementGraph_Lock(stmt, contextU, false/*i_Internal*/); |
1820 | 6.73k | } |
1821 | | |
1822 | | void librdf_Repository::addStatementGraph_Lock( |
1823 | | librdf_TypeConverter::Statement const& i_rStatement, |
1824 | | OUString const& i_rGraphName, |
1825 | | bool i_Internal) |
1826 | 6.73k | { |
1827 | 6.73k | if (!i_Internal |
1828 | 6.73k | && (m_NamedGraphs.find(i_rGraphName) == m_NamedGraphs.end())) |
1829 | 0 | { |
1830 | 0 | throw container::NoSuchElementException( |
1831 | 0 | u"librdf_Repository::addStatement: " |
1832 | 0 | "no graph with given URI exists"_ustr, *this); |
1833 | 0 | } |
1834 | 6.73k | const OString context( |
1835 | 6.73k | OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) ); |
1836 | | |
1837 | 6.73k | const std::shared_ptr<librdf_node> pContext( |
1838 | 6.73k | librdf_new_node_from_uri_string(m_pWorld.get(), |
1839 | 6.73k | reinterpret_cast<const unsigned char*> (context.getStr())), |
1840 | 6.73k | safe_librdf_free_node); |
1841 | 6.73k | if (!pContext) { |
1842 | 0 | throw uno::RuntimeException( |
1843 | 0 | u"librdf_Repository::addStatement: " |
1844 | 0 | "librdf_new_node_from_uri_string failed"_ustr, *this); |
1845 | 0 | } |
1846 | 6.73k | const std::shared_ptr<librdf_statement> pStatement( |
1847 | 6.73k | librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), i_rStatement), |
1848 | 6.73k | safe_librdf_free_statement); |
1849 | 6.73k | OSL_ENSURE(pStatement, "mkStatement failed"); |
1850 | | |
1851 | | // Test for duplicate statement |
1852 | | // librdf_model_add_statement disallows duplicates while |
1853 | | // librdf_model_context_add_statement allows duplicates |
1854 | 6.73k | { |
1855 | 6.73k | const std::shared_ptr<librdf_stream> pStream( |
1856 | 6.73k | librdf_model_find_statements_in_context(m_pModel.get(), |
1857 | 6.73k | pStatement.get(), pContext.get()), |
1858 | 6.73k | safe_librdf_free_stream); |
1859 | 6.73k | if (pStream && !librdf_stream_end(pStream.get())) |
1860 | 0 | return; |
1861 | 6.73k | } |
1862 | | |
1863 | 6.73k | if (librdf_model_context_add_statement(m_pModel.get(), |
1864 | 6.73k | pContext.get(), pStatement.get())) { |
1865 | 0 | throw rdf::RepositoryException( |
1866 | 0 | u"librdf_Repository::addStatement: " |
1867 | 0 | "librdf_model_context_add_statement failed"_ustr, *this); |
1868 | 0 | } |
1869 | 6.73k | } |
1870 | | |
1871 | | void librdf_Repository::removeStatementsGraph_NoLock( |
1872 | | const uno::Reference< rdf::XResource > & i_xSubject, |
1873 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
1874 | | const uno::Reference< rdf::XNode > & i_xObject, |
1875 | | const uno::Reference< rdf::XURI > & i_xGraphName) |
1876 | | //throw (uno::RuntimeException, lang::IllegalArgumentException, |
1877 | | // container::NoSuchElementException, rdf::RepositoryException) |
1878 | 0 | { |
1879 | 0 | if (isMetadatableWithoutMetadata(i_xSubject) || |
1880 | 0 | isMetadatableWithoutMetadata(i_xPredicate) || |
1881 | 0 | isMetadatableWithoutMetadata(i_xObject)) |
1882 | 0 | { |
1883 | 0 | return; |
1884 | 0 | } |
1885 | | |
1886 | 0 | librdf_TypeConverter::Statement const stmt( |
1887 | 0 | librdf_TypeConverter::extractStatement_NoLock( |
1888 | 0 | i_xSubject, i_xPredicate, i_xObject)); |
1889 | 0 | const OUString contextU( i_xGraphName->getStringValue() ); |
1890 | |
|
1891 | 0 | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1892 | |
|
1893 | 0 | if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) { |
1894 | 0 | throw container::NoSuchElementException( |
1895 | 0 | u"librdf_Repository::removeStatements: " |
1896 | 0 | "no graph with given URI exists"_ustr, *this); |
1897 | 0 | } |
1898 | 0 | const OString context( |
1899 | 0 | OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); |
1900 | |
|
1901 | 0 | const std::shared_ptr<librdf_node> pContext( |
1902 | 0 | librdf_new_node_from_uri_string(m_pWorld.get(), |
1903 | 0 | reinterpret_cast<const unsigned char*> (context.getStr())), |
1904 | 0 | safe_librdf_free_node); |
1905 | 0 | if (!pContext) { |
1906 | 0 | throw uno::RuntimeException( |
1907 | 0 | u"librdf_Repository::removeStatements: " |
1908 | 0 | "librdf_new_node_from_uri_string failed"_ustr, *this); |
1909 | 0 | } |
1910 | 0 | const std::shared_ptr<librdf_statement> pStatement( |
1911 | 0 | librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt), |
1912 | 0 | safe_librdf_free_statement); |
1913 | 0 | OSL_ENSURE(pStatement, "mkStatement failed"); |
1914 | |
|
1915 | 0 | const std::shared_ptr<librdf_stream> pStream( |
1916 | 0 | librdf_model_find_statements_in_context(m_pModel.get(), |
1917 | 0 | pStatement.get(), pContext.get()), |
1918 | 0 | safe_librdf_free_stream); |
1919 | 0 | if (!pStream) { |
1920 | 0 | throw rdf::RepositoryException( |
1921 | 0 | u"librdf_Repository::removeStatements: " |
1922 | 0 | "librdf_model_find_statements_in_context failed"_ustr, *this); |
1923 | 0 | } |
1924 | | |
1925 | 0 | if (librdf_stream_end(pStream.get())) |
1926 | 0 | return; |
1927 | | |
1928 | 0 | do { |
1929 | 0 | librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) ); |
1930 | 0 | if (!pStmt) { |
1931 | 0 | throw rdf::RepositoryException( |
1932 | 0 | u"librdf_Repository::removeStatements: " |
1933 | 0 | "librdf_stream_get_object failed"_ustr, *this); |
1934 | 0 | } |
1935 | 0 | if (librdf_model_context_remove_statement(m_pModel.get(), |
1936 | 0 | pContext.get(), pStmt)) { |
1937 | 0 | throw rdf::RepositoryException( |
1938 | 0 | u"librdf_Repository::removeStatements: " |
1939 | 0 | "librdf_model_context_remove_statement failed"_ustr, *this); |
1940 | 0 | } |
1941 | 0 | } while (!librdf_stream_next(pStream.get())); |
1942 | 0 | } |
1943 | | |
1944 | | std::vector<rdf::Statement> |
1945 | | librdf_Repository::getStatementsGraph_NoLock( |
1946 | | const uno::Reference< rdf::XResource > & i_xSubject, |
1947 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
1948 | | const uno::Reference< rdf::XNode > & i_xObject, |
1949 | | const uno::Reference< rdf::XURI > & i_xGraphName, |
1950 | | bool i_Internal) |
1951 | | //throw (uno::RuntimeException, lang::IllegalArgumentException, |
1952 | | // container::NoSuchElementException, rdf::RepositoryException) |
1953 | 6.73k | { |
1954 | 6.73k | std::vector<rdf::Statement> ret; |
1955 | | |
1956 | | // N.B.: if any of subject, predicate, object is an XMetadatable, and |
1957 | | // has no metadata reference, then there cannot be any node in the graph |
1958 | | // representing it; in order to prevent side effect |
1959 | | // (ensureMetadataReference), check for this condition and return |
1960 | 6.73k | if (isMetadatableWithoutMetadata(i_xSubject) || |
1961 | 6.73k | isMetadatableWithoutMetadata(i_xPredicate) || |
1962 | 6.73k | isMetadatableWithoutMetadata(i_xObject)) |
1963 | 0 | { |
1964 | 0 | return ret; |
1965 | 0 | } |
1966 | | |
1967 | 6.73k | librdf_TypeConverter::Statement const stmt( |
1968 | 6.73k | librdf_TypeConverter::extractStatement_NoLock( |
1969 | 6.73k | i_xSubject, i_xPredicate, i_xObject)); |
1970 | 6.73k | const OUString contextU( i_xGraphName->getStringValue() ); |
1971 | | |
1972 | 6.73k | std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked |
1973 | | |
1974 | 6.73k | if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) { |
1975 | 0 | throw container::NoSuchElementException( |
1976 | 0 | u"librdf_Repository::getStatements: " |
1977 | 0 | "no graph with given URI exists"_ustr, *this); |
1978 | 0 | } |
1979 | 6.73k | const OString context( |
1980 | 6.73k | OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) ); |
1981 | | |
1982 | 6.73k | const std::shared_ptr<librdf_node> pContext( |
1983 | 6.73k | librdf_new_node_from_uri_string(m_pWorld.get(), |
1984 | 6.73k | reinterpret_cast<const unsigned char*> (context.getStr())), |
1985 | 6.73k | safe_librdf_free_node); |
1986 | 6.73k | if (!pContext) { |
1987 | 0 | throw uno::RuntimeException( |
1988 | 0 | u"librdf_Repository::getStatements: " |
1989 | 0 | "librdf_new_node_from_uri_string failed"_ustr, *this); |
1990 | 0 | } |
1991 | 6.73k | const std::shared_ptr<librdf_statement> pStatement( |
1992 | 6.73k | librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt), |
1993 | 6.73k | safe_librdf_free_statement); |
1994 | 6.73k | OSL_ENSURE(pStatement, "mkStatement failed"); |
1995 | | |
1996 | 6.73k | const std::shared_ptr<librdf_stream> pStream( |
1997 | 6.73k | librdf_model_find_statements_in_context(m_pModel.get(), |
1998 | 6.73k | pStatement.get(), pContext.get()), |
1999 | 6.73k | safe_librdf_free_stream); |
2000 | 6.73k | if (!pStream) { |
2001 | 0 | throw rdf::RepositoryException( |
2002 | 0 | u"librdf_Repository::getStatements: " |
2003 | 0 | "librdf_model_find_statements_in_context failed"_ustr, *this); |
2004 | 0 | } |
2005 | | |
2006 | 6.73k | librdf_node *pCtxt1( |
2007 | 6.73k | #if LIBRDF_VERSION >= 10012 |
2008 | 6.73k | librdf_stream_get_context2(pStream.get()) ); |
2009 | | #else |
2010 | | static_cast<librdf_node *>(librdf_stream_get_context(pStream.get())) ); |
2011 | | #endif |
2012 | 6.73k | while (!librdf_stream_end(pStream.get())) |
2013 | 0 | { |
2014 | 0 | auto pCtxt = pCtxt1; |
2015 | 0 | librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) ); |
2016 | 0 | if (!pStmt) { |
2017 | 0 | rdf::QueryException e( |
2018 | 0 | u"librdf_GraphResult::nextElement: " |
2019 | 0 | "librdf_stream_get_object failed"_ustr, *this); |
2020 | 0 | throw lang::WrappedTargetException( |
2021 | 0 | u"librdf_GraphResult::nextElement: " |
2022 | 0 | "librdf_stream_get_object failed"_ustr, *this, |
2023 | 0 | uno::Any(e)); |
2024 | 0 | } |
2025 | | // NB: pCtxt may be null here if this is result of a graph query |
2026 | 0 | if (pCtxt && isInternalContext(pCtxt)) { |
2027 | 0 | pCtxt = nullptr; // XML ID context is implementation detail! |
2028 | 0 | } |
2029 | |
|
2030 | 0 | ret.emplace_back( |
2031 | 0 | getTypeConverter().convertToStatement(pStmt, pCtxt) ); |
2032 | | |
2033 | | // NB: this will invalidate current item. |
2034 | 0 | librdf_stream_next(pStream.get()); |
2035 | 0 | } |
2036 | | |
2037 | 6.73k | return ret; |
2038 | 6.73k | } |
2039 | | |
2040 | | extern "C" |
2041 | | void librdf_raptor_init(void* /*user_data*/, raptor_world* pRaptorWorld) |
2042 | 2 | { |
2043 | | // fdo#64672 prevent raptor from setting global libxml2 error handlers |
2044 | 2 | raptor_world_set_flag(pRaptorWorld, |
2045 | 2 | RAPTOR_WORLD_FLAG_LIBXML_STRUCTURED_ERROR_SAVE, 0); |
2046 | 2 | raptor_world_set_flag(pRaptorWorld, |
2047 | 2 | RAPTOR_WORLD_FLAG_LIBXML_GENERIC_ERROR_SAVE, 0); |
2048 | 2 | } |
2049 | | |
2050 | | librdf_world *librdf_TypeConverter::createWorld_Lock() const |
2051 | 2 | { |
2052 | | // create and initialize world |
2053 | 2 | librdf_world *pWorld( librdf_new_world() ); |
2054 | 2 | if (!pWorld) { |
2055 | 0 | throw uno::RuntimeException( |
2056 | 0 | u"librdf_TypeConverter::createWorld: librdf_new_world failed"_ustr, |
2057 | 0 | m_rRep); |
2058 | 0 | } |
2059 | 2 | librdf_world_set_raptor_init_handler(pWorld, nullptr, &librdf_raptor_init); |
2060 | | //FIXME logger, digest, features? |
2061 | 2 | xsltSecurityPrefsPtr origprefs = xsltGetDefaultSecurityPrefs(); |
2062 | 2 | librdf_world_open(pWorld); |
2063 | 2 | xsltSecurityPrefsPtr newprefs = xsltGetDefaultSecurityPrefs(); |
2064 | 2 | if (newprefs != origprefs) { |
2065 | | // #i110523# restore libxslt global configuration |
2066 | | // (gratuitously overwritten by raptor_init_parser_grddl_common) |
2067 | | // (this is the only reason unordf is linked against libxslt) |
2068 | 0 | xsltSetDefaultSecurityPrefs(origprefs); |
2069 | 0 | } |
2070 | 2 | return pWorld; |
2071 | 2 | } |
2072 | | |
2073 | | librdf_storage * |
2074 | | librdf_TypeConverter::createStorage_Lock(librdf_world *i_pWorld) const |
2075 | 6.73k | { |
2076 | 6.73k | librdf_storage *pStorage( |
2077 | | // librdf_new_storage(i_pWorld, "memory", NULL, "contexts='yes'") ); |
2078 | 6.73k | librdf_new_storage(i_pWorld, "hashes", nullptr, |
2079 | 6.73k | "contexts='yes',hash-type='memory'") ); |
2080 | 6.73k | if (!pStorage) { |
2081 | 0 | throw uno::RuntimeException( |
2082 | 0 | u"librdf_TypeConverter::createStorage: librdf_new_storage failed"_ustr, |
2083 | 0 | m_rRep); |
2084 | 0 | } |
2085 | 6.73k | return pStorage; |
2086 | 6.73k | } |
2087 | | |
2088 | | librdf_model *librdf_TypeConverter::createModel_Lock( |
2089 | | librdf_world *i_pWorld, librdf_storage * i_pStorage) const |
2090 | 6.73k | { |
2091 | 6.73k | librdf_model *pRepository( librdf_new_model(i_pWorld, i_pStorage, nullptr) ); |
2092 | 6.73k | if (!pRepository) { |
2093 | 0 | throw uno::RuntimeException( |
2094 | 0 | u"librdf_TypeConverter::createModel: librdf_new_model failed"_ustr, |
2095 | 0 | m_rRep); |
2096 | 0 | } |
2097 | | //FIXME |
2098 | | #if 0 |
2099 | | { |
2100 | | librdf_uri * ctxt = librdf_new_uri(i_pWorld, reinterpret_cast<const unsigned char *>(LIBRDF_MODEL_FEATURE_CONTEXTS)); |
2101 | | librdf_node * contexts = librdf_model_get_feature(repository, ctxt); |
2102 | | if (!contexts) |
2103 | | throw; |
2104 | | std::cout << "value of contexts feature: "; |
2105 | | prtNode(contexts); |
2106 | | std::cout << std::endl; |
2107 | | // librdf_model_set_feature(repository, LIBRDF_FEATURE_CONTEXTS, ...); |
2108 | | safe_librdf_free_node(contexts); |
2109 | | safe_librdf_free_uri(ctxt); |
2110 | | } |
2111 | | #endif |
2112 | 6.73k | return pRepository; |
2113 | 6.73k | } |
2114 | | |
2115 | | // this does NOT create a node, only URI |
2116 | | librdf_uri* librdf_TypeConverter::mkURI_Lock( librdf_world* i_pWorld, |
2117 | | OString const& i_rURI) |
2118 | 0 | { |
2119 | 0 | librdf_uri *pURI( librdf_new_uri(i_pWorld, |
2120 | 0 | reinterpret_cast<const unsigned char *>(i_rURI.getStr()))); |
2121 | 0 | if (!pURI) { |
2122 | 0 | throw uno::RuntimeException( |
2123 | 0 | u"librdf_TypeConverter::mkURI: librdf_new_uri failed"_ustr, nullptr); |
2124 | 0 | } |
2125 | 0 | return pURI; |
2126 | 0 | } |
2127 | | |
2128 | | // extract blank or URI node - call without Mutex locked |
2129 | | std::shared_ptr<librdf_TypeConverter::Resource> |
2130 | | librdf_TypeConverter::extractResource_NoLock( |
2131 | | const uno::Reference< rdf::XResource > & i_xResource) |
2132 | 33.6k | { |
2133 | 33.6k | if (!i_xResource.is()) { |
2134 | 0 | return std::shared_ptr<Resource>(); |
2135 | 0 | } |
2136 | 33.6k | uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY); |
2137 | 33.6k | if (xBlankNode.is()) { |
2138 | 0 | const OString label( |
2139 | 0 | OUStringToOString(xBlankNode->getStringValue(), |
2140 | 0 | RTL_TEXTENCODING_UTF8) ); |
2141 | 0 | return std::make_shared<BlankNode>(label); |
2142 | 33.6k | } else { // assumption: everything else is URI |
2143 | 33.6k | const OString uri( |
2144 | 33.6k | OUStringToOString(i_xResource->getStringValue(), |
2145 | 33.6k | RTL_TEXTENCODING_UTF8) ); |
2146 | 33.6k | return std::make_shared<URI>(uri); |
2147 | 33.6k | } |
2148 | 33.6k | } |
2149 | | |
2150 | | void |
2151 | | librdf_TypeConverter::extractResourceToCacheKey_NoLock( |
2152 | | const uno::Reference< rdf::XResource > & i_xResource, OUStringBuffer& rBuffer) |
2153 | 15.6k | { |
2154 | 15.6k | if (!i_xResource.is()) { |
2155 | 0 | return; |
2156 | 0 | } |
2157 | 15.6k | uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY); |
2158 | 15.6k | if (xBlankNode.is()) { |
2159 | 0 | rBuffer.append("BlankNode " + xBlankNode->getStringValue()); |
2160 | 15.6k | } else { // assumption: everything else is URI |
2161 | 15.6k | rBuffer.append("URI " + i_xResource->getStringValue()); |
2162 | 15.6k | } |
2163 | 15.6k | } |
2164 | | |
2165 | | // create blank or URI node |
2166 | | librdf_node* librdf_TypeConverter::mkResource_Lock( librdf_world* i_pWorld, |
2167 | | Resource const*const i_pResource) |
2168 | 33.6k | { |
2169 | 33.6k | if (!i_pResource) return nullptr; |
2170 | 33.6k | BlankNode const*const pBlankNode( |
2171 | 33.6k | dynamic_cast<BlankNode const*>(i_pResource)); |
2172 | 33.6k | if (pBlankNode) { |
2173 | 0 | librdf_node *pNode( |
2174 | 0 | librdf_new_node_from_blank_identifier(i_pWorld, |
2175 | 0 | reinterpret_cast<const unsigned char*>( |
2176 | 0 | pBlankNode->value.getStr()))); |
2177 | 0 | if (!pNode) { |
2178 | 0 | throw uno::RuntimeException( |
2179 | 0 | u"librdf_TypeConverter::mkResource: " |
2180 | 0 | "librdf_new_node_from_blank_identifier failed"_ustr, nullptr); |
2181 | 0 | } |
2182 | 0 | return pNode; |
2183 | 33.6k | } else { // assumption: everything else is URI |
2184 | 33.6k | URI const*const pURI(dynamic_cast<URI const*>(i_pResource)); |
2185 | 33.6k | assert(pURI); |
2186 | 33.6k | librdf_node *pNode( |
2187 | 33.6k | librdf_new_node_from_uri_string(i_pWorld, |
2188 | 33.6k | reinterpret_cast<const unsigned char*>(pURI->value.getStr()))); |
2189 | 33.6k | if (!pNode) { |
2190 | 0 | throw uno::RuntimeException( |
2191 | 0 | u"librdf_TypeConverter::mkResource: " |
2192 | 0 | "librdf_new_node_from_uri_string failed"_ustr, nullptr); |
2193 | 0 | } |
2194 | 33.6k | return pNode; |
2195 | 33.6k | } |
2196 | 33.6k | } |
2197 | | |
2198 | | // extract blank or URI or literal node - call without Mutex locked |
2199 | | std::shared_ptr<librdf_TypeConverter::Node> |
2200 | | librdf_TypeConverter::extractNode_NoLock( |
2201 | | const uno::Reference< rdf::XNode > & i_xNode) |
2202 | 13.4k | { |
2203 | 13.4k | if (!i_xNode.is()) { |
2204 | 6.73k | return std::shared_ptr<Node>(); |
2205 | 6.73k | } |
2206 | 6.73k | uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY); |
2207 | 6.73k | if (xResource.is()) { |
2208 | 6.73k | return extractResource_NoLock(xResource); |
2209 | 6.73k | } |
2210 | 0 | uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY); |
2211 | 0 | OSL_ENSURE(xLiteral.is(), |
2212 | 0 | "mkNode: someone invented a new rdf.XNode and did not tell me"); |
2213 | 0 | if (!xLiteral.is()) { |
2214 | 0 | return std::shared_ptr<Node>(); |
2215 | 0 | } |
2216 | 0 | const OString val( |
2217 | 0 | OUStringToOString(xLiteral->getValue(), |
2218 | 0 | RTL_TEXTENCODING_UTF8) ); |
2219 | 0 | const OString lang( |
2220 | 0 | OUStringToOString(xLiteral->getLanguage(), |
2221 | 0 | RTL_TEXTENCODING_UTF8) ); |
2222 | 0 | const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype()); |
2223 | 0 | std::optional<OString> type; |
2224 | 0 | if (xType.is()) |
2225 | 0 | { |
2226 | 0 | type = |
2227 | 0 | OUStringToOString(xType->getStringValue(), RTL_TEXTENCODING_UTF8); |
2228 | 0 | } |
2229 | 0 | return std::make_shared<Literal>(val, lang, type); |
2230 | 0 | } |
2231 | | |
2232 | | // extract blank or URI or literal node - call without Mutex locked |
2233 | | void |
2234 | | librdf_TypeConverter::extractNodeToCacheKey_NoLock( |
2235 | | const uno::Reference< rdf::XNode > & i_xNode, |
2236 | | OUStringBuffer& rBuffer) |
2237 | 7.81k | { |
2238 | 7.81k | if (!i_xNode.is()) { |
2239 | 7.81k | return; |
2240 | 7.81k | } |
2241 | 0 | uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY); |
2242 | 0 | if (xResource.is()) { |
2243 | 0 | return extractResourceToCacheKey_NoLock(xResource, rBuffer); |
2244 | 0 | } |
2245 | 0 | uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY); |
2246 | 0 | OSL_ENSURE(xLiteral.is(), |
2247 | 0 | "mkNode: someone invented a new rdf.XNode and did not tell me"); |
2248 | 0 | if (!xLiteral.is()) { |
2249 | 0 | return; |
2250 | 0 | } |
2251 | 0 | rBuffer.append("Literal " + xLiteral->getValue() + "\t" + xLiteral->getLanguage()); |
2252 | 0 | const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype()); |
2253 | 0 | if (xType.is()) |
2254 | 0 | rBuffer.append("\t" + xType->getStringValue()); |
2255 | 0 | } |
2256 | | |
2257 | | // create blank or URI or literal node |
2258 | | librdf_node* librdf_TypeConverter::mkNode_Lock( librdf_world* i_pWorld, |
2259 | | Node const*const i_pNode) |
2260 | 13.4k | { |
2261 | 13.4k | if (!i_pNode) return nullptr; |
2262 | 6.73k | Resource const*const pResource(dynamic_cast<Resource const*>(i_pNode)); |
2263 | 6.73k | if (pResource) { |
2264 | 6.73k | return mkResource_Lock(i_pWorld, pResource); |
2265 | 6.73k | } |
2266 | | |
2267 | 0 | Literal const*const pLiteral(dynamic_cast<Literal const*>(i_pNode)); |
2268 | 0 | assert(pLiteral); |
2269 | 0 | librdf_node * ret(nullptr); |
2270 | 0 | if (pLiteral->language.isEmpty()) { |
2271 | 0 | if (!pLiteral->type) { |
2272 | 0 | ret = librdf_new_node_from_literal(i_pWorld, |
2273 | 0 | reinterpret_cast<const unsigned char*>(pLiteral->value.getStr()) |
2274 | 0 | , nullptr, 0); |
2275 | 0 | } else { |
2276 | 0 | const std::shared_ptr<librdf_uri> pDatatype( |
2277 | 0 | mkURI_Lock(i_pWorld, *pLiteral->type), |
2278 | 0 | safe_librdf_free_uri); |
2279 | 0 | ret = librdf_new_node_from_typed_literal(i_pWorld, |
2280 | 0 | reinterpret_cast<const unsigned char*>(pLiteral->value.getStr()) |
2281 | 0 | , nullptr, pDatatype.get()); |
2282 | 0 | } |
2283 | 0 | } else { |
2284 | 0 | if (!pLiteral->type) { |
2285 | 0 | ret = librdf_new_node_from_literal(i_pWorld, |
2286 | 0 | reinterpret_cast<const unsigned char*>(pLiteral->value.getStr()) |
2287 | 0 | , pLiteral->language.getStr(), 0); |
2288 | 0 | } else { |
2289 | 0 | OSL_FAIL("mkNode: invalid literal"); |
2290 | 0 | return nullptr; |
2291 | 0 | } |
2292 | 0 | } |
2293 | 0 | if (!ret) { |
2294 | 0 | throw uno::RuntimeException( |
2295 | 0 | u"librdf_TypeConverter::mkNode: librdf_new_node_from_literal failed"_ustr, nullptr); |
2296 | 0 | } |
2297 | 0 | return ret; |
2298 | 0 | } |
2299 | | |
2300 | | // extract statement - call without Mutex locked |
2301 | | librdf_TypeConverter::Statement librdf_TypeConverter::extractStatement_NoLock( |
2302 | | const uno::Reference< rdf::XResource > & i_xSubject, |
2303 | | const uno::Reference< rdf::XURI > & i_xPredicate, |
2304 | | const uno::Reference< rdf::XNode > & i_xObject) |
2305 | 13.4k | { |
2306 | 13.4k | std::shared_ptr<Resource> pSubject( |
2307 | 13.4k | extractResource_NoLock(i_xSubject)); |
2308 | 13.4k | std::shared_ptr<URI> pPredicate( |
2309 | 13.4k | std::dynamic_pointer_cast<URI>(extractResource_NoLock(i_xPredicate))); |
2310 | 13.4k | std::shared_ptr<Node> pObject(extractNode_NoLock(i_xObject)); |
2311 | 13.4k | return Statement(std::move(pSubject), std::move(pPredicate), std::move(pObject)); |
2312 | 13.4k | } |
2313 | | |
2314 | | librdf_statement* librdf_TypeConverter::mkStatement_Lock(librdf_world* i_pWorld, |
2315 | | Statement const& i_rStatement) |
2316 | 13.4k | { |
2317 | 13.4k | librdf_node *const pSubject( |
2318 | 13.4k | mkResource_Lock(i_pWorld, i_rStatement.pSubject.get()) ); |
2319 | 13.4k | librdf_node* pPredicate(nullptr); |
2320 | 13.4k | librdf_node* pObject(nullptr); |
2321 | 13.4k | try { |
2322 | 13.4k | pPredicate = mkResource_Lock(i_pWorld, i_rStatement.pPredicate.get()); |
2323 | 13.4k | try { |
2324 | 13.4k | pObject = mkNode_Lock(i_pWorld, i_rStatement.pObject.get()); |
2325 | 13.4k | } catch (...) { |
2326 | 0 | safe_librdf_free_node(pPredicate); |
2327 | 0 | throw; |
2328 | 0 | } |
2329 | 13.4k | } catch (...) { |
2330 | 0 | safe_librdf_free_node(pSubject); |
2331 | 0 | throw; |
2332 | 0 | } |
2333 | | // NB: this takes ownership of the nodes! (which is really ugly) |
2334 | 13.4k | librdf_statement* pStatement( librdf_new_statement_from_nodes(i_pWorld, |
2335 | 13.4k | pSubject, pPredicate, pObject) ); |
2336 | 13.4k | if (!pStatement) { |
2337 | 0 | throw uno::RuntimeException( |
2338 | 0 | u"librdf_TypeConverter::mkStatement: " |
2339 | 0 | "librdf_new_statement_from_nodes failed"_ustr, nullptr); |
2340 | 0 | } |
2341 | 13.4k | return pStatement; |
2342 | 13.4k | } |
2343 | | |
2344 | | uno::Reference<rdf::XURI> |
2345 | | librdf_TypeConverter::convertToXURI(librdf_uri* i_pURI) const |
2346 | 0 | { |
2347 | 0 | if (!i_pURI) return nullptr; |
2348 | 0 | const unsigned char* uri( librdf_uri_as_string(i_pURI) ); |
2349 | 0 | if (!uri) { |
2350 | 0 | throw uno::RuntimeException( |
2351 | 0 | u"librdf_TypeConverter::convertToXURI: " |
2352 | 0 | "librdf_uri_as_string failed"_ustr, m_rRep); |
2353 | 0 | } |
2354 | 0 | OUString uriU( OStringToOUString( |
2355 | 0 | std::string_view(reinterpret_cast<const char*>(uri)), |
2356 | 0 | RTL_TEXTENCODING_UTF8) ); |
2357 | 0 | try { |
2358 | 0 | return rdf::URI::create(m_xContext, uriU); |
2359 | 0 | } catch (const lang::IllegalArgumentException &) { |
2360 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
2361 | 0 | throw lang::WrappedTargetRuntimeException( |
2362 | 0 | u"librdf_TypeConverter::convertToXURI: " |
2363 | 0 | "illegal uri"_ustr, m_rRep, anyEx); |
2364 | 0 | } |
2365 | 0 | } |
2366 | | |
2367 | | uno::Reference<rdf::XURI> |
2368 | | librdf_TypeConverter::convertToXURI(librdf_node* i_pNode) const |
2369 | 0 | { |
2370 | 0 | if (!i_pNode) return nullptr; |
2371 | 0 | if (librdf_node_is_resource(i_pNode)) { |
2372 | 0 | librdf_uri* pURI( librdf_node_get_uri(i_pNode) ); |
2373 | 0 | if (!pURI) { |
2374 | 0 | throw uno::RuntimeException( |
2375 | 0 | u"librdf_TypeConverter::convertToXURI: " |
2376 | 0 | "resource has no uri"_ustr, m_rRep); |
2377 | 0 | } |
2378 | 0 | return convertToXURI(pURI); |
2379 | 0 | } else { |
2380 | 0 | OSL_FAIL("convertToXURI: unknown librdf_node"); |
2381 | 0 | return nullptr; |
2382 | 0 | } |
2383 | 0 | } |
2384 | | |
2385 | | uno::Reference<rdf::XResource> |
2386 | | librdf_TypeConverter::convertToXResource(librdf_node* i_pNode) const |
2387 | 0 | { |
2388 | 0 | if (!i_pNode) return nullptr; |
2389 | 0 | if (librdf_node_is_blank(i_pNode)) { |
2390 | 0 | const unsigned char* label( librdf_node_get_blank_identifier(i_pNode) ); |
2391 | 0 | if (!label) { |
2392 | 0 | throw uno::RuntimeException( |
2393 | 0 | u"librdf_TypeConverter::convertToXResource: " |
2394 | 0 | "blank node has no label"_ustr, m_rRep); |
2395 | 0 | } |
2396 | 0 | OUString labelU( OStringToOUString( |
2397 | 0 | std::string_view(reinterpret_cast<const char*>(label)), |
2398 | 0 | RTL_TEXTENCODING_UTF8) ); |
2399 | 0 | try { |
2400 | 0 | return rdf::BlankNode::create(m_xContext, labelU); |
2401 | 0 | } catch (const lang::IllegalArgumentException &) { |
2402 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
2403 | 0 | throw lang::WrappedTargetRuntimeException( |
2404 | 0 | u"librdf_TypeConverter::convertToXResource: " |
2405 | 0 | "illegal blank node label"_ustr, m_rRep, anyEx); |
2406 | 0 | } |
2407 | 0 | } else { |
2408 | 0 | return convertToXURI(i_pNode); |
2409 | 0 | } |
2410 | 0 | } |
2411 | | |
2412 | | uno::Reference<rdf::XNode> |
2413 | | librdf_TypeConverter::convertToXNode(librdf_node* i_pNode) const |
2414 | 0 | { |
2415 | 0 | if (!i_pNode) return nullptr; |
2416 | 0 | if (!librdf_node_is_literal(i_pNode)) { |
2417 | 0 | return convertToXResource(i_pNode); |
2418 | 0 | } |
2419 | 0 | const unsigned char* value( librdf_node_get_literal_value(i_pNode) ); |
2420 | 0 | if (!value) { |
2421 | 0 | throw uno::RuntimeException( |
2422 | 0 | u"librdf_TypeConverter::convertToXNode: " |
2423 | 0 | "literal has no value"_ustr, m_rRep); |
2424 | 0 | } |
2425 | 0 | const char * lang( librdf_node_get_literal_value_language(i_pNode) ); |
2426 | 0 | librdf_uri* pType( |
2427 | 0 | librdf_node_get_literal_value_datatype_uri(i_pNode) ); |
2428 | 0 | OSL_ENSURE(!lang || !pType, "convertToXNode: invalid literal"); |
2429 | 0 | const OUString valueU( OStringToOUString( |
2430 | 0 | std::string_view(reinterpret_cast<const char*>(value)), |
2431 | 0 | RTL_TEXTENCODING_UTF8) ); |
2432 | 0 | if (lang) { |
2433 | 0 | const OUString langU( OStringToOUString( |
2434 | 0 | std::string_view(lang), |
2435 | 0 | RTL_TEXTENCODING_UTF8) ); |
2436 | 0 | return rdf::Literal::createWithLanguage(m_xContext, valueU, langU); |
2437 | 0 | } else if (pType) { |
2438 | 0 | uno::Reference<rdf::XURI> xType(convertToXURI(pType)); |
2439 | 0 | OSL_ENSURE(xType.is(), "convertToXNode: null uri"); |
2440 | 0 | return rdf::Literal::createWithType(m_xContext, valueU, xType); |
2441 | 0 | } else { |
2442 | 0 | return rdf::Literal::create(m_xContext, valueU); |
2443 | 0 | } |
2444 | 0 | } |
2445 | | |
2446 | | rdf::Statement |
2447 | | librdf_TypeConverter::convertToStatement(librdf_statement* i_pStmt, |
2448 | | librdf_node* i_pContext) const |
2449 | 0 | { |
2450 | 0 | if (!i_pStmt) { |
2451 | 0 | throw uno::RuntimeException(); |
2452 | 0 | } |
2453 | 0 | return rdf::Statement( |
2454 | 0 | convertToXResource(librdf_statement_get_subject(i_pStmt)), |
2455 | 0 | convertToXURI(librdf_statement_get_predicate(i_pStmt)), |
2456 | 0 | convertToXNode(librdf_statement_get_object(i_pStmt)), |
2457 | 0 | convertToXURI(i_pContext)); |
2458 | 0 | } |
2459 | | |
2460 | | } // closing anonymous implementation namespace |
2461 | | |
2462 | | |
2463 | | extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* |
2464 | | unoxml_rdfRepository_get_implementation( |
2465 | | css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&) |
2466 | 6.73k | { |
2467 | 6.73k | return cppu::acquire(new librdf_Repository(context)); |
2468 | 6.73k | } |
2469 | | |
2470 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |