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( "&" );
145 break;
146
147 case '"':
148 rBuffer.append( """ );
149 break;
150
151 case '\'':
152 rBuffer.append( "'" );
153 break;
154
155 case '<':
156 rBuffer.append( "<" );
157 break;
158
159 case '>':
160 rBuffer.append( ">" );
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