Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "services/modulemanager.hxx"
31 : : #include "services/frame.hxx"
32 : :
33 : : #include <threadhelp/readguard.hxx>
34 : : #include <threadhelp/writeguard.hxx>
35 : : #include <services.h>
36 : :
37 : : #include <com/sun/star/frame/XFrame.hpp>
38 : : #include <com/sun/star/frame/XController.hpp>
39 : : #include <com/sun/star/frame/XModel.hpp>
40 : : #include <com/sun/star/frame/XModule.hpp>
41 : : #include <comphelper/configurationhelper.hxx>
42 : : #include <comphelper/sequenceashashmap.hxx>
43 : : #include <comphelper/sequenceasvector.hxx>
44 : : #include <comphelper/enumhelper.hxx>
45 : :
46 : : #include <rtl/logfile.hxx>
47 : :
48 : : namespace framework
49 : : {
50 : :
51 : : static const char CFGPATH_FACTORIES[] = "/org.openoffice.Setup/Office/Factories";
52 : : static const char MODULEPROP_IDENTIFIER[] = "ooSetupFactoryModuleIdentifier";
53 : :
54 [ + + ][ + - ]: 765816 : DEFINE_XINTERFACE_7(ModuleManager ,
55 : : OWeakObject ,
56 : : DIRECT_INTERFACE(css::lang::XTypeProvider ),
57 : : DIRECT_INTERFACE(css::lang::XServiceInfo ),
58 : : DIRECT_INTERFACE(css::container::XNameReplace ),
59 : : DIRECT_INTERFACE(css::container::XNameAccess ),
60 : : DIRECT_INTERFACE(css::container::XElementAccess ),
61 : : DIRECT_INTERFACE(css::container::XContainerQuery),
62 : : DIRECT_INTERFACE(css::frame::XModuleManager ))
63 : :
64 [ # # ][ # # ]: 0 : DEFINE_XTYPEPROVIDER_7(ModuleManager ,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
65 : : css::lang::XTypeProvider ,
66 : : css::lang::XServiceInfo ,
67 : : css::container::XNameReplace ,
68 : : css::container::XNameAccess ,
69 : : css::container::XElementAccess ,
70 : : css::container::XContainerQuery,
71 : : css::frame::XModuleManager )
72 : :
73 [ + - ][ + - ]: 3165 : DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(ModuleManager ,
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
74 : : ::cppu::OWeakObject ,
75 : : SERVICENAME_MODULEMANAGER ,
76 : : IMPLEMENTATIONNAME_MODULEMANAGER)
77 : :
78 : 230 : DEFINE_INIT_SERVICE(
79 : : ModuleManager,
80 : : {
81 : : /*Attention
82 : : I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
83 : : to create a new instance of this class by our own supported service factory.
84 : : see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
85 : : */
86 : : }
87 : : )
88 : :
89 : 230 : ModuleManager::ModuleManager(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
90 : : : ThreadHelpBase( )
91 [ + - ]: 230 : , m_xSMGR (xSMGR)
92 : : {
93 : 230 : }
94 : :
95 [ + - ][ + - ]: 220 : ModuleManager::~ModuleManager()
96 : : {
97 [ + + ]: 220 : if (m_xCFG.is())
98 : 105 : m_xCFG.clear();
99 [ - + ]: 440 : }
100 : :
101 : 166293 : ::rtl::OUString SAL_CALL ModuleManager::identify(const css::uno::Reference< css::uno::XInterface >& xModule)
102 : : throw(css::lang::IllegalArgumentException,
103 : : css::frame::UnknownModuleException,
104 : : css::uno::RuntimeException )
105 : : {
106 : : // valid parameter?
107 [ + - ]: 166293 : css::uno::Reference< css::frame::XFrame > xFrame (xModule, css::uno::UNO_QUERY);
108 [ + - ]: 166293 : css::uno::Reference< css::awt::XWindow > xWindow (xModule, css::uno::UNO_QUERY);
109 [ + - ]: 166293 : css::uno::Reference< css::frame::XController > xController(xModule, css::uno::UNO_QUERY);
110 [ + - ]: 166293 : css::uno::Reference< css::frame::XModel > xModel (xModule, css::uno::UNO_QUERY);
111 : :
112 [ + + ][ + + : 269691 : if (
+ - + - +
+ ]
113 : 166293 : (!xFrame.is() ) &&
114 : 34466 : (!xWindow.is() ) &&
115 : 34466 : (!xController.is()) &&
116 : 34466 : (!xModel.is() )
117 : : )
118 : : {
119 : : throw css::lang::IllegalArgumentException(
120 : : ::rtl::OUString("Given module is not a frame nor a window, controller or model."),
121 : : static_cast< ::cppu::OWeakObject* >(this),
122 [ + - ][ + - ]: 474 : 1);
123 : : }
124 : :
125 [ + + ]: 165819 : if (xFrame.is())
126 : : {
127 [ + - ][ + - ]: 131827 : xController = xFrame->getController();
[ + - ]
128 [ + - ][ + - ]: 131827 : xWindow = xFrame->getComponentWindow();
[ + - ]
129 : : }
130 [ + + ]: 165819 : if (xController.is())
131 [ + - ][ + - ]: 120815 : xModel = xController->getModel();
[ + - ]
132 : :
133 : : // modules are implemented by the deepest component in hierarchy ...
134 : : // Means: model -> controller -> window
135 : : // No fallbacks to higher components are allowed !
136 : : // Note : A frame provides access to module components only ... but it's not a module by himself.
137 : :
138 : 165819 : ::rtl::OUString sModule;
139 [ + + ]: 165819 : if (xModel.is())
140 [ + - ]: 154407 : sModule = implts_identify(xModel);
141 : : else
142 [ + + ]: 11412 : if (xController.is())
143 [ + - ]: 400 : sModule = implts_identify(xController);
144 : : else
145 [ + + ]: 11012 : if (xWindow.is())
146 [ + - ]: 1233 : sModule = implts_identify(xWindow);
147 : :
148 [ + + ]: 165819 : if (sModule.isEmpty())
149 : : throw css::frame::UnknownModuleException(
150 : : ::rtl::OUString("Cant find suitable module for the given component."),
151 [ + - ][ + - ]: 11660 : static_cast< ::cppu::OWeakObject* >(this));
152 : :
153 : 166293 : return sModule;
154 : : }
155 : :
156 : 0 : void SAL_CALL ModuleManager::replaceByName(const ::rtl::OUString& sName ,
157 : : const css::uno::Any& aValue)
158 : : throw (css::lang::IllegalArgumentException ,
159 : : css::container::NoSuchElementException,
160 : : css::lang::WrappedTargetException ,
161 : : css::uno::RuntimeException )
162 : : {
163 [ # # ]: 0 : ::comphelper::SequenceAsHashMap lProps(aValue);
164 [ # # ]: 0 : if (lProps.empty() )
165 : : {
166 : : throw css::lang::IllegalArgumentException(
167 : : ::rtl::OUString("No properties given to replace part of module."),
168 : : static_cast< css::container::XNameAccess* >(this),
169 [ # # ][ # # ]: 0 : 2);
170 : : }
171 : :
172 : : // SAFE -> ----------------------------------
173 [ # # ]: 0 : ReadGuard aReadLock(m_aLock);
174 : 0 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
175 [ # # ]: 0 : aReadLock.unlock();
176 : : // <- SAFE ----------------------------------
177 : :
178 : : // get access to the element
179 : : // Note: Dont use impl_getConfig() method here. Because it creates a readonly access only, further
180 : : // it cache it as a member of this module manager instance. If we change some props there ... but dont
181 : : // flush changes (because an error occurred) we will read them later. If we use a different config access
182 : : // we can close it without a flush ... and our read data wont be affected .-)
183 : : css::uno::Reference< css::uno::XInterface > xCfg = ::comphelper::ConfigurationHelper::openConfig(
184 : : xSMGR,
185 : : rtl::OUString(CFGPATH_FACTORIES),
186 [ # # ]: 0 : ::comphelper::ConfigurationHelper::E_STANDARD);
187 [ # # ]: 0 : css::uno::Reference< css::container::XNameAccess > xModules (xCfg, css::uno::UNO_QUERY_THROW);
188 : 0 : css::uno::Reference< css::container::XNameReplace > xModule ;
189 : :
190 [ # # ][ # # ]: 0 : xModules->getByName(sName) >>= xModule;
[ # # ]
191 [ # # ]: 0 : if (!xModule.is())
192 : : {
193 : : throw css::uno::RuntimeException(
194 : : ::rtl::OUString("Was not able to get write access to the requested module entry inside configuration."),
195 [ # # ][ # # ]: 0 : static_cast< css::container::XNameAccess* >(this));
196 : : }
197 : :
198 : 0 : ::comphelper::SequenceAsHashMap::const_iterator pProp;
199 [ # # ][ # # ]: 0 : for ( pProp = lProps.begin();
200 [ # # ]: 0 : pProp != lProps.end() ;
201 : : ++pProp )
202 : : {
203 [ # # ]: 0 : const ::rtl::OUString& sPropName = pProp->first;
204 [ # # ]: 0 : const css::uno::Any& aPropValue = pProp->second;
205 : :
206 : : // let "NoSuchElementException" out ! We support the same API ...
207 : : // and without a flush() at the end all changed data before will be ignored !
208 [ # # ][ # # ]: 0 : xModule->replaceByName(sPropName, aPropValue);
209 : : }
210 : :
211 [ # # ][ # # ]: 0 : ::comphelper::ConfigurationHelper::flush(xCfg);
[ # # ]
212 : 0 : }
213 : :
214 : 13121 : css::uno::Any SAL_CALL ModuleManager::getByName(const ::rtl::OUString& sName)
215 : : throw(css::container::NoSuchElementException,
216 : : css::lang::WrappedTargetException ,
217 : : css::uno::RuntimeException )
218 : : {
219 : : // get access to the element
220 [ + - ]: 13121 : css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
221 : 13121 : css::uno::Reference< css::container::XNameAccess > xModule;
222 [ + - ][ + - ]: 13121 : xCFG->getByName(sName) >>= xModule;
[ + - ]
223 [ - + ]: 13121 : if (!xModule.is())
224 : : {
225 : : throw css::uno::RuntimeException(
226 : : ::rtl::OUString("Was not able to get write access to the requested module entry inside configuration."),
227 [ # # ][ # # ]: 0 : static_cast< css::container::XNameAccess* >(this));
228 : : }
229 : :
230 : : // convert it to seq< PropertyValue >
231 [ + - ][ + - ]: 13121 : const css::uno::Sequence< ::rtl::OUString > lPropNames = xModule->getElementNames();
232 [ + - ]: 13121 : ::comphelper::SequenceAsHashMap lProps ;
233 : 13121 : sal_Int32 c = lPropNames.getLength();
234 : 13121 : sal_Int32 i = 0;
235 : :
236 [ + - ][ + - ]: 13121 : lProps[rtl::OUString(MODULEPROP_IDENTIFIER)] <<= sName;
237 [ + + ]: 236178 : for (i=0; i<c; ++i)
238 : : {
239 : 223057 : const ::rtl::OUString& sPropName = lPropNames[i];
240 [ + - ][ + - ]: 223057 : lProps[sPropName] = xModule->getByName(sPropName);
[ + - ]
241 : : }
242 : :
243 [ + - ][ + - ]: 13121 : return css::uno::makeAny(lProps.getAsConstPropertyValueList());
[ + - ][ + - ]
[ + - ]
244 : : }
245 : :
246 : 2580 : css::uno::Sequence< ::rtl::OUString > SAL_CALL ModuleManager::getElementNames()
247 : : throw(css::uno::RuntimeException)
248 : : {
249 [ + - ]: 2580 : css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
250 [ + - ][ + - ]: 2580 : return xCFG->getElementNames();
251 : : }
252 : :
253 : 0 : sal_Bool SAL_CALL ModuleManager::hasByName(const ::rtl::OUString& sName)
254 : : throw(css::uno::RuntimeException)
255 : : {
256 [ # # ]: 0 : css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
257 [ # # ][ # # ]: 0 : return xCFG->hasByName(sName);
258 : : }
259 : :
260 : 0 : css::uno::Type SAL_CALL ModuleManager::getElementType()
261 : : throw(css::uno::RuntimeException)
262 : : {
263 : 0 : return ::getCppuType((const css::uno::Sequence< css::beans::PropertyValue >*)0);
264 : : }
265 : :
266 : 0 : sal_Bool SAL_CALL ModuleManager::hasElements()
267 : : throw(css::uno::RuntimeException)
268 : : {
269 [ # # ]: 0 : css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
270 [ # # ][ # # ]: 0 : return xCFG->hasElements();
271 : : }
272 : :
273 : 0 : css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByQuery(const ::rtl::OUString&)
274 : : throw(css::uno::RuntimeException)
275 : : {
276 : 0 : return css::uno::Reference< css::container::XEnumeration >();
277 : : }
278 : :
279 : 0 : css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
280 : : throw(css::uno::RuntimeException)
281 : : {
282 [ # # ]: 0 : ::comphelper::SequenceAsHashMap lSearchProps (lProperties);
283 [ # # ]: 0 : css::uno::Sequence< ::rtl::OUString > lModules = getElementNames();
284 : 0 : sal_Int32 c = lModules.getLength();
285 : 0 : sal_Int32 i = 0;
286 [ # # ]: 0 : ::comphelper::SequenceAsVector< css::uno::Any > lResult ;
287 : :
288 [ # # ]: 0 : for (i=0; i<c; ++i)
289 : : {
290 : : try
291 : : {
292 [ # # ]: 0 : const ::rtl::OUString& sModule = lModules[i];
293 [ # # ][ # # ]: 0 : ::comphelper::SequenceAsHashMap lModuleProps = getByName(sModule);
294 : :
295 [ # # ][ # # ]: 0 : if (lModuleProps.match(lSearchProps))
296 [ # # ][ # # ]: 0 : lResult.push_back(css::uno::makeAny(lModuleProps.getAsConstPropertyValueList()));
[ # # ][ # # ]
[ # # ][ # # ]
297 : : }
298 [ # # ]: 0 : catch(const css::uno::Exception&)
299 : : {
300 : : }
301 : : }
302 : :
303 [ # # ][ # # ]: 0 : ::comphelper::OAnyEnumeration* pEnum = new ::comphelper::OAnyEnumeration(lResult.getAsConstList());
[ # # ]
304 [ # # ][ # # ]: 0 : css::uno::Reference< css::container::XEnumeration > xEnum(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY_THROW);
305 [ # # ][ # # ]: 0 : return xEnum;
306 : : }
307 : :
308 : 15701 : css::uno::Reference< css::container::XNameAccess > ModuleManager::implts_getConfig()
309 : : throw(css::uno::RuntimeException)
310 : : {
311 : : // SAFE -> ----------------------------------
312 [ + - ]: 15701 : ReadGuard aReadLock(m_aLock);
313 [ + + ]: 15701 : if (m_xCFG.is())
314 : 15586 : return m_xCFG;
315 : 115 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
316 [ + - ]: 115 : aReadLock.unlock();
317 : : // <- SAFE ----------------------------------
318 : :
319 : 115 : css::uno::Reference< css::uno::XInterface > xCfg;
320 : : try
321 : : {
322 : : xCfg = ::comphelper::ConfigurationHelper::openConfig(
323 : : xSMGR,
324 : : rtl::OUString(CFGPATH_FACTORIES),
325 [ + - ][ + - ]: 115 : ::comphelper::ConfigurationHelper::E_READONLY);
326 : : }
327 [ # # # ]: 0 : catch(const css::uno::RuntimeException&)
328 : : {
329 : 0 : throw;
330 : : }
331 [ # # ]: 0 : catch(const css::uno::Exception&)
332 : : {
333 : 0 : xCfg.clear();
334 : : }
335 : :
336 : : // SAFE -> ----------------------------------
337 [ + - ]: 115 : WriteGuard aWriteLock(m_aLock);
338 [ + - ][ + - ]: 115 : m_xCFG = css::uno::Reference< css::container::XNameAccess >(xCfg, css::uno::UNO_QUERY_THROW);
339 [ + - ][ + - ]: 15701 : return m_xCFG;
340 : : // <- SAFE ----------------------------------
341 : : }
342 : :
343 : 156040 : ::rtl::OUString ModuleManager::implts_identify(const css::uno::Reference< css::uno::XInterface >& xComponent)
344 : : {
345 : : // Search for an optional (!) interface XModule first.
346 : : // Its used to overrule an existing service name. Used e.g. by our database form designer
347 : : // which uses a writer module internaly.
348 [ + - ]: 156040 : css::uno::Reference< css::frame::XModule > xModule(xComponent, css::uno::UNO_QUERY);
349 [ + + ]: 156040 : if (xModule.is())
350 [ + - ][ + - ]: 152521 : return xModule->getIdentifier();
351 : :
352 : : // detect modules in a generic way ...
353 : : // comparing service names with configured entries ...
354 [ + - ]: 3519 : css::uno::Reference< css::lang::XServiceInfo > xInfo(xComponent, css::uno::UNO_QUERY);
355 [ + + ]: 3519 : if (!xInfo.is())
356 : 1233 : return ::rtl::OUString();
357 : :
358 [ + - ]: 2286 : const css::uno::Sequence< ::rtl::OUString > lKnownModules = getElementNames();
359 : 2286 : const ::rtl::OUString* pKnownModules = lKnownModules.getConstArray();
360 : 2286 : sal_Int32 c = lKnownModules.getLength();
361 : 2286 : sal_Int32 i = 0;
362 : :
363 [ + + ]: 19270 : for (i=0; i<c; ++i)
364 : : {
365 [ + - ][ + - ]: 18934 : if (xInfo->supportsService(pKnownModules[i]))
[ + + ]
366 : 1950 : return pKnownModules[i];
367 : : }
368 : :
369 [ + - ]: 156040 : return ::rtl::OUString();
370 : : }
371 : :
372 : : } // namespace framework
373 : :
374 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|