LibreOffice Module ucbhelper (master) 1
providerhelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <com/sun/star/beans/IllegalTypeException.hpp>
23#include <com/sun/star/beans/PropertyExistException.hpp>
24#include <com/sun/star/beans/XPropertyAccess.hpp>
25#include <com/sun/star/container/XNameAccess.hpp>
26#include <com/sun/star/container/XNamed.hpp>
27#include <com/sun/star/ucb/Store.hpp>
28#include <com/sun/star/ucb/XPropertySetRegistry.hpp>
29#include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp>
33
34#include <osl/diagnose.h>
35#include <osl/mutex.hxx>
37
38#include <unordered_map>
39#include <utility>
40
41using namespace com::sun::star;
42
43namespace ucbhelper_impl
44{
45
46typedef std::unordered_map
47<
48 OUString,
49 uno::WeakReference< ucb::XContent >
50>
52
54{
55 uno::Reference< css::ucb::XPropertySetRegistry > m_xPropertySetRegistry;
57};
58
59} // namespace ucbhelper_impl
60
61namespace ucbhelper {
62
64 uno::Reference< uno::XComponentContext > xContext )
65: m_pImpl( new ucbhelper_impl::ContentProviderImplHelper_Impl ),
66 m_xContext(std::move( xContext ))
67{
68}
69
70// virtual
72{
73}
74
75// virtual
77 const OUString& ServiceName )
78{
80}
81
82// virtual
84 const uno::Reference< css::ucb::XContentIdentifier >& Id1,
85 const uno::Reference< css::ucb::XContentIdentifier >& Id2 )
86{
87 // Simply do a string compare.
88
89 OUString aURL1( Id1->getContentIdentifier() );
90 OUString aURL2( Id2->getContentIdentifier() );
91
92 return aURL1.compareTo( aURL2 );
93}
94
96{
97 osl::MutexGuard aGuard( m_aMutex );
98
99 ucbhelper_impl::Contents::iterator it
100 = m_pImpl->m_aContents.begin();
101 while( it != m_pImpl->m_aContents.end() )
102 {
103 uno::Reference< ucb::XContent > xContent( (*it).second );
104 if ( !xContent.is() )
105 {
106 ucbhelper_impl::Contents::iterator tmp = it;
107 ++it;
108 m_pImpl->m_aContents.erase( tmp );
109 }
110 else
111 {
112 ++it;
113 }
114 }
115}
116
118{
119 osl::MutexGuard aGuard( m_aMutex );
120
122
123 const OUString aURL(
124 pContent->getIdentifier()->getContentIdentifier() );
125
126 ucbhelper_impl::Contents::iterator it = m_pImpl->m_aContents.find( aURL );
127
128 if ( it != m_pImpl->m_aContents.end() )
129 m_pImpl->m_aContents.erase( it );
130}
131
134 const uno::Reference< css::ucb::XContentIdentifier >& Identifier )
135{
136 return queryExistingContent( Identifier->getContentIdentifier() );
137}
138
141{
142 osl::MutexGuard aGuard( m_aMutex );
143
145
146 // Check, if a content with given id already exists...
147
148 ucbhelper_impl::Contents::const_iterator it
149 = m_pImpl->m_aContents.find( rURL );
150 if ( it != m_pImpl->m_aContents.end() )
151 {
152 uno::Reference< ucb::XContent > xContent( (*it).second );
153 if ( xContent.is() )
154 {
156 static_cast< ContentImplHelper * >( xContent.get() ) );
157 }
158 }
160}
161
163 ContentRefList& rContents )
164{
165 osl::MutexGuard aGuard( m_aMutex );
166
168
169 for ( const auto& rContent : m_pImpl->m_aContents )
170 {
171 uno::Reference< ucb::XContent > xContent( rContent.second );
172 if ( xContent.is() )
173 {
174 rContents.emplace_back(
175 static_cast< ContentImplHelper * >( xContent.get() ) );
176 }
177 }
178}
179
181 const uno::Reference< ucb::XContent > & xContent )
182{
183 if ( !xContent.is() )
184 return;
185
186 osl::MutexGuard aGuard( m_aMutex );
187
189
190 const OUString aURL(
191 xContent->getIdentifier()->getContentIdentifier() );
192 ucbhelper_impl::Contents::const_iterator it
193 = m_pImpl->m_aContents.find( aURL );
194 if ( it == m_pImpl->m_aContents.end() )
195 m_pImpl->m_aContents[ aURL ] = xContent;
196}
197
198uno::Reference< css::ucb::XPropertySetRegistry >
200{
201 // Get propertyset registry.
202
203 osl::MutexGuard aGuard( m_aMutex );
204
205 if ( !m_pImpl->m_xPropertySetRegistry.is() )
206 {
207 uno::Reference< css::ucb::XPropertySetRegistryFactory >
208 xRegFac = css::ucb::Store::create( m_xContext );
209
210 // Open/create a registry.
211 m_pImpl->m_xPropertySetRegistry
212 = xRegFac->createPropertySetRegistry( OUString() );
213
214 OSL_ENSURE( m_pImpl->m_xPropertySetRegistry.is(),
215 "ContentProviderImplHelper::getAdditionalPropertySet - "
216 "Error opening registry!" );
217 }
218
219 return m_pImpl->m_xPropertySetRegistry;
220}
221
222uno::Reference< css::ucb::XPersistentPropertySet >
224 const OUString& rKey, bool bCreate )
225{
226 // Get propertyset registry.
228
229 if ( m_pImpl->m_xPropertySetRegistry.is() )
230 {
231 // Open/create persistent property set.
232 return m_pImpl->m_xPropertySetRegistry->openPropertySet(
233 rKey, bCreate );
234 }
235
236 return uno::Reference< css::ucb::XPersistentPropertySet >();
237}
238
240 const OUString& rOldKey,
241 const OUString& rNewKey,
242 bool bRecursive )
243{
244 if ( rOldKey == rNewKey )
245 return true;
246
247 osl::MutexGuard aGuard( m_aMutex );
248
249 if ( bRecursive )
250 {
251 // Get propertyset registry.
253
254 if ( !m_pImpl->m_xPropertySetRegistry.is() )
255 return false;
256
257 uno::Reference< container::XNameAccess > xNameAccess(
258 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
259 if ( !xNameAccess.is() )
260 return false;
261
262 const uno::Sequence< OUString > aKeys
263 = xNameAccess->getElementNames();
264 if ( aKeys.hasElements() )
265 {
266 OUString aOldKeyWithSlash = rOldKey;
267 OUString aOldKeyWithoutSlash;
268 if ( !aOldKeyWithSlash.endsWith("/") )
269 {
270 aOldKeyWithSlash += "/";
271 aOldKeyWithoutSlash = rOldKey;
272 }
273 else if ( !rOldKey.isEmpty() )
274 aOldKeyWithoutSlash
275 = rOldKey.copy( 0, rOldKey.getLength() - 1 );
276
277 for ( const OUString& rKey : aKeys )
278 {
279 if ( rKey.startsWith( aOldKeyWithSlash )
280 || rKey == aOldKeyWithoutSlash )
281 {
282 OUString aNewKey
283 = rKey.replaceAt(
284 0, rOldKey.getLength(), rNewKey );
286 rKey, aNewKey, false ) )
287 return false;
288 }
289 }
290 }
291 }
292 else
293 {
294 // Get old property set, if exists.
295 uno::Reference< css::ucb::XPersistentPropertySet > xOldSet
296 = getAdditionalPropertySet( rOldKey, false );
297 if ( xOldSet.is() )
298 {
299 // Rename property set.
300 uno::Reference< container::XNamed > xNamed(
301 xOldSet, uno::UNO_QUERY );
302 if ( !xNamed.is() )
303 return false;
304
305 // ??? throws no exceptions and has no return value ???
306 xNamed->setName( rNewKey );
307 }
308 }
309 return true;
310}
311
313 const OUString& rSourceKey,
314 const OUString& rTargetKey,
315 bool bRecursive )
316{
317 if ( rSourceKey == rTargetKey )
318 return true;
319
320 osl::MutexGuard aGuard( m_aMutex );
321
322 if ( bRecursive )
323 {
324 // Get propertyset registry.
326
327 if ( !m_pImpl->m_xPropertySetRegistry.is() )
328 return false;
329
330 uno::Reference< container::XNameAccess > xNameAccess(
331 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
332 if ( !xNameAccess.is() )
333 return false;
334
335 const uno::Sequence< OUString > aKeys
336 = xNameAccess->getElementNames();
337 if ( aKeys.hasElements() )
338 {
339 OUString aSrcKeyWithSlash = rSourceKey;
340 OUString aSrcKeyWithoutSlash;
341 if ( !aSrcKeyWithSlash.endsWith("/") )
342 {
343 aSrcKeyWithSlash += "/";
344 aSrcKeyWithoutSlash = rSourceKey;
345 }
346 else if ( !rSourceKey.isEmpty() )
347 aSrcKeyWithoutSlash = rSourceKey.copy(
348 0, rSourceKey.getLength() - 1 );
349
350 for ( const OUString& rKey : aKeys )
351 {
352 if ( rKey.startsWith(aSrcKeyWithSlash )
353 || rKey == aSrcKeyWithoutSlash )
354 {
355 OUString aNewKey
356 = rKey.replaceAt(
357 0, rSourceKey.getLength(), rTargetKey );
359 rKey, aNewKey, false ) )
360 return false;
361 }
362 }
363 }
364 }
365 else
366 {
367 // Get old property set, if exists.
368 uno::Reference< css::ucb::XPersistentPropertySet >
369 xOldPropSet = getAdditionalPropertySet( rSourceKey, false );
370 if ( !xOldPropSet.is() )
371 return false;
372
373 uno::Reference< beans::XPropertySetInfo > xPropSetInfo
374 = xOldPropSet->getPropertySetInfo();
375 if ( !xPropSetInfo.is() )
376 return false;
377
378 uno::Reference< beans::XPropertyAccess > xOldPropAccess(
379 xOldPropSet, uno::UNO_QUERY );
380 if ( !xOldPropAccess.is() )
381 return false;
382
383 // Obtain all values from old set.
384 const uno::Sequence< beans::PropertyValue > aValues
385 = xOldPropAccess->getPropertyValues();
386
387 const uno::Sequence< beans::Property > aProps
388 = xPropSetInfo->getProperties();
389
390 if ( aValues.hasElements() )
391 {
392 // Fail, if property set with new key already exists.
393 uno::Reference< css::ucb::XPersistentPropertySet >
394 xNewPropSet
395 = getAdditionalPropertySet( rTargetKey, false );
396 if ( xNewPropSet.is() )
397 return false;
398
399 // Create new, empty set.
400 xNewPropSet = getAdditionalPropertySet( rTargetKey, true );
401 if ( !xNewPropSet.is() )
402 return false;
403
404 uno::Reference< beans::XPropertyContainer > xNewPropContainer(
405 xNewPropSet, uno::UNO_QUERY );
406 if ( !xNewPropContainer.is() )
407 return false;
408
409 for ( const beans::PropertyValue& rValue : aValues )
410 {
411 sal_Int16 nAttribs = 0;
412 auto pProp = std::find_if(aProps.begin(), aProps.end(),
413 [&rValue](const beans::Property& rProp) { return rProp.Name == rValue.Name; });
414 if (pProp != aProps.end())
415 nAttribs = pProp->Attributes;
416
417 try
418 {
419 xNewPropContainer->addProperty(
420 rValue.Name, nAttribs, rValue.Value );
421 }
422 catch ( beans::PropertyExistException & )
423 {
424 }
425 catch ( beans::IllegalTypeException & )
426 {
427 }
428 catch ( lang::IllegalArgumentException & )
429 {
430 }
431 }
432 }
433 }
434 return true;
435}
436
438 const OUString& rKey, bool bRecursive )
439{
440 osl::MutexGuard aGuard( m_aMutex );
441
442 if ( bRecursive )
443 {
444 // Get propertyset registry.
446
447 if ( !m_pImpl->m_xPropertySetRegistry.is() )
448 return false;
449
450 uno::Reference< container::XNameAccess > xNameAccess(
451 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
452 if ( !xNameAccess.is() )
453 return false;
454
455 const uno::Sequence< OUString > aKeys
456 = xNameAccess->getElementNames();
457 if ( aKeys.hasElements() )
458 {
459 OUString aKeyWithSlash = rKey;
460 OUString aKeyWithoutSlash;
461 if ( !aKeyWithSlash.endsWith("/") )
462 {
463 aKeyWithSlash += "/";
464 aKeyWithoutSlash = rKey;
465 }
466 else if ( !rKey.isEmpty() )
467 aKeyWithoutSlash
468 = rKey.copy( 0, rKey.getLength() - 1 );
469
470 for ( const OUString& rCurrKey : aKeys )
471 {
472 if ( rCurrKey.startsWith(aKeyWithSlash )
473 || rCurrKey == aKeyWithoutSlash )
474 {
476 rCurrKey, false ) )
477 return false;
478 }
479 }
480 }
481 }
482 else
483 {
484 // Get propertyset registry.
486
487 if ( !m_pImpl->m_xPropertySetRegistry.is() )
488 return false;
489
490 m_pImpl->m_xPropertySetRegistry->removePropertySet( rKey );
491 }
492 return true;
493}
494
495} // namespace ucbhelper
496
497/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
Reference< XComponentContext > m_xContext
This is an abstract base class for implementations of the service com.sun.star.ucb....
virtual css::uno::Reference< css::ucb::XContentIdentifier > SAL_CALL getIdentifier() override
bool renameAdditionalPropertySet(const OUString &rOldKey, const OUString &rNewKey, bool bRecursive)
This method renames the propertyset containing the Additional Core Properties of a content.
bool removeAdditionalPropertySet(const OUString &rKey, bool bRecursive)
This method removes the propertyset containing the Additional Core Properties of a content.
rtl::Reference< ContentImplHelper > queryExistingContent(const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier)
This method returns a content with the given id, if it already exists.
bool copyAdditionalPropertySet(const OUString &rSourceKey, const OUString &rTargetKey, bool bRecursive)
This method copies the propertyset containing the Additional Core Properties of a content.
void registerNewContent(const css::uno::Reference< css::ucb::XContent > &xContent)
This method registers a newly created content instance with the content provider.
void queryExistingContents(ContentRefList &rContents)
This method fills a list with all contents existing at calling time.
ContentProviderImplHelper(css::uno::Reference< css::uno::XComponentContext > xContext)
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
UCBHELPER_DLLPRIVATE void removeContent(ContentImplHelper *pContent)
css::uno::Reference< css::ucb::XPersistentPropertySet > getAdditionalPropertySet(const OUString &rKey, bool bCreate)
This method returns the propertyset containing the Additional Core Properties of a content.
std::unique_ptr< ucbhelper_impl::ContentProviderImplHelper_Impl > m_pImpl
UCBHELPER_DLLPRIVATE css::uno::Reference< css::ucb::XPropertySetRegistry > getAdditionalPropertySetRegistry()
virtual ~ContentProviderImplHelper() override
UCBHELPER_DLLPRIVATE void cleanupRegisteredContents()
css::uno::Reference< css::uno::XComponentContext > m_xContext
virtual sal_Int32 SAL_CALL compareContentIds(const css::uno::Reference< css::ucb::XContentIdentifier > &Id1, const css::uno::Reference< css::ucb::XContentIdentifier > &Id2) override
URL aURL
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
std::unordered_map< OUString, uno::WeakReference< ucb::XContent > > Contents
std::vector< ContentImplHelperRef > ContentRefList
uno::Reference< css::ucb::XPropertySetRegistry > m_xPropertySetRegistry
unsigned char sal_Bool