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