1/*
2 Copyright (c) 2010 Volker Krause <vkrause@kde.org>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#include "agentserver.h"
21
22#include "agentthread.h"
23#include "libs/xdgbasedirs_p.h"
24#include "libs/protocol_p.h"
25#include "shared/akdebug.h"
26
27#include <QtCore/QCoreApplication>
28#include <QtCore/QDebug>
29#include <QtCore/QPluginLoader>
30#include <QtCore/QTimer>
31#include <QtDBus/QDBusConnection>
32
33using namespace Akonadi;
34
35AgentServer::AgentServer(QObject *parent)
36 : QObject(parent)
37 , m_processingConfigureRequests(false)
38 , m_quiting(false)
39{
40 QDBusConnection::sessionBus().registerObject(QLatin1String(AKONADI_DBUS_AGENTSERVER_PATH),
41 this, QDBusConnection::ExportScriptableSlots);
42}
43
44AgentServer::~AgentServer()
45{
46 qDebug() << Q_FUNC_INFO;
47 if (!m_quiting) {
48 quit();
49 }
50}
51
52void AgentServer::agentInstanceConfigure(const QString &identifier, qlonglong windowId)
53{
54 m_configureQueue.enqueue(ConfigureInfo(identifier, windowId));
55 if (!m_processingConfigureRequests) { // Start processing the requests if needed.
56 QTimer::singleShot(0, this, SLOT(processConfigureRequest()));
57 }
58}
59
60bool AgentServer::started(const QString &identifier) const
61{
62 return m_agents.contains(identifier);
63}
64
65void AgentServer::startAgent(const QString &identifier, const QString &typeIdentifier, const QString &fileName)
66{
67 akDebug() << Q_FUNC_INFO << identifier << typeIdentifier << fileName;
68
69 //First try to load it staticly
70 Q_FOREACH (QObject *plugin, QPluginLoader::staticInstances()) {
71 if (plugin->objectName() == fileName) {
72 AgentThread *thread = new AgentThread(identifier, plugin, this);
73 m_agents.insert(identifier, thread);
74 thread->start();
75 return;
76 }
77 }
78
79 QPluginLoader *loader = m_agentLoader.load(fileName);
80 if (loader == 0) {
81 return; // No plugin found, debug output in AgentLoader.
82 }
83
84 Q_ASSERT(loader->isLoaded());
85
86 AgentThread *thread = new AgentThread(identifier, loader->instance(), this);
87 m_agents.insert(identifier, thread);
88 thread->start();
89}
90
91void AgentServer::stopAgent(const QString &identifier)
92{
93 if (!m_agents.contains(identifier)) {
94 return;
95 }
96
97 AgentThread *thread = m_agents.take(identifier);
98 thread->quit();
99 thread->wait();
100 delete thread;
101}
102
103void AgentServer::quit()
104{
105 Q_ASSERT(!m_quiting);
106 m_quiting = true;
107
108 QMutableHashIterator<QString, AgentThread *> it(m_agents);
109 while (it.hasNext()) {
110 it.next();
111 stopAgent(it.key());
112 }
113
114 QCoreApplication::instance()->quit();
115}
116
117void AgentServer::processConfigureRequest()
118{
119 if (m_processingConfigureRequests) {
120 return; // Protect against reentrancy
121 }
122
123 m_processingConfigureRequests = true;
124
125 while (!m_configureQueue.empty()) {
126 const ConfigureInfo info = m_configureQueue.dequeue();
127 // call configure on the agent with id info.first for windowId info.second.
128 Q_ASSERT(m_agents.contains(info.first));
129 AgentThread *thread = m_agents.value(info.first);
130 thread->configure(info.second);
131 }
132
133 m_processingConfigureRequests = false;
134}
135