1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26
27 #include "services/modulemanager.hxx"
28 #include "services/frame.hxx"
29
30 //_______________________________________________
31 // own includes
32 #include <threadhelp/readguard.hxx>
33 #include <threadhelp/writeguard.hxx>
34 #include <services.h>
35
36 //_______________________________________________
37 // interface includes
38 #include <com/sun/star/frame/XFrame.hpp>
39 #include <com/sun/star/frame/XController.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
41 #include <com/sun/star/frame/XModule.hpp>
42 #include <comphelper/configurationhelper.hxx>
43 #include <comphelper/sequenceashashmap.hxx>
44 #include <comphelper/sequenceasvector.hxx>
45 #include <comphelper/enumhelper.hxx>
46
47 //_______________________________________________
48 // other includes
49 #include <rtl/logfile.hxx>
50
51 namespace framework
52 {
53
54 static const ::rtl::OUString CFGPATH_FACTORIES = ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Office/Factories");
55 static const ::rtl::OUString MODULEPROP_IDENTIFIER = ::rtl::OUString::createFromAscii("ooSetupFactoryModuleIdentifier" );
56
57 /*-----------------------------------------------
58 04.12.2003 09:32
59 -----------------------------------------------*/
DEFINE_XINTERFACE_7(ModuleManager,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::lang::XServiceInfo),DIRECT_INTERFACE (css::container::XNameReplace),DIRECT_INTERFACE (css::container::XNameAccess),DIRECT_INTERFACE (css::container::XElementAccess),DIRECT_INTERFACE (css::container::XContainerQuery),DIRECT_INTERFACE (css::frame::XModuleManager))60 DEFINE_XINTERFACE_7(ModuleManager ,
61 OWeakObject ,
62 DIRECT_INTERFACE(css::lang::XTypeProvider ),
63 DIRECT_INTERFACE(css::lang::XServiceInfo ),
64 DIRECT_INTERFACE(css::container::XNameReplace ),
65 DIRECT_INTERFACE(css::container::XNameAccess ),
66 DIRECT_INTERFACE(css::container::XElementAccess ),
67 DIRECT_INTERFACE(css::container::XContainerQuery),
68 DIRECT_INTERFACE(css::frame::XModuleManager ))
69
70 /*-----------------------------------------------
71 04.12.2003 09:32
72 -----------------------------------------------*/
73 DEFINE_XTYPEPROVIDER_7(ModuleManager ,
74 css::lang::XTypeProvider ,
75 css::lang::XServiceInfo ,
76 css::container::XNameReplace ,
77 css::container::XNameAccess ,
78 css::container::XElementAccess ,
79 css::container::XContainerQuery,
80 css::frame::XModuleManager )
81
82 /*-----------------------------------------------
83 04.12.2003 09:35
84 -----------------------------------------------*/
85 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(ModuleManager ,
86 ::cppu::OWeakObject ,
87 SERVICENAME_MODULEMANAGER ,
88 IMPLEMENTATIONNAME_MODULEMANAGER)
89
90 /*-----------------------------------------------
91 04.12.2003 09:35
92 -----------------------------------------------*/
93 DEFINE_INIT_SERVICE(
94 ModuleManager,
95 {
96 /*Attention
97 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
98 to create a new instance of this class by our own supported service factory.
99 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
100 */
101 }
102 )
103
104 /*-----------------------------------------------
105 04.12.2003 09:30
106 -----------------------------------------------*/
107 ModuleManager::ModuleManager(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
108 : ThreadHelpBase( )
109 , m_xSMGR (xSMGR)
110 {
111 }
112
113 /*-----------------------------------------------
114 10.12.2003 11:59
115 -----------------------------------------------*/
~ModuleManager()116 ModuleManager::~ModuleManager()
117 {
118 if (m_xCFG.is())
119 m_xCFG.clear();
120 }
121
122 /*-----------------------------------------------
123 10.12.2003 11:02
124 -----------------------------------------------*/
identify(const css::uno::Reference<css::uno::XInterface> & xModule)125 ::rtl::OUString SAL_CALL ModuleManager::identify(const css::uno::Reference< css::uno::XInterface >& xModule)
126 {
127 // valid parameter?
128 css::uno::Reference< css::frame::XFrame > xFrame (xModule, css::uno::UNO_QUERY);
129 css::uno::Reference< css::awt::XWindow > xWindow (xModule, css::uno::UNO_QUERY);
130 css::uno::Reference< css::frame::XController > xController(xModule, css::uno::UNO_QUERY);
131 css::uno::Reference< css::frame::XModel > xModel (xModule, css::uno::UNO_QUERY);
132
133 if (
134 (!xFrame.is() ) &&
135 (!xWindow.is() ) &&
136 (!xController.is()) &&
137 (!xModel.is() )
138 )
139 {
140 throw css::lang::IllegalArgumentException(
141 ::rtl::OUString::createFromAscii("Given module is not a frame nor a window, controller or model."),
142 static_cast< ::cppu::OWeakObject* >(this),
143 1);
144 }
145
146 if (xFrame.is())
147 {
148 xController = xFrame->getController();
149 xWindow = xFrame->getComponentWindow();
150 }
151 if (xController.is())
152 xModel = xController->getModel();
153
154 // modules are implemented by the deepest component in hierarchy ...
155 // Means: model -> controller -> window
156 // No fallbacks to higher components are allowed !
157 // Note : A frame provides access to module components only ... but it's not a module by himself.
158
159 ::rtl::OUString sModule;
160 if (xModel.is())
161 sModule = implts_identify(xModel);
162 else
163 if (xController.is())
164 sModule = implts_identify(xController);
165 else
166 if (xWindow.is())
167 sModule = implts_identify(xWindow);
168
169 if (sModule.getLength() < 1)
170 throw css::frame::UnknownModuleException(
171 ::rtl::OUString::createFromAscii("Can't find suitable module for the given component."),
172 static_cast< ::cppu::OWeakObject* >(this));
173
174 return sModule;
175 }
176
177 /*-----------------------------------------------
178 08.03.2007 09:55
179 -----------------------------------------------*/
replaceByName(const::rtl::OUString & sName,const css::uno::Any & aValue)180 void SAL_CALL ModuleManager::replaceByName(const ::rtl::OUString& sName ,
181 const css::uno::Any& aValue)
182 {
183 ::comphelper::SequenceAsHashMap lProps(aValue);
184 if (lProps.empty() )
185 {
186 throw css::lang::IllegalArgumentException(
187 ::rtl::OUString::createFromAscii("No properties given to replace part of module."),
188 static_cast< css::container::XNameAccess* >(this),
189 2);
190 }
191
192 // SAFE -> ----------------------------------
193 ReadGuard aReadLock(m_aLock);
194 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
195 aReadLock.unlock();
196 // <- SAFE ----------------------------------
197
198 // get access to the element
199 // Note: Dont use impl_getConfig() method here. Because it creates a readonly access only, further
200 // it cache it as a member of this module manager instance. If we change some props there ... but dont
201 // flush changes (because an error occurred) we will read them later. If we use a different config access
202 // we can close it without a flush ... and our read data won't be affected .-)
203 css::uno::Reference< css::uno::XInterface > xCfg = ::comphelper::ConfigurationHelper::openConfig(
204 xSMGR,
205 CFGPATH_FACTORIES,
206 ::comphelper::ConfigurationHelper::E_STANDARD);
207 css::uno::Reference< css::container::XNameAccess > xModules (xCfg, css::uno::UNO_QUERY_THROW);
208 css::uno::Reference< css::container::XNameReplace > xModule ;
209
210 xModules->getByName(sName) >>= xModule;
211 if (!xModule.is())
212 {
213 throw css::uno::RuntimeException(
214 ::rtl::OUString::createFromAscii("Was not able to get write access to the requested module entry inside configuration."),
215 static_cast< css::container::XNameAccess* >(this));
216 }
217
218 ::comphelper::SequenceAsHashMap::const_iterator pProp;
219 for ( pProp = lProps.begin();
220 pProp != lProps.end() ;
221 ++pProp )
222 {
223 const ::rtl::OUString& sPropName = pProp->first;
224 const css::uno::Any& aPropValue = pProp->second;
225
226 // let "NoSuchElementException" out ! We support the same API ...
227 // and without a flush() at the end all changed data before will be ignored !
228 xModule->replaceByName(sPropName, aPropValue);
229 }
230
231 ::comphelper::ConfigurationHelper::flush(xCfg);
232 }
233
234 /*-----------------------------------------------
235 10.12.2003 12:05
236 -----------------------------------------------*/
getByName(const::rtl::OUString & sName)237 css::uno::Any SAL_CALL ModuleManager::getByName(const ::rtl::OUString& sName)
238 {
239 // get access to the element
240 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
241 css::uno::Reference< css::container::XNameAccess > xModule;
242 xCFG->getByName(sName) >>= xModule;
243 if (!xModule.is())
244 {
245 throw css::uno::RuntimeException(
246 ::rtl::OUString::createFromAscii("Was not able to get write access to the requested module entry inside configuration."),
247 static_cast< css::container::XNameAccess* >(this));
248 }
249
250 // convert it to seq< PropertyValue >
251 const css::uno::Sequence< ::rtl::OUString > lPropNames = xModule->getElementNames();
252 ::comphelper::SequenceAsHashMap lProps ;
253 sal_Int32 c = lPropNames.getLength();
254 sal_Int32 i = 0;
255
256 lProps[MODULEPROP_IDENTIFIER] <<= sName;
257 for (i=0; i<c; ++i)
258 {
259 const ::rtl::OUString& sPropName = lPropNames[i];
260 lProps[sPropName] = xModule->getByName(sPropName);
261 }
262
263 return css::uno::makeAny(lProps.getAsConstPropertyValueList());
264 }
265
266 /*-----------------------------------------------
267 10.12.2003 11:58
268 -----------------------------------------------*/
getElementNames()269 css::uno::Sequence< ::rtl::OUString > SAL_CALL ModuleManager::getElementNames()
270 {
271 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
272 return xCFG->getElementNames();
273 }
274
275 /*-----------------------------------------------
276 10.12.2003 11:57
277 -----------------------------------------------*/
hasByName(const::rtl::OUString & sName)278 sal_Bool SAL_CALL ModuleManager::hasByName(const ::rtl::OUString& sName)
279 {
280 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
281 return xCFG->hasByName(sName);
282 }
283
284 /*-----------------------------------------------
285 10.12.2003 11:35
286 -----------------------------------------------*/
getElementType()287 css::uno::Type SAL_CALL ModuleManager::getElementType()
288 {
289 return ::getCppuType((const css::uno::Sequence< css::beans::PropertyValue >*)0);
290 }
291
292 /*-----------------------------------------------
293 10.12.2003 11:56
294 -----------------------------------------------*/
hasElements()295 sal_Bool SAL_CALL ModuleManager::hasElements()
296 {
297 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig();
298 return xCFG->hasElements();
299 }
300
301 /*-----------------------------------------------
302 07.03.2007 12:55
303 -----------------------------------------------*/
createSubSetEnumerationByQuery(const::rtl::OUString &)304 css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByQuery(const ::rtl::OUString&)
305 {
306 return css::uno::Reference< css::container::XEnumeration >();
307 }
308
309 /*-----------------------------------------------
310 07.03.2007 12:55
311 -----------------------------------------------*/
createSubSetEnumerationByProperties(const css::uno::Sequence<css::beans::NamedValue> & lProperties)312 css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
313 {
314 ::comphelper::SequenceAsHashMap lSearchProps (lProperties);
315 css::uno::Sequence< ::rtl::OUString > lModules = getElementNames();
316 sal_Int32 c = lModules.getLength();
317 sal_Int32 i = 0;
318 ::comphelper::SequenceAsVector< css::uno::Any > lResult ;
319
320 for (i=0; i<c; ++i)
321 {
322 try
323 {
324 const ::rtl::OUString& sModule = lModules[i];
325 ::comphelper::SequenceAsHashMap lModuleProps = getByName(sModule);
326
327 if (lModuleProps.match(lSearchProps))
328 lResult.push_back(css::uno::makeAny(lModuleProps.getAsConstPropertyValueList()));
329 }
330 catch(const css::uno::Exception&)
331 {}
332 }
333
334 ::comphelper::OAnyEnumeration* pEnum = new ::comphelper::OAnyEnumeration(lResult.getAsConstList());
335 css::uno::Reference< css::container::XEnumeration > xEnum(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY_THROW);
336 return xEnum;
337 }
338
339 /*-----------------------------------------------
340 14.12.2003 09:45
341 -----------------------------------------------*/
implts_getConfig()342 css::uno::Reference< css::container::XNameAccess > ModuleManager::implts_getConfig()
343 {
344 // SAFE -> ----------------------------------
345 ReadGuard aReadLock(m_aLock);
346 if (m_xCFG.is())
347 return m_xCFG;
348 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
349 aReadLock.unlock();
350 // <- SAFE ----------------------------------
351
352 css::uno::Reference< css::uno::XInterface > xCfg;
353 try
354 {
355 xCfg = ::comphelper::ConfigurationHelper::openConfig(
356 xSMGR,
357 CFGPATH_FACTORIES,
358 ::comphelper::ConfigurationHelper::E_READONLY);
359 }
360 catch(const css::uno::RuntimeException& exRun)
361 { throw exRun; }
362 catch(const css::uno::Exception&)
363 { xCfg.clear(); }
364
365 // SAFE -> ----------------------------------
366 WriteGuard aWriteLock(m_aLock);
367 m_xCFG = css::uno::Reference< css::container::XNameAccess >(xCfg, css::uno::UNO_QUERY_THROW);
368 return m_xCFG;
369 // <- SAFE ----------------------------------
370 }
371
372 /*-----------------------------------------------
373 30.01.2004 07:54
374 -----------------------------------------------*/
implts_identify(const css::uno::Reference<css::uno::XInterface> & xComponent)375 ::rtl::OUString ModuleManager::implts_identify(const css::uno::Reference< css::uno::XInterface >& xComponent)
376 {
377 // Search for an optional (!) interface XModule first.
378 // It's used to overrule an existing service name. Used e.g. by our database form designer
379 // which uses a writer module internally.
380 css::uno::Reference< css::frame::XModule > xModule(xComponent, css::uno::UNO_QUERY);
381 if (xModule.is())
382 return xModule->getIdentifier();
383
384 // detect modules in a generic way ...
385 // comparing service names with configured entries ...
386 css::uno::Reference< css::lang::XServiceInfo > xInfo(xComponent, css::uno::UNO_QUERY);
387 if (!xInfo.is())
388 return ::rtl::OUString();
389
390 const css::uno::Sequence< ::rtl::OUString > lKnownModules = getElementNames();
391 const ::rtl::OUString* pKnownModules = lKnownModules.getConstArray();
392 sal_Int32 c = lKnownModules.getLength();
393 sal_Int32 i = 0;
394
395 for (i=0; i<c; ++i)
396 {
397 if (xInfo->supportsService(pKnownModules[i]))
398 return pKnownModules[i];
399 }
400
401 return ::rtl::OUString();
402 }
403
404 } // namespace framework
405