xref: /trunk/main/ucb/source/core/ucb.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_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 {
306     if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
307     {
308         EventObject aEvt;
309         aEvt.Source = SAL_STATIC_CAST( XComponent*, this );
310         m_pDisposeEventListeners->disposeAndClear( aEvt );
311     }
312 
313      if ( m_xNotifier.is() )
314         m_xNotifier->removeChangesListener( this );
315 }
316 
317 //=========================================================================
318 // virtual
addEventListener(const Reference<XEventListener> & Listener)319 void SAL_CALL UniversalContentBroker::addEventListener(
320                             const Reference< XEventListener >& Listener )
321 {
322     if ( !m_pDisposeEventListeners )
323         m_pDisposeEventListeners = new OInterfaceContainerHelper( m_aMutex );
324 
325     m_pDisposeEventListeners->addInterface( Listener );
326 }
327 
328 //=========================================================================
329 // virtual
removeEventListener(const Reference<XEventListener> & Listener)330 void SAL_CALL UniversalContentBroker::removeEventListener(
331                             const Reference< XEventListener >& Listener )
332 {
333     if ( m_pDisposeEventListeners )
334         m_pDisposeEventListeners->removeInterface( Listener );
335 
336     // Note: Don't want to delete empty container here -> performance.
337 }
338 
339 //=========================================================================
340 //
341 // XServiceInfo methods.
342 //
343 //=========================================================================
344 
345 XSERVICEINFO_IMPL_1( UniversalContentBroker,
346                      OUString::createFromAscii(
347                         "com.sun.star.comp.ucb.UniversalContentBroker" ),
348                      OUString::createFromAscii(
349                         UCB_SERVICE_NAME ) );
350 
351 //=========================================================================
352 //
353 // Service factory implementation.
354 //
355 //=========================================================================
356 
357 ONE_INSTANCE_SERVICE_FACTORY_IMPL( UniversalContentBroker );
358 
359 //=========================================================================
360 //
361 // XInitialization methods.
362 //
363 //=========================================================================
364 
365 // virtual
initialize(const com::sun::star::uno::Sequence<Any> & aArguments)366 void SAL_CALL UniversalContentBroker::initialize(
367                     const com::sun::star::uno::Sequence< Any >& aArguments )
368 {
369     //@@@ At the moment, there's a problem when one (non-one-instance) factory
370     // 'wraps' another (one-instance) factory, causing this method to be
371     // called several times:
372     m_aArguments = aArguments;
373 
374     oslInterlockedCount nCount = osl_incrementInterlockedCount(&m_nInitCount);
375     if (nCount == 1)
376         configureUcb();
377     else
378         osl_decrementInterlockedCount(&m_nInitCount);
379             // make the possibility of overflow less likely...
380 }
381 
382 //=========================================================================
383 //
384 // XContentProviderManager methods.
385 //
386 //=========================================================================
387 
388 // virtual
389 Reference< XContentProvider > SAL_CALL
registerContentProvider(const Reference<XContentProvider> & Provider,const OUString & Scheme,sal_Bool ReplaceExisting)390 UniversalContentBroker::registerContentProvider(
391                             const Reference< XContentProvider >& Provider,
392                             const OUString& Scheme,
393                             sal_Bool ReplaceExisting )
394 {
395     osl::MutexGuard aGuard(m_aMutex);
396 
397     ProviderMap_Impl::iterator aIt;
398     try
399     {
400         aIt = m_aProviders.find(Scheme);
401     }
402     catch (IllegalArgumentException const &)
403     {
404         return 0; //@@@
405     }
406 
407     Reference< XContentProvider > xPrevious;
408     if (aIt == m_aProviders.end())
409     {
410         ProviderList_Impl aList;
411         aList.push_front(Provider);
412         try
413         {
414             m_aProviders.add(Scheme, aList, false);
415         }
416         catch (IllegalArgumentException const &)
417         {
418             return 0; //@@@
419         }
420     }
421     else
422     {
423         if (!ReplaceExisting)
424             throw DuplicateProviderException();
425 
426         ProviderList_Impl & rList = aIt->getValue();
427         xPrevious = rList.front().getProvider();
428         rList.push_front(Provider);
429     }
430 
431     return xPrevious;
432 }
433 
434 //=========================================================================
435 // virtual
deregisterContentProvider(const Reference<XContentProvider> & Provider,const OUString & Scheme)436 void SAL_CALL UniversalContentBroker::deregisterContentProvider(
437                             const Reference< XContentProvider >& Provider,
438                             const OUString& Scheme )
439 {
440     osl::MutexGuard aGuard(m_aMutex);
441 
442     ProviderMap_Impl::iterator aMapIt;
443     try
444     {
445         aMapIt = m_aProviders.find(Scheme);
446     }
447     catch (IllegalArgumentException const &)
448     {
449         return; //@@@
450     }
451 
452     if (aMapIt != m_aProviders.end())
453     {
454         ProviderList_Impl & rList = aMapIt->getValue();
455 
456         ProviderList_Impl::iterator aListEnd(rList.end());
457         for (ProviderList_Impl::iterator aListIt(rList.begin());
458              aListIt != aListEnd; ++aListIt)
459         {
460             if ((*aListIt).getProvider() == Provider)
461             {
462                 rList.erase(aListIt);
463                 break;
464             }
465         }
466 
467         if (rList.empty())
468             m_aProviders.erase(aMapIt);
469     }
470 }
471 
472 //=========================================================================
473 // virtual
474 com::sun::star::uno::Sequence< ContentProviderInfo > SAL_CALL
queryContentProviders()475                             UniversalContentBroker::queryContentProviders()
476 {
477     // Return a list with information about active(!) content providers.
478 
479     osl::MutexGuard aGuard(m_aMutex);
480 
481     com::sun::star::uno::Sequence< ContentProviderInfo > aSeq(
482                                                     m_aProviders.size() );
483     ContentProviderInfo* pInfo = aSeq.getArray();
484 
485     ProviderMap_Impl::const_iterator end = m_aProviders.end();
486     for (ProviderMap_Impl::const_iterator it(m_aProviders.begin()); it != end;
487          ++it)
488     {
489         // Note: Active provider is always the first list element.
490         pInfo->ContentProvider = it->getValue().front().getProvider();
491         pInfo->Scheme = it->getRegexp();
492         ++pInfo;
493     }
494 
495     return aSeq;
496 }
497 
498 //=========================================================================
499 // virtual
500 Reference< XContentProvider > SAL_CALL
queryContentProvider(const OUString & Identifier)501         UniversalContentBroker::queryContentProvider( const OUString&
502                                                           Identifier )
503 {
504     return queryContentProvider( Identifier, sal_False );
505 }
506 
507 //=========================================================================
508 //
509 // XContentProvider methods.
510 //
511 //=========================================================================
512 
513 // virtual
queryContent(const Reference<XContentIdentifier> & Identifier)514 Reference< XContent > SAL_CALL UniversalContentBroker::queryContent(
515                         const Reference< XContentIdentifier >& Identifier )
516 {
517     //////////////////////////////////////////////////////////////////////
518     // Let the content provider for the scheme given with the content
519     // identifier create the XContent instance.
520     //////////////////////////////////////////////////////////////////////
521 
522     if ( !Identifier.is() )
523         return Reference< XContent >();
524 
525     Reference< XContentProvider > xProv =
526         queryContentProvider( Identifier->getContentIdentifier(), sal_True );
527     if ( xProv.is() )
528         return  xProv->queryContent( Identifier );
529 
530     return Reference< XContent >();
531 }
532 
533 //=========================================================================
534 // virtual
compareContentIds(const Reference<XContentIdentifier> & Id1,const Reference<XContentIdentifier> & Id2)535 sal_Int32 SAL_CALL UniversalContentBroker::compareContentIds(
536                                 const Reference< XContentIdentifier >& Id1,
537                                 const Reference< XContentIdentifier >& Id2 )
538 {
539     OUString aURI1( Id1->getContentIdentifier() );
540     OUString aURI2( Id2->getContentIdentifier() );
541 
542     Reference< XContentProvider > xProv1
543                             = queryContentProvider( aURI1, sal_True );
544     Reference< XContentProvider > xProv2
545                             = queryContentProvider( aURI2, sal_True );
546 
547     // When both identifiers belong to the same provider, let that provider
548     // compare them; otherwise, simply compare the URI strings (which must
549     // be different):
550     if ( xProv1.is() && ( xProv1 == xProv2 ) )
551         return xProv1->compareContentIds( Id1, Id2 );
552     else
553         return aURI1.compareTo( aURI2 );
554 }
555 
556 //=========================================================================
557 //
558 // XContentIdentifierFactory methods.
559 //
560 //=========================================================================
561 
562 // virtual
563 Reference< XContentIdentifier > SAL_CALL
createContentIdentifier(const OUString & ContentId)564         UniversalContentBroker::createContentIdentifier(
565                                             const OUString& ContentId )
566 {
567     //////////////////////////////////////////////////////////////////////
568     // Let the content provider for the scheme given with content
569     // identifier create the XContentIdentifier instance, if he supports
570     // the XContentIdentifierFactory interface. Otherwise create standard
571     // implementation object for XContentIdentifier.
572     //////////////////////////////////////////////////////////////////////
573 
574     Reference< XContentIdentifier > xIdentifier;
575 
576     Reference< XContentProvider > xProv
577                             = queryContentProvider( ContentId, sal_True );
578     if ( xProv.is() )
579     {
580         Reference< XContentIdentifierFactory > xFac( xProv, UNO_QUERY );
581         if ( xFac.is() )
582             xIdentifier = xFac->createContentIdentifier( ContentId );
583     }
584 
585     if ( !xIdentifier.is() )
586         xIdentifier = new ContentIdentifier( m_xSMgr, ContentId );
587 
588     return xIdentifier;
589 }
590 
591 //=========================================================================
592 //
593 // XCommandProcessor methods.
594 //
595 //=========================================================================
596 
597 // virtual
createCommandIdentifier()598 sal_Int32 SAL_CALL UniversalContentBroker::createCommandIdentifier()
599 {
600     osl::MutexGuard aGuard( m_aMutex );
601 
602     // Just increase counter on every call to generate an identifier.
603     return ++m_nCommandId;
604 }
605 
606 //=========================================================================
607 // virtual
execute(const Command & aCommand,sal_Int32,const Reference<XCommandEnvironment> & Environment)608 Any SAL_CALL UniversalContentBroker::execute(
609                           const Command& aCommand,
610                           sal_Int32,
611                           const Reference< XCommandEnvironment >& Environment )
612 {
613     Any aRet;
614 
615     //////////////////////////////////////////////////////////////////////
616     // Note: Don't forget to adapt ucb_commands::CommandProcessorInfo
617     //       ctor in ucbcmds.cxx when adding new commands!
618     //////////////////////////////////////////////////////////////////////
619 
620     if ( ( aCommand.Handle == GETCOMMANDINFO_HANDLE ) ||
621          aCommand.Name.equalsAsciiL(
622                     RTL_CONSTASCII_STRINGPARAM( GETCOMMANDINFO_NAME ) ) )
623     {
624         //////////////////////////////////////////////////////////////////
625         // getCommandInfo
626         //////////////////////////////////////////////////////////////////
627 
628         aRet <<= getCommandInfo();
629     }
630     else if ( ( aCommand.Handle == GLOBALTRANSFER_HANDLE ) ||
631               aCommand.Name.equalsAsciiL(
632                     RTL_CONSTASCII_STRINGPARAM(GLOBALTRANSFER_NAME ) ) )
633     {
634         //////////////////////////////////////////////////////////////////
635         // globalTransfer
636         //////////////////////////////////////////////////////////////////
637 
638         GlobalTransferCommandArgument aTransferArg;
639         if ( !( aCommand.Argument >>= aTransferArg ) )
640         {
641             ucbhelper::cancelCommandExecution(
642                 makeAny( IllegalArgumentException(
643                                 rtl::OUString::createFromAscii(
644                                         "Wrong argument type!" ),
645                                 static_cast< cppu::OWeakObject * >( this ),
646                                 -1 ) ),
647                 Environment );
648             // Unreachable
649         }
650 
651         globalTransfer( aTransferArg, Environment );
652     }
653     else
654     {
655         //////////////////////////////////////////////////////////////////
656         // Unknown command
657         //////////////////////////////////////////////////////////////////
658 
659         ucbhelper::cancelCommandExecution(
660             makeAny( UnsupportedCommandException(
661                             rtl::OUString(),
662                             static_cast< cppu::OWeakObject * >( this ) ) ),
663             Environment );
664         // Unreachable
665     }
666 
667     return aRet;
668 }
669 
670 //=========================================================================
671 // virtual
abort(sal_Int32)672 void SAL_CALL UniversalContentBroker::abort( sal_Int32 )
673 {
674     // @@@ Not implemented ( yet).
675 }
676 
677 //=========================================================================
678 //
679 // XChangesListener methods
680 //
681 //=========================================================================
682 // virtual
changesOccurred(const util::ChangesEvent & Event)683 void SAL_CALL UniversalContentBroker::changesOccurred( const util::ChangesEvent& Event )
684 {
685     sal_Int32 nCount = Event.Changes.getLength();
686     if ( nCount )
687     {
688         uno::Reference< container::XHierarchicalNameAccess > xHierNameAccess;
689         Event.Base >>= xHierNameAccess;
690 
691         OSL_ASSERT( xHierNameAccess.is() );
692 
693         const util::ElementChange* pElementChanges
694             = Event.Changes.getConstArray();
695 
696         ContentProviderDataList aData;
697         for ( sal_Int32 n = 0; n < nCount; ++n )
698         {
699             const util::ElementChange& rElem = pElementChanges[ n ];
700             rtl::OUString aKey;
701             rElem.Accessor >>= aKey;
702 
703             ContentProviderData aInfo;
704 
705             // Removal of UCPs from the configuration leads to changesOccurred
706             // notifications, too, but it is hard to tell for a given
707             // ElementChange whether it is an addition or a removal, so as a
708             // heuristic consider as removals those that cause a
709             // NoSuchElementException in createContentProviderData.
710             //
711             // For now, removal of UCPs from the configuration is simply ignored
712             // (and not reflected in the UCB's data structures):
713             if (createContentProviderData(aKey, xHierNameAccess, aInfo))
714             {
715                 aData.push_back(aInfo);
716             }
717         }
718 
719         prepareAndRegister(aData);
720     }
721 }
722 
723 //=========================================================================
724 //
725 // XEventListener methods
726 //
727 //=========================================================================
728 // virtual
disposing(const lang::EventObject &)729 void SAL_CALL UniversalContentBroker::disposing(const lang::EventObject&)
730 {
731     if ( m_xNotifier.is() )
732     {
733         osl::Guard< osl::Mutex > aGuard( m_aMutex );
734 
735         if ( m_xNotifier.is() )
736             m_xNotifier.clear();
737     }
738 }
739 
740 //=========================================================================
741 //
742 // Non-interface methods
743 //
744 //=========================================================================
745 
queryContentProvider(const OUString & Identifier,sal_Bool bResolved)746 Reference< XContentProvider > UniversalContentBroker::queryContentProvider(
747                                 const OUString& Identifier,
748                                 sal_Bool bResolved )
749 {
750     osl::MutexGuard aGuard( m_aMutex );
751 
752     ProviderList_Impl const * pList = m_aProviders.map( Identifier );
753     return pList ? bResolved ? pList->front().getResolvedProvider()
754                              : pList->front().getProvider()
755                  : Reference< XContentProvider >();
756 }
757 
configureUcb()758 bool UniversalContentBroker::configureUcb()
759 {
760     rtl::OUString aKey1;
761     rtl::OUString aKey2;
762     if (m_aArguments.getLength() < 2
763         || !(m_aArguments[0] >>= aKey1) || !(m_aArguments[1] >>= aKey2))
764     {
765         OSL_ENSURE(false, "UniversalContentBroker::configureUcb(): Bad arguments");
766         return false;
767     }
768 
769     ContentProviderDataList aData;
770     if (!getContentProviderData(aKey1, aKey2, aData))
771     {
772         OSL_ENSURE(false, "UniversalContentBroker::configureUcb(): No configuration");
773         return false;
774     }
775 
776     prepareAndRegister(aData);
777 
778     return true;
779 }
780 
prepareAndRegister(const ContentProviderDataList & rData)781 void UniversalContentBroker::prepareAndRegister(
782     const ContentProviderDataList& rData)
783 {
784     ContentProviderDataList::const_iterator aEnd(rData.end());
785     for (ContentProviderDataList::const_iterator aIt(rData.begin());
786          aIt != aEnd; ++aIt)
787     {
788         rtl::OUString aProviderArguments;
789         if (fillPlaceholders(aIt->Arguments,
790                              m_aArguments,
791                              &aProviderArguments))
792         {
793             registerAtUcb(this,
794                                       m_xSMgr,
795                                       aIt->ServiceName,
796                                           aProviderArguments,
797                                           aIt->URLTemplate,
798                                           0);
799 
800         }
801         else
802             OSL_ENSURE(false,
803                        "UniversalContentBroker::prepareAndRegister(): Bad argument placeholders");
804     }
805 }
806 
807 //=========================================================================
getContentProviderData(const rtl::OUString & rKey1,const rtl::OUString & rKey2,ContentProviderDataList & rListToFill)808 bool UniversalContentBroker::getContentProviderData(
809             const rtl::OUString & rKey1,
810             const rtl::OUString & rKey2,
811             ContentProviderDataList & rListToFill )
812 {
813     if ( !m_xSMgr.is() || !rKey1.getLength() || !rKey2.getLength() )
814     {
815         OSL_ENSURE( false,
816             "UniversalContentBroker::getContentProviderData - Invalid argument!" );
817         return false;
818     }
819 
820     try
821     {
822         uno::Reference< lang::XMultiServiceFactory > xConfigProv(
823                 m_xSMgr->createInstance(
824                     rtl::OUString::createFromAscii(
825                         "com.sun.star.configuration.ConfigurationProvider" ) ),
826                 uno::UNO_QUERY_THROW );
827 
828         rtl::OUStringBuffer aFullPath;
829         aFullPath.appendAscii( CONFIG_CONTENTPROVIDERS_KEY "/['" );
830         makeAndAppendXMLName( aFullPath, rKey1 );
831         aFullPath.appendAscii( "']/SecondaryKeys/['" );
832         makeAndAppendXMLName( aFullPath, rKey2 );
833         aFullPath.appendAscii( "']/ProviderData" );
834 
835         uno::Sequence< uno::Any > aArguments( 1 );
836         beans::PropertyValue      aProperty;
837         aProperty.Name
838             = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
839         aProperty.Value <<= aFullPath.makeStringAndClear();
840         aArguments[ 0 ] <<= aProperty;
841 
842         uno::Reference< uno::XInterface > xInterface(
843                 xConfigProv->createInstanceWithArguments(
844                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
845                         "com.sun.star.configuration.ConfigurationAccess" ) ),
846                     aArguments ) );
847 
848         if ( !m_xNotifier.is() )
849         {
850             m_xNotifier = uno::Reference< util::XChangesNotifier >(
851                                                 xInterface, uno::UNO_QUERY_THROW );
852 
853             m_xNotifier->addChangesListener( this );
854         }
855 
856         uno::Reference< container::XNameAccess > xNameAccess(
857                                             xInterface, uno::UNO_QUERY_THROW );
858 
859         uno::Sequence< rtl::OUString > aElems = xNameAccess->getElementNames();
860         const rtl::OUString* pElems = aElems.getConstArray();
861         sal_Int32 nCount = aElems.getLength();
862 
863         if ( nCount > 0 )
864         {
865             uno::Reference< container::XHierarchicalNameAccess >
866                                 xHierNameAccess( xInterface, uno::UNO_QUERY_THROW );
867 
868             // Iterate over children.
869             for ( sal_Int32 n = 0; n < nCount; ++n )
870             {
871 
872                 try
873                 {
874 
875                     ContentProviderData aInfo;
876 
877                     rtl::OUStringBuffer aElemBuffer;
878                     aElemBuffer.appendAscii( "['" );
879                     makeAndAppendXMLName( aElemBuffer, pElems[ n ] );
880                     aElemBuffer.appendAscii( "']" );
881 
882                     OSL_VERIFY(
883                         createContentProviderData(
884                             aElemBuffer.makeStringAndClear(), xHierNameAccess,
885                             aInfo));
886 
887                     rListToFill.push_back( aInfo );
888                 }
889                 catch ( container::NoSuchElementException& )
890                 {
891                     // getByHierarchicalName
892                     OSL_ENSURE( false,
893                                 "UniversalContentBroker::getContentProviderData - "
894                                 "caught NoSuchElementException!" );
895                 }
896             }
897         }
898     }
899     catch ( uno::RuntimeException& )
900     {
901         OSL_ENSURE( false,
902                     "UniversalContentBroker::getContentProviderData - caught RuntimeException!" );
903         return false;
904     }
905     catch ( uno::Exception& )
906     {
907         // createInstance, createInstanceWithArguments
908 
909         OSL_ENSURE( false,
910                     "UniversalContentBroker::getContentProviderData - caught Exception!" );
911         return false;
912     }
913 
914     return true;
915 }
916 
917 //=========================================================================
918 //
919 // ProviderListEntry_Impl implementation.
920 //
921 //=========================================================================
922 
resolveProvider() const923 Reference< XContentProvider > ProviderListEntry_Impl::resolveProvider() const
924 {
925     if ( !m_xResolvedProvider.is() )
926     {
927         Reference< XContentProviderSupplier > xSupplier(
928                                                     m_xProvider, UNO_QUERY );
929         if ( xSupplier.is() )
930             m_xResolvedProvider = xSupplier->getContentProvider();
931 
932         if ( !m_xResolvedProvider.is() )
933             m_xResolvedProvider = m_xProvider;
934     }
935 
936     return m_xResolvedProvider;
937 }
938