1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cf_service.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <osl/mutex.hxx>
35 #include <osl/process.h>
36 #include <cppuhelper/implementationentry.hxx>
37 #include <cppuhelper/factory.hxx>
38 #include <cppuhelper/implbase3.hxx>
39 #include <vcl/configsettings.hxx>
41 #include <com/sun/star/uno/XComponentContext.hpp>
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
44 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
45 #include <com/sun/star/container/XNameAccess.hpp>
46 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
47 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <boost/bind.hpp>
55 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
56 #define ARLEN(x) (sizeof (x) / sizeof *(x))
59 using namespace ::com::sun::star
;
60 using namespace ::com::sun::star::uno
;
61 using ::rtl::OUString
;
66 OUString SAL_CALL
getImplName()
68 return OUSTR("com.sun.star.comp.rendering.CanvasFactory");
71 Sequence
<OUString
> SAL_CALL
getSuppServices()
73 OUString name
= OUSTR("com.sun.star.rendering.CanvasFactory");
74 return Sequence
<OUString
>(&name
, 1);
77 //==============================================================================
79 : public ::cppu::WeakImplHelper3
< lang::XServiceInfo
,
80 lang::XMultiComponentFactory
,
81 lang::XMultiServiceFactory
>
83 typedef std::pair
<OUString
,Sequence
<OUString
> > AvailPair
;
84 typedef std::pair
<OUString
,OUString
> CachePair
;
85 typedef std::vector
< AvailPair
> AvailVector
;
86 typedef std::vector
< CachePair
> CacheVector
;
89 mutable ::osl::Mutex m_mutex
;
90 Reference
<XComponentContext
> m_xContext
;
91 Reference
<container::XNameAccess
> m_xCanvasConfigNameAccess
;
92 AvailVector m_aAvailableImplementations
;
93 AvailVector m_aAcceleratedImplementations
;
94 AvailVector m_aAAImplementations
;
95 mutable CacheVector m_aCachedImplementations
;
96 mutable bool m_bCacheHasForcedLastImpl
;
97 mutable bool m_bCacheHasUseAcceleratedEntry
;
98 mutable bool m_bCacheHasUseAAEntry
;
100 void checkConfigFlag( bool& r_bFlag
,
102 const OUString
& nodeName
) const;
103 Reference
<XInterface
> use(
104 OUString
const & serviceName
,
105 Sequence
<Any
> const & args
,
106 Reference
<XComponentContext
> const & xContext
) const;
107 Reference
<XInterface
> lookupAndUse(
108 OUString
const & serviceName
, Sequence
<Any
> const & args
,
109 Reference
<XComponentContext
> const & xContext
) const;
112 virtual ~CanvasFactory();
113 CanvasFactory( Reference
<XComponentContext
> const & xContext
);
116 virtual OUString SAL_CALL
getImplementationName() throw (RuntimeException
);
117 virtual sal_Bool SAL_CALL
supportsService( OUString
const & serviceName
)
118 throw (RuntimeException
);
119 virtual Sequence
<OUString
> SAL_CALL
getSupportedServiceNames()
120 throw (RuntimeException
);
122 // XMultiComponentFactory
123 virtual Sequence
<OUString
> SAL_CALL
getAvailableServiceNames()
124 throw (RuntimeException
);
125 virtual Reference
<XInterface
> SAL_CALL
createInstanceWithContext(
126 OUString
const & name
,
127 Reference
<XComponentContext
> const & xContext
) throw (Exception
);
128 virtual Reference
<XInterface
> SAL_CALL
129 createInstanceWithArgumentsAndContext(
130 OUString
const & name
,
131 Sequence
<Any
> const & args
,
132 Reference
<XComponentContext
> const & xContext
) throw (Exception
);
134 // XMultiServiceFactory
135 virtual Reference
<XInterface
> SAL_CALL
createInstance(
136 OUString
const & name
)
138 virtual Reference
<XInterface
> SAL_CALL
createInstanceWithArguments(
139 OUString
const & name
, Sequence
<Any
> const & args
)
143 CanvasFactory::CanvasFactory( Reference
<XComponentContext
> const & xContext
) :
145 m_xContext(xContext
),
146 m_xCanvasConfigNameAccess(),
147 m_aAvailableImplementations(),
148 m_aAcceleratedImplementations(),
149 m_aAAImplementations(),
150 m_aCachedImplementations(),
151 m_bCacheHasForcedLastImpl(),
152 m_bCacheHasUseAcceleratedEntry(),
153 m_bCacheHasUseAAEntry()
157 // read out configuration for preferred services:
158 Reference
<lang::XMultiServiceFactory
> xConfigProvider(
159 m_xContext
->getServiceManager()->createInstanceWithContext(
160 OUSTR("com.sun.star.configuration.ConfigurationProvider"),
161 m_xContext
), UNO_QUERY_THROW
);
164 makeAny( beans::PropertyValue(
165 OUSTR("nodepath"), -1,
166 makeAny( OUSTR("/org.openoffice.Office.Canvas") ),
167 beans::PropertyState_DIRECT_VALUE
) ) );
169 m_xCanvasConfigNameAccess
.set(
170 xConfigProvider
->createInstanceWithArguments(
171 OUSTR("com.sun.star.configuration.ConfigurationAccess"),
172 Sequence
<Any
>( &propValue
, 1 ) ),
176 beans::PropertyValue(
177 OUSTR("nodepath"), -1,
178 makeAny( OUSTR("/org.openoffice.Office.Canvas/CanvasServiceList") ),
179 beans::PropertyState_DIRECT_VALUE
) );
181 Reference
<container::XNameAccess
> xNameAccess(
182 xConfigProvider
->createInstanceWithArguments(
183 OUSTR("com.sun.star.configuration.ConfigurationAccess"),
184 Sequence
<Any
>( &propValue
, 1 ) ), UNO_QUERY_THROW
);
185 Reference
<container::XHierarchicalNameAccess
> xHierarchicalNameAccess(
186 xNameAccess
, UNO_QUERY_THROW
);
188 Sequence
<OUString
> serviceNames
= xNameAccess
->getElementNames();
189 const OUString
* pCurr
= serviceNames
.getConstArray();
190 const OUString
* const pEnd
= pCurr
+ serviceNames
.getLength();
191 while( pCurr
!= pEnd
)
193 Reference
<container::XNameAccess
> xEntryNameAccess(
194 xHierarchicalNameAccess
->getByHierarchicalName(*pCurr
),
197 if( xEntryNameAccess
.is() )
199 Sequence
<OUString
> implementationList
;
200 if( (xEntryNameAccess
->getByName( OUSTR("PreferredImplementations") ) >>= implementationList
) )
201 m_aAvailableImplementations
.push_back( std::make_pair(*pCurr
,implementationList
) );
202 if( (xEntryNameAccess
->getByName( OUSTR("AcceleratedImplementations") ) >>= implementationList
) )
203 m_aAcceleratedImplementations
.push_back( std::make_pair(*pCurr
,implementationList
) );
204 if( (xEntryNameAccess
->getByName( OUSTR("AntialiasingImplementations") ) >>= implementationList
) )
205 m_aAAImplementations
.push_back( std::make_pair(*pCurr
,implementationList
) );
211 catch (RuntimeException
&)
219 if( m_aAvailableImplementations
.empty() )
221 // Ugh. Looks like configuration is borked. Fake minimal
223 Sequence
<OUString
> aServices(1);
224 aServices
[0] = OUSTR("com.sun.star.comp.rendering.Canvas.VCL");
225 m_aAvailableImplementations
.push_back( std::make_pair(OUSTR("com.sun.star.rendering.Canvas"),
228 aServices
[0] = OUSTR("com.sun.star.comp.rendering.SpriteCanvas.VCL");
229 m_aAvailableImplementations
.push_back( std::make_pair(OUSTR("com.sun.star.rendering.SpriteCanvas"),
234 CanvasFactory::~CanvasFactory()
238 //------------------------------------------------------------------------------
239 Reference
<XInterface
> create( Reference
<XComponentContext
> const & xContext
)
241 return static_cast< ::cppu::OWeakObject
* >(
242 new CanvasFactory( xContext
) );
246 //______________________________________________________________________________
247 OUString
CanvasFactory::getImplementationName() throw (RuntimeException
)
249 return getImplName();
252 //______________________________________________________________________________
253 sal_Bool
CanvasFactory::supportsService( OUString
const & serviceName
)
254 throw (RuntimeException
)
256 return serviceName
.equals(getSuppServices()[0]);
259 //______________________________________________________________________________
260 Sequence
<OUString
> CanvasFactory::getSupportedServiceNames()
261 throw (RuntimeException
)
263 return getSuppServices();
266 // XMultiComponentFactory
267 //______________________________________________________________________________
268 Sequence
<OUString
> CanvasFactory::getAvailableServiceNames()
269 throw (RuntimeException
)
271 Sequence
<OUString
> aServiceNames(m_aAvailableImplementations
.size());
272 std::transform(m_aAvailableImplementations
.begin(),
273 m_aAvailableImplementations
.end(),
274 aServiceNames
.getArray(),
275 std::select1st
<AvailPair
>());
276 return aServiceNames
;
279 //______________________________________________________________________________
280 Reference
<XInterface
> CanvasFactory::createInstanceWithContext(
281 OUString
const & name
, Reference
<XComponentContext
> const & xContext
)
284 return createInstanceWithArgumentsAndContext(
285 name
, Sequence
<Any
>(), xContext
);
288 //______________________________________________________________________________
289 Reference
<XInterface
> CanvasFactory::use(
290 OUString
const & serviceName
,
291 Sequence
<Any
> const & args
,
292 Reference
<XComponentContext
> const & xContext
) const
295 return m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
296 serviceName
, args
, xContext
);
298 catch (RuntimeException
&)
304 return Reference
<XInterface
>();
308 //______________________________________________________________________________
309 void CanvasFactory::checkConfigFlag( bool& r_bFlag
,
311 const OUString
& nodeName
) const
313 if( m_xCanvasConfigNameAccess
.is() )
315 m_xCanvasConfigNameAccess
->getByName( nodeName
) >>= r_bFlag
;
317 if( r_CacheFlag
!= r_bFlag
)
319 // cache is invalid, because of different order of
321 r_CacheFlag
= r_bFlag
;
322 m_aCachedImplementations
.clear();
327 //______________________________________________________________________________
328 Reference
<XInterface
> CanvasFactory::lookupAndUse(
329 OUString
const & serviceName
, Sequence
<Any
> const & args
,
330 Reference
<XComponentContext
> const & xContext
) const
332 ::osl::MutexGuard
guard(m_mutex
);
334 // forcing last entry from impl list, if config flag set
335 bool bForceLastEntry(false);
336 checkConfigFlag( bForceLastEntry
,
337 m_bCacheHasForcedLastImpl
,
338 OUSTR("ForceSafeServiceImpl") );
340 // use anti-aliasing canvas, if config flag set (or not existing)
341 bool bUseAAEntry(true);
342 checkConfigFlag( bUseAAEntry
,
343 m_bCacheHasUseAAEntry
,
344 OUSTR("UseAntialiasingCanvas") );
346 // use accelerated canvas, if config flag set (or not existing)
347 bool bUseAcceleratedEntry(true);
348 checkConfigFlag( bUseAcceleratedEntry
,
349 m_bCacheHasUseAcceleratedEntry
,
350 OUSTR("UseAcceleratedCanvas") );
352 // try to reuse last working implementation for given service name
353 const CacheVector::iterator
aEnd(m_aCachedImplementations
.end());
354 CacheVector::iterator aMatch
;
355 if( (aMatch
=std::find_if(m_aCachedImplementations
.begin(),
357 boost::bind(&OUString::equals
,
358 boost::cref(serviceName
),
360 std::select1st
<CachePair
>(),
363 Reference
<XInterface
> xCanvas( use( aMatch
->second
, args
, xContext
) );
368 // lookup in available service list
369 const AvailVector::const_iterator
aAvailEnd(m_aAvailableImplementations
.end());
370 AvailVector::const_iterator aAvailImplsMatch
;
371 if( (aAvailImplsMatch
=std::find_if(m_aAvailableImplementations
.begin(),
373 boost::bind(&OUString::equals
,
374 boost::cref(serviceName
),
376 std::select1st
<AvailPair
>(),
377 _1
)))) == aAvailEnd
)
379 return Reference
<XInterface
>();
382 const AvailVector::const_iterator
aAAEnd(m_aAAImplementations
.end());
383 AvailVector::const_iterator aAAImplsMatch
;
384 if( (aAAImplsMatch
=std::find_if(m_aAAImplementations
.begin(),
386 boost::bind(&OUString::equals
,
387 boost::cref(serviceName
),
389 std::select1st
<AvailPair
>(),
392 return Reference
<XInterface
>();
395 const AvailVector::const_iterator
aAccelEnd(m_aAcceleratedImplementations
.end());
396 AvailVector::const_iterator aAccelImplsMatch
;
397 if( (aAccelImplsMatch
=std::find_if(m_aAcceleratedImplementations
.begin(),
399 boost::bind(&OUString::equals
,
400 boost::cref(serviceName
),
402 std::select1st
<AvailPair
>(),
403 _1
)))) == aAccelEnd
)
405 return Reference
<XInterface
>();
408 const Sequence
<OUString
> aPreferredImpls( aAvailImplsMatch
->second
);
409 const OUString
* pCurrImpl
= aPreferredImpls
.getConstArray();
410 const OUString
* const pEndImpl
= pCurrImpl
+ aPreferredImpls
.getLength();
412 const Sequence
<OUString
> aAAImpls( aAAImplsMatch
->second
);
413 const OUString
* const pFirstAAImpl
= aAAImpls
.getConstArray();
414 const OUString
* const pEndAAImpl
= pFirstAAImpl
+ aAAImpls
.getLength();
416 const Sequence
<OUString
> aAccelImpls( aAccelImplsMatch
->second
);
417 const OUString
* const pFirstAccelImpl
= aAccelImpls
.getConstArray();
418 const OUString
* const pEndAccelImpl
= pFirstAccelImpl
+ aAccelImpls
.getLength();
420 // force last entry from impl list, if config flag set
421 if( bForceLastEntry
)
422 pCurrImpl
= pEndImpl
-1;
424 while( pCurrImpl
!= pEndImpl
)
426 const OUString
aCurrName(pCurrImpl
->trim());
428 // check whether given canvas service is listed in the
429 // sequence of "accelerated canvas implementations"
430 const bool bIsAcceleratedImpl(
431 std::find_if(pFirstAccelImpl
,
433 boost::bind(&OUString::equals
,
434 boost::cref(aCurrName
),
437 _1
))) != pEndAccelImpl
);
439 // check whether given canvas service is listed in the
440 // sequence of "antialiasing canvas implementations"
441 const bool bIsAAImpl(
442 std::find_if(pFirstAAImpl
,
444 boost::bind(&OUString::equals
,
445 boost::cref(aCurrName
),
448 _1
))) != pEndAAImpl
);
450 // try to instantiate canvas *only* if either accel and AA
451 // property match preference, *or*, if there's a mismatch, only
452 // go for a less capable canvas (that effectively let those
453 // pour canvas impls still work as fallbacks, should an
454 // accelerated/AA one fail). Property implies configuration:
455 // http://en.wikipedia.org/wiki/Truth_table#Logical_implication
456 if( (!bIsAAImpl
|| bUseAAEntry
) && (!bIsAcceleratedImpl
|| bUseAcceleratedEntry
) )
458 Reference
<XInterface
> xCanvas(
459 use( pCurrImpl
->trim(), args
, xContext
) );
465 // cache entry exists, replace dysfunctional
466 // implementation name
467 aMatch
->second
= pCurrImpl
->trim();
471 // new service name, add new cache entry
472 m_aCachedImplementations
.push_back(std::make_pair(serviceName
,
483 return Reference
<XInterface
>();
486 //______________________________________________________________________________
487 Reference
<XInterface
> CanvasFactory::createInstanceWithArgumentsAndContext(
488 OUString
const & preferredOne
, Sequence
<Any
> const & args
,
489 Reference
<XComponentContext
> const & xContext
) throw (Exception
)
491 Reference
<XInterface
> xCanvas(
492 lookupAndUse( preferredOne
, args
, xContext
) );
496 // last resort: try service name directly
497 return use( preferredOne
, args
, xContext
);
500 // XMultiServiceFactory
501 //______________________________________________________________________________
502 Reference
<XInterface
> CanvasFactory::createInstance( OUString
const & name
)
505 return createInstanceWithArgumentsAndContext(
506 name
, Sequence
<Any
>(), m_xContext
);
509 //______________________________________________________________________________
510 Reference
<XInterface
> CanvasFactory::createInstanceWithArguments(
511 OUString
const & name
, Sequence
<Any
> const & args
) throw (Exception
)
513 return createInstanceWithArgumentsAndContext(
514 name
, args
, m_xContext
);
517 const ::cppu::ImplementationEntry s_entries
[] = {
522 ::cppu::createSingleComponentFactory
,
532 void SAL_CALL
component_getImplementationEnvironment(
533 const sal_Char
** ppEnvTypeName
, uno_Environment
** /*ppEnv*/ )
535 *ppEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
538 sal_Bool SAL_CALL
component_writeInfo(
539 lang::XMultiServiceFactory
* pServiceManager
,
540 registry::XRegistryKey
* pRegistryKey
)
542 return ::cppu::component_writeInfoHelper(
543 pServiceManager
, pRegistryKey
, s_entries
);
546 void * SAL_CALL
component_getFactory(
547 sal_Char
const * pImplName
,
548 lang::XMultiServiceFactory
* pServiceManager
,
549 registry::XRegistryKey
* pRegistryKey
)
551 return ::cppu::component_getFactoryHelper(
552 pImplName
, pServiceManager
, pRegistryKey
, s_entries
);