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