nss: upgrade to release 3.73
[LibreOffice.git] / ucbhelper / source / provider / providerhelper.cxx
blob95fbe6a684536dfd93ac968942810089f104ab67
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
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>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <cppuhelper/queryinterface.hxx>
32 #include <ucbhelper/contenthelper.hxx>
33 #include <ucbhelper/providerhelper.hxx>
34 #include <ucbhelper/macros.hxx>
36 #include <osl/diagnose.h>
37 #include <osl/mutex.hxx>
38 #include <cppuhelper/weakref.hxx>
40 #include <unordered_map>
42 using namespace com::sun::star;
44 namespace ucbhelper_impl
47 typedef std::unordered_map
49 OUString,
50 uno::WeakReference< ucb::XContent >
52 Contents;
54 struct ContentProviderImplHelper_Impl
56 uno::Reference< css::ucb::XPropertySetRegistry > m_xPropertySetRegistry;
57 Contents m_aContents;
60 } // namespace ucbhelper_impl
62 namespace ucbhelper {
64 ContentProviderImplHelper::ContentProviderImplHelper(
65 const uno::Reference< uno::XComponentContext >& rxContext )
66 : m_pImpl( new ucbhelper_impl::ContentProviderImplHelper_Impl ),
67 m_xContext( rxContext )
71 // virtual
72 ContentProviderImplHelper::~ContentProviderImplHelper()
76 // virtual
77 sal_Bool SAL_CALL ContentProviderImplHelper::supportsService(
78 const OUString& ServiceName )
80 return cppu::supportsService(this, ServiceName);
83 // virtual
84 sal_Int32 SAL_CALL ContentProviderImplHelper::compareContentIds(
85 const uno::Reference< css::ucb::XContentIdentifier >& Id1,
86 const uno::Reference< css::ucb::XContentIdentifier >& Id2 )
88 // Simply do a string compare.
90 OUString aURL1( Id1->getContentIdentifier() );
91 OUString aURL2( Id2->getContentIdentifier() );
93 return aURL1.compareTo( aURL2 );
96 void ContentProviderImplHelper::cleanupRegisteredContents()
98 osl::MutexGuard aGuard( m_aMutex );
100 ucbhelper_impl::Contents::iterator it
101 = m_pImpl->m_aContents.begin();
102 while( it != m_pImpl->m_aContents.end() )
104 uno::Reference< ucb::XContent > xContent( (*it).second );
105 if ( !xContent.is() )
107 ucbhelper_impl::Contents::iterator tmp = it;
108 ++it;
109 m_pImpl->m_aContents.erase( tmp );
111 else
113 ++it;
118 void ContentProviderImplHelper::removeContent( ContentImplHelper* pContent )
120 osl::MutexGuard aGuard( m_aMutex );
122 cleanupRegisteredContents();
124 const OUString aURL(
125 pContent->getIdentifier()->getContentIdentifier() );
127 ucbhelper_impl::Contents::iterator it = m_pImpl->m_aContents.find( aURL );
129 if ( it != m_pImpl->m_aContents.end() )
130 m_pImpl->m_aContents.erase( it );
133 rtl::Reference< ContentImplHelper >
134 ContentProviderImplHelper::queryExistingContent(
135 const uno::Reference< css::ucb::XContentIdentifier >& Identifier )
137 return queryExistingContent( Identifier->getContentIdentifier() );
140 rtl::Reference< ContentImplHelper >
141 ContentProviderImplHelper::queryExistingContent( const OUString& rURL )
143 osl::MutexGuard aGuard( m_aMutex );
145 cleanupRegisteredContents();
147 // Check, if a content with given id already exists...
149 ucbhelper_impl::Contents::const_iterator it
150 = m_pImpl->m_aContents.find( rURL );
151 if ( it != m_pImpl->m_aContents.end() )
153 uno::Reference< ucb::XContent > xContent( (*it).second );
154 if ( xContent.is() )
156 return rtl::Reference< ContentImplHelper >(
157 static_cast< ContentImplHelper * >( xContent.get() ) );
160 return rtl::Reference< ContentImplHelper >();
163 void ContentProviderImplHelper::queryExistingContents(
164 ContentRefList& rContents )
166 osl::MutexGuard aGuard( m_aMutex );
168 cleanupRegisteredContents();
170 for ( const auto& rContent : m_pImpl->m_aContents )
172 uno::Reference< ucb::XContent > xContent( rContent.second );
173 if ( xContent.is() )
175 rContents.emplace_back(
176 static_cast< ContentImplHelper * >( xContent.get() ) );
181 void ContentProviderImplHelper::registerNewContent(
182 const uno::Reference< ucb::XContent > & xContent )
184 if ( !xContent.is() )
185 return;
187 osl::MutexGuard aGuard( m_aMutex );
189 cleanupRegisteredContents();
191 const OUString aURL(
192 xContent->getIdentifier()->getContentIdentifier() );
193 ucbhelper_impl::Contents::const_iterator it
194 = m_pImpl->m_aContents.find( aURL );
195 if ( it == m_pImpl->m_aContents.end() )
196 m_pImpl->m_aContents[ aURL ] = xContent;
199 uno::Reference< css::ucb::XPropertySetRegistry >
200 ContentProviderImplHelper::getAdditionalPropertySetRegistry()
202 // Get propertyset registry.
204 osl::MutexGuard aGuard( m_aMutex );
206 if ( !m_pImpl->m_xPropertySetRegistry.is() )
208 uno::Reference< css::ucb::XPropertySetRegistryFactory >
209 xRegFac = css::ucb::Store::create( m_xContext );
211 // Open/create a registry.
212 m_pImpl->m_xPropertySetRegistry
213 = xRegFac->createPropertySetRegistry( OUString() );
215 OSL_ENSURE( m_pImpl->m_xPropertySetRegistry.is(),
216 "ContentProviderImplHelper::getAdditionalPropertySet - "
217 "Error opening registry!" );
220 return m_pImpl->m_xPropertySetRegistry;
223 uno::Reference< css::ucb::XPersistentPropertySet >
224 ContentProviderImplHelper::getAdditionalPropertySet(
225 const OUString& rKey, bool bCreate )
227 // Get propertyset registry.
228 getAdditionalPropertySetRegistry();
230 if ( m_pImpl->m_xPropertySetRegistry.is() )
232 // Open/create persistent property set.
233 return m_pImpl->m_xPropertySetRegistry->openPropertySet(
234 rKey, bCreate );
237 return uno::Reference< css::ucb::XPersistentPropertySet >();
240 bool ContentProviderImplHelper::renameAdditionalPropertySet(
241 const OUString& rOldKey,
242 const OUString& rNewKey,
243 bool bRecursive )
245 if ( rOldKey == rNewKey )
246 return true;
248 osl::MutexGuard aGuard( m_aMutex );
250 if ( bRecursive )
252 // Get propertyset registry.
253 getAdditionalPropertySetRegistry();
255 if ( !m_pImpl->m_xPropertySetRegistry.is() )
256 return false;
258 uno::Reference< container::XNameAccess > xNameAccess(
259 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
260 if ( !xNameAccess.is() )
261 return false;
263 const uno::Sequence< OUString > aKeys
264 = xNameAccess->getElementNames();
265 if ( aKeys.hasElements() )
267 OUString aOldKeyWithSlash = rOldKey;
268 OUString aOldKeyWithoutSlash;
269 if ( !aOldKeyWithSlash.endsWith("/") )
271 aOldKeyWithSlash += "/";
272 aOldKeyWithoutSlash = rOldKey;
274 else if ( !rOldKey.isEmpty() )
275 aOldKeyWithoutSlash
276 = rOldKey.copy( 0, rOldKey.getLength() - 1 );
278 for ( const OUString& rKey : aKeys )
280 if ( rKey.startsWith( aOldKeyWithSlash )
281 || rKey == aOldKeyWithoutSlash )
283 OUString aNewKey
284 = rKey.replaceAt(
285 0, rOldKey.getLength(), rNewKey );
286 if ( !renameAdditionalPropertySet(
287 rKey, aNewKey, false ) )
288 return false;
293 else
295 // Get old property set, if exists.
296 uno::Reference< css::ucb::XPersistentPropertySet > xOldSet
297 = getAdditionalPropertySet( rOldKey, false );
298 if ( xOldSet.is() )
300 // Rename property set.
301 uno::Reference< container::XNamed > xNamed(
302 xOldSet, uno::UNO_QUERY );
303 if ( !xNamed.is() )
304 return false;
306 // ??? throws no exceptions and has no return value ???
307 xNamed->setName( rNewKey );
310 return true;
313 bool ContentProviderImplHelper::copyAdditionalPropertySet(
314 const OUString& rSourceKey,
315 const OUString& rTargetKey,
316 bool bRecursive )
318 if ( rSourceKey == rTargetKey )
319 return true;
321 osl::MutexGuard aGuard( m_aMutex );
323 if ( bRecursive )
325 // Get propertyset registry.
326 getAdditionalPropertySetRegistry();
328 if ( !m_pImpl->m_xPropertySetRegistry.is() )
329 return false;
331 uno::Reference< container::XNameAccess > xNameAccess(
332 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
333 if ( !xNameAccess.is() )
334 return false;
336 const uno::Sequence< OUString > aKeys
337 = xNameAccess->getElementNames();
338 if ( aKeys.hasElements() )
340 OUString aSrcKeyWithSlash = rSourceKey;
341 OUString aSrcKeyWithoutSlash;
342 if ( !aSrcKeyWithSlash.endsWith("/") )
344 aSrcKeyWithSlash += "/";
345 aSrcKeyWithoutSlash = rSourceKey;
347 else if ( !rSourceKey.isEmpty() )
348 aSrcKeyWithoutSlash = rSourceKey.copy(
349 0, rSourceKey.getLength() - 1 );
351 for ( const OUString& rKey : aKeys )
353 if ( rKey.startsWith(aSrcKeyWithSlash )
354 || rKey == aSrcKeyWithoutSlash )
356 OUString aNewKey
357 = rKey.replaceAt(
358 0, rSourceKey.getLength(), rTargetKey );
359 if ( !copyAdditionalPropertySet(
360 rKey, aNewKey, false ) )
361 return false;
366 else
368 // Get old property set, if exists.
369 uno::Reference< css::ucb::XPersistentPropertySet >
370 xOldPropSet = getAdditionalPropertySet( rSourceKey, false );
371 if ( !xOldPropSet.is() )
372 return false;
374 uno::Reference< beans::XPropertySetInfo > xPropSetInfo
375 = xOldPropSet->getPropertySetInfo();
376 if ( !xPropSetInfo.is() )
377 return false;
379 uno::Reference< beans::XPropertyAccess > xOldPropAccess(
380 xOldPropSet, uno::UNO_QUERY );
381 if ( !xOldPropAccess.is() )
382 return false;
384 // Obtain all values from old set.
385 const uno::Sequence< beans::PropertyValue > aValues
386 = xOldPropAccess->getPropertyValues();
388 uno::Sequence< beans::Property > aProps
389 = xPropSetInfo->getProperties();
391 if ( aValues.hasElements() )
393 // Fail, if property set with new key already exists.
394 uno::Reference< css::ucb::XPersistentPropertySet >
395 xNewPropSet
396 = getAdditionalPropertySet( rTargetKey, false );
397 if ( xNewPropSet.is() )
398 return false;
400 // Create new, empty set.
401 xNewPropSet = getAdditionalPropertySet( rTargetKey, true );
402 if ( !xNewPropSet.is() )
403 return false;
405 uno::Reference< beans::XPropertyContainer > xNewPropContainer(
406 xNewPropSet, uno::UNO_QUERY );
407 if ( !xNewPropContainer.is() )
408 return false;
410 for ( const beans::PropertyValue& rValue : aValues )
412 sal_Int16 nAttribs = 0;
413 auto pProp = std::find_if(aProps.begin(), aProps.end(),
414 [&rValue](const beans::Property& rProp) { return rProp.Name == rValue.Name; });
415 if (pProp != aProps.end())
416 nAttribs = pProp->Attributes;
420 xNewPropContainer->addProperty(
421 rValue.Name, nAttribs, rValue.Value );
423 catch ( beans::PropertyExistException & )
426 catch ( beans::IllegalTypeException & )
429 catch ( lang::IllegalArgumentException & )
435 return true;
438 bool ContentProviderImplHelper::removeAdditionalPropertySet(
439 const OUString& rKey, bool bRecursive )
441 osl::MutexGuard aGuard( m_aMutex );
443 if ( bRecursive )
445 // Get propertyset registry.
446 getAdditionalPropertySetRegistry();
448 if ( !m_pImpl->m_xPropertySetRegistry.is() )
449 return false;
451 uno::Reference< container::XNameAccess > xNameAccess(
452 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
453 if ( !xNameAccess.is() )
454 return false;
456 const uno::Sequence< OUString > aKeys
457 = xNameAccess->getElementNames();
458 if ( aKeys.hasElements() )
460 OUString aKeyWithSlash = rKey;
461 OUString aKeyWithoutSlash;
462 if ( !aKeyWithSlash.endsWith("/") )
464 aKeyWithSlash += "/";
465 aKeyWithoutSlash = rKey;
467 else if ( !rKey.isEmpty() )
468 aKeyWithoutSlash
469 = rKey.copy( 0, rKey.getLength() - 1 );
471 for ( const OUString& rCurrKey : aKeys )
473 if ( rCurrKey.startsWith(aKeyWithSlash )
474 || rCurrKey == aKeyWithoutSlash )
476 if ( !removeAdditionalPropertySet(
477 rCurrKey, false ) )
478 return false;
483 else
485 // Get propertyset registry.
486 getAdditionalPropertySetRegistry();
488 if ( !m_pImpl->m_xPropertySetRegistry.is() )
489 return false;
491 m_pImpl->m_xPropertySetRegistry->removePropertySet( rKey );
493 return true;
496 } // namespace ucbhelper
498 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */