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