plasma-framework/plasma/private/remoteservicejob.cpp
2013-01-30 13:43:33 +01:00

184 lines
5.5 KiB
C++

/*
* Copyright © 2009 Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "remoteservicejob_p.h"
#include <kconfiggroup.h>
#include <kurl.h>
#include <QtCore/QBuffer>
#include <QtJolie/Client>
#include <QtJolie/Message>
#include <QtJolie/PendingCallWatcher>
#include <QtJolie/PendingReply>
#include "../servicejob.h"
#include "../remote/accessmanager.h"
#include "../remote/authorizationmanager.h"
#include "authorizationmanager_p.h"
#include "remoteservice_p.h"
#include "servicejob_p.h"
#include "joliemessagehelper_p.h"
#include <qtimer.h>
namespace Plasma
{
RemoteServiceJob::RemoteServiceJob(KUrl location,
const QString& destination,
const QString& operation,
QHash<QString,QVariant>& parameters,
QByteArray initialToken,
RemoteService* parent)
: ServiceJob(destination, operation, parameters, parent),
m_token(initialToken),
m_location(location),
m_service(parent),
m_delayedDesc(0)
{
}
RemoteServiceJob::~RemoteServiceJob()
{
delete m_delayedDesc;
m_delayedDesc = 0;
}
void RemoteServiceJob::start()
{
QTimer::singleShot(30000, this, SLOT(timeout()));
if (m_service->m_busy || !m_service->m_ready) {
//enqueue and wait
m_service->m_queue.enqueue(this);
#ifndef NDEBUG
kDebug() << "already busy... enqueue, queue contains " << m_service->m_queue.count();
#endif
return;
}
// the service is now busy ... with us!
m_service->m_busy = true;
// while waiting in the queue, our validity may have changed; it's all async
// so don't assume anything
checkValidity();
if (error()) {
emitResult();
return;
}
//serialize the parameters
QByteArray params;
QBuffer buffer(&params);
buffer.open(QIODevice::WriteOnly);
QDataStream out(&buffer);
out << parameters();
Jolie::Message message(m_location.path(KUrl::RemoveTrailingSlash).remove(0, 1).toUtf8(),
"startOperationCall");
Jolie::Value data;
data.children(JolieMessage::Field::OPERATION) << (Jolie::Value(operationName().toLatin1()));
data.children(JolieMessage::Field::PARAMETERS) << Jolie::Value(params);
data.children(JolieMessage::Field::DESTINATION) << Jolie::Value(destination().toLatin1());
message.setData(data);
Jolie::Client *client = m_service->m_client;
Jolie::PendingCall pendingReply = client->asyncCall(m_service->signMessage(message));
Jolie::PendingCallWatcher *watcher = new Jolie::PendingCallWatcher(pendingReply, this);
connect(watcher, SIGNAL(finished(Jolie::PendingCallWatcher*)),
this, SLOT(callCompleted(Jolie::PendingCallWatcher*)));
}
void RemoteServiceJob::setDelayedDescription(const KConfigGroup &desc)
{
if (!m_delayedDesc) {
m_delayedDesc = new KConfigGroup(desc);
} else {
*m_delayedDesc = desc;
}
}
void RemoteServiceJob::checkValidity()
{
if (!m_service->isOperationEnabled(operationName())) {
setError(-1);
setErrorText(i18n("Job no longer valid, operation is not enabled."));
} else if (m_delayedDesc) {
d->parameters = m_service->parametersFromDescription(*m_delayedDesc);
} else {
KConfigGroup description = m_service->operationDescription(operationName());
QHashIterator<QString, QVariant> param(parameters());
while (param.hasNext()) {
param.next();
if (!description.hasKey(param.key())) {
setError(-1);
setErrorText(i18n("Job no longer valid, invalid parameters."));
break;
}
}
}
delete m_delayedDesc;
m_delayedDesc = 0;
}
void RemoteServiceJob::callCompleted(Jolie::PendingCallWatcher *watcher)
{
m_service->m_busy = false;
Jolie::PendingReply reply = *watcher;
Jolie::Message response = reply.reply();
//TODO:async
if (response.fault().isValid()) {
#ifndef NDEBUG
kDebug() << "fault: " << response.fault().name();
#endif
setError(-1);
setErrorText(JolieMessage::errorMessage(response.fault().name()));
emitResult();
return;
}
m_service->m_token = JolieMessage::field(JolieMessage::Field::TOKEN, response);
QVariant variantResult;
QByteArray byteArrayResult = JolieMessage::field(JolieMessage::Field::RESULT, response);
QBuffer buffer(&byteArrayResult);
buffer.open(QIODevice::ReadOnly);
QDataStream in(&buffer);
in >> variantResult;
setResult(variantResult);
}
void RemoteServiceJob::timeout()
{
m_service->m_busy = false;
#ifndef NDEBUG
kDebug() << "Service job timed out.";
#endif
setError(-1);
setErrorText(i18n("Timeout."));
m_service->m_queue.removeAll(this);
emitResult();
}
} // namespace Plasma