xref: /trunk/main/ucb/source/core/ucb.cxx (revision 2f86921c)
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( "&amp;" );
157                 break;
158 
159             case '"':
160                 rBuffer.appendAscii( "&quot;" );
161                 break;
162 
163             case '\'':
164                 rBuffer.appendAscii( "&apos;" );
165                 break;
166 
167             case '<':
168                 rBuffer.appendAscii( "&lt;" );
169                 break;
170 
171             case '>':
172                 rBuffer.appendAscii( "&gt;" );
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