merged tag ooo/OOO330_m14
[LibreOffice.git] / framework / source / jobs / jobexecutor.cxx
blobe3a6122d4938ebec860877866527dd185bee370a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
31 //________________________________
32 // my own includes
33 #include <jobs/jobexecutor.hxx>
34 #include <jobs/job.hxx>
35 #include <jobs/joburl.hxx>
37 #ifndef __FRAMEWORK_CLASS_CONVERTER_HXX_
38 #include <classes/converter.hxx>
39 #endif
40 #include <threadhelp/transactionguard.hxx>
41 #include <threadhelp/readguard.hxx>
42 #include <threadhelp/writeguard.hxx>
43 #include <general.h>
44 #include <services.h>
46 //________________________________
47 // interface includes
48 #include <com/sun/star/beans/XPropertySet.hpp>
49 #include <com/sun/star/container/XNameAccess.hpp>
50 #include <com/sun/star/container/XContainer.hpp>
52 //________________________________
53 // includes of other projects
54 #include <unotools/configpathes.hxx>
55 #include <rtl/ustrbuf.hxx>
56 #include <vcl/svapp.hxx>
58 #include <rtl/logfile.hxx>
60 //________________________________
61 // namespace
63 namespace framework{
65 //________________________________
66 // non exported const
68 //________________________________
69 // non exported definitions
71 //________________________________
72 // declarations
74 DEFINE_XINTERFACE_6( JobExecutor ,
75 OWeakObject ,
76 DIRECT_INTERFACE(css::lang::XTypeProvider ),
77 DIRECT_INTERFACE(css::lang::XServiceInfo ),
78 DIRECT_INTERFACE(css::task::XJobExecutor ),
79 DIRECT_INTERFACE(css::container::XContainerListener ),
80 DIRECT_INTERFACE(css::document::XEventListener ),
81 DERIVED_INTERFACE(css::lang::XEventListener,css::document::XEventListener)
84 DEFINE_XTYPEPROVIDER_6( JobExecutor ,
85 css::lang::XTypeProvider ,
86 css::lang::XServiceInfo ,
87 css::task::XJobExecutor ,
88 css::container::XContainerListener,
89 css::document::XEventListener ,
90 css::lang::XEventListener
93 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE( JobExecutor ,
94 ::cppu::OWeakObject ,
95 SERVICENAME_JOBEXECUTOR ,
96 IMPLEMENTATIONNAME_JOBEXECUTOR
99 DEFINE_INIT_SERVICE( JobExecutor,
101 /*Attention
102 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
103 to create a new instance of this class by our own supported service factory.
104 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
106 // read the list of all currently registered events inside configuration.
107 // e.g. "/org.openoffice.Office.Jobs/Events/<event name>"
108 // We need it later to check if an incoming event request can be executed successfully
109 // or must be rejected. It's an optimization! Of course we must implement updating of this
110 // list too ... Be listener at the configuration.
112 m_aConfig.open(ConfigAccess::E_READONLY);
113 if (m_aConfig.getMode() == ConfigAccess::E_READONLY)
115 css::uno::Reference< css::container::XNameAccess > xRegistry(m_aConfig.cfg(), css::uno::UNO_QUERY);
116 if (xRegistry.is())
117 m_lEvents = Converter::convert_seqOUString2OUStringList(xRegistry->getElementNames());
119 css::uno::Reference< css::container::XContainer > xNotifier(m_aConfig.cfg(), css::uno::UNO_QUERY);
120 if (xNotifier.is())
122 css::uno::Reference< css::container::XContainerListener > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
123 xNotifier->addContainerListener(xThis);
126 // don't close cfg here!
127 // It will be done inside disposing ...
132 //________________________________
135 @short standard ctor
136 @descr It initialize this new instance.
138 @param xSMGR
139 reference to the uno service manager
141 JobExecutor::JobExecutor( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
142 : ThreadHelpBase (&Application::GetSolarMutex() )
143 , ::cppu::OWeakObject ( )
144 , m_xSMGR (xSMGR )
145 , m_aConfig (xSMGR, ::rtl::OUString::createFromAscii(JobData::EVENTCFG_ROOT) )
147 // Don't do any reference related code here! Do it inside special
148 // impl_ method() ... see DEFINE_INIT_SERVICE() macro for further informations.
151 JobExecutor::~JobExecutor()
153 LOG_ASSERT(m_aConfig.getMode() == ConfigAccess::E_CLOSED, "JobExecutor::~JobExecutor()\nConfiguration don't send dispoing() message!\n")
156 //________________________________
159 @short implementation of XJobExecutor interface
160 @descr We use the given event to locate any registered job inside our configuration
161 and execute it. Further we control the lifetime of it and supress
162 shutdown of the office till all jobs was finished.
164 @param sEvent
165 is used to locate registered jobs
167 void SAL_CALL JobExecutor::trigger( const ::rtl::OUString& sEvent ) throw(css::uno::RuntimeException)
169 RTL_LOGFILE_CONTEXT(aLog, "fwk (as96863) JobExecutor::trigger()");
171 /* SAFE { */
172 ReadGuard aReadLock(m_aLock);
174 // Optimization!
175 // Check if the given event name exist inside configuration and reject wrong requests.
176 // This optimization supress using of the cfg api for getting event and job descriptions ...
177 if (m_lEvents.find(sEvent) == m_lEvents.end())
178 return;
180 // get list of all enabled jobs
181 // The called static helper methods read it from the configuration and
182 // filter disabled jobs using it's time stamp values.
183 css::uno::Sequence< ::rtl::OUString > lJobs = JobData::getEnabledJobsForEvent(m_xSMGR, sEvent);
185 aReadLock.unlock();
186 /* } SAFE */
188 // step over all enabled jobs and execute it
189 sal_Int32 c = lJobs.getLength();
190 for (sal_Int32 j=0; j<c; ++j)
192 /* SAFE { */
193 aReadLock.lock();
195 JobData aCfg(m_xSMGR);
196 aCfg.setEvent(sEvent, lJobs[j]);
197 aCfg.setEnvironment(JobData::E_EXECUTION);
199 /*Attention!
200 Jobs implements interfaces and dies by ref count!
201 And freeing of such uno object is done by uno itself.
202 So we have to use dynamic memory everytimes.
204 Job* pJob = new Job(m_xSMGR, css::uno::Reference< css::frame::XFrame >());
205 css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
206 pJob->setJobData(aCfg);
208 aReadLock.unlock();
209 /* } SAFE */
211 pJob->execute(css::uno::Sequence< css::beans::NamedValue >());
215 //________________________________
217 void SAL_CALL JobExecutor::notifyEvent( const css::document::EventObject& aEvent ) throw(css::uno::RuntimeException)
219 static ::rtl::OUString EVENT_ON_NEW = DECLARE_ASCII("OnNew" ); // Doc UI event
220 static ::rtl::OUString EVENT_ON_LOAD = DECLARE_ASCII("OnLoad" ); // Doc UI event
221 static ::rtl::OUString EVENT_ON_CREATE = DECLARE_ASCII("OnCreate" ); // Doc API event
222 static ::rtl::OUString EVENT_ON_LOAD_FINISHED = DECLARE_ASCII("OnLoadFinished" ); // Doc API event
223 static ::rtl::OUString EVENT_ON_DOCUMENT_OPENED = DECLARE_ASCII("onDocumentOpened" ); // Job UI event : OnNew or OnLoad
224 static ::rtl::OUString EVENT_ON_DOCUMENT_ADDED = DECLARE_ASCII("onDocumentAdded" ); // Job API event : OnCreate or OnLoadFinished
226 /* SAFE { */
227 ReadGuard aReadLock(m_aLock);
229 ::comphelper::SequenceAsVector< JobData::TJob2DocEventBinding > lJobs;
231 // Optimization!
232 // Check if the given event name exist inside configuration and reject wrong requests.
233 // This optimization supress using of the cfg api for getting event and job descriptions.
234 // see using of m_lEvents.find() below ...
236 // Special feature: If the events "OnNew" or "OnLoad" occures - we generate our own event "onDocumentOpened".
237 if (
238 (aEvent.EventName.equals(EVENT_ON_NEW )) ||
239 (aEvent.EventName.equals(EVENT_ON_LOAD))
242 if (m_lEvents.find(EVENT_ON_DOCUMENT_OPENED) != m_lEvents.end())
243 JobData::appendEnabledJobsForEvent(m_xSMGR, EVENT_ON_DOCUMENT_OPENED, lJobs);
246 // Special feature: If the events "OnCreate" or "OnLoadFinished" occures - we generate our own event "onDocumentAdded".
247 if (
248 (aEvent.EventName.equals(EVENT_ON_CREATE )) ||
249 (aEvent.EventName.equals(EVENT_ON_LOAD_FINISHED))
252 if (m_lEvents.find(EVENT_ON_DOCUMENT_ADDED) != m_lEvents.end())
253 JobData::appendEnabledJobsForEvent(m_xSMGR, EVENT_ON_DOCUMENT_ADDED, lJobs);
256 // Add all jobs for "real" notified event too .-)
257 if (m_lEvents.find(aEvent.EventName) != m_lEvents.end())
258 JobData::appendEnabledJobsForEvent(m_xSMGR, aEvent.EventName, lJobs);
260 aReadLock.unlock();
261 /* } SAFE */
263 // step over all enabled jobs and execute it
264 ::comphelper::SequenceAsVector< JobData::TJob2DocEventBinding >::const_iterator pIt;
265 for ( pIt = lJobs.begin();
266 pIt != lJobs.end() ;
267 ++pIt )
269 /* SAFE { */
270 aReadLock.lock();
272 const JobData::TJob2DocEventBinding& rBinding = *pIt;
274 JobData aCfg(m_xSMGR);
275 aCfg.setEvent(rBinding.m_sDocEvent, rBinding.m_sJobName);
276 aCfg.setEnvironment(JobData::E_DOCUMENTEVENT);
278 /*Attention!
279 Jobs implements interfaces and dies by ref count!
280 And freeing of such uno object is done by uno itself.
281 So we have to use dynamic memory everytimes.
283 css::uno::Reference< css::frame::XModel > xModel(aEvent.Source, css::uno::UNO_QUERY);
284 Job* pJob = new Job(m_xSMGR, xModel);
285 css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
286 pJob->setJobData(aCfg);
288 aReadLock.unlock();
289 /* } SAFE */
291 pJob->execute(css::uno::Sequence< css::beans::NamedValue >());
295 //________________________________
297 void SAL_CALL JobExecutor::elementInserted( const css::container::ContainerEvent& aEvent ) throw(css::uno::RuntimeException)
299 ::rtl::OUString sValue;
300 if (aEvent.Accessor >>= sValue)
302 ::rtl::OUString sEvent = ::utl::extractFirstFromConfigurationPath(sValue);
303 if (sEvent.getLength() > 0)
305 OUStringList::iterator pEvent = m_lEvents.find(sEvent);
306 if (pEvent == m_lEvents.end())
307 m_lEvents.push_back(sEvent);
312 void SAL_CALL JobExecutor::elementRemoved ( const css::container::ContainerEvent& aEvent ) throw(css::uno::RuntimeException)
314 ::rtl::OUString sValue;
315 if (aEvent.Accessor >>= sValue)
317 ::rtl::OUString sEvent = ::utl::extractFirstFromConfigurationPath(sValue);
318 if (sEvent.getLength() > 0)
320 OUStringList::iterator pEvent = m_lEvents.find(sEvent);
321 if (pEvent != m_lEvents.end())
322 m_lEvents.erase(pEvent);
327 void SAL_CALL JobExecutor::elementReplaced( const css::container::ContainerEvent& ) throw(css::uno::RuntimeException)
329 // I'm not interested on changed items :-)
332 //________________________________
334 /** @short the used cfg changes notifier wish to be released in its reference.
336 @descr We close our internal used configuration instance to
337 free this reference.
339 @attention For the special feature "bind global document event broadcaster to job execution"
340 this job executor instance was registered from outside code as
341 css.document.XEventListener. So it can be, that this disposing call comes from
342 the global event broadcaster service. But we don't hold any reference to this service
343 which can or must be released. Because this broadcaster itself is an one instance service
344 too, we can ignore this request. On the other side we must relase our internal CFG
345 reference ... SOLUTION => check the given event source and react only, if it's our internal
346 hold configuration object!
348 void SAL_CALL JobExecutor::disposing( const css::lang::EventObject& aEvent ) throw(css::uno::RuntimeException)
350 /* SAFE { */
351 ReadGuard aReadLock(m_aLock);
352 css::uno::Reference< css::uno::XInterface > xCFG(m_aConfig.cfg(), css::uno::UNO_QUERY);
353 if (
354 (xCFG == aEvent.Source ) &&
355 (m_aConfig.getMode() != ConfigAccess::E_CLOSED)
358 m_aConfig.close();
360 aReadLock.unlock();
361 /* } SAFE */
364 } // namespace framework