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