xref: /trunk/main/sd/source/ui/framework/module/ModuleController.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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