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