tools/qdbus/src/qdbusmessage.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the tools applications of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qdbusmessage.h"
00025 
00026 #include <qdebug.h>
00027 #include <qstringlist.h>
00028 
00029 #include <dbus/dbus.h>
00030 
00031 #include "qdbusargument_p.h"
00032 #include "qdbuserror.h"
00033 #include "qdbusmessage_p.h"
00034 #include "qdbusmetatype.h"
00035 
00036 static inline const char *data(const QByteArray &arr)
00037 {
00038     return arr.isEmpty() ? 0 : arr.constData();
00039 }
00040 
00041 QDBusMessagePrivate::QDBusMessagePrivate()
00042     : msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID),
00043       timeout(-1), ref(1), delayedReply(false), localMessage(false)
00044 {
00045 }
00046 
00047 QDBusMessagePrivate::~QDBusMessagePrivate()
00048 {
00049     if (msg)
00050         dbus_message_unref(msg);
00051     if (reply)
00052         dbus_message_unref(reply);
00053 }
00054 
00059 QDBusMessage QDBusMessagePrivate::fromError(const QDBusError &error)
00060 {
00061     QDBusMessage message;
00062     message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
00063     message.d_ptr->name = error.name();
00064     message << error.message();
00065     return message;
00066 }
00067 
00073 DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message)
00074 {
00075     DBusMessage *msg = 0;
00076     const QDBusMessagePrivate *d_ptr = message.d_ptr;
00077 
00078     switch (d_ptr->type) {
00079     case DBUS_MESSAGE_TYPE_INVALID:
00080         //qDebug() << "QDBusMessagePrivate::toDBusMessage" <<  "message is invalid";
00081         break;
00082     case DBUS_MESSAGE_TYPE_METHOD_CALL:
00083         msg = dbus_message_new_method_call(data(d_ptr->service.toUtf8()), data(d_ptr->path.toUtf8()),
00084                                            data(d_ptr->interface.toUtf8()), data(d_ptr->name.toUtf8()));
00085         break;
00086     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
00087         if (d_ptr->reply)
00088             msg = dbus_message_new_method_return(d_ptr->reply);
00089         else
00090             qDebug() << "QDBusMessagePrivate::toDBusMessage" << "reply is invalid";
00091         break;
00092     case DBUS_MESSAGE_TYPE_ERROR:
00093         msg = dbus_message_new_error(d_ptr->reply, data(d_ptr->name.toUtf8()), data(d_ptr->message.toUtf8()));
00094         break;
00095     case DBUS_MESSAGE_TYPE_SIGNAL:
00096         msg = dbus_message_new_signal(data(d_ptr->path.toUtf8()), data(d_ptr->interface.toUtf8()),
00097                                       data(d_ptr->name.toUtf8()));
00098         break;
00099     default:
00100         Q_ASSERT(false);
00101         break;
00102     }
00103 #if 0
00104     DBusError err;
00105     dbus_error_init(&err);
00106     if (dbus_error_is_set(&err)) {
00107         QDBusError qe(&err);
00108         qDebug() << "QDBusMessagePrivate::toDBusMessage" << qe;
00109     }
00110 #endif
00111     if (!msg)
00112         return 0;
00113 
00114     QDBusMarshaller marshaller;
00115     QVariantList::ConstIterator it =  d_ptr->arguments.constBegin();
00116     QVariantList::ConstIterator cend = d_ptr->arguments.constEnd();
00117     dbus_message_iter_init_append(msg, &marshaller.iterator);
00118     for ( ; it != cend; ++it)
00119         marshaller.appendVariantInternal(*it);
00120 
00121     // check if everything is ok
00122     if (marshaller.ok)
00123         return msg;
00124 
00125     // not ok;
00126     dbus_message_unref(msg);
00127     Q_ASSERT(false);
00128     return 0;
00129 }
00130 
00131 /*
00132 struct DBusMessage
00133 {
00134     DBusAtomic refcount;
00135     DBusHeader header;
00136     DBusString body;
00137     char byte_order;
00138     unsigned int locked : 1;
00139 DBUS_DISABLE_CHECKS
00140     unsigned int in_cache : 1;
00141 #endif
00142     DBusList *size_counters;
00143     long size_counter_delta;
00144     dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS;
00145     DBusDataSlotList slot_list;
00146 #ifndef DBUS_DISABLE_CHECKS
00147     int generation;
00148 #endif
00149 };
00150 */
00151 
00156 QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg)
00157 {
00158     QDBusMessage message;
00159     if (!dmsg)
00160         return message;
00161 
00162     message.d_ptr->type = dbus_message_get_type(dmsg);
00163     message.d_ptr->path = QString::fromUtf8(dbus_message_get_path(dmsg));
00164     message.d_ptr->interface = QString::fromUtf8(dbus_message_get_interface(dmsg));
00165     message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
00166                       QString::fromUtf8(dbus_message_get_error_name(dmsg)) :
00167                       QString::fromUtf8(dbus_message_get_member(dmsg));
00168     message.d_ptr->service = QString::fromUtf8(dbus_message_get_sender(dmsg));
00169     message.d_ptr->signature = QString::fromUtf8(dbus_message_get_signature(dmsg));
00170     message.d_ptr->msg = dbus_message_ref(dmsg);
00171 
00172     QDBusDemarshaller demarshaller;
00173     demarshaller.message = dbus_message_ref(dmsg);
00174     if (dbus_message_iter_init(demarshaller.message, &demarshaller.iterator))
00175         while (!demarshaller.atEnd())
00176             message << demarshaller.toVariantInternal();
00177     return message;
00178 }
00179 
00180 QDBusMessage QDBusMessagePrivate::updateSignature(const QDBusMessage &message, DBusMessage *dmsg)
00181 {
00182     QDBusMessage messageWithSignature = message; // no signature
00183     QString signature = QString::fromUtf8(dbus_message_get_signature(dmsg));
00184     messageWithSignature.d_ptr->signature = signature;
00185     return messageWithSignature;
00186 }
00187 
00188 void QDBusMessagePrivate::setLocal(const QDBusMessage *message, bool local)
00189 {
00190     Q_ASSERT(message);
00191     message->d_ptr->localMessage = local;
00192 }
00193 
00194 bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
00195 {
00196     return message.d_ptr->localMessage;
00197 }
00198 
00199 void QDBusMessagePrivate::setArguments(const QDBusMessage *message, const QList<QVariant> &arguments)
00200 {
00201     Q_ASSERT(message);
00202     message->d_ptr->arguments = arguments;
00203 }
00204 
00205 void QDBusMessagePrivate::setType(const QDBusMessage *message, QDBusMessage::MessageType type)
00206 {
00207     Q_ASSERT(message);
00208     message->d_ptr->type = type;
00209 }
00210 
00256 QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface,
00257                                         const QString &name)
00258 {
00259     QDBusMessage message;
00260     message.d_ptr->type = DBUS_MESSAGE_TYPE_SIGNAL;
00261     message.d_ptr->path = path;
00262     message.d_ptr->interface = interface;
00263     message.d_ptr->name = name;
00264 
00265     return message;
00266 }
00267 
00287 QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path,
00288                                             const QString &interface, const QString &method)
00289 {
00290     QDBusMessage message;
00291     message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
00292     message.d_ptr->service = service;
00293     message.d_ptr->path = path;
00294     message.d_ptr->interface = interface;
00295     message.d_ptr->name = method;
00296 
00297     return message;
00298 }
00299 
00304 QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg)
00305 {
00306     QDBusMessage error;
00307     error.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
00308     error.d_ptr->name = name;
00309     error.d_ptr->message = msg;
00310 
00311     return error;
00312 }
00313 
00327 QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const
00328 {
00329     QDBusMessage reply;
00330     reply.setArguments(arguments);
00331     reply.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
00332     if (d_ptr->msg)
00333         reply.d_ptr->reply = dbus_message_ref(d_ptr->msg);
00334     else
00335         d_ptr->localMessage = true;
00336     Q_ASSERT(d_ptr->msg || d_ptr->localMessage);
00337     //qDebug() << "QDBusMessagePrivate::createReply" << "message has no dbus message";
00338 
00339     return reply;
00340 }
00341 
00346 QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &msg) const
00347 {
00348     QDBusMessage reply = QDBusMessage::createError(name, msg);
00349     if (d_ptr->msg)
00350         reply.d_ptr->reply = dbus_message_ref(d_ptr->msg);
00351     else
00352         d_ptr->localMessage = true;
00353     Q_ASSERT(d_ptr->msg || d_ptr->localMessage);
00354 
00355     return reply;
00356 }
00357 
00377 QDBusMessage::QDBusMessage()
00378 {
00379     d_ptr = new QDBusMessagePrivate;
00380 }
00381 
00389 QDBusMessage::QDBusMessage(const QDBusMessage &other)
00390 {
00391     d_ptr = other.d_ptr;
00392     d_ptr->ref.ref();
00393 }
00394 
00398 QDBusMessage::~QDBusMessage()
00399 {
00400     if (!d_ptr->ref.deref())
00401         delete d_ptr;
00402 }
00403 
00411 QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
00412 {
00413     qAtomicAssign(d_ptr, other.d_ptr);
00414     return *this;
00415 }
00416 
00420 QString QDBusMessage::service() const
00421 {
00422     return d_ptr->service;
00423 }
00424 
00429 QString QDBusMessage::path() const
00430 {
00431     return d_ptr->path;
00432 }
00433 
00438 QString QDBusMessage::interface() const
00439 {
00440     return d_ptr->interface;
00441 }
00442 
00446 QString QDBusMessage::member() const
00447 {
00448     if (d_ptr->type != ErrorMessage)
00449         return d_ptr->name;
00450     return QString();
00451 }
00452 
00456 QString QDBusMessage::errorName() const
00457 {
00458     if (d_ptr->type == ErrorMessage)
00459         return d_ptr->name;
00460     return QString();
00461 }
00462 
00467 QString QDBusMessage::signature() const
00468 {
00469     return d_ptr->signature;
00470 }
00471 
00478 bool QDBusMessage::isReplyRequired() const
00479 {
00480     if (!d_ptr->msg)
00481         return false;
00482     return dbus_message_get_no_reply(d_ptr->msg);
00483 }
00484 
00499 void QDBusMessage::setDelayedReply(bool enable) const
00500 {
00501     d_ptr->delayedReply = enable;
00502 }
00503 
00509 bool QDBusMessage::isDelayedReply() const
00510 {
00511     return d_ptr->delayedReply;
00512 }
00513 
00520 void QDBusMessage::setArguments(const QList<QVariant> &arguments)
00521 {
00522     d_ptr->arguments = arguments;
00523 }
00524 
00529 QList<QVariant> QDBusMessage::arguments() const
00530 {
00531     return d_ptr->arguments;
00532 }
00533 
00539 QDBusMessage &QDBusMessage::operator<<(const QVariant &arg)
00540 {
00541     d_ptr->arguments.append(arg);
00542     return *this;
00543 }
00544 
00548 QDBusMessage::MessageType QDBusMessage::type() const
00549 {
00550     switch (d_ptr->type) {
00551     case DBUS_MESSAGE_TYPE_METHOD_CALL:
00552         return MethodCallMessage;
00553     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
00554         return ReplyMessage;
00555     case DBUS_MESSAGE_TYPE_ERROR:
00556         return ErrorMessage;
00557     case DBUS_MESSAGE_TYPE_SIGNAL:
00558         return SignalMessage;
00559     default:
00560         break;
00561     }
00562     return InvalidMessage;
00563 }
00564 
00575 #ifndef QT_NO_DEBUG_STREAM
00576 QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
00577 {
00578     switch (t)
00579     {
00580     case QDBusMessage::MethodCallMessage:
00581         return dbg << "MethodCall";
00582     case QDBusMessage::ReplyMessage:
00583         return dbg << "MethodReturn";
00584     case QDBusMessage::SignalMessage:
00585         return dbg << "Signal";
00586     case QDBusMessage::ErrorMessage:
00587         return dbg << "Error";
00588     default:
00589         return dbg << "Invalid";
00590     }
00591 }
00592 
00593 static void debugVariantList(QDebug dbg, const QVariantList &list);
00594 static void debugVariantMap(QDebug dbg, const QVariantMap &map);
00595 
00596 static void debugVariant(QDebug dbg, const QVariant &v)
00597 {
00598     if (v.userType() == qMetaTypeId<QDBusArgument>()) {
00599         dbg.nospace() << "argument of type "
00600                       << qvariant_cast<QDBusArgument>(v).currentSignature();
00601         return;
00602     }
00603     dbg.nospace() << v.typeName() << "(";
00604     switch (v.userType())
00605     {
00606     case QVariant::Bool:
00607         dbg.nospace() << v.toBool();
00608         break;
00609     case QMetaType::UChar:
00610         dbg.nospace() << qvariant_cast<uchar>(v);
00611         break;
00612     case QMetaType::Short:
00613         dbg.nospace() << qvariant_cast<short>(v);
00614         break;
00615     case QMetaType::UShort:
00616         dbg.nospace() << qvariant_cast<ushort>(v);
00617         break;
00618     case QVariant::Int:
00619         dbg.nospace() << v.toInt();
00620         break;
00621     case QVariant::UInt:
00622         dbg.nospace() << v.toUInt();
00623         break;
00624     case QVariant::LongLong:
00625         dbg.nospace() << v.toLongLong();
00626         break;
00627     case QVariant::ULongLong:
00628         dbg.nospace() << v.toULongLong();
00629         break;
00630     case QVariant::Double:
00631         dbg.nospace() << v.toDouble();
00632         break;
00633     case QVariant::String:
00634         dbg.nospace() << v.toString();
00635         break;
00636     case QVariant::ByteArray:
00637         dbg.nospace() << v.toByteArray();
00638         break;
00639     case QVariant::StringList:
00640         dbg.nospace() << v.toStringList();
00641         break;
00642     case QVariant::List:
00643         debugVariantList(dbg, v.toList());
00644         break;
00645     case QVariant::Map:
00646         debugVariantMap(dbg, v.toMap());
00647         break;
00648 
00649     default: {
00650         int id = v.userType();
00651         if (id == qMetaTypeId<QDBusVariant>())
00652             debugVariant(dbg, qvariant_cast<QDBusVariant>(v).variant());
00653         else if (id == qMetaTypeId<QDBusObjectPath>())
00654             dbg.nospace() << qvariant_cast<QDBusObjectPath>(v).path();
00655         else if (id == qMetaTypeId<QDBusSignature>())
00656             dbg.nospace() << qvariant_cast<QDBusSignature>(v).signature();
00657         else
00658             dbg.nospace() << "unknown";
00659     }
00660     }
00661     dbg.nospace() << ")";
00662 }
00663 
00664 static void debugVariantList(QDebug dbg, const QVariantList &list)
00665 {
00666     bool first = true;
00667     QVariantList::ConstIterator it = list.constBegin();
00668     QVariantList::ConstIterator end = list.constEnd();
00669     for ( ; it != end; ++it) {
00670         if (!first)
00671             dbg.nospace() << ", ";
00672         debugVariant(dbg, *it);
00673         first = false;
00674     }
00675 }
00676 
00677 static void debugVariantMap(QDebug dbg, const QVariantMap &map)
00678 {
00679     QVariantMap::ConstIterator it = map.constBegin();
00680     QVariantMap::ConstIterator end = map.constEnd();
00681     for ( ; it != end; ++it) {
00682         dbg << "(" << it.key() << ", ";
00683         debugVariant(dbg, it.value());
00684         dbg.nospace() << ") ";
00685     }
00686 }
00687 
00688 QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
00689 {
00690     dbg.nospace() << "QDBusMessage(type=" << msg.type()
00691                   << ", service=" << msg.service()
00692                   << ", path=" << msg.path()
00693                   << ", interface=" << msg.interface()
00694                   << ", member=" << msg.member()
00695                   << ", signature=" << msg.signature()
00696                   << ", contents=(";
00697     debugVariantList(dbg, msg.arguments());
00698     dbg.nospace() << ") )";
00699     return dbg.space();
00700 }
00701 #endif
00702 

Generated on Thu Mar 15 12:03:08 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1