Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/beans/XPropertyAccess.hpp>
21 : #include <com/sun/star/container/XNameAccess.hpp>
22 : #include <com/sun/star/container/XNamed.hpp>
23 : #include <com/sun/star/ucb/Store.hpp>
24 : #include <com/sun/star/ucb/XPropertySetRegistry.hpp>
25 : #include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp>
26 : #include <cppuhelper/supportsservice.hxx>
27 : #include <ucbhelper/contenthelper.hxx>
28 : #include <ucbhelper/contentidentifier.hxx>
29 : #include <ucbhelper/providerhelper.hxx>
30 :
31 : #include "osl/diagnose.h"
32 : #include "osl/mutex.hxx"
33 : #include "cppuhelper/weakref.hxx"
34 :
35 : #include <unordered_map>
36 :
37 : using namespace com::sun::star;
38 :
39 : namespace ucbhelper_impl
40 : {
41 :
42 : typedef std::unordered_map
43 : <
44 : OUString,
45 : uno::WeakReference< ucb::XContent >,
46 : OUStringHash
47 : >
48 : Contents;
49 :
50 314 : struct ContentProviderImplHelper_Impl
51 : {
52 : uno::Reference< com::sun::star::ucb::XPropertySetRegistry >
53 : m_xPropertySetRegistry;
54 : Contents
55 : m_aContents;
56 : };
57 :
58 : } // namespace ucbhelper_impl
59 :
60 : namespace ucbhelper {
61 :
62 158 : ContentProviderImplHelper::ContentProviderImplHelper(
63 : const uno::Reference< uno::XComponentContext >& rxContext )
64 158 : : m_pImpl( new ucbhelper_impl::ContentProviderImplHelper_Impl ),
65 316 : m_xContext( rxContext )
66 : {
67 158 : }
68 :
69 : // virtual
70 312 : ContentProviderImplHelper::~ContentProviderImplHelper()
71 : {
72 156 : delete m_pImpl;
73 156 : }
74 :
75 : // XInterface
76 0 : void SAL_CALL ContentProviderImplHelper::acquire()
77 : throw()
78 : {
79 0 : OWeakObject::acquire();
80 0 : }
81 :
82 0 : void SAL_CALL ContentProviderImplHelper::release()
83 : throw()
84 : {
85 0 : OWeakObject::release();
86 0 : }
87 :
88 0 : css::uno::Any SAL_CALL ContentProviderImplHelper::queryInterface( const css::uno::Type & rType )
89 : throw( css::uno::RuntimeException, std::exception )
90 : {
91 : css::uno::Any aRet = cppu::queryInterface( rType,
92 : (static_cast< lang::XTypeProvider* >(this)),
93 : (static_cast< lang::XServiceInfo* >(this)),
94 : (static_cast< css::ucb::XContentProvider* >(this))
95 0 : );
96 0 : return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
97 : }
98 :
99 0 : XTYPEPROVIDER_IMPL_3( ContentProviderImplHelper,
100 : lang::XTypeProvider,
101 : lang::XServiceInfo,
102 : com::sun::star::ucb::XContentProvider );
103 :
104 : // virtual
105 0 : sal_Bool SAL_CALL ContentProviderImplHelper::supportsService(
106 : const OUString& ServiceName )
107 : throw( uno::RuntimeException, std::exception )
108 : {
109 0 : return cppu::supportsService(this, ServiceName);
110 : }
111 :
112 : // virtual
113 11 : sal_Int32 SAL_CALL ContentProviderImplHelper::compareContentIds(
114 : const uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id1,
115 : const uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id2 )
116 : throw( uno::RuntimeException, std::exception )
117 : {
118 : // Simply do a string compare.
119 :
120 11 : OUString aURL1( Id1->getContentIdentifier() );
121 22 : OUString aURL2( Id2->getContentIdentifier() );
122 :
123 22 : return aURL1.compareTo( aURL2 );
124 : }
125 :
126 12451 : void ContentProviderImplHelper::cleanupRegisteredContents()
127 : {
128 12451 : osl::MutexGuard aGuard( m_aMutex );
129 :
130 : ucbhelper_impl::Contents::iterator it
131 12451 : = m_pImpl->m_aContents.begin();
132 28026 : while( it != m_pImpl->m_aContents.end() )
133 : {
134 3124 : uno::Reference< ucb::XContent > xContent( (*it).second );
135 3124 : if ( !xContent.is() )
136 : {
137 3089 : ucbhelper_impl::Contents::iterator tmp = it;
138 3089 : ++it;
139 3089 : m_pImpl->m_aContents.erase( tmp );
140 : }
141 : else
142 : {
143 35 : ++it;
144 : }
145 15575 : }
146 12451 : }
147 :
148 0 : void ContentProviderImplHelper::removeContent( ContentImplHelper* pContent )
149 : {
150 0 : osl::MutexGuard aGuard( m_aMutex );
151 :
152 0 : cleanupRegisteredContents();
153 :
154 : const OUString aURL(
155 0 : pContent->getIdentifier()->getContentIdentifier() );
156 :
157 0 : ucbhelper_impl::Contents::iterator it = m_pImpl->m_aContents.find( aURL );
158 :
159 0 : if ( it != m_pImpl->m_aContents.end() )
160 0 : m_pImpl->m_aContents.erase( it );
161 0 : }
162 :
163 : rtl::Reference< ContentImplHelper >
164 6679 : ContentProviderImplHelper::queryExistingContent(
165 : const uno::Reference< com::sun::star::ucb::XContentIdentifier >&
166 : Identifier )
167 : {
168 6679 : return queryExistingContent( Identifier->getContentIdentifier() );
169 : }
170 :
171 : rtl::Reference< ContentImplHelper >
172 6679 : ContentProviderImplHelper::queryExistingContent( const OUString& rURL )
173 : {
174 6679 : osl::MutexGuard aGuard( m_aMutex );
175 :
176 6679 : cleanupRegisteredContents();
177 :
178 : // Check, if a content with given id already exists...
179 :
180 : ucbhelper_impl::Contents::const_iterator it
181 6679 : = m_pImpl->m_aContents.find( rURL );
182 6679 : if ( it != m_pImpl->m_aContents.end() )
183 : {
184 3 : uno::Reference< ucb::XContent > xContent( (*it).second );
185 3 : if ( xContent.is() )
186 : {
187 : return rtl::Reference< ContentImplHelper >(
188 3 : static_cast< ContentImplHelper * >( xContent.get() ) );
189 0 : }
190 : }
191 6676 : return rtl::Reference< ContentImplHelper >();
192 : }
193 :
194 2633 : void ContentProviderImplHelper::queryExistingContents(
195 : ContentRefList& rContents )
196 : {
197 2633 : osl::MutexGuard aGuard( m_aMutex );
198 :
199 2633 : cleanupRegisteredContents();
200 :
201 : ucbhelper_impl::Contents::const_iterator it
202 2633 : = m_pImpl->m_aContents.begin();
203 : ucbhelper_impl::Contents::const_iterator end
204 2633 : = m_pImpl->m_aContents.end();
205 :
206 5266 : while ( it != end )
207 : {
208 0 : uno::Reference< ucb::XContent > xContent( (*it).second );
209 0 : if ( xContent.is() )
210 : {
211 : rContents.push_back(
212 : rtl::Reference< ContentImplHelper >(
213 0 : static_cast< ContentImplHelper * >( xContent.get() ) ) );
214 : }
215 0 : ++it;
216 2633 : }
217 2633 : }
218 :
219 3139 : void ContentProviderImplHelper::registerNewContent(
220 : const uno::Reference< ucb::XContent > & xContent )
221 : {
222 3139 : if ( xContent.is() )
223 : {
224 3139 : osl::MutexGuard aGuard( m_aMutex );
225 :
226 3139 : cleanupRegisteredContents();
227 :
228 : const OUString aURL(
229 6278 : xContent->getIdentifier()->getContentIdentifier() );
230 : ucbhelper_impl::Contents::const_iterator it
231 3139 : = m_pImpl->m_aContents.find( aURL );
232 3139 : if ( it == m_pImpl->m_aContents.end() )
233 6278 : m_pImpl->m_aContents[ aURL ] = xContent;
234 : }
235 3139 : }
236 :
237 : uno::Reference< com::sun::star::ucb::XPropertySetRegistry >
238 3349 : ContentProviderImplHelper::getAdditionalPropertySetRegistry()
239 : {
240 : // Get propertyset registry.
241 :
242 3349 : osl::MutexGuard aGuard( m_aMutex );
243 :
244 3349 : if ( !m_pImpl->m_xPropertySetRegistry.is() )
245 : {
246 : uno::Reference< com::sun::star::ucb::XPropertySetRegistryFactory >
247 41 : xRegFac = com::sun::star::ucb::Store::create( m_xContext );
248 :
249 : // Open/create a registry.
250 : m_pImpl->m_xPropertySetRegistry
251 41 : = xRegFac->createPropertySetRegistry( OUString() );
252 :
253 : OSL_ENSURE( m_pImpl->m_xPropertySetRegistry.is(),
254 : "ContentProviderImplHelper::getAdditionalPropertySet - "
255 41 : "Error opening registry!" );
256 : }
257 :
258 3349 : return m_pImpl->m_xPropertySetRegistry;
259 : }
260 :
261 : uno::Reference< com::sun::star::ucb::XPersistentPropertySet >
262 3349 : ContentProviderImplHelper::getAdditionalPropertySet(
263 : const OUString& rKey, bool bCreate )
264 : {
265 : // Get propertyset registry.
266 3349 : getAdditionalPropertySetRegistry();
267 :
268 3349 : if ( m_pImpl->m_xPropertySetRegistry.is() )
269 : {
270 : // Open/create persistent property set.
271 : return uno::Reference< com::sun::star::ucb::XPersistentPropertySet >(
272 3349 : m_pImpl->m_xPropertySetRegistry->openPropertySet(
273 3349 : rKey, bCreate ) );
274 : }
275 :
276 0 : return uno::Reference< com::sun::star::ucb::XPersistentPropertySet >();
277 : }
278 :
279 0 : bool ContentProviderImplHelper::renameAdditionalPropertySet(
280 : const OUString& rOldKey,
281 : const OUString& rNewKey,
282 : bool bRecursive )
283 : {
284 0 : if ( rOldKey == rNewKey )
285 0 : return true;
286 :
287 0 : osl::MutexGuard aGuard( m_aMutex );
288 :
289 0 : if ( bRecursive )
290 : {
291 : // Get propertyset registry.
292 0 : getAdditionalPropertySetRegistry();
293 :
294 0 : if ( m_pImpl->m_xPropertySetRegistry.is() )
295 : {
296 : uno::Reference< container::XNameAccess > xNameAccess(
297 0 : m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
298 0 : if ( xNameAccess.is() )
299 : {
300 : uno::Sequence< OUString > aKeys
301 0 : = xNameAccess->getElementNames();
302 0 : sal_Int32 nCount = aKeys.getLength();
303 0 : if ( nCount > 0 )
304 : {
305 0 : OUString aOldKeyWithSlash = rOldKey;
306 0 : OUString aOldKeyWithoutSlash;
307 0 : if ( !aOldKeyWithSlash.endsWith("/") )
308 : {
309 0 : aOldKeyWithSlash += OUString( '/' );
310 0 : aOldKeyWithoutSlash = rOldKey;
311 : }
312 0 : else if ( !rOldKey.isEmpty() )
313 : aOldKeyWithoutSlash
314 0 : = rOldKey.copy( 0, rOldKey.getLength() - 1 );
315 :
316 0 : const OUString* pKeys = aKeys.getConstArray();
317 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
318 : {
319 0 : const OUString& rKey = pKeys[ n ];
320 0 : if ( rKey.compareTo(
321 : aOldKeyWithSlash,
322 0 : aOldKeyWithSlash.getLength() ) == 0
323 0 : || rKey.equals( aOldKeyWithoutSlash ) )
324 : {
325 : OUString aNewKey
326 : = rKey.replaceAt(
327 0 : 0, rOldKey.getLength(), rNewKey );
328 0 : if ( !renameAdditionalPropertySet(
329 0 : rKey, aNewKey, false ) )
330 0 : return false;
331 : }
332 0 : }
333 0 : }
334 : }
335 : else
336 0 : return false;
337 : }
338 : else
339 0 : return false;
340 : }
341 : else
342 : {
343 : // Get old property set, if exists.
344 : uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xOldSet
345 0 : = getAdditionalPropertySet( rOldKey, false );
346 0 : if ( xOldSet.is() )
347 : {
348 : // Rename property set.
349 : uno::Reference< container::XNamed > xNamed(
350 0 : xOldSet, uno::UNO_QUERY );
351 0 : if ( xNamed.is() )
352 : {
353 : // ??? throws no exceptions and has no return value ???
354 0 : xNamed->setName( rNewKey );
355 : }
356 : else
357 0 : return false;
358 0 : }
359 : }
360 0 : return true;
361 : }
362 :
363 0 : bool ContentProviderImplHelper::copyAdditionalPropertySet(
364 : const OUString& rSourceKey,
365 : const OUString& rTargetKey,
366 : bool bRecursive )
367 : {
368 0 : if ( rSourceKey == rTargetKey )
369 0 : return true;
370 :
371 0 : osl::MutexGuard aGuard( m_aMutex );
372 :
373 0 : if ( bRecursive )
374 : {
375 : // Get propertyset registry.
376 0 : getAdditionalPropertySetRegistry();
377 :
378 0 : if ( m_pImpl->m_xPropertySetRegistry.is() )
379 : {
380 : uno::Reference< container::XNameAccess > xNameAccess(
381 0 : m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
382 0 : if ( xNameAccess.is() )
383 : {
384 : uno::Sequence< OUString > aKeys
385 0 : = xNameAccess->getElementNames();
386 0 : sal_Int32 nCount = aKeys.getLength();
387 0 : if ( nCount > 0 )
388 : {
389 0 : OUString aSrcKeyWithSlash = rSourceKey;
390 0 : OUString aSrcKeyWithoutSlash;
391 0 : if ( !aSrcKeyWithSlash.endsWith("/") )
392 : {
393 0 : aSrcKeyWithSlash += OUString( '/' );
394 0 : aSrcKeyWithoutSlash = rSourceKey;
395 : }
396 0 : else if ( !rSourceKey.isEmpty() )
397 0 : aSrcKeyWithoutSlash = rSourceKey.copy(
398 0 : 0, rSourceKey.getLength() - 1 );
399 :
400 0 : const OUString* pKeys = aKeys.getConstArray();
401 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
402 : {
403 0 : const OUString& rKey = pKeys[ n ];
404 0 : if ( rKey.compareTo(
405 : aSrcKeyWithSlash,
406 0 : aSrcKeyWithSlash.getLength() ) == 0
407 0 : || rKey.equals( aSrcKeyWithoutSlash ) )
408 : {
409 : OUString aNewKey
410 : = rKey.replaceAt(
411 0 : 0, rSourceKey.getLength(), rTargetKey );
412 0 : if ( !copyAdditionalPropertySet(
413 0 : rKey, aNewKey, false ) )
414 0 : return false;
415 : }
416 0 : }
417 0 : }
418 : }
419 : else
420 0 : return false;
421 : }
422 : else
423 0 : return false;
424 : }
425 : else
426 : {
427 : // Get old property set, if exists.
428 : uno::Reference< com::sun::star::ucb::XPersistentPropertySet >
429 0 : xOldPropSet = getAdditionalPropertySet( rSourceKey, false );
430 0 : if ( !xOldPropSet.is() )
431 0 : return false;
432 :
433 : uno::Reference< beans::XPropertySetInfo > xPropSetInfo
434 0 : = xOldPropSet->getPropertySetInfo();
435 0 : if ( !xPropSetInfo.is() )
436 0 : return false;
437 :
438 : uno::Reference< beans::XPropertyAccess > xOldPropAccess(
439 0 : xOldPropSet, uno::UNO_QUERY );
440 0 : if ( !xOldPropAccess.is() )
441 0 : return false;
442 :
443 : // Obtain all values from old set.
444 : uno::Sequence< beans::PropertyValue > aValues
445 0 : = xOldPropAccess->getPropertyValues();
446 0 : sal_Int32 nCount = aValues.getLength();
447 :
448 : uno::Sequence< beans::Property > aProps
449 0 : = xPropSetInfo->getProperties();
450 :
451 0 : if ( nCount )
452 : {
453 : // Fail, if property set with new key already exists.
454 : uno::Reference< com::sun::star::ucb::XPersistentPropertySet >
455 : xNewPropSet
456 0 : = getAdditionalPropertySet( rTargetKey, false );
457 0 : if ( xNewPropSet.is() )
458 0 : return false;
459 :
460 : // Create new, empty set.
461 0 : xNewPropSet = getAdditionalPropertySet( rTargetKey, true );
462 0 : if ( !xNewPropSet.is() )
463 0 : return false;
464 :
465 : uno::Reference< beans::XPropertyContainer > xNewPropContainer(
466 0 : xNewPropSet, uno::UNO_QUERY );
467 0 : if ( !xNewPropContainer.is() )
468 0 : return false;
469 :
470 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
471 : {
472 0 : const beans::PropertyValue& rValue = aValues[ n ];
473 :
474 0 : sal_Int16 nAttribs = 0;
475 0 : for ( sal_Int32 m = 0; m < aProps.getLength(); ++m )
476 : {
477 0 : if ( aProps[ m ].Name == rValue.Name )
478 : {
479 0 : nAttribs = aProps[ m ].Attributes;
480 0 : break;
481 : }
482 : }
483 :
484 : try
485 : {
486 0 : xNewPropContainer->addProperty(
487 0 : rValue.Name, nAttribs, rValue.Value );
488 : }
489 0 : catch ( beans::PropertyExistException & )
490 : {
491 : }
492 0 : catch ( beans::IllegalTypeException & )
493 : {
494 : }
495 0 : catch ( lang::IllegalArgumentException & )
496 : {
497 : }
498 0 : }
499 0 : }
500 : }
501 0 : return true;
502 : }
503 :
504 0 : bool ContentProviderImplHelper::removeAdditionalPropertySet(
505 : const OUString& rKey, bool bRecursive )
506 : {
507 0 : osl::MutexGuard aGuard( m_aMutex );
508 :
509 0 : if ( bRecursive )
510 : {
511 : // Get propertyset registry.
512 0 : getAdditionalPropertySetRegistry();
513 :
514 0 : if ( m_pImpl->m_xPropertySetRegistry.is() )
515 : {
516 : uno::Reference< container::XNameAccess > xNameAccess(
517 0 : m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
518 0 : if ( xNameAccess.is() )
519 : {
520 : uno::Sequence< OUString > aKeys
521 0 : = xNameAccess->getElementNames();
522 0 : sal_Int32 nCount = aKeys.getLength();
523 0 : if ( nCount > 0 )
524 : {
525 0 : OUString aKeyWithSlash = rKey;
526 0 : OUString aKeyWithoutSlash;
527 0 : if ( !aKeyWithSlash.endsWith("/") )
528 : {
529 0 : aKeyWithSlash += OUString( '/' );
530 0 : aKeyWithoutSlash = rKey;
531 : }
532 0 : else if ( !rKey.isEmpty() )
533 : aKeyWithoutSlash
534 0 : = rKey.copy( 0, rKey.getLength() - 1 );
535 :
536 0 : const OUString* pKeys = aKeys.getConstArray();
537 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
538 : {
539 0 : const OUString& rCurrKey = pKeys[ n ];
540 0 : if ( rCurrKey.compareTo(
541 : aKeyWithSlash,
542 0 : aKeyWithSlash.getLength() ) == 0
543 0 : || rCurrKey.equals( aKeyWithoutSlash ) )
544 : {
545 0 : if ( !removeAdditionalPropertySet(
546 0 : rCurrKey, false ) )
547 0 : return false;
548 : }
549 0 : }
550 0 : }
551 : }
552 : else
553 0 : return false;
554 : }
555 : else
556 0 : return false;
557 : }
558 : else
559 : {
560 : // Get propertyset registry.
561 0 : getAdditionalPropertySetRegistry();
562 :
563 0 : if ( m_pImpl->m_xPropertySetRegistry.is() )
564 0 : m_pImpl->m_xPropertySetRegistry->removePropertySet( rKey );
565 : else
566 0 : return false;
567 : }
568 0 : return true;
569 : }
570 :
571 : } // namespace ucbhelper
572 :
573 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|