xref: /AOO41X/main/ucb/source/core/ucb.cxx (revision 2f86921c33504fdff5a030df6c0b258927045abb)
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_ucb.hxx"
26 
27 /**************************************************************************
28                                 TODO
29  **************************************************************************
30 
31  *************************************************************************/
32 #include <osl/diagnose.h>
33 #include <cppuhelper/interfacecontainer.hxx>
34 #include <com/sun/star/lang/IllegalArgumentException.hpp>
35 #include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp>
36 #include <com/sun/star/ucb/XCommandInfo.hpp>
37 #include <com/sun/star/ucb/XContentProvider.hpp>
38 #include <com/sun/star/ucb/XContentProviderSupplier.hpp>
39 #include <com/sun/star/ucb/XParameterizedContentProvider.hpp>
40 #include <com/sun/star/ucb/XContentProviderFactory.hpp>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
43 #include <com/sun/star/container/XNameAccess.hpp>
44 #include <com/sun/star/uno/Any.hxx>
45 #include <ucbhelper/cancelcommandexecution.hxx>
46 #include "identify.hxx"
47 #include "ucbcmds.hxx"
48 
49 #include "ucb.hxx"
50 
51 // Definitions for ProviderMap_Impl (Solaris wouldn't find explicit template
52 // instantiations for these in another compilation unit...):
53 #ifndef _UCB_REGEXPMAP_TPT_
54 #include <regexpmap.tpt>
55 #endif
56 
57 using namespace rtl;
58 using namespace cppu;
59 using namespace com::sun::star::uno;
60 using namespace com::sun::star::lang;
61 using namespace com::sun::star::ucb;
62 using namespace ucb_impl;
63 using namespace com::sun::star;
64 using namespace ucbhelper;
65 
66 
67 #define CONFIG_CONTENTPROVIDERS_KEY \
68                 "/org.openoffice.ucb.Configuration/ContentProviders"
69 
70 
71 namespace {
72 
fillPlaceholders(rtl::OUString const & rInput,uno::Sequence<uno::Any> const & rReplacements,rtl::OUString * pOutput)73 bool fillPlaceholders(rtl::OUString const & rInput,
74                       uno::Sequence< uno::Any > const & rReplacements,
75                       rtl::OUString * pOutput)
76 {
77     sal_Unicode const * p = rInput.getStr();
78     sal_Unicode const * pEnd = p + rInput.getLength();
79     sal_Unicode const * pCopy = p;
80     rtl::OUStringBuffer aBuffer;
81     while (p != pEnd)
82         switch (*p++)
83         {
84             case '&':
85                 if (pEnd - p >= 4
86                     && p[0] == 'a' && p[1] == 'm' && p[2] == 'p'
87                     && p[3] == ';')
88                 {
89                     aBuffer.append(pCopy, p - 1 - pCopy);
90                     aBuffer.append(sal_Unicode('&'));
91                     p += 4;
92                     pCopy = p;
93                 }
94                 else if (pEnd - p >= 3
95                          && p[0] == 'l' && p[1] == 't' && p[2] == ';')
96                 {
97                     aBuffer.append(pCopy, p - 1 - pCopy);
98                     aBuffer.append(sal_Unicode('<'));
99                     p += 3;
100                     pCopy = p;
101                 }
102                 else if (pEnd - p >= 3
103                          && p[0] == 'g' && p[1] == 't' && p[2] == ';')
104                 {
105                     aBuffer.append(pCopy, p - 1 - pCopy);
106                     aBuffer.append(sal_Unicode('>'));
107                     p += 3;
108                     pCopy = p;
109                 }
110                 break;
111 
112             case '<':
113                 sal_Unicode const * q = p;
114                 while (q != pEnd && *q != '>')
115                     ++q;
116                 if (q == pEnd)
117                     break;
118                 rtl::OUString aKey(p, q - p);
119                 rtl::OUString aValue;
120                 bool bFound = false;
121                 for (sal_Int32 i = 2; i + 1 < rReplacements.getLength();
122                      i += 2)
123                 {
124                     rtl::OUString aReplaceKey;
125                     if ((rReplacements[i] >>= aReplaceKey)
126                         && aReplaceKey == aKey
127                         && (rReplacements[i + 1] >>= aValue))
128                     {
129                         bFound = true;
130                         break;
131                     }
132                 }
133                 if (!bFound)
134                     return false;
135                 aBuffer.append(pCopy, p - 1 - pCopy);
136                 aBuffer.append(aValue);
137                 p = q + 1;
138                 pCopy = p;
139                 break;
140         }
141     aBuffer.append(pCopy, pEnd - pCopy);
142     *pOutput = aBuffer.makeStringAndClear();
143     return true;
144 }
145 
makeAndAppendXMLName(rtl::OUStringBuffer & rBuffer,const rtl::OUString & rIn)146 void makeAndAppendXMLName(
147                 rtl::OUStringBuffer & rBuffer, const rtl::OUString & rIn )
148 {
149     sal_Int32 nCount = rIn.getLength();
150     for ( sal_Int32 n = 0; n < nCount; ++n )
151     {
152         const sal_Unicode c = rIn.getStr()[ n ];
153         switch ( c )
154         {
155             case '&':
156                 rBuffer.appendAscii( "&amp;" );
157                 break;
158 
159             case '"':
160                 rBuffer.appendAscii( "&quot;" );
161                 break;
162 
163             case '\'':
164                 rBuffer.appendAscii( "&apos;" );
165                 break;
166 
167             case '<':
168                 rBuffer.appendAscii( "&lt;" );
169                 break;
170 
171             case '>':
172                 rBuffer.appendAscii( "&gt;" );
173                 break;
174 
175             default:
176                 rBuffer.append( c );
177                 break;
178         }
179     }
180 }
181 
createContentProviderData(const rtl::OUString & rProvider,const uno::Reference<container::XHierarchicalNameAccess> & rxHierNameAccess,ContentProviderData & rInfo)182 bool createContentProviderData(
183     const rtl::OUString & rProvider,
184     const uno::Reference< container::XHierarchicalNameAccess >& rxHierNameAccess,
185     ContentProviderData & rInfo)
186 {
187     // Obtain service name.
188     rtl::OUStringBuffer aKeyBuffer (rProvider);
189     aKeyBuffer.appendAscii( "/ServiceName" );
190 
191     rtl::OUString aValue;
192     try
193     {
194         if ( !( rxHierNameAccess->getByHierarchicalName(
195                     aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
196         {
197             OSL_ENSURE( false,
198                         "UniversalContentBroker::getContentProviderData - "
199                         "Error getting item value!" );
200         }
201     }
202     catch (container::NoSuchElementException &)
203     {
204         return false;
205     }
206 
207     rInfo.ServiceName = aValue;
208 
209     // Obtain URL Template.
210     aKeyBuffer.append(rProvider);
211     aKeyBuffer.appendAscii( "/URLTemplate" );
212 
213     if ( !( rxHierNameAccess->getByHierarchicalName(
214                 aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
215     {
216         OSL_ENSURE( false,
217                     "UniversalContentBroker::getContentProviderData - "
218                     "Error getting item value!" );
219     }
220 
221     rInfo.URLTemplate = aValue;
222 
223     // Obtain Arguments.
224     aKeyBuffer.append(rProvider);
225     aKeyBuffer.appendAscii( "/Arguments" );
226 
227     if ( !( rxHierNameAccess->getByHierarchicalName(
228                 aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
229     {
230         OSL_ENSURE( false,
231                     "UniversalContentBroker::getContentProviderData - "
232                     "Error getting item value!" );
233     }
234 
235     rInfo.Arguments = aValue;
236     return true;
237 }
238 
239 }
240 
241 //=========================================================================
242 //
243 // UniversalContentBroker Implementation.
244 //
245 //=========================================================================
246 
UniversalContentBroker(const Reference<com::sun::star::lang::XMultiServiceFactory> & rXSMgr)247 UniversalContentBroker::UniversalContentBroker(
248     const Reference< com::sun::star::lang::XMultiServiceFactory >& rXSMgr )
249 : m_xSMgr( rXSMgr ),
250   m_pDisposeEventListeners( NULL ),
251   m_nInitCount( 0 ), //@@@ see initialize() method
252   m_nCommandId( 0 )
253 {
254     OSL_ENSURE( m_xSMgr.is(),
255                 "UniversalContentBroker ctor: No service manager" );
256 }
257 
258 //=========================================================================
259 // virtual
~UniversalContentBroker()260 UniversalContentBroker::~UniversalContentBroker()
261 {
262     delete m_pDisposeEventListeners;
263 }
264 
265 //=========================================================================
266 //
267 // XInterface methods.
268 //
269 //=========================================================================
270 
271 XINTERFACE_IMPL_8( UniversalContentBroker,
272                    XTypeProvider,
273                    XComponent,
274                    XServiceInfo,
275                    XInitialization,
276                    XContentProviderManager,
277                    XContentProvider,
278                    XContentIdentifierFactory,
279                    XCommandProcessor );
280 
281 //=========================================================================
282 //
283 // XTypeProvider methods.
284 //
285 //=========================================================================
286 
287 XTYPEPROVIDER_IMPL_8( UniversalContentBroker,
288                       XTypeProvider,
289                       XComponent,
290                       XServiceInfo,
291                       XInitialization,
292                       XContentProviderManager,
293                       XContentProvider,
294                       XContentIdentifierFactory,
295                       XCommandProcessor );
296 
297 //=========================================================================
298 //
299 // XComponent methods.
300 //
301 //=========================================================================
302 
303 // virtual
dispose()304 void SAL_CALL UniversalContentBroker::dispose()
305     throw( com::sun::star::uno::RuntimeException )
306 {
307     if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
308     {
309         EventObject aEvt;
310         aEvt.Source = SAL_STATIC_CAST( XComponent*, this );
311         m_pDisposeEventListeners->disposeAndClear( aEvt );
312     }
313 
314      if ( m_xNotifier.is() )
315         m_xNotifier->removeChangesListener( this );
316 }
317 
318 //=========================================================================
319 // virtual
addEventListener(const Reference<XEventListener> & Listener)320 void SAL_CALL UniversalContentBroker::addEventListener(
321                             const Reference< XEventListener >& Listener )
322     throw( com::sun::star::uno::RuntimeException )
323 {
324     if ( !m_pDisposeEventListeners )
325         m_pDisposeEventListeners = new OInterfaceContainerHelper( m_aMutex );
326 
327     m_pDisposeEventListeners->addInterface( Listener );
328 }
329 
330 //=========================================================================
331 // virtual
removeEventListener(const Reference<XEventListener> & Listener)332 void SAL_CALL UniversalContentBroker::removeEventListener(
333                             const Reference< XEventListener >& Listener )
334     throw( com::sun::star::uno::RuntimeException )
335 {
336     if ( m_pDisposeEventListeners )
337         m_pDisposeEventListeners->removeInterface( Listener );
338 
339     // Note: Don't want to delete empty container here -> performance.
340 }
341 
342 //=========================================================================
343 //
344 // XServiceInfo methods.
345 //
346 //=========================================================================
347 
348 XSERVICEINFO_IMPL_1( UniversalContentBroker,
349                      OUString::createFromAscii(
350                         "com.sun.star.comp.ucb.UniversalContentBroker" ),
351                      OUString::createFromAscii(
352                         UCB_SERVICE_NAME ) );
353 
354 //=========================================================================
355 //
356 // Service factory implementation.
357 //
358 //=========================================================================
359 
360 ONE_INSTANCE_SERVICE_FACTORY_IMPL( UniversalContentBroker );
361 
362 //=========================================================================
363 //
364 // XInitialization methods.
365 //
366 //=========================================================================
367 
368 // virtual
initialize(const com::sun::star::uno::Sequence<Any> & aArguments)369 void SAL_CALL UniversalContentBroker::initialize(
370                     const com::sun::star::uno::Sequence< Any >& aArguments )
371     throw( com::sun::star::uno::Exception,
372            com::sun::star::uno::RuntimeException )
373 {
374     //@@@ At the moment, there's a problem when one (non-one-instance) factory
375     // 'wraps' another (one-instance) factory, causing this method to be
376     // called several times:
377     m_aArguments = aArguments;
378 
379     oslInterlockedCount nCount = osl_incrementInterlockedCount(&m_nInitCount);
380     if (nCount == 1)
381         configureUcb();
382     else
383         osl_decrementInterlockedCount(&m_nInitCount);
384             // make the possibility of overflow less likely...
385 }
386 
387 //=========================================================================
388 //
389 // XContentProviderManager methods.
390 //
391 //=========================================================================
392 
393 // virtual
394 Reference< XContentProvider > SAL_CALL
registerContentProvider(const Reference<XContentProvider> & Provider,const OUString & Scheme,sal_Bool ReplaceExisting)395 UniversalContentBroker::registerContentProvider(
396                             const Reference< XContentProvider >& Provider,
397                             const OUString& Scheme,
398                             sal_Bool ReplaceExisting )
399     throw( DuplicateProviderException, com::sun::star::uno::RuntimeException )
400 {
401     osl::MutexGuard aGuard(m_aMutex);
402 
403     ProviderMap_Impl::iterator aIt;
404     try
405     {
406         aIt = m_aProviders.find(Scheme);
407     }
408     catch (IllegalArgumentException const &)
409     {
410         return 0; //@@@
411     }
412 
413     Reference< XContentProvider > xPrevious;
414     if (aIt == m_aProviders.end())
415     {
416         ProviderList_Impl aList;
417         aList.push_front(Provider);
418         try
419         {
420             m_aProviders.add(Scheme, aList, false);
421         }
422         catch (IllegalArgumentException const &)
423         {
424             return 0; //@@@
425         }
426     }
427     else
428     {
429         if (!ReplaceExisting)
430             throw DuplicateProviderException();
431 
432         ProviderList_Impl & rList = aIt->getValue();
433         xPrevious = rList.front().getProvider();
434         rList.push_front(Provider);
435     }
436 
437     return xPrevious;
438 }
439 
440 //=========================================================================
441 // virtual
deregisterContentProvider(const Reference<XContentProvider> & Provider,const OUString & Scheme)442 void SAL_CALL UniversalContentBroker::deregisterContentProvider(
443                             const Reference< XContentProvider >& Provider,
444                             const OUString& Scheme )
445     throw( com::sun::star::uno::RuntimeException )
446 {
447     osl::MutexGuard aGuard(m_aMutex);
448 
449     ProviderMap_Impl::iterator aMapIt;
450     try
451     {
452         aMapIt = m_aProviders.find(Scheme);
453     }
454     catch (IllegalArgumentException const &)
455     {
456         return; //@@@
457     }
458 
459     if (aMapIt != m_aProviders.end())
460     {
461         ProviderList_Impl & rList = aMapIt->getValue();
462 
463         ProviderList_Impl::iterator aListEnd(rList.end());
464         for (ProviderList_Impl::iterator aListIt(rList.begin());
465              aListIt != aListEnd; ++aListIt)
466         {
467             if ((*aListIt).getProvider() == Provider)
468             {
469                 rList.erase(aListIt);
470                 break;
471             }
472         }
473 
474         if (rList.empty())
475             m_aProviders.erase(aMapIt);
476     }
477 }
478 
479 //=========================================================================
480 // virtual
481 com::sun::star::uno::Sequence< ContentProviderInfo > SAL_CALL
queryContentProviders()482                             UniversalContentBroker::queryContentProviders()
483     throw( com::sun::star::uno::RuntimeException )
484 {
485     // Return a list with information about active(!) content providers.
486 
487     osl::MutexGuard aGuard(m_aMutex);
488 
489     com::sun::star::uno::Sequence< ContentProviderInfo > aSeq(
490                                                     m_aProviders.size() );
491     ContentProviderInfo* pInfo = aSeq.getArray();
492 
493     ProviderMap_Impl::const_iterator end = m_aProviders.end();
494     for (ProviderMap_Impl::const_iterator it(m_aProviders.begin()); it != end;
495          ++it)
496     {
497         // Note: Active provider is always the first list element.
498         pInfo->ContentProvider = it->getValue().front().getProvider();
499         pInfo->Scheme = it->getRegexp();
500         ++pInfo;
501     }
502 
503     return aSeq;
504 }
505 
506 //=========================================================================
507 // virtual
508 Reference< XContentProvider > SAL_CALL
queryContentProvider(const OUString & Identifier)509         UniversalContentBroker::queryContentProvider( const OUString&
510                                                           Identifier )
511     throw( com::sun::star::uno::RuntimeException )
512 {
513     return queryContentProvider( Identifier, sal_False );
514 }
515 
516 //=========================================================================
517 //
518 // XContentProvider methods.
519 //
520 //=========================================================================
521 
522 // virtual
queryContent(const Reference<XContentIdentifier> & Identifier)523 Reference< XContent > SAL_CALL UniversalContentBroker::queryContent(
524                         const Reference< XContentIdentifier >& Identifier )
525     throw( IllegalIdentifierException, com::sun::star::uno::RuntimeException )
526 {
527     //////////////////////////////////////////////////////////////////////
528     // Let the content provider for the scheme given with the content
529     // identifier create the XContent instance.
530     //////////////////////////////////////////////////////////////////////
531 
532     if ( !Identifier.is() )
533         return Reference< XContent >();
534 
535     Reference< XContentProvider > xProv =
536         queryContentProvider( Identifier->getContentIdentifier(), sal_True );
537     if ( xProv.is() )
538         return  xProv->queryContent( Identifier );
539 
540     return Reference< XContent >();
541 }
542 
543 //=========================================================================
544 // virtual
compareContentIds(const Reference<XContentIdentifier> & Id1,const Reference<XContentIdentifier> & Id2)545 sal_Int32 SAL_CALL UniversalContentBroker::compareContentIds(
546                                 const Reference< XContentIdentifier >& Id1,
547                                 const Reference< XContentIdentifier >& Id2 )
548     throw( com::sun::star::uno::RuntimeException )
549 {
550     OUString aURI1( Id1->getContentIdentifier() );
551     OUString aURI2( Id2->getContentIdentifier() );
552 
553     Reference< XContentProvider > xProv1
554                             = queryContentProvider( aURI1, sal_True );
555     Reference< XContentProvider > xProv2
556                             = queryContentProvider( aURI2, sal_True );
557 
558     // When both identifiers belong to the same provider, let that provider
559     // compare them; otherwise, simply compare the URI strings (which must
560     // be different):
561     if ( xProv1.is() && ( xProv1 == xProv2 ) )
562         return xProv1->compareContentIds( Id1, Id2 );
563     else
564         return aURI1.compareTo( aURI2 );
565 }
566 
567 //=========================================================================
568 //
569 // XContentIdentifierFactory methods.
570 //
571 //=========================================================================
572 
573 // virtual
574 Reference< XContentIdentifier > SAL_CALL
createContentIdentifier(const OUString & ContentId)575         UniversalContentBroker::createContentIdentifier(
576                                             const OUString& ContentId )
577     throw( com::sun::star::uno::RuntimeException )
578 {
579     //////////////////////////////////////////////////////////////////////
580     // Let the content provider for the scheme given with content
581     // identifier create the XContentIdentifier instance, if he supports
582     // the XContentIdentifierFactory interface. Otherwise create standard
583     // implementation object for XContentIdentifier.
584     //////////////////////////////////////////////////////////////////////
585 
586     Reference< XContentIdentifier > xIdentifier;
587 
588     Reference< XContentProvider > xProv
589                             = queryContentProvider( ContentId, sal_True );
590     if ( xProv.is() )
591     {
592         Reference< XContentIdentifierFactory > xFac( xProv, UNO_QUERY );
593         if ( xFac.is() )
594             xIdentifier = xFac->createContentIdentifier( ContentId );
595     }
596 
597     if ( !xIdentifier.is() )
598         xIdentifier = new ContentIdentifier( m_xSMgr, ContentId );
599 
600     return xIdentifier;
601 }
602 
603 //=========================================================================
604 //
605 // XCommandProcessor methods.
606 //
607 //=========================================================================
608 
609 // virtual
createCommandIdentifier()610 sal_Int32 SAL_CALL UniversalContentBroker::createCommandIdentifier()
611     throw( RuntimeException )
612 {
613     osl::MutexGuard aGuard( m_aMutex );
614 
615     // Just increase counter on every call to generate an identifier.
616     return ++m_nCommandId;
617 }
618 
619 //=========================================================================
620 // virtual
execute(const Command & aCommand,sal_Int32,const Reference<XCommandEnvironment> & Environment)621 Any SAL_CALL UniversalContentBroker::execute(
622                           const Command& aCommand,
623                           sal_Int32,
624                           const Reference< XCommandEnvironment >& Environment )
625     throw( Exception, CommandAbortedException, RuntimeException )
626 {
627     Any aRet;
628 
629     //////////////////////////////////////////////////////////////////////
630     // Note: Don't forget to adapt ucb_commands::CommandProcessorInfo
631     //       ctor in ucbcmds.cxx when adding new commands!
632     //////////////////////////////////////////////////////////////////////
633 
634     if ( ( aCommand.Handle == GETCOMMANDINFO_HANDLE ) ||
635          aCommand.Name.equalsAsciiL(
636                     RTL_CONSTASCII_STRINGPARAM( GETCOMMANDINFO_NAME ) ) )
637     {
638         //////////////////////////////////////////////////////////////////
639         // getCommandInfo
640         //////////////////////////////////////////////////////////////////
641 
642         aRet <<= getCommandInfo();
643     }
644     else if ( ( aCommand.Handle == GLOBALTRANSFER_HANDLE ) ||
645               aCommand.Name.equalsAsciiL(
646                     RTL_CONSTASCII_STRINGPARAM(GLOBALTRANSFER_NAME ) ) )
647     {
648         //////////////////////////////////////////////////////////////////
649         // globalTransfer
650         //////////////////////////////////////////////////////////////////
651 
652         GlobalTransferCommandArgument aTransferArg;
653         if ( !( aCommand.Argument >>= aTransferArg ) )
654         {
655             ucbhelper::cancelCommandExecution(
656                 makeAny( IllegalArgumentException(
657                                 rtl::OUString::createFromAscii(
658                                         "Wrong argument type!" ),
659                                 static_cast< cppu::OWeakObject * >( this ),
660                                 -1 ) ),
661                 Environment );
662             // Unreachable
663         }
664 
665         globalTransfer( aTransferArg, Environment );
666     }
667     else
668     {
669         //////////////////////////////////////////////////////////////////
670         // Unknown command
671         //////////////////////////////////////////////////////////////////
672 
673         ucbhelper::cancelCommandExecution(
674             makeAny( UnsupportedCommandException(
675                             rtl::OUString(),
676                             static_cast< cppu::OWeakObject * >( this ) ) ),
677             Environment );
678         // Unreachable
679     }
680 
681     return aRet;
682 }
683 
684 //=========================================================================
685 // virtual
abort(sal_Int32)686 void SAL_CALL UniversalContentBroker::abort( sal_Int32 )
687     throw( RuntimeException )
688 {
689     // @@@ Not implemeted ( yet).
690 }
691 
692 //=========================================================================
693 //
694 // XChangesListener methods
695 //
696 //=========================================================================
697 // virtual
changesOccurred(const util::ChangesEvent & Event)698 void SAL_CALL UniversalContentBroker::changesOccurred( const util::ChangesEvent& Event )
699         throw( uno::RuntimeException )
700 {
701     sal_Int32 nCount = Event.Changes.getLength();
702     if ( nCount )
703     {
704         uno::Reference< container::XHierarchicalNameAccess > xHierNameAccess;
705         Event.Base >>= xHierNameAccess;
706 
707         OSL_ASSERT( xHierNameAccess.is() );
708 
709         const util::ElementChange* pElementChanges
710             = Event.Changes.getConstArray();
711 
712         ContentProviderDataList aData;
713         for ( sal_Int32 n = 0; n < nCount; ++n )
714         {
715             const util::ElementChange& rElem = pElementChanges[ n ];
716             rtl::OUString aKey;
717             rElem.Accessor >>= aKey;
718 
719             ContentProviderData aInfo;
720 
721             // Removal of UCPs from the configuration leads to changesOccurred
722             // notifications, too, but it is hard to tell for a given
723             // ElementChange whether it is an addition or a removal, so as a
724             // heuristic consider as removals those that cause a
725             // NoSuchElementException in createContentProviderData.
726             //
727             // For now, removal of UCPs from the configuration is simply ignored
728             // (and not reflected in the UCB's data structures):
729             if (createContentProviderData(aKey, xHierNameAccess, aInfo))
730             {
731                 aData.push_back(aInfo);
732             }
733         }
734 
735         prepareAndRegister(aData);
736     }
737 }
738 
739 //=========================================================================
740 //
741 // XEventListener methods
742 //
743 //=========================================================================
744 // virtual
disposing(const lang::EventObject &)745 void SAL_CALL UniversalContentBroker::disposing(const lang::EventObject&)
746     throw( uno::RuntimeException )
747 {
748     if ( m_xNotifier.is() )
749     {
750         osl::Guard< osl::Mutex > aGuard( m_aMutex );
751 
752         if ( m_xNotifier.is() )
753             m_xNotifier.clear();
754     }
755 }
756 
757 //=========================================================================
758 //
759 // Non-interface methods
760 //
761 //=========================================================================
762 
queryContentProvider(const OUString & Identifier,sal_Bool bResolved)763 Reference< XContentProvider > UniversalContentBroker::queryContentProvider(
764                                 const OUString& Identifier,
765                                 sal_Bool bResolved )
766 {
767     osl::MutexGuard aGuard( m_aMutex );
768 
769     ProviderList_Impl const * pList = m_aProviders.map( Identifier );
770     return pList ? bResolved ? pList->front().getResolvedProvider()
771                              : pList->front().getProvider()
772                  : Reference< XContentProvider >();
773 }
774 
configureUcb()775 bool UniversalContentBroker::configureUcb()
776     throw (uno::RuntimeException)
777 {
778     rtl::OUString aKey1;
779     rtl::OUString aKey2;
780     if (m_aArguments.getLength() < 2
781         || !(m_aArguments[0] >>= aKey1) || !(m_aArguments[1] >>= aKey2))
782     {
783         OSL_ENSURE(false, "UniversalContentBroker::configureUcb(): Bad arguments");
784         return false;
785     }
786 
787     ContentProviderDataList aData;
788     if (!getContentProviderData(aKey1, aKey2, aData))
789     {
790         OSL_ENSURE(false, "UniversalContentBroker::configureUcb(): No configuration");
791         return false;
792     }
793 
794     prepareAndRegister(aData);
795 
796     return true;
797 }
798 
prepareAndRegister(const ContentProviderDataList & rData)799 void UniversalContentBroker::prepareAndRegister(
800     const ContentProviderDataList& rData)
801 {
802     ContentProviderDataList::const_iterator aEnd(rData.end());
803     for (ContentProviderDataList::const_iterator aIt(rData.begin());
804          aIt != aEnd; ++aIt)
805     {
806         rtl::OUString aProviderArguments;
807         if (fillPlaceholders(aIt->Arguments,
808                              m_aArguments,
809                              &aProviderArguments))
810         {
811             registerAtUcb(this,
812                                       m_xSMgr,
813                                       aIt->ServiceName,
814                                           aProviderArguments,
815                                           aIt->URLTemplate,
816                                           0);
817 
818         }
819         else
820             OSL_ENSURE(false,
821                        "UniversalContentBroker::prepareAndRegister(): Bad argument placeholders");
822     }
823 }
824 
825 //=========================================================================
getContentProviderData(const rtl::OUString & rKey1,const rtl::OUString & rKey2,ContentProviderDataList & rListToFill)826 bool UniversalContentBroker::getContentProviderData(
827             const rtl::OUString & rKey1,
828             const rtl::OUString & rKey2,
829             ContentProviderDataList & rListToFill )
830 {
831     if ( !m_xSMgr.is() || !rKey1.getLength() || !rKey2.getLength() )
832     {
833         OSL_ENSURE( false,
834             "UniversalContentBroker::getContentProviderData - Invalid argument!" );
835         return false;
836     }
837 
838     try
839     {
840         uno::Reference< lang::XMultiServiceFactory > xConfigProv(
841                 m_xSMgr->createInstance(
842                     rtl::OUString::createFromAscii(
843                         "com.sun.star.configuration.ConfigurationProvider" ) ),
844                 uno::UNO_QUERY_THROW );
845 
846         rtl::OUStringBuffer aFullPath;
847         aFullPath.appendAscii( CONFIG_CONTENTPROVIDERS_KEY "/['" );
848         makeAndAppendXMLName( aFullPath, rKey1 );
849         aFullPath.appendAscii( "']/SecondaryKeys/['" );
850         makeAndAppendXMLName( aFullPath, rKey2 );
851         aFullPath.appendAscii( "']/ProviderData" );
852 
853         uno::Sequence< uno::Any > aArguments( 1 );
854         beans::PropertyValue      aProperty;
855         aProperty.Name
856             = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
857         aProperty.Value <<= aFullPath.makeStringAndClear();
858         aArguments[ 0 ] <<= aProperty;
859 
860         uno::Reference< uno::XInterface > xInterface(
861                 xConfigProv->createInstanceWithArguments(
862                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
863                         "com.sun.star.configuration.ConfigurationAccess" ) ),
864                     aArguments ) );
865 
866         if ( !m_xNotifier.is() )
867         {
868             m_xNotifier = uno::Reference< util::XChangesNotifier >(
869                                                 xInterface, uno::UNO_QUERY_THROW );
870 
871             m_xNotifier->addChangesListener( this );
872         }
873 
874         uno::Reference< container::XNameAccess > xNameAccess(
875                                             xInterface, uno::UNO_QUERY_THROW );
876 
877         uno::Sequence< rtl::OUString > aElems = xNameAccess->getElementNames();
878         const rtl::OUString* pElems = aElems.getConstArray();
879         sal_Int32 nCount = aElems.getLength();
880 
881         if ( nCount > 0 )
882         {
883             uno::Reference< container::XHierarchicalNameAccess >
884                                 xHierNameAccess( xInterface, uno::UNO_QUERY_THROW );
885 
886             // Iterate over children.
887             for ( sal_Int32 n = 0; n < nCount; ++n )
888             {
889 
890                 try
891                 {
892 
893                     ContentProviderData aInfo;
894 
895                     rtl::OUStringBuffer aElemBuffer;
896                     aElemBuffer.appendAscii( "['" );
897                     makeAndAppendXMLName( aElemBuffer, pElems[ n ] );
898                     aElemBuffer.appendAscii( "']" );
899 
900                     OSL_VERIFY(
901                         createContentProviderData(
902                             aElemBuffer.makeStringAndClear(), xHierNameAccess,
903                             aInfo));
904 
905                     rListToFill.push_back( aInfo );
906                 }
907                 catch ( container::NoSuchElementException& )
908                 {
909                     // getByHierarchicalName
910                     OSL_ENSURE( false,
911                                 "UniversalContentBroker::getContentProviderData - "
912                                 "caught NoSuchElementException!" );
913                 }
914             }
915         }
916     }
917     catch ( uno::RuntimeException& )
918     {
919         OSL_ENSURE( false,
920                     "UniversalContentBroker::getContentProviderData - caught RuntimeException!" );
921         return false;
922     }
923     catch ( uno::Exception& )
924     {
925         // createInstance, createInstanceWithArguments
926 
927         OSL_ENSURE( false,
928                     "UniversalContentBroker::getContentProviderData - caught Exception!" );
929         return false;
930     }
931 
932     return true;
933 }
934 
935 //=========================================================================
936 //
937 // ProviderListEntry_Impl implementation.
938 //
939 //=========================================================================
940 
resolveProvider() const941 Reference< XContentProvider > ProviderListEntry_Impl::resolveProvider() const
942 {
943     if ( !m_xResolvedProvider.is() )
944     {
945         Reference< XContentProviderSupplier > xSupplier(
946                                                     m_xProvider, UNO_QUERY );
947         if ( xSupplier.is() )
948             m_xResolvedProvider = xSupplier->getContentProvider();
949 
950         if ( !m_xResolvedProvider.is() )
951             m_xResolvedProvider = m_xProvider;
952     }
953 
954     return m_xResolvedProvider;
955 }
956