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 {
156 uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames();
157 const rtl::OUString* pArray = aSNL.getConstArray();
158 for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
159 {
160 if ( pArray[ i ] == ServiceName )
161 return sal_True;
162 }
163
164 return sal_False;
165 }
166
167 //=========================================================================
168 //
169 // XContentProvider methods.
170 //
171 //=========================================================================
172
173 // virtual
compareContentIds(const uno::Reference<com::sun::star::ucb::XContentIdentifier> & Id1,const uno::Reference<com::sun::star::ucb::XContentIdentifier> & Id2)174 sal_Int32 SAL_CALL ContentProviderImplHelper::compareContentIds(
175 const uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id1,
176 const uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id2 )
177 {
178 // Simply do a string compare.
179
180 rtl::OUString aURL1( Id1->getContentIdentifier() );
181 rtl::OUString aURL2( Id2->getContentIdentifier() );
182
183 return aURL1.compareTo( aURL2 );
184 }
185
186 //=========================================================================
187 //
188 // Non-interface methods
189 //
190 //=========================================================================
191
cleanupRegisteredContents()192 void ContentProviderImplHelper::cleanupRegisteredContents()
193 {
194 osl::MutexGuard aGuard( m_aMutex );
195
196 ucbhelper_impl::Contents::iterator it
197 = m_pImpl->m_aContents.begin();
198 while( it != m_pImpl->m_aContents.end() )
199 {
200 uno::Reference< ucb::XContent > xContent( (*it).second );
201 if ( !xContent.is() )
202 {
203 ucbhelper_impl::Contents::iterator tmp = it;
204 ++it;
205 m_pImpl->m_aContents.erase( tmp );
206 }
207 else
208 {
209 ++it;
210 }
211 }
212 }
213
214 //=========================================================================
215
removeContent(ContentImplHelper * pContent)216 void ContentProviderImplHelper::removeContent( ContentImplHelper* pContent )
217 {
218 osl::MutexGuard aGuard( m_aMutex );
219
220 cleanupRegisteredContents();
221
222 const rtl::OUString aURL(
223 pContent->getIdentifier()->getContentIdentifier() );
224
225 ucbhelper_impl::Contents::iterator it = m_pImpl->m_aContents.find( aURL );
226
227 if ( it != m_pImpl->m_aContents.end() )
228 m_pImpl->m_aContents.erase( it );
229 }
230
231 //=========================================================================
232 rtl::Reference< ContentImplHelper >
queryExistingContent(const uno::Reference<com::sun::star::ucb::XContentIdentifier> & Identifier)233 ContentProviderImplHelper::queryExistingContent(
234 const uno::Reference< com::sun::star::ucb::XContentIdentifier >&
235 Identifier )
236 {
237 return queryExistingContent( Identifier->getContentIdentifier() );
238 }
239
240 //=========================================================================
241 rtl::Reference< ContentImplHelper >
queryExistingContent(const rtl::OUString & rURL)242 ContentProviderImplHelper::queryExistingContent( const rtl::OUString& rURL )
243 {
244 osl::MutexGuard aGuard( m_aMutex );
245
246 cleanupRegisteredContents();
247
248 // Check, if a content with given id already exists...
249
250 ucbhelper_impl::Contents::const_iterator it
251 = m_pImpl->m_aContents.find( rURL );
252 if ( it != m_pImpl->m_aContents.end() )
253 {
254 uno::Reference< ucb::XContent > xContent( (*it).second );
255 if ( xContent.is() )
256 {
257 return rtl::Reference< ContentImplHelper >(
258 static_cast< ContentImplHelper * >( xContent.get() ) );
259 }
260 }
261 return rtl::Reference< ContentImplHelper >();
262 }
263
264 //=========================================================================
queryExistingContents(ContentRefList & rContents)265 void ContentProviderImplHelper::queryExistingContents(
266 ContentRefList& rContents )
267 {
268 osl::MutexGuard aGuard( m_aMutex );
269
270 cleanupRegisteredContents();
271
272 ucbhelper_impl::Contents::const_iterator it
273 = m_pImpl->m_aContents.begin();
274 ucbhelper_impl::Contents::const_iterator end
275 = m_pImpl->m_aContents.end();
276
277 while ( it != end )
278 {
279 uno::Reference< ucb::XContent > xContent( (*it).second );
280 if ( xContent.is() )
281 {
282 rContents.push_back(
283 rtl::Reference< ContentImplHelper >(
284 static_cast< ContentImplHelper * >( xContent.get() ) ) );
285 }
286 ++it;
287 }
288 }
289
290 //=========================================================================
registerNewContent(const uno::Reference<ucb::XContent> & xContent)291 void ContentProviderImplHelper::registerNewContent(
292 const uno::Reference< ucb::XContent > & xContent )
293 {
294 if ( xContent.is() )
295 {
296 osl::MutexGuard aGuard( m_aMutex );
297
298 cleanupRegisteredContents();
299
300 const rtl::OUString aURL(
301 xContent->getIdentifier()->getContentIdentifier() );
302 ucbhelper_impl::Contents::const_iterator it
303 = m_pImpl->m_aContents.find( aURL );
304 if ( it == m_pImpl->m_aContents.end() )
305 m_pImpl->m_aContents[ aURL ] = xContent;
306 }
307 }
308
309 //=========================================================================
310 uno::Reference< com::sun::star::ucb::XPropertySetRegistry >
getAdditionalPropertySetRegistry()311 ContentProviderImplHelper::getAdditionalPropertySetRegistry()
312 {
313 // Get propertyset registry.
314
315 osl::MutexGuard aGuard( m_aMutex );
316
317 if ( !m_pImpl->m_xPropertySetRegistry.is() )
318 {
319 uno::Reference< com::sun::star::ucb::XPropertySetRegistryFactory >
320 xRegFac(
321 m_xSMgr->createInstance(
322 rtl::OUString::createFromAscii(
323 "com.sun.star.ucb.Store" ) ),
324 uno::UNO_QUERY );
325
326 OSL_ENSURE( xRegFac.is(),
327 "ContentProviderImplHelper::getAdditionalPropertySet - "
328 "No UCB-Store service!" );
329
330 if ( xRegFac.is() )
331 {
332 // Open/create a registry.
333 m_pImpl->m_xPropertySetRegistry
334 = xRegFac->createPropertySetRegistry( rtl::OUString() );
335
336 OSL_ENSURE( m_pImpl->m_xPropertySetRegistry.is(),
337 "ContentProviderImplHelper::getAdditionalPropertySet - "
338 "Error opening registry!" );
339 }
340 }
341
342 return m_pImpl->m_xPropertySetRegistry;
343 }
344
345
346 //=========================================================================
347 uno::Reference< com::sun::star::ucb::XPersistentPropertySet >
getAdditionalPropertySet(const rtl::OUString & rKey,sal_Bool bCreate)348 ContentProviderImplHelper::getAdditionalPropertySet(
349 const rtl::OUString& rKey, sal_Bool bCreate )
350 {
351 // Get propertyset registry.
352 getAdditionalPropertySetRegistry();
353
354 if ( m_pImpl->m_xPropertySetRegistry.is() )
355 {
356 // Open/create persistent property set.
357 return uno::Reference< com::sun::star::ucb::XPersistentPropertySet >(
358 m_pImpl->m_xPropertySetRegistry->openPropertySet(
359 rKey, bCreate ) );
360 }
361
362 return uno::Reference< com::sun::star::ucb::XPersistentPropertySet >();
363 }
364
365 //=========================================================================
renameAdditionalPropertySet(const rtl::OUString & rOldKey,const rtl::OUString & rNewKey,sal_Bool bRecursive)366 sal_Bool ContentProviderImplHelper::renameAdditionalPropertySet(
367 const rtl::OUString& rOldKey,
368 const rtl::OUString& rNewKey,
369 sal_Bool bRecursive )
370 {
371 if ( rOldKey == rNewKey )
372 return sal_True;
373
374 osl::MutexGuard aGuard( m_aMutex );
375
376 if ( bRecursive )
377 {
378 // Get propertyset registry.
379 getAdditionalPropertySetRegistry();
380
381 if ( m_pImpl->m_xPropertySetRegistry.is() )
382 {
383 uno::Reference< container::XNameAccess > xNameAccess(
384 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
385 if ( xNameAccess.is() )
386 {
387 uno::Sequence< rtl::OUString > aKeys
388 = xNameAccess->getElementNames();
389 sal_Int32 nCount = aKeys.getLength();
390 if ( nCount > 0 )
391 {
392 rtl::OUString aOldKeyWithSlash = rOldKey;
393 rtl::OUString aOldKeyWithoutSlash;
394 if ( aOldKeyWithSlash.lastIndexOf(
395 sal_Unicode('/')
396 != aOldKeyWithSlash.getLength() - 1 ) )
397 {
398 aOldKeyWithSlash += rtl::OUString( sal_Unicode('/') );
399 aOldKeyWithoutSlash = rOldKey;
400 }
401 else if ( rOldKey.getLength() )
402 aOldKeyWithoutSlash
403 = rOldKey.copy( 0, rOldKey.getLength() - 1 );
404
405 const rtl::OUString* pKeys = aKeys.getConstArray();
406 for ( sal_Int32 n = 0; n < nCount; ++n )
407 {
408 const rtl::OUString& rKey = pKeys[ n ];
409 if ( rKey.compareTo(
410 aOldKeyWithSlash,
411 aOldKeyWithSlash.getLength() ) == 0
412 || rKey.equals( aOldKeyWithoutSlash ) )
413 {
414 rtl::OUString aNewKey
415 = rKey.replaceAt(
416 0, rOldKey.getLength(), rNewKey );
417 if ( !renameAdditionalPropertySet(
418 rKey, aNewKey, sal_False ) )
419 return sal_False;
420 }
421 }
422 }
423 }
424 else
425 return sal_False;
426 }
427 else
428 return sal_False;
429 }
430 else
431 {
432 // Get old property set, if exists.
433 uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xOldSet
434 = getAdditionalPropertySet( rOldKey, sal_False );
435 if ( xOldSet.is() )
436 {
437 // Rename property set.
438 uno::Reference< container::XNamed > xNamed(
439 xOldSet, uno::UNO_QUERY );
440 if ( xNamed.is() )
441 {
442 // ??? throws no exceptions and has no return value ???
443 xNamed->setName( rNewKey );
444 }
445 else
446 return sal_False;
447 }
448 }
449 return sal_True;
450 }
451
452 //=========================================================================
copyAdditionalPropertySet(const rtl::OUString & rSourceKey,const rtl::OUString & rTargetKey,sal_Bool bRecursive)453 sal_Bool ContentProviderImplHelper::copyAdditionalPropertySet(
454 const rtl::OUString& rSourceKey,
455 const rtl::OUString& rTargetKey,
456 sal_Bool bRecursive )
457 {
458 if ( rSourceKey == rTargetKey )
459 return sal_True;
460
461 osl::MutexGuard aGuard( m_aMutex );
462
463 if ( bRecursive )
464 {
465 // Get propertyset registry.
466 getAdditionalPropertySetRegistry();
467
468 if ( m_pImpl->m_xPropertySetRegistry.is() )
469 {
470 uno::Reference< container::XNameAccess > xNameAccess(
471 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
472 if ( xNameAccess.is() )
473 {
474 uno::Sequence< rtl::OUString > aKeys
475 = xNameAccess->getElementNames();
476 sal_Int32 nCount = aKeys.getLength();
477 if ( nCount > 0 )
478 {
479 rtl::OUString aSrcKeyWithSlash = rSourceKey;
480 rtl::OUString aSrcKeyWithoutSlash;
481 if ( aSrcKeyWithSlash.lastIndexOf(
482 sal_Unicode('/')
483 != aSrcKeyWithSlash.getLength() - 1 ) )
484 {
485 aSrcKeyWithSlash += rtl::OUString( sal_Unicode('/') );
486 aSrcKeyWithoutSlash = rSourceKey;
487 }
488 else if ( rSourceKey.getLength() )
489 aSrcKeyWithoutSlash = rSourceKey.copy(
490 0, rSourceKey.getLength() - 1 );
491
492 const rtl::OUString* pKeys = aKeys.getConstArray();
493 for ( sal_Int32 n = 0; n < nCount; ++n )
494 {
495 const rtl::OUString& rKey = pKeys[ n ];
496 if ( rKey.compareTo(
497 aSrcKeyWithSlash,
498 aSrcKeyWithSlash.getLength() ) == 0
499 || rKey.equals( aSrcKeyWithoutSlash ) )
500 {
501 rtl::OUString aNewKey
502 = rKey.replaceAt(
503 0, rSourceKey.getLength(), rTargetKey );
504 if ( !copyAdditionalPropertySet(
505 rKey, aNewKey, sal_False ) )
506 return sal_False;
507 }
508 }
509 }
510 }
511 else
512 return sal_False;
513 }
514 else
515 return sal_False;
516 }
517 else
518 {
519 // Get old property set, if exists.
520 uno::Reference< com::sun::star::ucb::XPersistentPropertySet >
521 xOldPropSet = getAdditionalPropertySet( rSourceKey, sal_False );
522 if ( !xOldPropSet.is() )
523 return sal_False;
524
525 uno::Reference< beans::XPropertySetInfo > xPropSetInfo
526 = xOldPropSet->getPropertySetInfo();
527 if ( !xPropSetInfo.is() )
528 return sal_False;
529
530 uno::Reference< beans::XPropertyAccess > xOldPropAccess(
531 xOldPropSet, uno::UNO_QUERY );
532 if ( !xOldPropAccess.is() )
533 return sal_False;
534
535 // Obtain all values from old set.
536 uno::Sequence< beans::PropertyValue > aValues
537 = xOldPropAccess->getPropertyValues();
538 sal_Int32 nCount = aValues.getLength();
539
540 uno::Sequence< beans::Property > aProps
541 = xPropSetInfo->getProperties();
542
543 if ( nCount )
544 {
545 // Fail, if property set with new key already exists.
546 uno::Reference< com::sun::star::ucb::XPersistentPropertySet >
547 xNewPropSet
548 = getAdditionalPropertySet( rTargetKey, sal_False );
549 if ( xNewPropSet.is() )
550 return sal_False;
551
552 // Create new, empty set.
553 xNewPropSet = getAdditionalPropertySet( rTargetKey, sal_True );
554 if ( !xNewPropSet.is() )
555 return sal_False;
556
557 uno::Reference< beans::XPropertyContainer > xNewPropContainer(
558 xNewPropSet, uno::UNO_QUERY );
559 if ( !xNewPropContainer.is() )
560 return sal_False;
561
562 for ( sal_Int32 n = 0; n < nCount; ++n )
563 {
564 const beans::PropertyValue& rValue = aValues[ n ];
565
566 sal_Int16 nAttribs = 0;
567 for ( sal_Int32 m = 0; m < aProps.getLength(); ++m )
568 {
569 if ( aProps[ m ].Name == rValue.Name )
570 {
571 nAttribs = aProps[ m ].Attributes;
572 break;
573 }
574 }
575
576 try
577 {
578 xNewPropContainer->addProperty(
579 rValue.Name, nAttribs, rValue.Value );
580 }
581 catch ( beans::PropertyExistException & )
582 {
583 }
584 catch ( beans::IllegalTypeException & )
585 {
586 }
587 catch ( lang::IllegalArgumentException & )
588 {
589 }
590 }
591 }
592 }
593 return sal_True;
594 }
595
596 //=========================================================================
removeAdditionalPropertySet(const rtl::OUString & rKey,sal_Bool bRecursive)597 sal_Bool ContentProviderImplHelper::removeAdditionalPropertySet(
598 const rtl::OUString& rKey, sal_Bool bRecursive )
599 {
600 osl::MutexGuard aGuard( m_aMutex );
601
602 if ( bRecursive )
603 {
604 // Get propertyset registry.
605 getAdditionalPropertySetRegistry();
606
607 if ( m_pImpl->m_xPropertySetRegistry.is() )
608 {
609 uno::Reference< container::XNameAccess > xNameAccess(
610 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
611 if ( xNameAccess.is() )
612 {
613 uno::Sequence< rtl::OUString > aKeys
614 = xNameAccess->getElementNames();
615 sal_Int32 nCount = aKeys.getLength();
616 if ( nCount > 0 )
617 {
618 rtl::OUString aKeyWithSlash = rKey;
619 rtl::OUString aKeyWithoutSlash;
620 if ( aKeyWithSlash.lastIndexOf(
621 sal_Unicode('/')
622 != aKeyWithSlash.getLength() - 1 ) )
623 {
624 aKeyWithSlash += rtl::OUString( (sal_Unicode)'/' );
625 aKeyWithoutSlash = rKey;
626 }
627 else if ( rKey.getLength() )
628 aKeyWithoutSlash
629 = rKey.copy( 0, rKey.getLength() - 1 );
630
631 const rtl::OUString* pKeys = aKeys.getConstArray();
632 for ( sal_Int32 n = 0; n < nCount; ++n )
633 {
634 const rtl::OUString& rCurrKey = pKeys[ n ];
635 if ( rCurrKey.compareTo(
636 aKeyWithSlash,
637 aKeyWithSlash.getLength() ) == 0
638 || rCurrKey.equals( aKeyWithoutSlash ) )
639 {
640 if ( !removeAdditionalPropertySet(
641 rCurrKey, sal_False ) )
642 return sal_False;
643 }
644 }
645 }
646 }
647 else
648 return sal_False;
649 }
650 else
651 return sal_False;
652 }
653 else
654 {
655 // Get propertyset registry.
656 getAdditionalPropertySetRegistry();
657
658 if ( m_pImpl->m_xPropertySetRegistry.is() )
659 m_pImpl->m_xPropertySetRegistry->removePropertySet( rKey );
660 else
661 return sal_False;
662 }
663 return sal_True;
664 }
665
666 } // namespace ucbhelper
667