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