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