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 #include "precompiled_sd.hxx"
25
26 #include "framework/ModuleController.hxx"
27
28 #include "tools/ConfigurationAccess.hxx"
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/stl_types.hxx>
31 #include <boost/bind.hpp>
32 #include <hash_map>
33
34 #include <tools/diagnose_ex.h>
35
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::drawing::framework;
39 using ::rtl::OUString;
40 using ::sd::tools::ConfigurationAccess;
41
42 #undef VERBOSE
43 //#define VERBOSE 2
44
45 namespace sd { namespace framework {
46
47 static const sal_uInt32 snFactoryPropertyCount (2);
48 static const sal_uInt32 snStartupPropertyCount (1);
49
50
51
52
53 class ModuleController::ResourceToFactoryMap
54 : public ::std::hash_map<
55 rtl::OUString,
56 rtl::OUString,
57 ::comphelper::UStringHash,
58 ::comphelper::UStringEqual>
59 {
60 public:
ResourceToFactoryMap(void)61 ResourceToFactoryMap (void) {}
62 };
63
64
65 class ModuleController::LoadedFactoryContainer
66 : public ::std::hash_map<
67 rtl::OUString,
68 WeakReference<XInterface>,
69 ::comphelper::UStringHash,
70 ::comphelper::UStringEqual>
71 {
72 public:
LoadedFactoryContainer(void)73 LoadedFactoryContainer (void) {}
74 };
75
76
77
78
79
ModuleController_createInstance(const Reference<XComponentContext> & rxContext)80 Reference<XInterface> SAL_CALL ModuleController_createInstance (
81 const Reference<XComponentContext>& rxContext)
82 {
83 return Reference<XInterface>(ModuleController::CreateInstance(rxContext), UNO_QUERY);
84 }
85
86
87
88
ModuleController_getImplementationName(void)89 ::rtl::OUString ModuleController_getImplementationName (void)
90 {
91 return ::rtl::OUString(
92 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.module.ModuleController"));
93 }
94
95
96
97
ModuleController_getSupportedServiceNames(void)98 Sequence<rtl::OUString> SAL_CALL ModuleController_getSupportedServiceNames (void)
99 {
100 static const ::rtl::OUString sServiceName(
101 ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.ModuleController"));
102 return Sequence<rtl::OUString>(&sServiceName, 1);
103 }
104
105
106
107
108 //===== ModuleController ======================================================
109
CreateInstance(const Reference<XComponentContext> & rxContext)110 Reference<XModuleController> ModuleController::CreateInstance (
111 const Reference<XComponentContext>& rxContext)
112 {
113 return new ModuleController(rxContext);
114 }
115
116
117
118
ModuleController(const Reference<XComponentContext> & rxContext)119 ModuleController::ModuleController (const Reference<XComponentContext>& rxContext) throw()
120 : ModuleControllerInterfaceBase(MutexOwner::maMutex),
121 mxController(),
122 mpResourceToFactoryMap(new ResourceToFactoryMap()),
123 mpLoadedFactories(new LoadedFactoryContainer())
124 {
125 (void)rxContext;
126 LoadFactories(rxContext);
127 }
128
129
130
131
~ModuleController(void)132 ModuleController::~ModuleController (void) throw()
133 {
134 }
135
136
137
138
disposing(void)139 void SAL_CALL ModuleController::disposing (void)
140 {
141 // Break the cyclic reference back to DrawController object
142 mpLoadedFactories.reset();
143 mpResourceToFactoryMap.reset();
144 mxController.clear();
145 }
146
147
148
149
LoadFactories(const Reference<XComponentContext> & rxContext)150 void ModuleController::LoadFactories (const Reference<XComponentContext>& rxContext)
151 {
152 try
153 {
154 ConfigurationAccess aConfiguration (
155 rxContext,
156 OUString::createFromAscii("/org.openoffice.Office.Impress/"),
157 ConfigurationAccess::READ_ONLY);
158 Reference<container::XNameAccess> xFactories (
159 aConfiguration.GetConfigurationNode(
160 OUString::createFromAscii("MultiPaneGUI/Framework/ResourceFactories")),
161 UNO_QUERY);
162 ::std::vector<rtl::OUString> aProperties (snFactoryPropertyCount);
163 aProperties[0] = OUString::createFromAscii("ServiceName");
164 aProperties[1] = OUString::createFromAscii("ResourceList");
165 ConfigurationAccess::ForAll(
166 xFactories,
167 aProperties,
168 ::boost::bind(&ModuleController::ProcessFactory, this, _2));
169 }
170 catch (Exception&)
171 {
172 DBG_UNHANDLED_EXCEPTION();
173 }
174 }
175
176
177
178
ProcessFactory(const::std::vector<Any> & rValues)179 void ModuleController::ProcessFactory (const ::std::vector<Any>& rValues)
180 {
181 OSL_ASSERT(rValues.size() == snFactoryPropertyCount);
182
183 // Get the service name of the factory.
184 rtl::OUString sServiceName;
185 rValues[0] >>= sServiceName;
186
187 // Get all resource URLs that are created by the factory.
188 Reference<container::XNameAccess> xResources (rValues[1], UNO_QUERY);
189 ::std::vector<rtl::OUString> aURLs;
190 tools::ConfigurationAccess::FillList(
191 xResources,
192 OUString::createFromAscii("URL"),
193 aURLs);
194
195 #if defined VERBOSE && VERBOSE>0
196 OSL_TRACE("ModuleController::adding factory %s",
197 OUStringToOString(sServiceName, RTL_TEXTENCODING_UTF8).getStr());
198 #endif
199
200 // Add the resource URLs to the map.
201 ::std::vector<rtl::OUString>::const_iterator iResource;
202 for (iResource=aURLs.begin(); iResource!=aURLs.end(); ++iResource)
203 {
204 (*mpResourceToFactoryMap)[*iResource] = sServiceName;
205 #if defined VERBOSE && VERBOSE>1
206 OSL_TRACE(" %s",
207 OUStringToOString(*iResource, RTL_TEXTENCODING_UTF8).getStr());
208 #endif
209 }
210 }
211
212
213
214
InstantiateStartupServices(void)215 void ModuleController::InstantiateStartupServices (void)
216 {
217 try
218 {
219 tools::ConfigurationAccess aConfiguration (
220 OUString::createFromAscii("/org.openoffice.Office.Impress/"),
221 tools::ConfigurationAccess::READ_ONLY);
222 Reference<container::XNameAccess> xFactories (
223 aConfiguration.GetConfigurationNode(
224 OUString::createFromAscii("MultiPaneGUI/Framework/StartupServices")),
225 UNO_QUERY);
226 ::std::vector<rtl::OUString> aProperties (snStartupPropertyCount);
227 aProperties[0] = OUString::createFromAscii("ServiceName");
228 tools::ConfigurationAccess::ForAll(
229 xFactories,
230 aProperties,
231 ::boost::bind(&ModuleController::ProcessStartupService, this, _2));
232 }
233 catch (Exception&)
234 {
235 OSL_TRACE("ERROR in ModuleController::InstantiateStartupServices");
236 }
237 }
238
239
240
241
ProcessStartupService(const::std::vector<Any> & rValues)242 void ModuleController::ProcessStartupService (const ::std::vector<Any>& rValues)
243 {
244 OSL_ASSERT(rValues.size() == snStartupPropertyCount);
245
246 try
247 {
248 // Get the service name of the startup service.
249 rtl::OUString sServiceName;
250 rValues[0] >>= sServiceName;
251
252 // Instantiate service.
253 Reference<lang::XMultiServiceFactory> xGlobalFactory (
254 ::comphelper::getProcessServiceFactory(), UNO_QUERY);
255 if (xGlobalFactory.is())
256 {
257 // Create the startup service.
258 Sequence<Any> aArguments(1);
259 aArguments[0] <<= mxController;
260 // Note that when the new object will be destroyed at the end of
261 // this scope when it does not register itself anywhere.
262 // Typically it will add itself as ConfigurationChangeListener
263 // at the configuration controller.
264 xGlobalFactory->createInstanceWithArguments(sServiceName, aArguments);
265
266 #if defined VERBOSE && VERBOSE>0
267 OSL_TRACE("ModuleController::created startup service %s",
268 OUStringToOString(sServiceName, RTL_TEXTENCODING_UTF8).getStr());
269 #endif
270 }
271 }
272 catch (Exception&)
273 {
274 OSL_TRACE("ERROR in ModuleController::ProcessStartupServices");
275 }
276 }
277
278
279
280
281 //----- XModuleController -----------------------------------------------------
282
requestResource(const OUString & rsResourceURL)283 void SAL_CALL ModuleController::requestResource (const OUString& rsResourceURL)
284 {
285 ResourceToFactoryMap::const_iterator iFactory (mpResourceToFactoryMap->find(rsResourceURL));
286 if (iFactory != mpResourceToFactoryMap->end())
287 {
288 // Check that the factory has already been loaded and not been
289 // destroyed in the meantime.
290 Reference<XInterface> xFactory;
291 LoadedFactoryContainer::const_iterator iLoadedFactory (
292 mpLoadedFactories->find(iFactory->second));
293 if (iLoadedFactory != mpLoadedFactories->end())
294 xFactory = Reference<XInterface>(iLoadedFactory->second, UNO_QUERY);
295 if ( ! xFactory.is())
296 {
297 // Create a new instance of the factory.
298 Reference<lang::XMultiServiceFactory> xGlobalFactory (
299 ::comphelper::getProcessServiceFactory(), UNO_QUERY);
300 if (xGlobalFactory.is())
301 {
302 // Create the factory service.
303 Sequence<Any> aArguments(1);
304 aArguments[0] <<= mxController;
305 OSL_TRACE("creating resource %s",
306 OUStringToOString(iFactory->second, RTL_TEXTENCODING_ASCII_US).getStr());
307 try
308 {
309 xFactory = xGlobalFactory->createInstanceWithArguments(
310 iFactory->second,
311 aArguments);
312 }
313 catch(Exception&e)
314 {
315 OSL_TRACE("caught exception while creating factory.");
316 }
317
318 // Remember that this factory has been instanced.
319 (*mpLoadedFactories)[iFactory->second] = xFactory;
320 }
321 }
322 }
323 }
324
325
326
327
328 //----- XInitialization -------------------------------------------------------
329
initialize(const Sequence<Any> & aArguments)330 void SAL_CALL ModuleController::initialize (const Sequence<Any>& aArguments)
331 {
332 if (aArguments.getLength() > 0)
333 {
334 try
335 {
336 // Get the XController from the first argument.
337 mxController = Reference<frame::XController>(aArguments[0], UNO_QUERY_THROW);
338
339 InstantiateStartupServices();
340 }
341 catch (RuntimeException&)
342 {}
343 }
344 }
345
346
347 } } // end of namespace sd::framework
348