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