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( "&" );
157 break;
158
159 case '"':
160 rBuffer.appendAscii( """ );
161 break;
162
163 case '\'':
164 rBuffer.appendAscii( "'" );
165 break;
166
167 case '<':
168 rBuffer.appendAscii( "<" );
169 break;
170
171 case '>':
172 rBuffer.appendAscii( ">" );
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