From d99e623ae9ded50d0e8933f2f0e64920e98b9b10 Mon Sep 17 00:00:00 2001 From: Kevin Ottens Date: Fri, 5 Jun 2009 22:51:08 +0000 Subject: [PATCH] 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 --- .../qtjolie-branch/includes/CMakeLists.txt | 2 + .../includes/QtJolie/AbstractAdaptor | 2 + .../qtjolie-branch/includes/QtJolie/Server | 2 + private/qtjolie-branch/qtjolie/CMakeLists.txt | 5 + .../qtjolie/abstractadaptor.cpp | 40 ++++++ .../qtjolie-branch/qtjolie/abstractadaptor.h | 53 ++++++++ private/qtjolie-branch/qtjolie/server.cpp | 83 ++++++++++++ private/qtjolie-branch/qtjolie/server.h | 59 ++++++++ private/qtjolie-branch/qtjolie/server_p.h | 60 +++++++++ .../qtjolie-branch/qtjolie/serverthread.cpp | 109 +++++++++++++++ .../qtjolie-branch/qtjolie/serverthread_p.h | 76 +++++++++++ private/qtjolie-branch/tests/CMakeLists.txt | 1 + .../qtjolie-branch/tests/calculatorclient.ol | 21 +++ .../tests/calculatorservice.cpp | 126 ++++++++++++++++++ 14 files changed, 639 insertions(+) create mode 100644 private/qtjolie-branch/includes/QtJolie/AbstractAdaptor create mode 100644 private/qtjolie-branch/includes/QtJolie/Server create mode 100644 private/qtjolie-branch/qtjolie/abstractadaptor.cpp create mode 100644 private/qtjolie-branch/qtjolie/abstractadaptor.h create mode 100644 private/qtjolie-branch/qtjolie/server.cpp create mode 100644 private/qtjolie-branch/qtjolie/server.h create mode 100644 private/qtjolie-branch/qtjolie/server_p.h create mode 100644 private/qtjolie-branch/qtjolie/serverthread.cpp create mode 100644 private/qtjolie-branch/qtjolie/serverthread_p.h create mode 100644 private/qtjolie-branch/tests/calculatorclient.ol create mode 100644 private/qtjolie-branch/tests/calculatorservice.cpp diff --git a/private/qtjolie-branch/includes/CMakeLists.txt b/private/qtjolie-branch/includes/CMakeLists.txt index 95e741b69..6bfdcf7b6 100644 --- a/private/qtjolie-branch/includes/CMakeLists.txt +++ b/private/qtjolie-branch/includes/CMakeLists.txt @@ -1,4 +1,5 @@ install( FILES + QtJolie/AbstractAdaptor QtJolie/Client QtJolie/Fault QtJolie/Message @@ -6,5 +7,6 @@ install( FILES QtJolie/PendingCall QtJolie/PendingCallWatcher QtJolie/PendingReply + QtJolie/Server QtJolie/Value DESTINATION ${INCLUDE_INSTALL_DIR}/QtJolie COMPONENT Devel) diff --git a/private/qtjolie-branch/includes/QtJolie/AbstractAdaptor b/private/qtjolie-branch/includes/QtJolie/AbstractAdaptor new file mode 100644 index 000000000..978d9fab3 --- /dev/null +++ b/private/qtjolie-branch/includes/QtJolie/AbstractAdaptor @@ -0,0 +1,2 @@ +#include "../qtjolie/abstractadaptor.h" + diff --git a/private/qtjolie-branch/includes/QtJolie/Server b/private/qtjolie-branch/includes/QtJolie/Server new file mode 100644 index 000000000..299f3ddf9 --- /dev/null +++ b/private/qtjolie-branch/includes/QtJolie/Server @@ -0,0 +1,2 @@ +#include "../qtjolie/server.h" + diff --git a/private/qtjolie-branch/qtjolie/CMakeLists.txt b/private/qtjolie-branch/qtjolie/CMakeLists.txt index 89887b4f4..e7e2691f3 100644 --- a/private/qtjolie-branch/qtjolie/CMakeLists.txt +++ b/private/qtjolie-branch/qtjolie/CMakeLists.txt @@ -6,6 +6,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDE_DIR}) set(qtjolie_LIB_SRCS + abstractadaptor.cpp client.cpp clientthread.cpp value.cpp @@ -15,6 +16,8 @@ set(qtjolie_LIB_SRCS pendingcall.cpp pendingcallwatcher.cpp pendingreply.cpp + server.cpp + serverthread.cpp ) 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) install(FILES + abstractadaptor.h client.h value.h fault.h @@ -35,4 +39,5 @@ install(FILES pendingcall.h pendingcallwatcher.h pendingreply.h + server.h DESTINATION ${INCLUDE_INSTALL_DIR}/qtjolie) diff --git a/private/qtjolie-branch/qtjolie/abstractadaptor.cpp b/private/qtjolie-branch/qtjolie/abstractadaptor.cpp new file mode 100644 index 000000000..fcfc597a8 --- /dev/null +++ b/private/qtjolie-branch/qtjolie/abstractadaptor.cpp @@ -0,0 +1,40 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2009 Kevin Ottens + * + * 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() +{ +} diff --git a/private/qtjolie-branch/qtjolie/abstractadaptor.h b/private/qtjolie-branch/qtjolie/abstractadaptor.h new file mode 100644 index 000000000..fb7a3416c --- /dev/null +++ b/private/qtjolie-branch/qtjolie/abstractadaptor.h @@ -0,0 +1,53 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2009 Kevin Ottens + * + * 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 + +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 + diff --git a/private/qtjolie-branch/qtjolie/server.cpp b/private/qtjolie-branch/qtjolie/server.cpp new file mode 100644 index 000000000..9750a8921 --- /dev/null +++ b/private/qtjolie-branch/qtjolie/server.cpp @@ -0,0 +1,83 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2009 Kevin Ottens + * + * 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 + +#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(); + } +} + diff --git a/private/qtjolie-branch/qtjolie/server.h b/private/qtjolie-branch/qtjolie/server.h new file mode 100644 index 000000000..2855ecef3 --- /dev/null +++ b/private/qtjolie-branch/qtjolie/server.h @@ -0,0 +1,59 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2009 Kevin Ottens + * + * 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 + +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 + diff --git a/private/qtjolie-branch/qtjolie/server_p.h b/private/qtjolie-branch/qtjolie/server_p.h new file mode 100644 index 000000000..56a1ca421 --- /dev/null +++ b/private/qtjolie-branch/qtjolie/server_p.h @@ -0,0 +1,60 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2009 Kevin Ottens + * + * 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 +#include + +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 adaptors; +}; + +} // namespace Jolie + +#endif + diff --git a/private/qtjolie-branch/qtjolie/serverthread.cpp b/private/qtjolie-branch/qtjolie/serverthread.cpp new file mode 100644 index 000000000..48e506706 --- /dev/null +++ b/private/qtjolie-branch/qtjolie/serverthread.cpp @@ -0,0 +1,109 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2009 Kevin Ottens + * + * 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 +#include + +#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(descriptor, message)); + QMetaObject::invokeMethod(this, "writeMessageQueue", Qt::QueuedConnection); +} + +void ServerThread::writeMessageQueue() +{ + QMutexLocker locker(&m_mutex); + + while (!m_messageQueue.isEmpty()) { + QPair 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(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" diff --git a/private/qtjolie-branch/qtjolie/serverthread_p.h b/private/qtjolie-branch/qtjolie/serverthread_p.h new file mode 100644 index 000000000..e96a3ee5b --- /dev/null +++ b/private/qtjolie-branch/qtjolie/serverthread_p.h @@ -0,0 +1,76 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2009 Kevin Ottens + * + * 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 +#include +#include +#include +#include + +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 m_sockets; + + ServerPrivate *m_server; + + QQueue< QPair > m_messageQueue; + + QMutex m_mutex; +}; + +} // namespace Jolie + +#endif + diff --git a/private/qtjolie-branch/tests/CMakeLists.txt b/private/qtjolie-branch/tests/CMakeLists.txt index aef783ebd..467a9d551 100644 --- a/private/qtjolie-branch/tests/CMakeLists.txt +++ b/private/qtjolie-branch/tests/CMakeLists.txt @@ -25,4 +25,5 @@ SODEP_UNIT_TESTS( SODEP_EXECUTABLE_TESTS( testprinter + calculatorservice ) diff --git a/private/qtjolie-branch/tests/calculatorclient.ol b/private/qtjolie-branch/tests/calculatorclient.ol new file mode 100644 index 000000000..da796997d --- /dev/null +++ b/private/qtjolie-branch/tests/calculatorclient.ol @@ -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 )() +} diff --git a/private/qtjolie-branch/tests/calculatorservice.cpp b/private/qtjolie-branch/tests/calculatorservice.cpp new file mode 100644 index 000000000..286a61128 --- /dev/null +++ b/private/qtjolie-branch/tests/calculatorservice.cpp @@ -0,0 +1,126 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2009 Kevin Ottens + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#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"