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 "ChangeRequestQueueProcessor.hxx"
27 #include "ConfigurationTracer.hxx"
28 
29 #include "framework/ConfigurationController.hxx"
30 #include "ConfigurationUpdater.hxx"
31 
32 #include <vcl/svapp.hxx>
33 #include <com/sun/star/container/XNamed.hpp>
34 #include <com/sun/star/drawing/framework/XConfiguration.hpp>
35 #include <com/sun/star/drawing/framework/ConfigurationChangeEvent.hpp>
36 
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::drawing::framework;
40 
41 #undef VERBOSE
42 //#define VERBOSE 1
43 
44 namespace {
45 
46 #ifdef VERBOSE
47 
TraceRequest(const Reference<XConfigurationChangeRequest> & rxRequest)48 void TraceRequest (const Reference<XConfigurationChangeRequest>& rxRequest)
49 {
50     Reference<container::XNamed> xNamed (rxRequest, UNO_QUERY);
51     if (xNamed.is())
52         OSL_TRACE("    %s\n",
53             ::rtl::OUStringToOString(xNamed->getName(), RTL_TEXTENCODING_UTF8).getStr());
54 }
55 
56 #endif
57 
58 } // end of anonymous namespace
59 
60 
61 namespace sd { namespace framework {
62 
ChangeRequestQueueProcessor(const::rtl::Reference<ConfigurationController> & rpConfigurationController,const::boost::shared_ptr<ConfigurationUpdater> & rpConfigurationUpdater)63 ChangeRequestQueueProcessor::ChangeRequestQueueProcessor (
64     const ::rtl::Reference<ConfigurationController>& rpConfigurationController,
65     const ::boost::shared_ptr<ConfigurationUpdater>& rpConfigurationUpdater)
66     : maMutex(),
67       maQueue(),
68       mnUserEventId(0),
69       mxConfiguration(),
70       mpConfigurationController(rpConfigurationController),
71       mpConfigurationUpdater(rpConfigurationUpdater)
72 {
73 }
74 
75 
76 
77 
~ChangeRequestQueueProcessor(void)78 ChangeRequestQueueProcessor::~ChangeRequestQueueProcessor (void)
79 {
80     if (mnUserEventId != 0)
81         Application::RemoveUserEvent(mnUserEventId);
82 }
83 
84 
85 
86 
SetConfiguration(const Reference<XConfiguration> & rxConfiguration)87 void ChangeRequestQueueProcessor::SetConfiguration (
88     const Reference<XConfiguration>& rxConfiguration)
89 {
90     ::osl::MutexGuard aGuard (maMutex);
91 
92     mxConfiguration = rxConfiguration;
93     StartProcessing();
94 }
95 
96 
97 
98 
AddRequest(const Reference<XConfigurationChangeRequest> & rxRequest)99 void ChangeRequestQueueProcessor::AddRequest (
100     const Reference<XConfigurationChangeRequest>& rxRequest)
101 {
102     ::osl::MutexGuard aGuard (maMutex);
103 
104 #ifdef VERBOSE
105     if (maQueue.empty())
106     {
107         OSL_TRACE("Adding requests to empty queue\n");
108         ConfigurationTracer::TraceConfiguration(
109             mxConfiguration, "current configuration of queue processor");
110     }
111     OSL_TRACE("Adding request\n");
112     TraceRequest(rxRequest);
113 #endif
114 
115     maQueue.push_back(rxRequest);
116     StartProcessing();
117 }
118 
119 
120 
121 
StartProcessing(void)122 void ChangeRequestQueueProcessor::StartProcessing (void)
123 {
124     ::osl::MutexGuard aGuard (maMutex);
125 
126     if (mnUserEventId == 0
127         && mxConfiguration.is()
128         && ! maQueue.empty())
129     {
130 #ifdef VERBOSE
131         OSL_TRACE("ChangeRequestQueueProcessor scheduling processing\n");
132 #endif
133         mnUserEventId = Application::PostUserEvent(
134             LINK(this,ChangeRequestQueueProcessor,ProcessEvent));
135     }
136 }
137 
138 
139 
140 
IMPL_LINK(ChangeRequestQueueProcessor,ProcessEvent,void *,pUnused)141 IMPL_LINK(ChangeRequestQueueProcessor, ProcessEvent, void*, pUnused)
142 {
143     (void)pUnused;
144 
145     ::osl::MutexGuard aGuard (maMutex);
146 
147     mnUserEventId = 0;
148 
149     ProcessOneEvent();
150 
151     if ( ! maQueue.empty())
152     {
153         // Schedule the processing of the next event.
154         StartProcessing();
155     }
156 
157     return 0;
158 }
159 
160 
161 
162 
ProcessOneEvent(void)163 void ChangeRequestQueueProcessor::ProcessOneEvent (void)
164 {
165     ::osl::MutexGuard aGuard (maMutex);
166 
167 #ifdef VERBOSE
168     OSL_TRACE("ProcessOneEvent\n");
169 #endif
170 
171     if (mxConfiguration.is()
172         && ! maQueue.empty())
173     {
174         // Get and remove the first entry from the queue.
175         Reference<XConfigurationChangeRequest> xRequest (maQueue.front());
176         maQueue.pop_front();
177 
178         // Execute the change request.
179         if (xRequest.is())
180         {
181 #ifdef VERBOSE
182             TraceRequest(xRequest);
183 #endif
184             xRequest->execute(mxConfiguration);
185         }
186 
187         if (maQueue.empty())
188         {
189 #ifdef VERBOSE
190             OSL_TRACE("All requests are processed\n");
191 #endif
192             // The queue is empty so tell the ConfigurationManager to update
193             // its state.
194             if (mpConfigurationUpdater.get() != NULL)
195             {
196 #ifdef VERBOSE
197                 ConfigurationTracer::TraceConfiguration (
198                     mxConfiguration, "updating to configuration");
199 #endif
200                 mpConfigurationUpdater->RequestUpdate(mxConfiguration);
201             }
202         }
203     }
204 }
205 
206 
207 
208 
IsEmpty(void) const209 bool ChangeRequestQueueProcessor::IsEmpty (void) const
210 {
211     return maQueue.empty();
212 }
213 
214 
215 
216 
ProcessUntilEmpty(void)217 void ChangeRequestQueueProcessor::ProcessUntilEmpty (void)
218 {
219     while ( ! IsEmpty())
220         ProcessOneEvent();
221 }
222 
223 
224 
225 
Clear(void)226 void ChangeRequestQueueProcessor::Clear (void)
227 {
228     ::osl::MutexGuard aGuard (maMutex);
229     maQueue.clear();
230 }
231 
232 
233 } } // end of namespace sd::framework::configuration
234