1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <uifactory/factoryconfiguration.hxx>
21 
22 #include <com/sun/star/beans/PropertyValue.hpp>
23 #include <com/sun/star/container/XContainer.hpp>
24 #include <com/sun/star/lang/XServiceInfo.hpp>
25 #include <com/sun/star/frame/XUIControllerFactory.hpp>
26 
27 #include <rtl/ustrbuf.hxx>
28 #include <rtl/ref.hxx>
29 #include <cppuhelper/basemutex.hxx>
30 #include <cppuhelper/compbase.hxx>
31 #include <cppuhelper/supportsservice.hxx>
32 
33 using namespace css::uno;
34 using namespace css::lang;
35 using namespace css::beans;
36 using namespace css::container;
37 using namespace css::frame;
38 using namespace framework;
39 
40 namespace {
41 
42 typedef ::cppu::WeakComponentImplHelper<
43     css::lang::XServiceInfo,
44     css::frame::XUIControllerFactory > UIControllerFactory_BASE;
45 
46 class UIControllerFactory : private cppu::BaseMutex,
47                             public UIControllerFactory_BASE
48 {
49 public:
50     virtual ~UIControllerFactory() override;
51 
52     // XMultiComponentFactory
53     virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithContext( const OUString& aServiceSpecifier, const css::uno::Reference< css::uno::XComponentContext >& Context ) override;
54     virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArgumentsAndContext( const OUString& ServiceSpecifier, const css::uno::Sequence< css::uno::Any >& Arguments, const css::uno::Reference< css::uno::XComponentContext >& Context ) override;
55     virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
56 
57     // XUIControllerRegistration
58     virtual sal_Bool SAL_CALL hasController( const OUString& aCommandURL, const OUString& aModuleName ) override;
59     virtual void SAL_CALL registerController( const OUString& aCommandURL, const OUString& aModuleName, const OUString& aControllerImplementationName ) override;
60     virtual void SAL_CALL deregisterController( const OUString& aCommandURL, const OUString& aModuleName ) override;
61 
62 protected:
63     UIControllerFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext, const OUString &rUINode  );
64     bool                                                    m_bConfigRead;
65     css::uno::Reference< css::uno::XComponentContext >       m_xContext;
66     rtl::Reference<ConfigurationAccess_ControllerFactory>    m_pConfigAccess;
67 
68 private:
69     virtual void SAL_CALL disposing() final override;
70 };
71 
UIControllerFactory(const Reference<XComponentContext> & xContext,const OUString & rConfigurationNode)72 UIControllerFactory::UIControllerFactory(
73     const Reference< XComponentContext >& xContext,
74     const OUString &rConfigurationNode )
75     : UIControllerFactory_BASE(m_aMutex)
76     , m_bConfigRead( false )
77     , m_xContext( xContext )
78     , m_pConfigAccess()
79 {
80     m_pConfigAccess = new ConfigurationAccess_ControllerFactory(m_xContext,
81             "/org.openoffice.Office.UI.Controller/Registered/" + rConfigurationNode);
82 }
83 
~UIControllerFactory()84 UIControllerFactory::~UIControllerFactory()
85 {
86     disposing();
87 }
88 
disposing()89 void SAL_CALL UIControllerFactory::disposing()
90 {
91     osl::MutexGuard g(rBHelper.rMutex);
92     m_pConfigAccess.clear();
93 }
94 
95 // XMultiComponentFactory
createInstanceWithContext(const OUString & aServiceSpecifier,const Reference<XComponentContext> &)96 Reference< XInterface > SAL_CALL UIControllerFactory::createInstanceWithContext(
97     const OUString& aServiceSpecifier,
98     const Reference< XComponentContext >& )
99 {
100     // SAFE
101     osl::MutexGuard g(rBHelper.rMutex);
102 
103     if ( !m_bConfigRead )
104     {
105         m_bConfigRead = true;
106         m_pConfigAccess->readConfigurationData();
107     }
108 
109     OUString aServiceName = m_pConfigAccess->getServiceFromCommandModule( aServiceSpecifier, OUString() );
110     if ( !aServiceName.isEmpty() )
111         return m_xContext->getServiceManager()->createInstanceWithContext( aServiceName, m_xContext );
112     else
113         return Reference< XInterface >();
114     // SAFE
115 }
116 
createInstanceWithArgumentsAndContext(const OUString & ServiceSpecifier,const Sequence<Any> & Arguments,const Reference<XComponentContext> &)117 Reference< XInterface > SAL_CALL UIControllerFactory::createInstanceWithArgumentsAndContext(
118     const OUString&                  ServiceSpecifier,
119     const Sequence< Any >&                  Arguments,
120     const Reference< XComponentContext >& )
121 {
122     const OUString aPropModuleName( "ModuleIdentifier" );
123     const OUString aPropValueName( "Value" );
124 
125     OUString   aPropName;
126     PropertyValue   aPropValue;
127 
128     // Retrieve the optional module name from the Arguments sequence. It is used as a part of
129     // the hash map key to support different controller implementation for the same URL but different
130     // module!!
131     for ( int i = 0; i < Arguments.getLength(); i++ )
132     {
133         if (( Arguments[i] >>= aPropValue ) && ( aPropValue.Name == aPropModuleName ))
134         {
135             aPropValue.Value >>= aPropName;
136             break;
137         }
138     }
139 
140     Sequence< Any > aNewArgs( Arguments );
141 
142     sal_Int32 nAppendIndex = aNewArgs.getLength();
143     aNewArgs.realloc( aNewArgs.getLength() + 2 );
144 
145     // Append the command URL to the Arguments sequence so that one controller can be
146     // used for more than one command URL.
147     aPropValue.Name     = "CommandURL";
148     aPropValue.Value  <<= ServiceSpecifier;
149     aNewArgs[nAppendIndex] <<= aPropValue;
150 
151     // Append the optional value argument. It's an empty string if no additional info
152     // is provided to the controller.
153     OUString aValue = m_pConfigAccess->getValueFromCommandModule( ServiceSpecifier, aPropName );
154     aPropValue.Name = aPropValueName;
155     aPropValue.Value <<= aValue;
156     aNewArgs[nAppendIndex+1] <<= aPropValue;
157 
158     {
159         OUString aServiceName;
160         { // SAFE
161         osl::MutexGuard g(rBHelper.rMutex);
162 
163         if ( !m_bConfigRead )
164         {
165             m_bConfigRead = true;
166             m_pConfigAccess->readConfigurationData();
167         }
168 
169         aServiceName = m_pConfigAccess->getServiceFromCommandModule( ServiceSpecifier, aPropName );
170         } // SAFE
171 
172         if ( !aServiceName.isEmpty() )
173             return m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aServiceName, aNewArgs, m_xContext );
174         else
175             return Reference< XInterface >();
176     }
177 }
178 
getAvailableServiceNames()179 Sequence< OUString > SAL_CALL UIControllerFactory::getAvailableServiceNames()
180 {
181     return Sequence< OUString >();
182 }
183 
184 // XUIControllerRegistration
hasController(const OUString & aCommandURL,const OUString & aModuleName)185 sal_Bool SAL_CALL UIControllerFactory::hasController(
186     const OUString& aCommandURL,
187     const OUString& aModuleName )
188 {
189     osl::MutexGuard g(rBHelper.rMutex);
190 
191     if ( !m_bConfigRead )
192     {
193         m_bConfigRead = true;
194         m_pConfigAccess->readConfigurationData();
195     }
196 
197     return ( !m_pConfigAccess->getServiceFromCommandModule( aCommandURL, aModuleName ).isEmpty() );
198 }
199 
registerController(const OUString & aCommandURL,const OUString & aModuleName,const OUString & aControllerImplementationName)200 void SAL_CALL UIControllerFactory::registerController(
201     const OUString& aCommandURL,
202     const OUString& aModuleName,
203     const OUString& aControllerImplementationName )
204 {
205     // SAFE
206     osl::MutexGuard g(rBHelper.rMutex);
207 
208     if ( !m_bConfigRead )
209     {
210         m_bConfigRead = true;
211         m_pConfigAccess->readConfigurationData();
212     }
213 
214     m_pConfigAccess->addServiceToCommandModule( aCommandURL, aModuleName, aControllerImplementationName );
215     // SAFE
216 }
217 
deregisterController(const OUString & aCommandURL,const OUString & aModuleName)218 void SAL_CALL UIControllerFactory::deregisterController(
219     const OUString& aCommandURL,
220     const OUString& aModuleName )
221 {
222     // SAFE
223     osl::MutexGuard g(rBHelper.rMutex);
224 
225     if ( !m_bConfigRead )
226     {
227         m_bConfigRead = true;
228         m_pConfigAccess->readConfigurationData();
229     }
230 
231     m_pConfigAccess->removeServiceFromCommandModule( aCommandURL, aModuleName );
232     // SAFE
233 }
234 
235 class PopupMenuControllerFactory :  public UIControllerFactory
236 {
237 public:
238     explicit PopupMenuControllerFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext );
239 
getImplementationName()240     virtual OUString SAL_CALL getImplementationName() override
241     {
242         return "com.sun.star.comp.framework.PopupMenuControllerFactory";
243     }
244 
supportsService(OUString const & ServiceName)245     virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
246     {
247         return cppu::supportsService(this, ServiceName);
248     }
249 
getSupportedServiceNames()250     virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
251     {
252         return {"com.sun.star.frame.PopupMenuControllerFactory"};
253     }
254 
255 };
256 
PopupMenuControllerFactory(const Reference<XComponentContext> & xContext)257 PopupMenuControllerFactory::PopupMenuControllerFactory( const Reference< XComponentContext >& xContext ) :
258     UIControllerFactory( xContext, "PopupMenu" )
259 {
260 }
261 
262 struct PopupMenuControllerFactoryInstance {
PopupMenuControllerFactoryInstance__anondffad4420111::PopupMenuControllerFactoryInstance263     explicit PopupMenuControllerFactoryInstance(
264         css::uno::Reference<css::uno::XComponentContext> const & context):
265         instance(static_cast<cppu::OWeakObject *>(
266                     new PopupMenuControllerFactory(context)))
267     {
268     }
269 
270     css::uno::Reference<css::uno::XInterface> instance;
271 };
272 
273 struct PopupMenuControllerFactorySingleton:
274     public rtl::StaticWithArg<
275         PopupMenuControllerFactoryInstance,
276         css::uno::Reference<css::uno::XComponentContext>,
277         PopupMenuControllerFactorySingleton>
278 {};
279 
280 class ToolbarControllerFactory :  public UIControllerFactory
281 {
282 public:
283     explicit ToolbarControllerFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext );
284 
getImplementationName()285     virtual OUString SAL_CALL getImplementationName() override
286     {
287         return "com.sun.star.comp.framework.ToolBarControllerFactory";
288     }
289 
supportsService(OUString const & ServiceName)290     virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
291     {
292         return cppu::supportsService(this, ServiceName);
293     }
294 
getSupportedServiceNames()295     virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
296     {
297         return {"com.sun.star.frame.ToolbarControllerFactory"};
298     }
299 
300 };
301 
ToolbarControllerFactory(const Reference<XComponentContext> & xContext)302 ToolbarControllerFactory::ToolbarControllerFactory( const Reference< XComponentContext >& xContext ) :
303     UIControllerFactory( xContext, "ToolBar" )
304 {
305 }
306 
307 struct ToolbarControllerFactoryInstance {
ToolbarControllerFactoryInstance__anondffad4420111::ToolbarControllerFactoryInstance308     explicit ToolbarControllerFactoryInstance(
309         css::uno::Reference<css::uno::XComponentContext> const & context):
310         instance(static_cast<cppu::OWeakObject *>(
311                     new ToolbarControllerFactory(context)))
312     {
313     }
314 
315     css::uno::Reference<css::uno::XInterface> instance;
316 };
317 
318 struct ToolbarControllerFactorySingleton:
319     public rtl::StaticWithArg<
320         ToolbarControllerFactoryInstance,
321         css::uno::Reference<css::uno::XComponentContext>,
322         ToolbarControllerFactorySingleton>
323 {};
324 
325 class StatusbarControllerFactory :  public UIControllerFactory
326 {
327 public:
328     explicit StatusbarControllerFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext );
329 
getImplementationName()330     virtual OUString SAL_CALL getImplementationName() override
331     {
332         return "com.sun.star.comp.framework.StatusBarControllerFactory";
333     }
334 
supportsService(OUString const & ServiceName)335     virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
336     {
337         return cppu::supportsService(this, ServiceName);
338     }
339 
getSupportedServiceNames()340     virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
341     {
342         return {"com.sun.star.frame.StatusbarControllerFactory"};
343     }
344 
345 };
346 
StatusbarControllerFactory(const Reference<XComponentContext> & xContext)347 StatusbarControllerFactory::StatusbarControllerFactory( const Reference< XComponentContext >& xContext ) :
348     UIControllerFactory( xContext, "StatusBar" )
349 {
350 }
351 
352 struct StatusbarControllerFactoryInstance {
StatusbarControllerFactoryInstance__anondffad4420111::StatusbarControllerFactoryInstance353     explicit StatusbarControllerFactoryInstance(
354         css::uno::Reference<css::uno::XComponentContext> const & context):
355         instance(static_cast<cppu::OWeakObject *>(
356                     new StatusbarControllerFactory(context)))
357     {
358     }
359 
360     css::uno::Reference<css::uno::XInterface> instance;
361 };
362 
363 struct StatusbarControllerFactorySingleton:
364     public rtl::StaticWithArg<
365         StatusbarControllerFactoryInstance,
366         css::uno::Reference<css::uno::XComponentContext>,
367         StatusbarControllerFactorySingleton>
368 {};
369 
370 }
371 
372 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_framework_PopupMenuControllerFactory_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)373 com_sun_star_comp_framework_PopupMenuControllerFactory_get_implementation(
374     css::uno::XComponentContext *context,
375     css::uno::Sequence<css::uno::Any> const &)
376 {
377     return cppu::acquire(static_cast<cppu::OWeakObject *>(
378             PopupMenuControllerFactorySingleton::get(context).instance.get()));
379 }
380 
381 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_framework_ToolBarControllerFactory_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)382 com_sun_star_comp_framework_ToolBarControllerFactory_get_implementation(
383     css::uno::XComponentContext *context,
384     css::uno::Sequence<css::uno::Any> const &)
385 {
386     return cppu::acquire(static_cast<cppu::OWeakObject *>(
387             ToolbarControllerFactorySingleton::get(context).instance.get()));
388 }
389 
390 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_framework_StatusBarControllerFactory_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)391 com_sun_star_comp_framework_StatusBarControllerFactory_get_implementation(
392     css::uno::XComponentContext *context,
393     css::uno::Sequence<css::uno::Any> const &)
394 {
395     return cppu::acquire(static_cast<cppu::OWeakObject *>(
396             StatusbarControllerFactorySingleton::get(context).instance.get()));
397 }
398 
399 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
400