summaryrefslogtreecommitdiff
path: root/canvas/source/factory/cf_service.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'canvas/source/factory/cf_service.cxx')
-rw-r--r--canvas/source/factory/cf_service.cxx553
1 files changed, 553 insertions, 0 deletions
diff --git a/canvas/source/factory/cf_service.cxx b/canvas/source/factory/cf_service.cxx
new file mode 100644
index 000000000000..f949016d9f83
--- /dev/null
+++ b/canvas/source/factory/cf_service.cxx
@@ -0,0 +1,553 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <osl/mutex.hxx>
+#include <osl/process.h>
+#include <cppuhelper/implementationentry.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase3.hxx>
+#include <vcl/configsettings.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <boost/bind.hpp>
+#include <vector>
+#include <utility>
+#include <functional>
+#include <algorithm>
+
+#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
+#define ARLEN(x) (sizeof (x) / sizeof *(x))
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using ::rtl::OUString;
+
+namespace
+{
+
+OUString SAL_CALL getImplName()
+{
+ return OUSTR("com.sun.star.comp.rendering.CanvasFactory");
+}
+
+Sequence<OUString> SAL_CALL getSuppServices()
+{
+ OUString name = OUSTR("com.sun.star.rendering.CanvasFactory");
+ return Sequence<OUString>(&name, 1);
+}
+
+//==============================================================================
+class CanvasFactory
+ : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
+ lang::XMultiComponentFactory,
+ lang::XMultiServiceFactory >
+{
+ typedef std::pair<OUString,Sequence<OUString> > AvailPair;
+ typedef std::pair<OUString,OUString> CachePair;
+ typedef std::vector< AvailPair > AvailVector;
+ typedef std::vector< CachePair > CacheVector;
+
+
+ mutable ::osl::Mutex m_mutex;
+ Reference<XComponentContext> m_xContext;
+ Reference<container::XNameAccess> m_xCanvasConfigNameAccess;
+ AvailVector m_aAvailableImplementations;
+ AvailVector m_aAcceleratedImplementations;
+ AvailVector m_aAAImplementations;
+ mutable CacheVector m_aCachedImplementations;
+ mutable bool m_bCacheHasForcedLastImpl;
+ mutable bool m_bCacheHasUseAcceleratedEntry;
+ mutable bool m_bCacheHasUseAAEntry;
+
+ void checkConfigFlag( bool& r_bFlag,
+ bool& r_CacheFlag,
+ const OUString& nodeName ) const;
+ Reference<XInterface> use(
+ OUString const & serviceName,
+ Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) const;
+ Reference<XInterface> lookupAndUse(
+ OUString const & serviceName, Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) const;
+
+public:
+ virtual ~CanvasFactory();
+ CanvasFactory( Reference<XComponentContext> const & xContext );
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
+ throw (RuntimeException);
+ virtual Sequence<OUString> SAL_CALL getSupportedServiceNames()
+ throw (RuntimeException);
+
+ // XMultiComponentFactory
+ virtual Sequence<OUString> SAL_CALL getAvailableServiceNames()
+ throw (RuntimeException);
+ virtual Reference<XInterface> SAL_CALL createInstanceWithContext(
+ OUString const & name,
+ Reference<XComponentContext> const & xContext ) throw (Exception);
+ virtual Reference<XInterface> SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ OUString const & name,
+ Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) throw (Exception);
+
+ // XMultiServiceFactory
+ virtual Reference<XInterface> SAL_CALL createInstance(
+ OUString const & name )
+ throw (Exception);
+ virtual Reference<XInterface> SAL_CALL createInstanceWithArguments(
+ OUString const & name, Sequence<Any> const & args )
+ throw (Exception);
+};
+
+CanvasFactory::CanvasFactory( Reference<XComponentContext> const & xContext ) :
+ m_mutex(),
+ m_xContext(xContext),
+ m_xCanvasConfigNameAccess(),
+ m_aAvailableImplementations(),
+ m_aAcceleratedImplementations(),
+ m_aAAImplementations(),
+ m_aCachedImplementations(),
+ m_bCacheHasForcedLastImpl(),
+ m_bCacheHasUseAcceleratedEntry(),
+ m_bCacheHasUseAAEntry()
+{
+ try
+ {
+ // read out configuration for preferred services:
+ Reference<lang::XMultiServiceFactory> xConfigProvider(
+ m_xContext->getServiceManager()->createInstanceWithContext(
+ OUSTR("com.sun.star.configuration.ConfigurationProvider"),
+ m_xContext ), UNO_QUERY_THROW );
+
+ Any propValue(
+ makeAny( beans::PropertyValue(
+ OUSTR("nodepath"), -1,
+ makeAny( OUSTR("/org.openoffice.Office.Canvas") ),
+ beans::PropertyState_DIRECT_VALUE ) ) );
+
+ m_xCanvasConfigNameAccess.set(
+ xConfigProvider->createInstanceWithArguments(
+ OUSTR("com.sun.star.configuration.ConfigurationAccess"),
+ Sequence<Any>( &propValue, 1 ) ),
+ UNO_QUERY_THROW );
+
+ propValue = makeAny(
+ beans::PropertyValue(
+ OUSTR("nodepath"), -1,
+ makeAny( OUSTR("/org.openoffice.Office.Canvas/CanvasServiceList") ),
+ beans::PropertyState_DIRECT_VALUE ) );
+
+ Reference<container::XNameAccess> xNameAccess(
+ xConfigProvider->createInstanceWithArguments(
+ OUSTR("com.sun.star.configuration.ConfigurationAccess"),
+ Sequence<Any>( &propValue, 1 ) ), UNO_QUERY_THROW );
+ Reference<container::XHierarchicalNameAccess> xHierarchicalNameAccess(
+ xNameAccess, UNO_QUERY_THROW);
+
+ Sequence<OUString> serviceNames = xNameAccess->getElementNames();
+ const OUString* pCurr = serviceNames.getConstArray();
+ const OUString* const pEnd = pCurr + serviceNames.getLength();
+ while( pCurr != pEnd )
+ {
+ Reference<container::XNameAccess> xEntryNameAccess(
+ xHierarchicalNameAccess->getByHierarchicalName(*pCurr),
+ UNO_QUERY );
+
+ if( xEntryNameAccess.is() )
+ {
+ Sequence<OUString> implementationList;
+ if( (xEntryNameAccess->getByName( OUSTR("PreferredImplementations") ) >>= implementationList) )
+ m_aAvailableImplementations.push_back( std::make_pair(*pCurr,implementationList) );
+ if( (xEntryNameAccess->getByName( OUSTR("AcceleratedImplementations") ) >>= implementationList) )
+ m_aAcceleratedImplementations.push_back( std::make_pair(*pCurr,implementationList) );
+ if( (xEntryNameAccess->getByName( OUSTR("AntialiasingImplementations") ) >>= implementationList) )
+ m_aAAImplementations.push_back( std::make_pair(*pCurr,implementationList) );
+ }
+
+ ++pCurr;
+ }
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (Exception&)
+ {
+ }
+
+ if( m_aAvailableImplementations.empty() )
+ {
+ // Ugh. Looks like configuration is borked. Fake minimal
+ // setup.
+ Sequence<OUString> aServices(1);
+ aServices[0] = OUSTR("com.sun.star.comp.rendering.Canvas.VCL");
+ m_aAvailableImplementations.push_back( std::make_pair(OUSTR("com.sun.star.rendering.Canvas"),
+ aServices) );
+
+ aServices[0] = OUSTR("com.sun.star.comp.rendering.SpriteCanvas.VCL");
+ m_aAvailableImplementations.push_back( std::make_pair(OUSTR("com.sun.star.rendering.SpriteCanvas"),
+ aServices) );
+ }
+}
+
+CanvasFactory::~CanvasFactory()
+{
+}
+
+//------------------------------------------------------------------------------
+Reference<XInterface> create( Reference<XComponentContext> const & xContext )
+{
+ return static_cast< ::cppu::OWeakObject * >(
+ new CanvasFactory( xContext ) );
+}
+
+// XServiceInfo
+//______________________________________________________________________________
+OUString CanvasFactory::getImplementationName() throw (RuntimeException)
+{
+ return getImplName();
+}
+
+//______________________________________________________________________________
+sal_Bool CanvasFactory::supportsService( OUString const & serviceName )
+ throw (RuntimeException)
+{
+ return serviceName.equals(getSuppServices()[0]);
+}
+
+//______________________________________________________________________________
+Sequence<OUString> CanvasFactory::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ return getSuppServices();
+}
+
+// XMultiComponentFactory
+//______________________________________________________________________________
+Sequence<OUString> CanvasFactory::getAvailableServiceNames()
+ throw (RuntimeException)
+{
+ Sequence<OUString> aServiceNames(m_aAvailableImplementations.size());
+ std::transform(m_aAvailableImplementations.begin(),
+ m_aAvailableImplementations.end(),
+ aServiceNames.getArray(),
+ std::select1st<AvailPair>());
+ return aServiceNames;
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::createInstanceWithContext(
+ OUString const & name, Reference<XComponentContext> const & xContext )
+ throw (Exception)
+{
+ return createInstanceWithArgumentsAndContext(
+ name, Sequence<Any>(), xContext );
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::use(
+ OUString const & serviceName,
+ Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) const
+{
+ try {
+ return m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ serviceName, args, xContext);
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (Exception &)
+ {
+ return Reference<XInterface>();
+ }
+}
+
+//______________________________________________________________________________
+void CanvasFactory::checkConfigFlag( bool& r_bFlag,
+ bool& r_CacheFlag,
+ const OUString& nodeName ) const
+{
+ if( m_xCanvasConfigNameAccess.is() )
+ {
+ m_xCanvasConfigNameAccess->getByName( nodeName ) >>= r_bFlag;
+
+ if( r_CacheFlag != r_bFlag )
+ {
+ // cache is invalid, because of different order of
+ // elements
+ r_CacheFlag = r_bFlag;
+ m_aCachedImplementations.clear();
+ }
+ }
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::lookupAndUse(
+ OUString const & serviceName, Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) const
+{
+ ::osl::MutexGuard guard(m_mutex);
+
+ // forcing last entry from impl list, if config flag set
+ bool bForceLastEntry(false);
+ checkConfigFlag( bForceLastEntry,
+ m_bCacheHasForcedLastImpl,
+ OUSTR("ForceSafeServiceImpl") );
+
+ // use anti-aliasing canvas, if config flag set (or not existing)
+ bool bUseAAEntry(true);
+ checkConfigFlag( bUseAAEntry,
+ m_bCacheHasUseAAEntry,
+ OUSTR("UseAntialiasingCanvas") );
+
+ // use accelerated canvas, if config flag set (or not existing)
+ bool bUseAcceleratedEntry(true);
+ checkConfigFlag( bUseAcceleratedEntry,
+ m_bCacheHasUseAcceleratedEntry,
+ OUSTR("UseAcceleratedCanvas") );
+
+ // try to reuse last working implementation for given service name
+ const CacheVector::iterator aEnd(m_aCachedImplementations.end());
+ CacheVector::iterator aMatch;
+ if( (aMatch=std::find_if(m_aCachedImplementations.begin(),
+ aEnd,
+ boost::bind(&OUString::equals,
+ boost::cref(serviceName),
+ boost::bind(
+ std::select1st<CachePair>(),
+ _1)))) != aEnd )
+ {
+ Reference<XInterface> xCanvas( use( aMatch->second, args, xContext ) );
+ if(xCanvas.is())
+ return xCanvas;
+ }
+
+ // lookup in available service list
+ const AvailVector::const_iterator aAvailEnd(m_aAvailableImplementations.end());
+ AvailVector::const_iterator aAvailImplsMatch;
+ if( (aAvailImplsMatch=std::find_if(m_aAvailableImplementations.begin(),
+ aAvailEnd,
+ boost::bind(&OUString::equals,
+ boost::cref(serviceName),
+ boost::bind(
+ std::select1st<AvailPair>(),
+ _1)))) == aAvailEnd )
+ {
+ return Reference<XInterface>();
+ }
+
+ const AvailVector::const_iterator aAAEnd(m_aAAImplementations.end());
+ AvailVector::const_iterator aAAImplsMatch;
+ if( (aAAImplsMatch=std::find_if(m_aAAImplementations.begin(),
+ aAAEnd,
+ boost::bind(&OUString::equals,
+ boost::cref(serviceName),
+ boost::bind(
+ std::select1st<AvailPair>(),
+ _1)))) == aAAEnd )
+ {
+ return Reference<XInterface>();
+ }
+
+ const AvailVector::const_iterator aAccelEnd(m_aAcceleratedImplementations.end());
+ AvailVector::const_iterator aAccelImplsMatch;
+ if( (aAccelImplsMatch=std::find_if(m_aAcceleratedImplementations.begin(),
+ aAccelEnd,
+ boost::bind(&OUString::equals,
+ boost::cref(serviceName),
+ boost::bind(
+ std::select1st<AvailPair>(),
+ _1)))) == aAccelEnd )
+ {
+ return Reference<XInterface>();
+ }
+
+ const Sequence<OUString> aPreferredImpls( aAvailImplsMatch->second );
+ const OUString* pCurrImpl = aPreferredImpls.getConstArray();
+ const OUString* const pEndImpl = pCurrImpl + aPreferredImpls.getLength();
+
+ const Sequence<OUString> aAAImpls( aAAImplsMatch->second );
+ const OUString* const pFirstAAImpl = aAAImpls.getConstArray();
+ const OUString* const pEndAAImpl = pFirstAAImpl + aAAImpls.getLength();
+
+ const Sequence<OUString> aAccelImpls( aAccelImplsMatch->second );
+ const OUString* const pFirstAccelImpl = aAccelImpls.getConstArray();
+ const OUString* const pEndAccelImpl = pFirstAccelImpl + aAccelImpls.getLength();
+
+ // force last entry from impl list, if config flag set
+ if( bForceLastEntry )
+ pCurrImpl = pEndImpl-1;
+
+ while( pCurrImpl != pEndImpl )
+ {
+ const OUString aCurrName(pCurrImpl->trim());
+
+ // check whether given canvas service is listed in the
+ // sequence of "accelerated canvas implementations"
+ const bool bIsAcceleratedImpl(
+ std::find_if(pFirstAccelImpl,
+ pEndAccelImpl,
+ boost::bind(&OUString::equals,
+ boost::cref(aCurrName),
+ boost::bind(
+ &OUString::trim,
+ _1))) != pEndAccelImpl );
+
+ // check whether given canvas service is listed in the
+ // sequence of "antialiasing canvas implementations"
+ const bool bIsAAImpl(
+ std::find_if(pFirstAAImpl,
+ pEndAAImpl,
+ boost::bind(&OUString::equals,
+ boost::cref(aCurrName),
+ boost::bind(
+ &OUString::trim,
+ _1))) != pEndAAImpl );
+
+ // try to instantiate canvas *only* if either accel and AA
+ // property match preference, *or*, if there's a mismatch, only
+ // go for a less capable canvas (that effectively let those
+ // pour canvas impls still work as fallbacks, should an
+ // accelerated/AA one fail). Property implies configuration:
+ // http://en.wikipedia.org/wiki/Truth_table#Logical_implication
+ if( (!bIsAAImpl || bUseAAEntry) && (!bIsAcceleratedImpl || bUseAcceleratedEntry) )
+ {
+ Reference<XInterface> xCanvas(
+ use( pCurrImpl->trim(), args, xContext ) );
+
+ if(xCanvas.is())
+ {
+ if( aMatch != aEnd )
+ {
+ // cache entry exists, replace dysfunctional
+ // implementation name
+ aMatch->second = pCurrImpl->trim();
+ }
+ else
+ {
+ // new service name, add new cache entry
+ m_aCachedImplementations.push_back(std::make_pair(serviceName,
+ pCurrImpl->trim()));
+ }
+
+ return xCanvas;
+ }
+ }
+
+ ++pCurrImpl;
+ }
+
+ return Reference<XInterface>();
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::createInstanceWithArgumentsAndContext(
+ OUString const & preferredOne, Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) throw (Exception)
+{
+ Reference<XInterface> xCanvas(
+ lookupAndUse( preferredOne, args, xContext ) );
+ if(xCanvas.is())
+ return xCanvas;
+
+ // last resort: try service name directly
+ return use( preferredOne, args, xContext );
+}
+
+// XMultiServiceFactory
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::createInstance( OUString const & name )
+ throw (Exception)
+{
+ return createInstanceWithArgumentsAndContext(
+ name, Sequence<Any>(), m_xContext );
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::createInstanceWithArguments(
+ OUString const & name, Sequence<Any> const & args ) throw (Exception)
+{
+ return createInstanceWithArgumentsAndContext(
+ name, args, m_xContext );
+}
+
+const ::cppu::ImplementationEntry s_entries [] = {
+ {
+ create,
+ getImplName,
+ getSuppServices,
+ ::cppu::createSingleComponentFactory,
+ 0, 0
+ },
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+} // anon namespace
+
+extern "C" {
+
+void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+sal_Bool SAL_CALL component_writeInfo(
+ lang::XMultiServiceFactory * pServiceManager,
+ registry::XRegistryKey * pRegistryKey )
+{
+ return ::cppu::component_writeInfoHelper(
+ pServiceManager, pRegistryKey, s_entries );
+}
+
+void * SAL_CALL component_getFactory(
+ sal_Char const * pImplName,
+ lang::XMultiServiceFactory * pServiceManager,
+ registry::XRegistryKey * pRegistryKey )
+{
+ return ::cppu::component_getFactoryHelper(
+ pImplName, pServiceManager, pRegistryKey, s_entries );
+}
+
+}
+