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