// It's necessary to hold us self alive! // Otherwise we might die by ref count ...
css::uno::Reference< css::task::XJobListener > xThis(this);
try
{ // create the job // We must check for the supported interface on demand! // But we prefer the synchronous one ...
m_xJob = m_xContext->getServiceManager()->createInstanceWithContext(m_aJobCfg.getService(), m_xContext);
xSJob.set(m_xJob, css::uno::UNO_QUERY); if (!xSJob.is())
xAJob.set(m_xJob, css::uno::UNO_QUERY);
// execute it asynchronous if (xAJob.is())
{
m_aAsyncWait.reset();
SolarMutexAntiGuard const ag(aWriteLock); /* } SAFE */
xAJob->executeAsync(lJobArgs, xThis); // wait for finishing this job - so this method // does the same for synchronous and asynchronous jobs!
m_aAsyncWait.wait(); /* SAFE { */ // Note: Result handling was already done inside the callback!
} // execute it synchron elseif (xSJob.is())
{
css::uno::Any aResult;
{
SolarMutexAntiGuard const ag(aWriteLock); /* } SAFE */
aResult = xSJob->execute(lJobArgs);
} /* SAFE { */
impl_reactForJobResult(aResult);
}
} #if OSL_DEBUG_LEVEL > 0 catch(const css::uno::Exception&)
{
TOOLS_INFO_EXCEPTION("fwk", "Job::execute(): Got exception during job execution");
} #else catch(const css::uno::Exception&)
{} #endif
// deinitialize the environment and mark this job as finished... // but don't overwrite any information about STOPPED or might DISPOSED jobs!
impl_stopListening(); if (m_eRunState == E_RUNNING)
m_eRunState = E_STOPPED_OR_FINISHED;
// If we got a close request from our frame or model... // but we disagreed with that by throwing a veto exception... // and got the ownership... // we have to close the resource frame or model now - // and to disable ourself! if (m_bPendingCloseFrame)
{
m_bPendingCloseFrame = false;
css::uno::Reference< css::util::XCloseable > xClose(m_xFrame, css::uno::UNO_QUERY); if (xClose.is())
{ try
{
xClose->close(true);
} catch(const css::util::CloseVetoException&) {}
}
}
// the real structure of the returned list depends from the environment of this job!
JobData::EMode eMode = m_aJobCfg.getMode();
// Create list of environment variables. This list must be part of the // returned structure every time... but some of its members are optional!
sal_Int32 nLen = 1; if (m_xFrame.is())
++nLen; if (m_xModel.is())
++nLen; if (eMode==JobData::E_EVENT)
++nLen;
css::uno::Sequence< css::beans::NamedValue > lEnvArgs(nLen); auto plEnvArgs = lEnvArgs.getArray();
plEnvArgs[0].Name = "EnvType";
plEnvArgs[0].Value <<= m_aJobCfg.getEnvironmentDescriptor();
sal_Int32 i = 0; if (m_xFrame.is())
{
++i;
plEnvArgs[i].Name = "Frame";
plEnvArgs[i].Value <<= m_xFrame;
} if (m_xModel.is())
{
++i;
plEnvArgs[i].Name = "Model";
plEnvArgs[i].Value <<= m_xModel;
} if (eMode==JobData::E_EVENT)
{
++i;
plEnvArgs[i].Name = "EventName";
plEnvArgs[i].Value <<= m_aJobCfg.getEvent();
}
// get the configuration data from the job data container ... if possible // Means: if this job has any configuration data. Note: only really // filled lists will be set to the return structure at the end of this method.
css::uno::Sequence< css::beans::NamedValue > lConfigArgs;
std::vector< css::beans::NamedValue > lJobConfigArgs; if (eMode==JobData::E_ALIAS || eMode==JobData::E_EVENT)
{
lConfigArgs = m_aJobCfg.getConfig();
lJobConfigArgs = m_aJobCfg.getJobConfig();
}
aReadLock.clear(); /* } SAFE */
// Add all valid (not empty) lists to the return list if (lConfigArgs.hasElements())
{
sal_Int32 nLength = lAllArgs.getLength();
lAllArgs.realloc(nLength+1); auto plAllArgs = lAllArgs.getArray();
plAllArgs[nLength].Name = "Config";
plAllArgs[nLength].Value <<= lConfigArgs;
} if (!lJobConfigArgs.empty())
{
sal_Int32 nLength = lAllArgs.getLength();
lAllArgs.realloc(nLength+1); auto plAllArgs = lAllArgs.getArray();
plAllArgs[nLength].Name = "JobConfig";
plAllArgs[nLength].Value <<= comphelper::containerToSequence(lJobConfigArgs);
} if (lEnvArgs.hasElements())
{
sal_Int32 nLength = lAllArgs.getLength();
lAllArgs.realloc(nLength+1); auto plAllArgs = lAllArgs.getArray();
plAllArgs[nLength].Name = "Environment";
plAllArgs[nLength].Value <<= lEnvArgs;
} if (lDynamicArgs.hasElements())
{
sal_Int32 nLength = lAllArgs.getLength();
lAllArgs.realloc(nLength+1); auto plAllArgs = lAllArgs.getArray();
plAllArgs[nLength].Name = "DynamicData";
plAllArgs[nLength].Value <<= lDynamicArgs;
}
// analyze the result set ...
JobResult aAnalyzedResult(aResult);
// some of the following operations will be supported for different environments // or different type of jobs only.
JobData::EEnvironment eEnvironment = m_aJobCfg.getEnvironment();
// write back the job specific configuration data ... // If the environment allow it and if this job has a configuration! if (
(m_aJobCfg.hasConfig() ) &&
(aAnalyzedResult.existPart(JobResult::E_ARGUMENTS))
)
{
m_aJobCfg.setJobConfig(std::vector{aAnalyzedResult.getArguments()});
}
// disable a job for further executions. // Note: this option is available inside the environment EXECUTOR only if ( // (eEnvironment == JobData::E_EXECUTION ) &&
(m_aJobCfg.hasConfig() ) &&
(aAnalyzedResult.existPart(JobResult::E_DEACTIVATE))
)
{
m_aJobCfg.disableJob();
}
// notify any interested listener with the may given result state. // Note: this option is available inside the environment DISPATCH only if (
(eEnvironment == JobData::E_DISPATCH ) &&
(m_xResultListener.is() ) &&
(aAnalyzedResult.existPart(JobResult::E_DISPATCHRESULT))
)
{ // Attention: Because the listener expect that the original object send this event ... // and we nor the job are the right ones ... // our user has set itself before. So we can fake this source address!
css::frame::DispatchResultEvent aEvent = aAnalyzedResult.getDispatchResult();
aEvent.Source = m_xResultSourceFake;
m_xResultListener->dispatchFinished(aEvent);
}
}
// It's necessary to check this. // May this job was cancelled by any other reason // some milliseconds before. :-) if (m_xJob.is() && m_xJob==xJob)
{ // react for his results // (means enable/disable it for further requests // or save arguments or notify listener ...)
impl_reactForJobResult(aResult);
// Let the job die!
m_xJob.clear();
}
// And let the start method "execute()" finishing it's job. // But do it every time. So any outside blocking code can finish // his work too.
m_aAsyncWait.set();
}
// do nothing, if no internal job is still running ... // The frame or model can be closed then successfully. if (m_eRunState != E_RUNNING) return;
// try close() first at the job. // The job can agree or disagree with this request.
css::uno::Reference< css::util::XCloseable > xClose(m_xJob, css::uno::UNO_QUERY); if (xClose.is())
{
xClose->close(bGetsOwnership); // Here we can say: "this job was stopped successfully". Because // no veto exception was thrown!
m_eRunState = E_STOPPED_OR_FINISHED; return;
}
// try dispose() then // Here the job has no chance for a veto. // But we must be aware of an "already disposed exception"... try
{
css::uno::Reference< css::lang::XComponent > xDispose(m_xJob, css::uno::UNO_QUERY); if (xDispose.is())
{
xDispose->dispose();
m_eRunState = E_DISPOSED;
}
} catch(const css::lang::DisposedException&)
{ // the job was already disposed by any other mechanism !? // But it's not interesting for us. For us this job is stopped now.
m_eRunState = E_DISPOSED;
}
if (m_eRunState != E_DISPOSED)
{ // analyze event source - to find out, which resource called queryClosing() at this // job wrapper. We must bind a "pending close" request to this resource. // Closing of the corresponding resource will be done if our internal job finish it's work.
m_bPendingCloseFrame = (m_xFrame.is() && aEvent.Source == m_xFrame);
m_bPendingCloseModel = (m_xModel.is() && aEvent.Source == m_xModel);
// throw suitable veto exception - because the internal job could not be cancelled.
css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY); throw css::util::CloseVetoException(u"job still in progress"_ustr, xThis);
}
// No veto ... // But don't call die() here or free our internal member. // This must be done inside notifyClosing() only. Otherwise the // might stopped job has no chance to return its results or // call us back. We must give him the chance to finish it's work successfully.
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.