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