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 
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 
59 ConfigurationControllerResourceManager::~ConfigurationControllerResourceManager (void)
60 {
61 }
62 
63 
64 
65 
66 ConfigurationControllerResourceManager::ResourceDescriptor
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 
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 
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 */
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 fo %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&)
167         {
168             DBG_UNHANDLED_EXCEPTION();
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.
208     3. Remove the resource id from the current configuration.
209     4. Release the resource.
210 */
211 void ConfigurationControllerResourceManager::DeactivateResource (
212     const Reference<XResourceId>& rxResourceId,
213     const Reference<XConfiguration>& rxConfiguration)
214 {
215     if ( ! rxResourceId.is())
216         return;
217 
218     bool bSuccess (false);
219     try
220     {
221         // 1. Remove resource from URL->Object map.
222         ResourceDescriptor aDescriptor (RemoveResource(rxResourceId));
223 
224         if (aDescriptor.mxResource.is() && aDescriptor.mxResourceFactory.is())
225         {
226             // 2.  Notifiy listeners that the resource is being deactivated.
227             mpBroadcaster->NotifyListeners(
228                 FrameworkHelper::msResourceDeactivationEvent,
229                 rxResourceId,
230                 aDescriptor.mxResource);
231 
232             // 3. Remove resource id from current configuration.
233             rxConfiguration->removeResource(rxResourceId);
234 
235             // 4. Release the resource.
236             try
237             {
238                 aDescriptor.mxResourceFactory->releaseResource(aDescriptor.mxResource);
239             }
240             catch (lang::DisposedException& rException)
241             {
242                 if ( ! rException.Context.is()
243                     || rException.Context == aDescriptor.mxResourceFactory)
244                 {
245                     // The factory is disposed and can be removed from the
246                     // list of registered factories.
247                     mpResourceFactoryContainer->RemoveFactoryForReference(
248                         aDescriptor.mxResourceFactory);
249                 }
250             }
251 
252             bSuccess = true;
253         }
254     }
255     catch (RuntimeException&)
256     {
257         DBG_UNHANDLED_EXCEPTION();
258     }
259 
260 #if defined VERBOSE && VERBOSE>=1
261     if (bSuccess)
262         OSL_TRACE("successfully deactivated %s\n", OUStringToOString(
263             FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
264     else
265         OSL_TRACE("activating resource %s failed\n", OUStringToOString(
266             FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
267 #endif
268 }
269 
270 
271 
272 
273 void ConfigurationControllerResourceManager::AddResource (
274     const Reference<XResource>& rxResource,
275     const Reference<XResourceFactory>& rxFactory)
276 {
277     if ( ! rxResource.is())
278     {
279         OSL_ASSERT(rxResource.is());
280         return;
281     }
282 
283     // Add the resource to the resource container.
284     ResourceDescriptor aDescriptor;
285     aDescriptor.mxResource = rxResource;
286     aDescriptor.mxResourceFactory = rxFactory;
287     maResourceMap[rxResource->getResourceId()] = aDescriptor;
288 
289 #if defined VERBOSE && VERBOSE>=2
290     OSL_TRACE("ConfigurationControllerResourceManager::AddResource(): added %s -> %x\n",
291         OUStringToOString(
292             FrameworkHelper::ResourceIdToString(rxResource->getResourceId()),
293             RTL_TEXTENCODING_UTF8).getStr(),
294         rxResource.get());
295 #endif
296 }
297 
298 
299 
300 
301 ConfigurationControllerResourceManager::ResourceDescriptor
302     ConfigurationControllerResourceManager::RemoveResource (
303         const Reference<XResourceId>& rxResourceId)
304 {
305     ResourceDescriptor aDescriptor;
306 
307     ResourceMap::iterator iResource (maResourceMap.find(rxResourceId));
308     if (iResource != maResourceMap.end())
309     {
310 #if defined VERBOSE && VERBOSE>=2
311         OSL_TRACE("ConfigurationControllerResourceManager::RemoveResource(): removing %s -> %x\n",
312             OUStringToOString(
313                 FrameworkHelper::ResourceIdToString(rxResourceId),
314                 RTL_TEXTENCODING_UTF8).getStr(),
315             *iResource);
316 #endif
317 
318         aDescriptor = iResource->second;
319         maResourceMap.erase(rxResourceId);
320     }
321 
322     return aDescriptor;
323 }
324 
325 
326 
327 
328 //===== ConfigurationControllerResourceManager::ResourceComparator ============
329 
330 bool ConfigurationControllerResourceManager::ResourceComparator::operator() (
331     const Reference<XResourceId>& rxId1,
332     const Reference<XResourceId>& rxId2) const
333 {
334     if (rxId1.is() && rxId2.is())
335         return rxId1->compareTo(rxId2)<0;
336     else if (rxId1.is())
337         return true;
338     else if (rxId2.is())
339         return false;
340     else
341         return false;
342 }
343 
344 
345 
346 
347 } } // end of namespace sd::framework
348 
349