Allow to export services thanks to the Server and AbstractAdaptor

classes. Also introduce a small calculatorservice example showing that,
with a quick client written using jolie.

svn path=/branches/work/~ervin/qtjolie/; revision=978075
This commit is contained in:
Kevin Ottens 2009-06-05 22:51:08 +00:00
parent 3f553aafe3
commit d99e623ae9
14 changed files with 639 additions and 0 deletions

View File

@ -1,4 +1,5 @@
install( FILES install( FILES
QtJolie/AbstractAdaptor
QtJolie/Client QtJolie/Client
QtJolie/Fault QtJolie/Fault
QtJolie/Message QtJolie/Message
@ -6,5 +7,6 @@ install( FILES
QtJolie/PendingCall QtJolie/PendingCall
QtJolie/PendingCallWatcher QtJolie/PendingCallWatcher
QtJolie/PendingReply QtJolie/PendingReply
QtJolie/Server
QtJolie/Value QtJolie/Value
DESTINATION ${INCLUDE_INSTALL_DIR}/QtJolie COMPONENT Devel) DESTINATION ${INCLUDE_INSTALL_DIR}/QtJolie COMPONENT Devel)

View File

@ -0,0 +1,2 @@
#include "../qtjolie/abstractadaptor.h"

View File

@ -0,0 +1,2 @@
#include "../qtjolie/server.h"

View File

@ -6,6 +6,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${QT_INCLUDE_DIR}) ${QT_INCLUDE_DIR})
set(qtjolie_LIB_SRCS set(qtjolie_LIB_SRCS
abstractadaptor.cpp
client.cpp client.cpp
clientthread.cpp clientthread.cpp
value.cpp value.cpp
@ -15,6 +16,8 @@ set(qtjolie_LIB_SRCS
pendingcall.cpp pendingcall.cpp
pendingcallwatcher.cpp pendingcallwatcher.cpp
pendingreply.cpp pendingreply.cpp
server.cpp
serverthread.cpp
) )
kde4_add_library(QtJolie SHARED ${qtjolie_LIB_SRCS}) kde4_add_library(QtJolie SHARED ${qtjolie_LIB_SRCS})
@ -27,6 +30,7 @@ install(TARGETS QtJolie
set_target_properties(QtJolie PROPERTIES VERSION 1.0.0 SOVERSION 1) set_target_properties(QtJolie PROPERTIES VERSION 1.0.0 SOVERSION 1)
install(FILES install(FILES
abstractadaptor.h
client.h client.h
value.h value.h
fault.h fault.h
@ -35,4 +39,5 @@ install(FILES
pendingcall.h pendingcall.h
pendingcallwatcher.h pendingcallwatcher.h
pendingreply.h pendingreply.h
server.h
DESTINATION ${INCLUDE_INSTALL_DIR}/qtjolie) DESTINATION ${INCLUDE_INSTALL_DIR}/qtjolie)

View File

@ -0,0 +1,40 @@
/**
* This file is part of the KDE project
* Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "abstractadaptor.h"
namespace Jolie
{
class AbstractAdaptorPrivate
{
};
}
using namespace Jolie;
AbstractAdaptor::AbstractAdaptor(QObject *parent)
: d(new AbstractAdaptorPrivate)
{
}
AbstractAdaptor::~AbstractAdaptor()
{
}

View File

@ -0,0 +1,53 @@
/**
* This file is part of the KDE project
* Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef QTJOLIE_ABSTRACTADAPTOR_H
#define QTJOLIE_ABSTRACTADAPTOR_H
#include <QtCore/QObject>
namespace Jolie
{
class AbstractAdaptorPrivate;
class Server;
class ServerPrivate;
class Message;
class Q_DECL_EXPORT AbstractAdaptor : public QObject
{
Q_OBJECT
protected:
AbstractAdaptor(QObject *parent = 0);
public:
~AbstractAdaptor();
private:
virtual Message relay(Server *server, const Message &message) = 0;
friend class ServerPrivate;
AbstractAdaptorPrivate * const d;
};
} // namespace Jolie
#endif

View File

@ -0,0 +1,83 @@
/**
* This file is part of the KDE project
* Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "server.h"
#include "server_p.h"
#include <QtCore/QDebug>
#include "abstractadaptor.h"
#include "serverthread_p.h"
#include "message.h"
#include "pendingcall.h"
#include "pendingreply.h"
using namespace Jolie;
Server::Server(quint16 port)
: d(new ServerPrivate(this))
{
d->serverThread = new ServerThread(port, d);
d->serverThread->start();
}
Server::~Server()
{
delete d->serverThread;
delete d;
}
Server::Error Server::error() const
{
return d->error;
}
QString Server::errorString() const
{
return d->errorString;
}
bool Server::registerAdaptor(const QByteArray &path, AbstractAdaptor *adaptor)
{
if (path.isEmpty() || d->adaptors.contains(path)) {
return false;
}
d->adaptors[path] = adaptor;
}
bool Server::unregisterAdaptor(const QByteArray &path)
{
return d->adaptors.take(path)!=0;
}
void ServerPrivate::messageReceived(int descriptor, const Message &message)
{
if (adaptors.contains(message.resourcePath())) {
Message reply = adaptors[message.resourcePath()]->relay(q, message);
serverThread->sendMessage(descriptor, reply);
} else {
qWarning() << "Got a message for an unregistered object:"
<< message.operationName()
<< "@"
<< message.resourcePath();
}
}

View File

@ -0,0 +1,59 @@
/**
* This file is part of the KDE project
* Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef QTJOLIE_SERVER_H
#define QTJOLIE_SERVER_H
#include <QtCore/QtGlobal>
namespace Jolie
{
class AbstractAdaptor;
class ServerPrivate;
class Message;
class Q_DECL_EXPORT Server
{
public:
enum Error
{
NoError,
UnexpectedClose,
UnkownError
};
explicit Server(quint16 port);
~Server();
Error error() const;
QString errorString() const;
bool registerAdaptor(const QByteArray &path, AbstractAdaptor *adaptor);
bool unregisterAdaptor(const QByteArray &path);
private:
friend class ServerPrivate;
ServerPrivate * const d;
};
} // namespace Jolie
#endif

View File

@ -0,0 +1,60 @@
/**
* This file is part of the KDE project
* Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef QTJOLIE_SERVER_P_H
#define QTJOLIE_SERVER_P_H
#include "server.h"
#include <QtCore/QMap>
#include <QtCore/QObject>
class QIODevice;
namespace Jolie
{
class ServerThread;
class AbstractAdaptor;
class ServerPrivate : public QObject
{
Q_OBJECT
public:
ServerPrivate(Server *server)
: q(server),
error(Server::NoError) {}
public slots:
void messageReceived(int descriptor, const Jolie::Message &message);
private:
friend class Server;
Server * const q;
ServerThread *serverThread;
Server::Error error;
QString errorString;
QMap<QByteArray, AbstractAdaptor*> adaptors;
};
} // namespace Jolie
#endif

View File

@ -0,0 +1,109 @@
/**
* This file is part of the KDE project
* Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "serverthread_p.h"
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QTcpServer>
#include "server_p.h"
#include "message.h"
#include "sodephelpers_p.h"
using namespace Jolie;
ServerThread::ServerThread(quint16 port, ServerPrivate *server)
: QThread(), m_port(port), m_serverSocket(0), m_server(server)
{
moveToThread(this);
}
ServerThread::~ServerThread()
{
quit();
wait();
}
void ServerThread::sendMessage(int descriptor, const Message &message)
{
QMutexLocker locker(&m_mutex);
m_messageQueue.enqueue(QPair<int, Message>(descriptor, message));
QMetaObject::invokeMethod(this, "writeMessageQueue", Qt::QueuedConnection);
}
void ServerThread::writeMessageQueue()
{
QMutexLocker locker(&m_mutex);
while (!m_messageQueue.isEmpty()) {
QPair<int, Message> pair = m_messageQueue.dequeue();
sodepWrite(*m_sockets[pair.first], pair.second);
}
}
void ServerThread::onIncomingConnection()
{
while (m_serverSocket->hasPendingConnections()) {
QAbstractSocket *socket = m_serverSocket->nextPendingConnection();
m_sockets[socket->socketDescriptor()] = socket;
connect(socket, SIGNAL(readyRead()),
this, SLOT(onReadyRead()), Qt::QueuedConnection);
}
}
void ServerThread::onReadyRead()
{
QAbstractSocket *socket = static_cast<QAbstractSocket*>(sender());
readMessage(socket);
}
void ServerThread::readMessage(QAbstractSocket *socket)
{
if (socket->bytesAvailable()==0) {
return;
}
Message message = sodepReadMessage(*socket);
emit messageReceived(socket->socketDescriptor(), message);
if (socket->bytesAvailable()>0) {
QMetaObject::invokeMethod(this, "readMessage", Qt::QueuedConnection, Q_ARG(QAbstractSocket*, socket));
}
}
void ServerThread::run()
{
m_serverSocket = new QTcpServer;
connect(this, SIGNAL(messageReceived(int, Jolie::Message)),
m_server, SLOT(messageReceived(int, Jolie::Message)));
connect(m_serverSocket, SIGNAL(newConnection()),
this, SLOT(onIncomingConnection()), Qt::QueuedConnection);
m_serverSocket->listen(QHostAddress::Any, m_port);
exec();
delete m_serverSocket;
}
#include "serverthread_p.moc"

View File

@ -0,0 +1,76 @@
/**
* This file is part of the KDE project
* Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef QTJOLIE_SERVERTHREAD_P_H
#define QTJOLIE_SERVERTHREAD_P_H
#include <QtCore/QThread>
#include <QtCore/QMap>
#include <QtCore/QMutex>
#include <QtCore/QPair>
#include <QtCore/QQueue>
class QAbstractSocket;
class QTcpServer;
namespace Jolie
{
class Message;
class ServerPrivate;
class ServerThread : public QThread
{
Q_OBJECT
public:
explicit ServerThread(quint16 port, ServerPrivate *server);
~ServerThread();
void run();
void sendMessage(int descriptor, const Message &message);
signals:
void messageReceived(int descriptor, const Jolie::Message &message);
private slots:
void onIncomingConnection();
void onReadyRead();
void readMessage(QAbstractSocket *socket);
void writeMessageQueue();
private:
quint16 m_port;
QTcpServer *m_serverSocket;
QMap<int, QAbstractSocket*> m_sockets;
ServerPrivate *m_server;
QQueue< QPair<int, Message> > m_messageQueue;
QMutex m_mutex;
};
} // namespace Jolie
#endif

View File

@ -25,4 +25,5 @@ SODEP_UNIT_TESTS(
SODEP_EXECUTABLE_TESTS( SODEP_EXECUTABLE_TESTS(
testprinter testprinter
calculatorservice
) )

View File

@ -0,0 +1,21 @@
include "console.iol"
interface CalculatorInterface {
RequestResponse:
add
}
outputPort Calculator {
Location: "socket://localhost:9001/!/Calculator"
Protocol: soap { .debug = 1 }
Interfaces: CalculatorInterface
}
main
{
request.x = 2;
request.y = 3;
add@Calculator( request )( response );
println@Console( response )()
}

View File

@ -0,0 +1,126 @@
/**
* This file is part of the KDE project
* Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QBoxLayout>
#include <QtGui/QTextEdit>
#include <QtNetwork/QTcpSocket>
#include <QtJolie/AbstractAdaptor>
#include <QtJolie/Server>
#include <QtJolie/Message>
#include <QtJolie/MetaService>
#include "testhelpers.h"
using namespace Jolie;
class CalculatorAdaptor : public AbstractAdaptor
{
Q_OBJECT
public:
CalculatorAdaptor(QObject *parent = 0)
: AbstractAdaptor(parent)
{
}
signals:
void added(int a, int b, int result);
private:
Message relay(Server *server, const Message &message)
{
qint32 x = message.data().children("x").first().toInt();
qint32 y = message.data().children("y").first().toInt();
emit added(x, y, x+y);
sodepDump(message);
Message reply(message.resourcePath(),
message.operationName(),
message.id());
reply.setData(Value(x+y));
return reply;
}
};
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow()
{
setLayout(new QHBoxLayout());
m_textEdit = new QTextEdit(this);
layout()->addWidget(m_textEdit);
m_meta.start();
QTimer::singleShot(1000, this, SLOT(delayedInit()));
}
~MainWindow()
{
m_meta.stop();
delete m_server;
}
private slots:
void delayedInit()
{
m_server = new Server(8000);
CalculatorAdaptor *adaptor = new CalculatorAdaptor(this);
connect(adaptor, SIGNAL(added(int, int, int)),
this, SLOT(onAdded(int, int, int)));
m_server->registerAdaptor("/", adaptor);
m_meta.addRedirection(QString::fromUtf8("Calculator"),
QString::fromUtf8("socket://localhost:8000/"),
QString::fromUtf8("sodep"),
QString::fromUtf8("soap"));
}
void onAdded(int a, int b, int result)
{
m_textEdit->append(QString::number(a)
+ QString::fromUtf8(" + ")
+ QString::number(b)
+ QString::fromUtf8(" = ")
+ QString::number(result));
}
private:
MetaService m_meta;
QTextEdit *m_textEdit;
Server *m_server;
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
#include "calculatorservice.moc"