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