/src/libreoffice/desktop/source/deployment/registry/dp_backenddb.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | |
21 | | #include <cppuhelper/exc_hlp.hxx> |
22 | | #include <osl/diagnose.h> |
23 | | #include <osl/file.hxx> |
24 | | #include <com/sun/star/deployment/DeploymentException.hpp> |
25 | | #include <com/sun/star/uno/XComponentContext.hpp> |
26 | | #include <com/sun/star/xml/dom/DocumentBuilder.hpp> |
27 | | #include <com/sun/star/xml/xpath/XPathAPI.hpp> |
28 | | #include <com/sun/star/io/XActiveDataSource.hpp> |
29 | | #include <com/sun/star/io/XActiveDataControl.hpp> |
30 | | #include <dp_misc.h> |
31 | | #include <ucbhelper/content.hxx> |
32 | | #include <xmlscript/xml_helper.hxx> |
33 | | #include <dp_backenddb.hxx> |
34 | | |
35 | | |
36 | | using namespace ::com::sun::star::uno; |
37 | | |
38 | | |
39 | | namespace dp_registry::backend { |
40 | | |
41 | | BackendDb::BackendDb( |
42 | | Reference<css::uno::XComponentContext> const & xContext, |
43 | | OUString const & url): |
44 | 0 | m_xContext(xContext) |
45 | 0 | { |
46 | 0 | m_urlDb = dp_misc::expandUnoRcUrl(url); |
47 | 0 | } |
48 | | |
49 | | void BackendDb::save() |
50 | 0 | { |
51 | 0 | const Reference<css::io::XActiveDataSource> xDataSource(m_doc,css::uno::UNO_QUERY_THROW); |
52 | 0 | std::vector<sal_Int8> bytes; |
53 | 0 | xDataSource->setOutputStream(::xmlscript::createOutputStream(&bytes)); |
54 | 0 | const Reference<css::io::XActiveDataControl> xDataControl(m_doc,css::uno::UNO_QUERY_THROW); |
55 | 0 | xDataControl->start(); |
56 | |
|
57 | 0 | const Reference<css::io::XInputStream> xData( |
58 | 0 | ::xmlscript::createInputStream(std::move(bytes))); |
59 | 0 | ::ucbhelper::Content ucbDb(m_urlDb, nullptr, m_xContext); |
60 | 0 | ucbDb.writeStream(xData, true /*replace existing*/); |
61 | 0 | } |
62 | | |
63 | | css::uno::Reference<css::xml::dom::XDocument> const & BackendDb::getDocument() |
64 | 0 | { |
65 | 0 | if (!m_doc.is()) |
66 | 0 | { |
67 | 0 | const Reference<css::xml::dom::XDocumentBuilder> xDocBuilder( |
68 | 0 | css::xml::dom::DocumentBuilder::create(m_xContext) ); |
69 | |
|
70 | 0 | ::osl::DirectoryItem item; |
71 | 0 | ::osl::File::RC err = ::osl::DirectoryItem::get(m_urlDb, item); |
72 | 0 | if (err == ::osl::File::E_None) |
73 | 0 | { |
74 | 0 | ::ucbhelper::Content descContent( |
75 | 0 | m_urlDb, css::uno::Reference<css::ucb::XCommandEnvironment>(), |
76 | 0 | m_xContext); |
77 | 0 | Reference<css::io::XInputStream> xIn = descContent.openStream(); |
78 | 0 | m_doc = xDocBuilder->parse(xIn); |
79 | 0 | } |
80 | 0 | else if (err == ::osl::File::E_NOENT) |
81 | 0 | { |
82 | | //Create a new document and insert some basic stuff |
83 | 0 | m_doc = xDocBuilder->newDocument(); |
84 | 0 | const Reference<css::xml::dom::XElement> rootNode = |
85 | 0 | m_doc->createElementNS(getDbNSName(), getNSPrefix() + |
86 | 0 | ":" + getRootElementName()); |
87 | |
|
88 | 0 | m_doc->appendChild(Reference<css::xml::dom::XNode>( |
89 | 0 | rootNode, UNO_QUERY_THROW)); |
90 | 0 | save(); |
91 | 0 | } |
92 | 0 | else |
93 | 0 | throw css::uno::RuntimeException( |
94 | 0 | "Extension manager could not access database file:" |
95 | 0 | + m_urlDb, nullptr); |
96 | | |
97 | 0 | if (!m_doc.is()) |
98 | 0 | throw css::uno::RuntimeException( |
99 | 0 | "Extension manager could not get root node of data base file: " |
100 | 0 | + m_urlDb, nullptr); |
101 | 0 | } |
102 | | |
103 | 0 | return m_doc; |
104 | 0 | } |
105 | | |
106 | | Reference<css::xml::xpath::XXPathAPI> const & BackendDb::getXPathAPI() |
107 | 0 | { |
108 | 0 | if (!m_xpathApi.is()) |
109 | 0 | { |
110 | 0 | m_xpathApi = css::xml::xpath::XPathAPI::create( m_xContext ); |
111 | |
|
112 | 0 | m_xpathApi->registerNS( getNSPrefix(), getDbNSName() ); |
113 | 0 | } |
114 | |
|
115 | 0 | return m_xpathApi; |
116 | 0 | } |
117 | | |
118 | | void BackendDb::removeElement(OUString const & sXPathExpression) |
119 | 0 | { |
120 | 0 | try |
121 | 0 | { |
122 | 0 | const Reference<css::xml::dom::XDocument> doc = getDocument(); |
123 | 0 | const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); |
124 | 0 | const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); |
125 | | //find the extension element that is to be removed |
126 | 0 | const Reference<css::xml::dom::XNode> aNode = |
127 | 0 | xpathApi->selectSingleNode(root, sXPathExpression); |
128 | |
|
129 | 0 | if (aNode.is()) |
130 | 0 | { |
131 | 0 | root->removeChild(aNode); |
132 | 0 | save(); |
133 | 0 | } |
134 | |
|
135 | | #if OSL_DEBUG_LEVEL > 0 |
136 | | //There must not be any other entry with the same url |
137 | | const Reference<css::xml::dom::XNode> nextNode = |
138 | | xpathApi->selectSingleNode(root, sXPathExpression); |
139 | | OSL_ASSERT(! nextNode.is()); |
140 | | #endif |
141 | 0 | } |
142 | 0 | catch(const css::uno::Exception &) |
143 | 0 | { |
144 | 0 | Any exc( ::cppu::getCaughtException() ); |
145 | 0 | throw css::deployment::DeploymentException( |
146 | 0 | "Extension Manager: failed to write data entry in backend db: " + |
147 | 0 | m_urlDb, nullptr, exc); |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | | void BackendDb::removeEntry(std::u16string_view url) |
152 | 0 | { |
153 | 0 | const OUString sKeyElement = getKeyElementName(); |
154 | 0 | const OUString sPrefix = getNSPrefix(); |
155 | 0 | OUString sExpression = |
156 | 0 | sPrefix + |
157 | 0 | ":" + |
158 | 0 | sKeyElement + |
159 | 0 | "[@url = \"" + |
160 | 0 | url + |
161 | 0 | "\"]"; |
162 | |
|
163 | 0 | removeElement(sExpression); |
164 | 0 | } |
165 | | |
166 | | void BackendDb::revokeEntry(std::u16string_view url) |
167 | 0 | { |
168 | 0 | try |
169 | 0 | { |
170 | 0 | Reference<css::xml::dom::XElement> entry(getKeyElement(url), UNO_QUERY); |
171 | 0 | if (entry.is()) |
172 | 0 | { |
173 | 0 | entry->setAttribute(u"revoked"_ustr, u"true"_ustr); |
174 | 0 | save(); |
175 | 0 | } |
176 | 0 | } |
177 | 0 | catch(const css::uno::Exception &) |
178 | 0 | { |
179 | 0 | Any exc( ::cppu::getCaughtException() ); |
180 | 0 | throw css::deployment::DeploymentException( |
181 | 0 | "Extension Manager: failed to revoke data entry in backend db: " + |
182 | 0 | m_urlDb, nullptr, exc); |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | | bool BackendDb::activateEntry(std::u16string_view url) |
187 | 0 | { |
188 | 0 | try |
189 | 0 | { |
190 | 0 | bool ret = false; |
191 | 0 | Reference<css::xml::dom::XElement> entry(getKeyElement(url), UNO_QUERY); |
192 | 0 | if (entry.is()) |
193 | 0 | { |
194 | | //no attribute "active" means it is active, that is, registered. |
195 | 0 | entry->removeAttribute(u"revoked"_ustr); |
196 | 0 | save(); |
197 | 0 | ret = true; |
198 | 0 | } |
199 | 0 | return ret; |
200 | 0 | } |
201 | 0 | catch(const css::uno::Exception &) |
202 | 0 | { |
203 | 0 | Any exc( ::cppu::getCaughtException() ); |
204 | 0 | throw css::deployment::DeploymentException( |
205 | 0 | "Extension Manager: failed to revoke data entry in backend db: " + |
206 | 0 | m_urlDb, nullptr, exc); |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | | bool BackendDb::hasActiveEntry(std::u16string_view url) |
211 | 0 | { |
212 | 0 | try |
213 | 0 | { |
214 | 0 | bool ret = false; |
215 | 0 | Reference<css::xml::dom::XElement> entry(getKeyElement(url), UNO_QUERY); |
216 | 0 | if (entry.is()) |
217 | 0 | { |
218 | 0 | OUString sActive = entry->getAttribute(u"revoked"_ustr); |
219 | 0 | if (!(sActive == "true")) |
220 | 0 | ret = true; |
221 | 0 | } |
222 | 0 | return ret; |
223 | |
|
224 | 0 | } |
225 | 0 | catch(const css::uno::Exception &) |
226 | 0 | { |
227 | 0 | Any exc( ::cppu::getCaughtException() ); |
228 | 0 | throw css::deployment::DeploymentException( |
229 | 0 | "Extension Manager: failed to determine an active entry in backend db: " + |
230 | 0 | m_urlDb, nullptr, exc); |
231 | 0 | } |
232 | 0 | } |
233 | | |
234 | | Reference<css::xml::dom::XNode> BackendDb::getKeyElement( |
235 | | std::u16string_view url) |
236 | 0 | { |
237 | 0 | try |
238 | 0 | { |
239 | 0 | const OUString sPrefix = getNSPrefix(); |
240 | 0 | const OUString sKeyElement = getKeyElementName(); |
241 | 0 | OUString sExpression = |
242 | 0 | sPrefix + |
243 | 0 | ":" + |
244 | 0 | sKeyElement + |
245 | 0 | "[@url = \"" + |
246 | 0 | url + |
247 | 0 | "\"]"; |
248 | |
|
249 | 0 | const Reference<css::xml::dom::XDocument> doc = getDocument(); |
250 | 0 | const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); |
251 | 0 | const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); |
252 | 0 | return xpathApi->selectSingleNode(root, sExpression); |
253 | 0 | } |
254 | 0 | catch(const css::uno::Exception &) |
255 | 0 | { |
256 | 0 | Any exc( ::cppu::getCaughtException() ); |
257 | 0 | throw css::deployment::DeploymentException( |
258 | 0 | "Extension Manager: failed to read key element in backend db: " + |
259 | 0 | m_urlDb, nullptr, exc); |
260 | 0 | } |
261 | 0 | } |
262 | | |
263 | | //Only writes the data if there is at least one entry |
264 | | void BackendDb::writeVectorOfPair( |
265 | | std::vector< std::pair< OUString, OUString > > const & vecPairs, |
266 | | std::u16string_view sVectorTagName, |
267 | | std::u16string_view sPairTagName, |
268 | | std::u16string_view sFirstTagName, |
269 | | std::u16string_view sSecondTagName, |
270 | | css::uno::Reference<css::xml::dom::XNode> const & xParent) |
271 | 0 | { |
272 | 0 | try{ |
273 | 0 | if (vecPairs.empty()) |
274 | 0 | return; |
275 | 0 | const OUString sNameSpace = getDbNSName(); |
276 | 0 | OSL_ASSERT(!sNameSpace.isEmpty()); |
277 | 0 | const OUString sPrefix(getNSPrefix() + ":"); |
278 | 0 | const Reference<css::xml::dom::XDocument> doc = getDocument(); |
279 | |
|
280 | 0 | const Reference<css::xml::dom::XElement> vectorNode( |
281 | 0 | doc->createElementNS(sNameSpace, sPrefix + sVectorTagName)); |
282 | |
|
283 | 0 | xParent->appendChild( |
284 | 0 | Reference<css::xml::dom::XNode>( |
285 | 0 | vectorNode, css::uno::UNO_QUERY_THROW)); |
286 | 0 | for (auto const& vecPair : vecPairs) |
287 | 0 | { |
288 | 0 | const Reference<css::xml::dom::XElement> pairNode( |
289 | 0 | doc->createElementNS(sNameSpace, sPrefix + sPairTagName)); |
290 | |
|
291 | 0 | vectorNode->appendChild( |
292 | 0 | Reference<css::xml::dom::XNode>( |
293 | 0 | pairNode, css::uno::UNO_QUERY_THROW)); |
294 | |
|
295 | 0 | const Reference<css::xml::dom::XElement> firstNode( |
296 | 0 | doc->createElementNS(sNameSpace, sPrefix + sFirstTagName)); |
297 | |
|
298 | 0 | pairNode->appendChild( |
299 | 0 | Reference<css::xml::dom::XNode>( |
300 | 0 | firstNode, css::uno::UNO_QUERY_THROW)); |
301 | |
|
302 | 0 | const Reference<css::xml::dom::XText> firstTextNode( |
303 | 0 | doc->createTextNode( vecPair.first)); |
304 | |
|
305 | 0 | firstNode->appendChild( |
306 | 0 | Reference<css::xml::dom::XNode>( |
307 | 0 | firstTextNode, css::uno::UNO_QUERY_THROW)); |
308 | |
|
309 | 0 | const Reference<css::xml::dom::XElement> secondNode( |
310 | 0 | doc->createElementNS(sNameSpace, sPrefix + sSecondTagName)); |
311 | |
|
312 | 0 | pairNode->appendChild( |
313 | 0 | Reference<css::xml::dom::XNode>( |
314 | 0 | secondNode, css::uno::UNO_QUERY_THROW)); |
315 | |
|
316 | 0 | const Reference<css::xml::dom::XText> secondTextNode( |
317 | 0 | doc->createTextNode( vecPair.second)); |
318 | |
|
319 | 0 | secondNode->appendChild( |
320 | 0 | Reference<css::xml::dom::XNode>( |
321 | 0 | secondTextNode, css::uno::UNO_QUERY_THROW)); |
322 | 0 | } |
323 | 0 | } |
324 | 0 | catch(const css::uno::Exception &) |
325 | 0 | { |
326 | 0 | Any exc( ::cppu::getCaughtException() ); |
327 | 0 | throw css::deployment::DeploymentException( |
328 | 0 | "Extension Manager: failed to write data entry in backend db: " + |
329 | 0 | m_urlDb, nullptr, exc); |
330 | 0 | } |
331 | 0 | } |
332 | | |
333 | | std::vector< std::pair< OUString, OUString > > |
334 | | BackendDb::readVectorOfPair( |
335 | | Reference<css::xml::dom::XNode> const & parent, |
336 | | std::u16string_view sListTagName, |
337 | | std::u16string_view sPairTagName, |
338 | | std::u16string_view sFirstTagName, |
339 | | std::u16string_view sSecondTagName) |
340 | 0 | { |
341 | 0 | try |
342 | 0 | { |
343 | 0 | OSL_ASSERT(parent.is()); |
344 | 0 | const OUString sPrefix(getNSPrefix() + ":"); |
345 | 0 | const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); |
346 | 0 | const OUString sExprPairs( |
347 | 0 | sPrefix + sListTagName + "/" + sPrefix + sPairTagName); |
348 | 0 | const Reference<css::xml::dom::XNodeList> listPairs = |
349 | 0 | xpathApi->selectNodeList(parent, sExprPairs); |
350 | |
|
351 | 0 | std::vector< std::pair< OUString, OUString > > retVector; |
352 | 0 | sal_Int32 length = listPairs->getLength(); |
353 | 0 | for (sal_Int32 i = 0; i < length; i++) |
354 | 0 | { |
355 | 0 | const Reference<css::xml::dom::XNode> aPair = listPairs->item(i); |
356 | 0 | const OUString sExprFirst(sPrefix + sFirstTagName + "/text()"); |
357 | 0 | const Reference<css::xml::dom::XNode> first = |
358 | 0 | xpathApi->selectSingleNode(aPair, sExprFirst); |
359 | |
|
360 | 0 | const OUString sExprSecond(sPrefix + sSecondTagName + "/text()"); |
361 | 0 | const Reference<css::xml::dom::XNode> second = |
362 | 0 | xpathApi->selectSingleNode(aPair, sExprSecond); |
363 | 0 | OSL_ASSERT(first.is() && second.is()); |
364 | |
|
365 | 0 | retVector.emplace_back( |
366 | 0 | first->getNodeValue(), second->getNodeValue()); |
367 | 0 | } |
368 | 0 | return retVector; |
369 | 0 | } |
370 | 0 | catch(const css::uno::Exception &) |
371 | 0 | { |
372 | 0 | Any exc( ::cppu::getCaughtException() ); |
373 | 0 | throw css::deployment::DeploymentException( |
374 | 0 | "Extension Manager: failed to read data entry in backend db: " + |
375 | 0 | m_urlDb, nullptr, exc); |
376 | 0 | } |
377 | 0 | } |
378 | | |
379 | | //Only writes the data if there is at least one entry |
380 | | void BackendDb::writeSimpleList( |
381 | | std::deque< OUString> const & list, |
382 | | std::u16string_view sListTagName, |
383 | | std::u16string_view sMemberTagName, |
384 | | Reference<css::xml::dom::XNode> const & xParent) |
385 | 0 | { |
386 | 0 | try |
387 | 0 | { |
388 | 0 | if (list.empty()) |
389 | 0 | return; |
390 | 0 | const OUString sNameSpace = getDbNSName(); |
391 | 0 | const OUString sPrefix(getNSPrefix() + ":"); |
392 | 0 | const Reference<css::xml::dom::XDocument> doc = getDocument(); |
393 | |
|
394 | 0 | const Reference<css::xml::dom::XElement> listNode( |
395 | 0 | doc->createElementNS(sNameSpace, sPrefix + sListTagName)); |
396 | |
|
397 | 0 | xParent->appendChild( |
398 | 0 | Reference<css::xml::dom::XNode>( |
399 | 0 | listNode, css::uno::UNO_QUERY_THROW)); |
400 | |
|
401 | 0 | for (auto const& elem : list) |
402 | 0 | { |
403 | 0 | const Reference<css::xml::dom::XNode> memberNode( |
404 | 0 | doc->createElementNS(sNameSpace, sPrefix + sMemberTagName), css::uno::UNO_QUERY_THROW); |
405 | |
|
406 | 0 | listNode->appendChild(memberNode); |
407 | |
|
408 | 0 | const Reference<css::xml::dom::XNode> textNode( |
409 | 0 | doc->createTextNode(elem), css::uno::UNO_QUERY_THROW); |
410 | |
|
411 | 0 | memberNode->appendChild(textNode); |
412 | 0 | } |
413 | 0 | } |
414 | 0 | catch(const css::uno::Exception &) |
415 | 0 | { |
416 | 0 | Any exc( ::cppu::getCaughtException() ); |
417 | 0 | throw css::deployment::DeploymentException( |
418 | 0 | "Extension Manager: failed to write data entry in backend db: " + |
419 | 0 | m_urlDb, nullptr, exc); |
420 | 0 | } |
421 | 0 | } |
422 | | |
423 | | //Writes only the element if is has a value. |
424 | | //The prefix is automatically added to the element name |
425 | | void BackendDb::writeSimpleElement( |
426 | | std::u16string_view sElementName, OUString const & value, |
427 | | Reference<css::xml::dom::XNode> const & xParent) |
428 | 0 | { |
429 | 0 | try |
430 | 0 | { |
431 | 0 | if (value.isEmpty()) |
432 | 0 | return; |
433 | 0 | const OUString sPrefix = getNSPrefix(); |
434 | 0 | const Reference<css::xml::dom::XDocument> doc = getDocument(); |
435 | 0 | const OUString sNameSpace = getDbNSName(); |
436 | 0 | const Reference<css::xml::dom::XNode> dataNode( |
437 | 0 | doc->createElementNS(sNameSpace, sPrefix + ":" + sElementName), |
438 | 0 | UNO_QUERY_THROW); |
439 | 0 | xParent->appendChild(dataNode); |
440 | |
|
441 | 0 | const Reference<css::xml::dom::XNode> dataValue( |
442 | 0 | doc->createTextNode(value), UNO_QUERY_THROW); |
443 | 0 | dataNode->appendChild(dataValue); |
444 | 0 | } |
445 | 0 | catch(const css::uno::Exception &) |
446 | 0 | { |
447 | 0 | Any exc( ::cppu::getCaughtException() ); |
448 | 0 | throw css::deployment::DeploymentException( |
449 | 0 | "Extension Manager: failed to write data entry(writeSimpleElement) in backend db: " + |
450 | 0 | m_urlDb, nullptr, exc); |
451 | 0 | } |
452 | |
|
453 | 0 | } |
454 | | |
455 | | /// The key elements have a url attribute and are always children of the root element. |
456 | | Reference<css::xml::dom::XNode> BackendDb::writeKeyElement( |
457 | | OUString const & url) |
458 | 0 | { |
459 | 0 | try |
460 | 0 | { |
461 | 0 | const OUString sNameSpace = getDbNSName(); |
462 | 0 | const OUString sPrefix = getNSPrefix(); |
463 | 0 | const OUString sElementName = getKeyElementName(); |
464 | 0 | const Reference<css::xml::dom::XDocument> doc = getDocument(); |
465 | 0 | const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); |
466 | | |
467 | | //Check if there are an entry with the same url. This can be the case if the |
468 | | //status of an XPackage is ambiguous. In this case a call to activateExtension |
469 | | //(dp_extensionmanager.cxx), will register the package again. See also |
470 | | //Package::processPackage_impl in dp_backend.cxx. |
471 | | //A package can become |
472 | | //invalid after its successful registration, for example if a second extension with |
473 | | //the same service is installed. |
474 | 0 | const OUString sExpression( |
475 | 0 | sPrefix + ":" + sElementName + "[@url = \"" + url + "\"]"); |
476 | 0 | const Reference<css::xml::dom::XNode> existingNode = |
477 | 0 | getXPathAPI()->selectSingleNode(root, sExpression); |
478 | 0 | if (existingNode.is()) |
479 | 0 | { |
480 | 0 | OSL_ASSERT(false); |
481 | | //replace the existing entry. |
482 | 0 | removeEntry(url); |
483 | 0 | } |
484 | |
|
485 | 0 | const Reference<css::xml::dom::XElement> keyElement( |
486 | 0 | doc->createElementNS(sNameSpace, sPrefix + ":" + sElementName)); |
487 | |
|
488 | 0 | keyElement->setAttribute(u"url"_ustr, url); |
489 | |
|
490 | 0 | const Reference<css::xml::dom::XNode> keyNode( |
491 | 0 | keyElement, UNO_QUERY_THROW); |
492 | 0 | root->appendChild(keyNode); |
493 | 0 | return keyNode; |
494 | 0 | } |
495 | 0 | catch(const css::uno::Exception &) |
496 | 0 | { |
497 | 0 | Any exc( ::cppu::getCaughtException() ); |
498 | 0 | throw css::deployment::DeploymentException( |
499 | 0 | "Extension Manager: failed to write key element in backend db: " + |
500 | 0 | m_urlDb, nullptr, exc); |
501 | 0 | } |
502 | 0 | } |
503 | | |
504 | | OUString BackendDb::readSimpleElement( |
505 | | std::u16string_view sElementName, Reference<css::xml::dom::XNode> const & xParent) |
506 | 0 | { |
507 | 0 | try |
508 | 0 | { |
509 | 0 | const OUString sPrefix = getNSPrefix(); |
510 | 0 | const OUString sExpr(sPrefix + ":" + sElementName + "/text()"); |
511 | 0 | const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); |
512 | 0 | const Reference<css::xml::dom::XNode> val = |
513 | 0 | xpathApi->selectSingleNode(xParent, sExpr); |
514 | 0 | if (val.is()) |
515 | 0 | return val->getNodeValue(); |
516 | 0 | return OUString(); |
517 | 0 | } |
518 | 0 | catch(const css::uno::Exception &) |
519 | 0 | { |
520 | 0 | Any exc( ::cppu::getCaughtException() ); |
521 | 0 | throw css::deployment::DeploymentException( |
522 | 0 | "Extension Manager: failed to read data (readSimpleElement) in backend db: " + |
523 | 0 | m_urlDb, nullptr, exc); |
524 | 0 | } |
525 | 0 | } |
526 | | |
527 | | |
528 | | std::deque< OUString> BackendDb::readList( |
529 | | Reference<css::xml::dom::XNode> const & parent, |
530 | | std::u16string_view sListTagName, |
531 | | std::u16string_view sMemberTagName) |
532 | 0 | { |
533 | 0 | try |
534 | 0 | { |
535 | 0 | OSL_ASSERT(parent.is()); |
536 | 0 | const OUString sPrefix(getNSPrefix() + ":"); |
537 | 0 | const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); |
538 | 0 | const OUString sExprList( |
539 | 0 | sPrefix + sListTagName + "/" + sPrefix + sMemberTagName + "/text()"); |
540 | 0 | const Reference<css::xml::dom::XNodeList> list = |
541 | 0 | xpathApi->selectNodeList(parent, sExprList); |
542 | |
|
543 | 0 | std::deque<OUString > retList; |
544 | 0 | sal_Int32 length = list->getLength(); |
545 | 0 | for (sal_Int32 i = 0; i < length; i++) |
546 | 0 | { |
547 | 0 | const Reference<css::xml::dom::XNode> member = list->item(i); |
548 | 0 | retList.push_back(member->getNodeValue()); |
549 | 0 | } |
550 | 0 | return retList; |
551 | 0 | } |
552 | 0 | catch(const css::uno::Exception &) |
553 | 0 | { |
554 | 0 | Any exc( ::cppu::getCaughtException() ); |
555 | 0 | throw css::deployment::DeploymentException( |
556 | 0 | "Extension Manager: failed to read data entry in backend db: " + |
557 | 0 | m_urlDb, nullptr, exc); |
558 | 0 | } |
559 | 0 | } |
560 | | |
561 | | std::vector<OUString> BackendDb::getOneChildFromAllEntries( |
562 | | std::u16string_view name) |
563 | 0 | { |
564 | 0 | try |
565 | 0 | { |
566 | 0 | std::vector<OUString> listRet; |
567 | 0 | Reference<css::xml::dom::XDocument> doc = getDocument(); |
568 | 0 | Reference<css::xml::dom::XNode> root = doc->getFirstChild(); |
569 | |
|
570 | 0 | Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); |
571 | 0 | const OUString sPrefix = getNSPrefix(); |
572 | 0 | const OUString sKeyElement = getKeyElementName(); |
573 | 0 | OUString sNodeSelectExpr = |
574 | 0 | sPrefix + |
575 | 0 | ":" + |
576 | 0 | sKeyElement + |
577 | 0 | "/" + |
578 | 0 | sPrefix + |
579 | 0 | ":" + |
580 | 0 | name + |
581 | 0 | "/text()"; |
582 | |
|
583 | 0 | Reference<css::xml::dom::XNodeList> nodes = |
584 | 0 | xpathApi->selectNodeList(root, sNodeSelectExpr); |
585 | 0 | if (nodes.is()) |
586 | 0 | { |
587 | 0 | sal_Int32 length = nodes->getLength(); |
588 | 0 | for (sal_Int32 i = 0; i < length; i++) |
589 | 0 | listRet.push_back(nodes->item(i)->getNodeValue()); |
590 | 0 | } |
591 | 0 | return listRet; |
592 | 0 | } |
593 | 0 | catch ( const css::deployment::DeploymentException& ) |
594 | 0 | { |
595 | 0 | throw; |
596 | 0 | } |
597 | 0 | catch(const css::uno::Exception &) |
598 | 0 | { |
599 | 0 | Any exc( ::cppu::getCaughtException() ); |
600 | 0 | throw css::deployment::DeploymentException( |
601 | 0 | "Extension Manager: failed to read data entry in backend db: " + |
602 | 0 | m_urlDb, nullptr, exc); |
603 | 0 | } |
604 | 0 | } |
605 | | |
606 | | |
607 | | RegisteredDb::RegisteredDb( |
608 | | Reference<XComponentContext> const & xContext, |
609 | 0 | OUString const & url):BackendDb(xContext, url) |
610 | 0 | { |
611 | 0 | } |
612 | | |
613 | | void RegisteredDb::addEntry(OUString const & url) |
614 | 0 | { |
615 | 0 | try{ |
616 | 0 | if (!activateEntry(url)) |
617 | 0 | { |
618 | 0 | const OUString sNameSpace = getDbNSName(); |
619 | 0 | const OUString sPrefix = getNSPrefix(); |
620 | 0 | const OUString sEntry = getKeyElementName(); |
621 | |
|
622 | 0 | Reference<css::xml::dom::XDocument> doc = getDocument(); |
623 | 0 | Reference<css::xml::dom::XNode> root = doc->getFirstChild(); |
624 | |
|
625 | | #if OSL_DEBUG_LEVEL > 0 |
626 | | //There must not be yet an entry with the same url |
627 | | OUString sExpression( |
628 | | sPrefix + ":" + sEntry + "[@url = \"" + url + "\"]"); |
629 | | Reference<css::xml::dom::XNode> _extensionNode = |
630 | | getXPathAPI()->selectSingleNode(root, sExpression); |
631 | | OSL_ASSERT(! _extensionNode.is()); |
632 | | #endif |
633 | 0 | Reference<css::xml::dom::XElement> helpElement( |
634 | 0 | doc->createElementNS(sNameSpace, sPrefix + ":" + sEntry)); |
635 | |
|
636 | 0 | helpElement->setAttribute(u"url"_ustr, url); |
637 | |
|
638 | 0 | Reference<css::xml::dom::XNode> helpNode( |
639 | 0 | helpElement, UNO_QUERY_THROW); |
640 | 0 | root->appendChild(helpNode); |
641 | |
|
642 | 0 | save(); |
643 | 0 | } |
644 | 0 | } |
645 | 0 | catch(const css::uno::Exception &) |
646 | 0 | { |
647 | 0 | Any exc( ::cppu::getCaughtException() ); |
648 | 0 | throw css::deployment::DeploymentException( |
649 | 0 | "Extension Manager: failed to write data entry in backend db: " + |
650 | 0 | m_urlDb, nullptr, exc); |
651 | 0 | } |
652 | 0 | } |
653 | | |
654 | | } // namespace dp_registry |
655 | | |
656 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |