xref: /trunk/main/ucbhelper/source/provider/providerhelper.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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