1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "ConfigurationControllerResourceManager.hxx"
31 #include "ConfigurationControllerBroadcaster.hxx"
32 #include "ResourceFactoryManager.hxx"
33 #include "framework/FrameworkHelper.hxx"
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #include <tools/diagnose_ex.h>
36 #include <algorithm>
37 #include <boost/bind.hpp>
38 
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::drawing::framework;
42 using ::rtl::OUString;
43 
44 #undef VERBOSE
45 //#define VERBOSE 1
46 
47 namespace sd { namespace framework {
48 
49 //===== ConfigurationControllerResourceManager ================================
50 
51 ConfigurationControllerResourceManager::ConfigurationControllerResourceManager (
52     const ::boost::shared_ptr<ResourceFactoryManager>& rpResourceFactoryContainer,
53     const ::boost::shared_ptr<ConfigurationControllerBroadcaster>& rpBroadcaster)
54     : maResourceMap(ResourceComparator()),
55       mpResourceFactoryContainer(rpResourceFactoryContainer),
56       mpBroadcaster(rpBroadcaster)
57 {
58 }
59 
60 
61 
62 
63 ConfigurationControllerResourceManager::~ConfigurationControllerResourceManager (void)
64 {
65 }
66 
67 
68 
69 
70 ConfigurationControllerResourceManager::ResourceDescriptor
71     ConfigurationControllerResourceManager::GetResource (
72         const Reference<XResourceId>& rxResourceId)
73 {
74     ::osl::MutexGuard aGuard (maMutex);
75     ResourceMap::const_iterator iResource (maResourceMap.find(rxResourceId));
76     if (iResource != maResourceMap.end())
77         return iResource->second;
78     else
79         return ResourceDescriptor();
80 }
81 
82 
83 
84 
85 void ConfigurationControllerResourceManager::ActivateResources (
86     const ::std::vector<Reference<XResourceId> >& rResources,
87     const Reference<XConfiguration>& rxConfiguration)
88 {
89     ::osl::MutexGuard aGuard (maMutex);
90     // Iterate in normal order over the resources that are to be
91     // activated so that resources on which others depend are activated
92     // beforet the depending resources are activated.
93     ::std::for_each(
94         rResources.begin(),
95         rResources.end(),
96         ::boost::bind(&ConfigurationControllerResourceManager::ActivateResource,
97             this, _1, rxConfiguration));
98 }
99 
100 
101 
102 
103 void ConfigurationControllerResourceManager::DeactivateResources (
104     const ::std::vector<Reference<XResourceId> >& rResources,
105     const Reference<XConfiguration>& rxConfiguration)
106 {
107     ::osl::MutexGuard aGuard (maMutex);
108     // Iterate in reverese order over the resources that are to be
109     // deactivated so that resources on which others depend are deactivated
110     // only when the depending resources have already been deactivated.
111     ::std::for_each(
112         rResources.rbegin(),
113         rResources.rend(),
114         ::boost::bind(&ConfigurationControllerResourceManager::DeactivateResource,
115             this, _1, rxConfiguration));
116 }
117 
118 
119 
120 
121 /* In this method we do following steps.
122     1. Get the factory with which the resource will be created.
123     2. Create the resource.
124     3. Add the resource to the URL->Object map of the configuration
125     controller.
126     4. Add the resource id to the current configuration.
127     5. Notify listeners.
128 */
129 void ConfigurationControllerResourceManager::ActivateResource (
130     const Reference<XResourceId>& rxResourceId,
131     const Reference<XConfiguration>& rxConfiguration)
132 {
133    if ( ! rxResourceId.is())
134    {
135        OSL_ASSERT(rxResourceId.is());
136        return;
137    }
138 
139 #if defined VERBOSE && VERBOSE>=1
140     OSL_TRACE("activating resource %s\n", OUStringToOString(
141         FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
142 #endif
143 
144     // 1. Get the factory.
145     const OUString sResourceURL (rxResourceId->getResourceURL());
146     Reference<XResourceFactory> xFactory (mpResourceFactoryContainer->GetFactory(sResourceURL));
147     if ( ! xFactory.is())
148     {
149 #if defined VERBOSE && VERBOSE>=1
150         OSL_TRACE("    no factory found fo %s\n",
151             OUStringToOString(sResourceURL, RTL_TEXTENCODING_UTF8).getStr());
152 #endif
153         return;
154     }
155 
156     try
157     {
158         // 2. Create the resource.
159         Reference<XResource> xResource;
160         try
161         {
162             xResource = xFactory->createResource(rxResourceId);
163         }
164         catch (lang::DisposedException&)
165         {
166             // The factory is disposed and can be removed from the list
167             // of registered factories.
168             mpResourceFactoryContainer->RemoveFactoryForReference(xFactory);
169         }
170         catch(Exception&)
171         {
172             DBG_UNHANDLED_EXCEPTION();
173         }
174 
175         if (xResource.is())
176         {
177 #if defined VERBOSE && VERBOSE>=1
178             OSL_TRACE("    successfully created\n");
179 #endif
180             // 3. Add resource to URL->Object map.
181             AddResource(xResource, xFactory);
182 
183             // 4. Add resource id to current configuration.
184             rxConfiguration->addResource(rxResourceId);
185 
186             // 5. Notify the new resource to listeners of the ConfigurationController.
187             mpBroadcaster->NotifyListeners(
188                 FrameworkHelper::msResourceActivationEvent,
189                 rxResourceId,
190                 xResource);
191         }
192         else
193         {
194 #if defined VERBOSE && VERBOSE>=1
195             OSL_TRACE("    resource creation failed\n");
196 #endif
197         }
198     }
199     catch (RuntimeException&)
200     {
201         DBG_UNHANDLED_EXCEPTION();
202     }
203 }
204 
205 
206 
207 
208 /* In this method we do following steps.
209     1. Remove the resource from the URL->Object map of the configuration
210     controller.
211     2. Notify listeners.
212     3. Remove the resource id from the current configuration.
213     4. Release the resource.
214 */
215 void ConfigurationControllerResourceManager::DeactivateResource (
216     const Reference<XResourceId>& rxResourceId,
217     const Reference<XConfiguration>& rxConfiguration)
218 {
219     if ( ! rxResourceId.is())
220         return;
221 
222     bool bSuccess (false);
223     try
224     {
225         // 1. Remove resource from URL->Object map.
226         ResourceDescriptor aDescriptor (RemoveResource(rxResourceId));
227 
228         if (aDescriptor.mxResource.is() && aDescriptor.mxResourceFactory.is())
229         {
230             // 2.  Notifiy listeners that the resource is being deactivated.
231             mpBroadcaster->NotifyListeners(
232                 FrameworkHelper::msResourceDeactivationEvent,
233                 rxResourceId,
234                 aDescriptor.mxResource);
235 
236             // 3. Remove resource id from current configuration.
237             rxConfiguration->removeResource(rxResourceId);
238 
239             // 4. Release the resource.
240             try
241             {
242                 aDescriptor.mxResourceFactory->releaseResource(aDescriptor.mxResource);
243             }
244             catch (lang::DisposedException& rException)
245             {
246                 if ( ! rException.Context.is()
247                     || rException.Context == aDescriptor.mxResourceFactory)
248                 {
249                     // The factory is disposed and can be removed from the
250                     // list of registered factories.
251                     mpResourceFactoryContainer->RemoveFactoryForReference(
252                         aDescriptor.mxResourceFactory);
253                 }
254             }
255 
256             bSuccess = true;
257         }
258     }
259     catch (RuntimeException&)
260     {
261         DBG_UNHANDLED_EXCEPTION();
262     }
263 
264 #if defined VERBOSE && VERBOSE>=1
265     if (bSuccess)
266         OSL_TRACE("successfully deactivated %s\n", OUStringToOString(
267             FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
268     else
269         OSL_TRACE("activating resource %s failed\n", OUStringToOString(
270             FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
271 #endif
272 }
273 
274 
275 
276 
277 void ConfigurationControllerResourceManager::AddResource (
278     const Reference<XResource>& rxResource,
279     const Reference<XResourceFactory>& rxFactory)
280 {
281     if ( ! rxResource.is())
282     {
283         OSL_ASSERT(rxResource.is());
284         return;
285     }
286 
287     // Add the resource to the resource container.
288     ResourceDescriptor aDescriptor;
289     aDescriptor.mxResource = rxResource;
290     aDescriptor.mxResourceFactory = rxFactory;
291     maResourceMap[rxResource->getResourceId()] = aDescriptor;
292 
293 #if defined VERBOSE && VERBOSE>=2
294     OSL_TRACE("ConfigurationControllerResourceManager::AddResource(): added %s -> %x\n",
295         OUStringToOString(
296             FrameworkHelper::ResourceIdToString(rxResource->getResourceId()),
297             RTL_TEXTENCODING_UTF8).getStr(),
298         rxResource.get());
299 #endif
300 }
301 
302 
303 
304 
305 ConfigurationControllerResourceManager::ResourceDescriptor
306     ConfigurationControllerResourceManager::RemoveResource (
307         const Reference<XResourceId>& rxResourceId)
308 {
309     ResourceDescriptor aDescriptor;
310 
311     ResourceMap::iterator iResource (maResourceMap.find(rxResourceId));
312     if (iResource != maResourceMap.end())
313     {
314 #if defined VERBOSE && VERBOSE>=2
315         OSL_TRACE("ConfigurationControllerResourceManager::RemoveResource(): removing %s -> %x\n",
316             OUStringToOString(
317                 FrameworkHelper::ResourceIdToString(rxResourceId),
318                 RTL_TEXTENCODING_UTF8).getStr(),
319             *iResource);
320 #endif
321 
322         aDescriptor = iResource->second;
323         maResourceMap.erase(rxResourceId);
324     }
325 
326     return aDescriptor;
327 }
328 
329 
330 
331 
332 //===== ConfigurationControllerResourceManager::ResourceComparator ============
333 
334 bool ConfigurationControllerResourceManager::ResourceComparator::operator() (
335     const Reference<XResourceId>& rxId1,
336     const Reference<XResourceId>& rxId2) const
337 {
338     if (rxId1.is() && rxId2.is())
339         return rxId1->compareTo(rxId2)<0;
340     else if (rxId1.is())
341         return true;
342     else if (rxId2.is())
343         return false;
344     else
345         return false;
346 }
347 
348 
349 
350 
351 } } // end of namespace sd::framework
352 
353