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