Update ooo320-m1
[ooovba.git] / canvas / source / factory / cf_service.cxx
blob5c897d62be8fcdb5ed6db4f41868fab92558a108
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cf_service.cxx,v $
10 * $Revision: 1.13 $
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>
50 #include <vector>
51 #include <utility>
52 #include <functional>
53 #include <algorithm>
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;
63 namespace
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 //==============================================================================
78 class CanvasFactory
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,
101 bool& r_CacheFlag,
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;
111 public:
112 virtual ~CanvasFactory();
113 CanvasFactory( Reference<XComponentContext> const & xContext );
115 // XServiceInfo
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 )
137 throw (Exception);
138 virtual Reference<XInterface> SAL_CALL createInstanceWithArguments(
139 OUString const & name, Sequence<Any> const & args )
140 throw (Exception);
143 CanvasFactory::CanvasFactory( Reference<XComponentContext> const & xContext ) :
144 m_mutex(),
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()
155 try
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 );
163 Any propValue(
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 ) ),
173 UNO_QUERY_THROW );
175 propValue = makeAny(
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),
195 UNO_QUERY );
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) );
208 ++pCurr;
211 catch (RuntimeException &)
213 throw;
215 catch (Exception&)
219 if( m_aAvailableImplementations.empty() )
221 // Ugh. Looks like configuration is borked. Fake minimal
222 // setup.
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"),
226 aServices) );
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"),
230 aServices) );
234 CanvasFactory::~CanvasFactory()
238 //------------------------------------------------------------------------------
239 Reference<XInterface> create( Reference<XComponentContext> const & xContext )
241 return static_cast< ::cppu::OWeakObject * >(
242 new CanvasFactory( xContext ) );
245 // XServiceInfo
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 )
282 throw (Exception)
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
294 try {
295 return m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
296 serviceName, args, xContext);
298 catch (RuntimeException &)
300 throw;
302 catch (Exception &)
304 return Reference<XInterface>();
308 //______________________________________________________________________________
309 void CanvasFactory::checkConfigFlag( bool& r_bFlag,
310 bool& r_CacheFlag,
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
320 // elements
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(),
356 aEnd,
357 boost::bind(&OUString::equals,
358 boost::cref(serviceName),
359 boost::bind(
360 std::select1st<CachePair>(),
361 _1)))) != aEnd )
363 Reference<XInterface> xCanvas( use( aMatch->second, args, xContext ) );
364 if(xCanvas.is())
365 return xCanvas;
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(),
372 aAvailEnd,
373 boost::bind(&OUString::equals,
374 boost::cref(serviceName),
375 boost::bind(
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(),
385 aAAEnd,
386 boost::bind(&OUString::equals,
387 boost::cref(serviceName),
388 boost::bind(
389 std::select1st<AvailPair>(),
390 _1)))) == aAAEnd )
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(),
398 aAccelEnd,
399 boost::bind(&OUString::equals,
400 boost::cref(serviceName),
401 boost::bind(
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,
432 pEndAccelImpl,
433 boost::bind(&OUString::equals,
434 boost::cref(aCurrName),
435 boost::bind(
436 &OUString::trim,
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,
443 pEndAAImpl,
444 boost::bind(&OUString::equals,
445 boost::cref(aCurrName),
446 boost::bind(
447 &OUString::trim,
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 ) );
461 if(xCanvas.is())
463 if( aMatch != aEnd )
465 // cache entry exists, replace dysfunctional
466 // implementation name
467 aMatch->second = pCurrImpl->trim();
469 else
471 // new service name, add new cache entry
472 m_aCachedImplementations.push_back(std::make_pair(serviceName,
473 pCurrImpl->trim()));
476 return xCanvas;
480 ++pCurrImpl;
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 ) );
493 if(xCanvas.is())
494 return xCanvas;
496 // last resort: try service name directly
497 return use( preferredOne, args, xContext );
500 // XMultiServiceFactory
501 //______________________________________________________________________________
502 Reference<XInterface> CanvasFactory::createInstance( OUString const & name )
503 throw (Exception)
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 [] = {
519 create,
520 getImplName,
521 getSuppServices,
522 ::cppu::createSingleComponentFactory,
523 0, 0
525 { 0, 0, 0, 0, 0, 0 }
528 } // anon namespace
530 extern "C" {
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 );