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