diff -r 5d007b20cfd0 -r cd2778e5acfe qthighway/xqservice/src/xqservicerequest.cpp --- a/qthighway/xqservice/src/xqservicerequest.cpp Tue Aug 31 16:02:37 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,707 +0,0 @@ -/* -* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, version 2.1 of the License. -* -* 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 Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, -* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/". -* -* Description: -* -*/ - -#include "xqservicelog.h" - -#include "xqservicerequest.h" -#include "xqservicethreaddata.h" - -#include "xqservicechannel.h" -#include "xqserviceadaptor.h" -#include "xqrequestutil.h" -#include -#include - -/*! - \class XQServiceRequest_Private - \inpublicgroup QtBaseModule - - \ingroup ipc - \brief Private implementation of the XQServiceRequest. -*/ - -class XQServiceRequest_Private : public XQServiceRequestCompletedAsync -{ -public: - XQServiceRequest_Private(XQServiceRequest* parent) - : mSynchronous(true), mParent(parent),mServiceManager(NULL) - { - XQSERVICE_DEBUG_PRINT("XQServiceRequest_Private::XQServiceRequest_Private(1)"); - - }; - - XQServiceRequest_Private(const QString& fullServiceName, - const QString& message, - const bool &synchronous, - XQServiceRequest* parent) - : mService(fullServiceName), mMessage(message), mSynchronous(synchronous), mParent(parent),mServiceManager(NULL) - { - XQSERVICE_DEBUG_PRINT("XQServiceRequest_Private::XQServiceRequest_Private(2)"); - }; - - XQServiceRequest_Private(const XQAiwInterfaceDescriptor &descriptor, - const QString& message, - const bool &synchronous, - XQServiceRequest* parent) - : mMessage(message), mSynchronous(synchronous), mParent(parent),mServiceManager(NULL) - { - XQSERVICE_DEBUG_PRINT("XQServiceRequest_Private::XQServiceRequest_Private(3)"); - - // Construct service name understood by the QtHighway FW - // (The descriptor has been created from the XML) - mService = descriptor.serviceName() + "." + descriptor.interfaceName(); - XQSERVICE_DEBUG_PRINT("XQServiceRequest_Private(3)::service=%s", qPrintable(mService)); - - // Remember the descriptor - mRequestUtil.mDescriptor = descriptor; - }; - - ~XQServiceRequest_Private(); - // from XQServiceRequestCompletedAsync - void requestCompletedAsync(const QVariant &retValue); - void requestErrorAsync(int err); - - QList mArguments; - QString mService; - QString mMessage; - bool mSynchronous; - XQServiceRequest* mParent; - XQRequestUtil mRequestUtil; - XQServiceManager* mServiceManager; - QString mUniqueChannelName; - -}; - -XQServiceRequest_Private::~XQServiceRequest_Private() -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest_Private::~XQServiceRequest_Private"); - delete mServiceManager; -}; - -void XQServiceRequest_Private::requestCompletedAsync(const QVariant &retValue) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest_Private::requestCompletedAsync"); - emit mParent->requestCompleted(retValue); -} - -void XQServiceRequest_Private::requestErrorAsync(int err) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest_Private::requestErrorAsync"); - emit mParent->requestError(err); -} - -/*! - \class XQServiceRequest - \inpublicgroup QtBaseModule - - \ingroup ipc - \brief Allows applications to request services from other applications. - - The XQServiceRequest class allows applications to request services from other applications. - A XQServiceRequest encapsulates a service name and the message to be sent to that service. - - \note One should be using XQApplicationManager and the related XQAiwRequest instead of XQServiceRequest. - The XQApplicationManager and related classes encapsulate basic, target-architecture approved - support for out-of-process Application Interworking, e.g. support for launching URLs - (including activity URLs), normal files, sharable files, etc. (whatever needed). - - \b Examples: \n - - How to create synchronous request without parameters and return value? - \note The full name (yourservice.Interface) need to be used (with dot (.) between service name and interface name). - - \code - XQServiceRequest request("yourservice.Interface", "functionName1()"); - bool res = request.send(); - if (!res) { - int error = request.latestError(); - } - \endcode - - How to create synchronous request with several parameters and return value? - - \code - QString parameter1("+3581234567890"); - int parameter2 = 3; - XQServiceRequest request("yourservice.Interface", "functionName2(QString, int)"); - request << parameter1; - request << parameter2; - int returnvalue; - bool res = request.send(returnvalue); - if (!res) { - int error = request.latestError(); - } - \endcode - - How to create asynchronous request without return value? - - \code - QString parameter1("+3581234567890"); - int parameter2 = 3; - XQServiceRequest request("yourservice.Interface", "functionName2(QString, int)", false); - request << parameter1; - request << parameter2; - bool res = request.send(); - if (!res) { - int error = request.latestError(); - } - \endcode - - How to create asynchronous request with return value? - - \code - QString parameter1("+3581234567890"); - int parameter2 = 3; - XQServiceRequest request("yourservice.Interface", "functionName2(QString, int)", false); - request << parameter1; - request << parameter2; - connect(request, SIGNAL(requestCompleted(QVariant)), this, SLOT(requestCompleted(QVariant))); - bool res = request.send(); - if (!res) { - int error = request.latestError(); - } - - ... - - void requestCompleted(const QVariant& value) - { - int returnvalue = value.toInt(); - } - \endcode - - How to use declare custom type? - - Header: - \code - class CustomType - { - public: - CustomType (){}; - virtual ~CustomType(){}; - - QString mString1; - QString mString2; - QUuid mUid; - - template void serialize(Stream &stream) const; - template void deserialize(Stream &stream); - }; - - Q_DECLARE_USER_METATYPE(CustomType) - \endcode - - Implementation: - \code - template void CustomType::serialize(Stream &s) const - { - s << mString1; - s << mString2; - s << mUid; - } - - template void CustomType::deserialize(Stream &s) - { - s >> mString1; - s >> mString2; - s >> mUid; - } - - Q_IMPLEMENT_USER_METATYPE(CustomType) - \endcode - - How to declare custom type that doesn't need data stream operators? - - Header: - \code - typedef QList CustomTypeList; - - Q_DECLARE_USER_METATYPE_NO_OPERATORS(CustomTypeList) - \endcode - - Implementation: - \code - Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(CustomTypeList) - \endcode -*/ - -/*! - \fn bool XQServiceRequest::send(T& retValue) - - Sends the request. If the request is synchronous, then client is blocked - until service provider completes the request or request fails for some reason. - If the request is asynchronous, then client won't be blocked. - \param retValue Defines refence to a value service provider will return after service. - \return False if there was no application that could service the request, otherwise true. -*/ - -/*! - \fn XQServiceRequest &XQServiceRequest::operator<< (const T &var) - - Adds \a var to the list of arguments for this service request. - \param var Defines the argument value to add to the list of arguments. -*/ - -/*! - \fn XQServiceRequest &XQServiceRequest::operator<< (const char *var) - - Adds \a var to the list of arguments for this service request. - \param var Defines the argument value to add to the list of arguments. -*/ - -/*! - \fn void XQServiceRequest::requestCompleted(const QVariant& value) - - This signal is emitted when service provider returns a return value asynchronously back to the client. - \param value Result of the request. -*/ - -/*! - \fn void XQServiceRequest::requestError(int err); - - This signal is emitted when error has happened in request handling. - \param err Error code as integer value. - \sa XQService::ServiceIPCErrors -*/ - -/*! - \fn void XQServiceRequest::addVariantArg(const QVariant& var) - - Adds the variant value to the list of arguments, so that the variant's - value is serialized in send() rather than the variant itself. - \param var Value to be added to the list of arguments. -*/ - -/*! - Construct a null service request. - setService() and setMessage() must be called before send(), but the - service may be written prior to the calls. - */ -XQServiceRequest::XQServiceRequest() -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::XQServiceRequest(1)"); - mData = new XQServiceRequest_Private(this); -} - -/*! - Construct a service request that will send \a message to - a \a service when send() is called. The service may be written - prior to the calls. - \param service Defines the full service name to send message. The full name is: - - The name of the service in the service configuration file - - Character *.* (dot) - - The name of the interface from the service XML. - \param message Defines the message to send to the service provider i.e. it is - the signature of the service provider function to be called. - \param synchronous Defines should message be sent synchronously or asynchronously. - By default message is sent synchronously. -*/ -XQServiceRequest::XQServiceRequest(const QString& service, const QString& message, const bool &synchronous) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::XQServiceRequest(2)"); - XQSERVICE_DEBUG_PRINT("service: %s, message: %s, synchronous: %d", qPrintable(service), qPrintable(message), synchronous); - mData = new XQServiceRequest_Private(service,message,synchronous,this); -} - -/*! - Copy constructor. Any data previously written to the \a orig - service will be in the copy. - \param orig XQServiceRequest from which data will be copied to this object. -*/ -XQServiceRequest::XQServiceRequest(const XQServiceRequest& orig) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::XQServiceRequest(3)"); - mData = new XQServiceRequest_Private(orig.mData->mService,orig.mData->mMessage,orig.mData->mSynchronous,this); - mData->mArguments = orig.mData->mArguments; -} - -/*! - Construct a service request by service descriptor which contains exact details of the service and interface. - The service may be written prior to the calls. - \param descriptor Defines details of the service and it's interface. - \param message Message to be sent when send() is called. - \param synchronous Defines should message be sent synchronously or asynchronously. - By default message is sent synchronously. -*/ -XQServiceRequest::XQServiceRequest(const XQAiwInterfaceDescriptor &descriptor, const QString& message, const bool &synchronous) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::XQServiceRequest(2)"); - XQSERVICE_DEBUG_PRINT("service: %s, interface %s, message: %s, synchronous: %d", - qPrintable(descriptor.serviceName()), qPrintable(descriptor.interfaceName()), - qPrintable(message), synchronous); - mData = new XQServiceRequest_Private(descriptor,message,synchronous,this); -} - -/*! - Assignment operator. - Any data previously written to the \a orig - service will be in the copy. -*/ -XQServiceRequest& XQServiceRequest::operator=(const XQServiceRequest& orig) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::operator="); - if( &orig == this ) - return *this; - - mData->mService = orig.mData->mService; - mData->mMessage = orig.mData->mMessage; - mData->mArguments = orig.mData->mArguments; - mData->mRequestUtil = orig.mData->mRequestUtil; - - return *this; -} - -/*! - Destroys the service request. Unlike QtopiaIpcEnvelope, the - request is not automatically sent. -*/ -XQServiceRequest::~XQServiceRequest() -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::~XQServiceRequest %s", qPrintable(mData->mUniqueChannelName)); - XQServiceAdaptor::cancelPendingSend(mData->mUniqueChannelName); - delete mData; -} - -/*! - Checks if request is NULL. - \return True if either the service() or message() is not set. - \sa service(), message() - */ -bool XQServiceRequest::isNull() const -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::isNull"); - bool ret = mData->mService.isEmpty() || mData->mService.isNull() || mData->mMessage.isNull(); - XQSERVICE_DEBUG_PRINT("mData->mService.isEmpty() = %d", mData->mService.isEmpty()); - XQSERVICE_DEBUG_PRINT("mData->mService.isNull() = %d", mData->mService.isNull()); - XQSERVICE_DEBUG_PRINT("mData->mMessage.isNull() = %d", mData->mMessage.isNull()); - XQSERVICE_DEBUG_PRINT("return %d", ret); - return ret; -} - -/*! - Checks if request is synchronous or asynchronous. - \return True if request is synchronous, false if request is asynchronous. - \sa setSynchronous() - */ -bool XQServiceRequest::isSynchronous() const -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::isSynchronous"); - return mData->mSynchronous; -} - -/*! - Sets request to be synchronous or asynchronous. - \param synchronous If set to true, request will be synchronous. - If set to false, request will be asynchronous. - \sa isSynchronous() - */ -void XQServiceRequest::setSynchronous(const bool& synchronous) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::setSynchronous"); - mData->mSynchronous = synchronous; -} -/*! - Sends the request. If the request is synchronous, then client is blocked - until service provider completes the request or request fails for some reason. - If the request is asynchronous, then client won't be blocked. If the request - is asynchronous and clients wants to receive a return value from the service - provider, then clients should connect to the requestCompleted() signal. - \return False if there was no application that could service the request, otherwise true. -*/ -bool XQServiceRequest::send() -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::send(1)"); - QVariant retValue; - return send(retValue); -} - -/*! - Sends the request. If the request is synchronous, then client is blocked - until service provider completes the request or request fails for some reason. - If the request is asynchronous, then client won't be blocked. - \param retData Defines refence to a value service provider will return after service. - \return False if there was no application that could service the request, otherwise true. -*/ -bool XQServiceRequest::send(QVariant& retData) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::send(2)"); - if (isNull()) - { - XQSERVICE_DEBUG_PRINT("XQServiceRequest::send error: null request"); - XQService::serviceThreadData()->setLatestError(XQService::EArgumentError); - return false; - } - - // Handle sharable file argument(s), if any - if (!handleSharableFileArgs()) - { - XQSERVICE_DEBUG_PRINT("XQServiceRequest::send error:invalid sharable file"); - XQService::serviceThreadData()->setLatestError(XQService::EArgumentError); - return false; - } - - mData->mRequestUtil.setSynchronous(mData->mSynchronous); // Ensure option is set ! - mData->mRequestUtil.mOperation = mData->mMessage; // Save the operation name for startup - - // !!! - // Add the info as extra argument to the request - // This shall be removed by the server - // !!! - addArg(qVariantFromValue(mData->mRequestUtil.mInfo)); - - // Pass always the util instance onwards as user data. - // It can be utilized by the XQServiceManager::startServer - // e.g. to optimize startup of a service server - - // Create unique channel name to separate multiple client requests to same channel name. - quint32 handle = (unsigned int)mData; - mData->mUniqueChannelName = QString("%1:").arg(handle) + mData->mService; - XQSERVICE_DEBUG_PRINT("XQServiceRequest::send(2):uniqueChannel=%s", qPrintable(mData->mUniqueChannelName)); - return XQServiceAdaptor::send(mData->mUniqueChannelName, message(), mData->mArguments, retData, mData->mSynchronous,mData, - (const void *)&mData->mRequestUtil); -} -/*! - Sets the full name of the service to which the request will be sent. - \param fullServiceName Full name of the service to send message to. See - XQServiceRequest(const QString& service, const QString& message, const bool &synchronous) - for the full name definition. - \sa service() - */ -void XQServiceRequest::setService(const QString& fullServiceName) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::setService"); - XQSERVICE_DEBUG_PRINT("service: %s", qPrintable(fullServiceName)); - mData->mService = fullServiceName; - mData->mArguments.clear(); - mData->mRequestUtil.mDescriptor = XQAiwInterfaceDescriptor(); // Invalid descriptor -} - -/*! - Gets the service name to which this request will be sent. - \return Full service name to which request will be sent. - \sa setService() -*/ -QString XQServiceRequest::service() const -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::service"); - XQSERVICE_DEBUG_PRINT("service: %s", qPrintable(mData->mService)); - return mData->mService; -} - -/*! - Sets the \a message to be sent to the service. - \param message Defines the message to send to a service provider. The message - is a valid Qt slot signature published by the service provider. - For example, "view(QString)". - \sa message() -*/ -void XQServiceRequest::setMessage(const QString& message) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::setMessage"); - XQSERVICE_DEBUG_PRINT("message: %s", qPrintable(message)); - mData->mMessage = message; - mData->mArguments.clear(); -} - -/*! - Gets the message set for the request. - \return Message of the request as QString. - \sa setMessage() -*/ -QString XQServiceRequest::message() const -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::message"); - XQSERVICE_DEBUG_PRINT("message: %s", qPrintable(mData->mMessage)); - return mData->mMessage; -} - -/*! - Gets the complete list of arguments for this service request. - \return List of arguments set to the request. - \sa setArguments() -*/ -const QList &XQServiceRequest::arguments() const -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::arguments"); - return mData->mArguments; -} - -/*! - Sets \a arguments for this service request. - \param arguments Complete list of arguments for this service request - i.e. the values to be transferred to service provider - function to be called. - \sa arguments() -*/ -void XQServiceRequest::setArguments(const QList &arguments) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::setArguments"); - mData->mArguments = arguments; -} - -/*! - Gets the latest error that happened in the request execution. - \return The latest error that happened in the request execution. - Errors are defined in xqserviceglobal.h. - \sa XQService::ServiceIPCErrors. -*/ -int XQServiceRequest::latestError() - { - XQSERVICE_DEBUG_PRINT("XQServiceRequest::latestError"); - return XQServiceAdaptor::latestError(); - } - -/*! - Sets additional options for the request, like embedding or start to background. - \param info Additional info to be set to the request. - \sa info() -*/ -void XQServiceRequest::setInfo(const XQRequestInfo &info) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::setInfo"); - mData->mRequestUtil.mInfo = info; -} - -/*! - Gets current info set for the request. - \return Info data set to the request. - \sa setInfo() -*/ -XQRequestInfo XQServiceRequest::info() const -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::info"); - return mData->mRequestUtil.mInfo; -} - -/*! - \internal - Adds the variant \a var to the list of arguments, so that the variant's - value is serialized in send() rather than the variant itself. -*/ -void XQServiceRequest::addArg(const QVariant& v) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::addArg %s,%d", v.typeName()); - XQSERVICE_DEBUG_PRINT("v: %s", qPrintable(v.toString())); - mData->mArguments.append(v); -} - -/*! - \internal - Picks the XQSharableFile argument, if any, into the request util - This way scan parameter is listed only once. -*/ -bool XQServiceRequest::handleSharableFileArgs() -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::handleSharableFile"); - - bool ret = true; - mData->mRequestUtil.mSharableFileArgs.clear(); - - for(int i=0; i < mData->mArguments.size(); i++) - { - if (QString(mData->mArguments[i].typeName()) == QString("XQSharableFile")) - { - XQSERVICE_DEBUG_PRINT("XQServiceRequest::sharable file detected"); - // Pick up the sharable file(s) to utility so that no need to scan any more later - XQSharableFile file = mData->mArguments[i].value(); - if (!file.isValid()) - { - // No point to pass invalid file handle onwards - XQSERVICE_DEBUG_PRINT("\t Invalid sharable file"); - ret = false; - break; - } - if (mData->mRequestUtil.mSharableFileArgs.count() > 0) - { - XQSERVICE_DEBUG_PRINT("\t Too many sharable files"); - ret = false; - break; - } - mData->mRequestUtil.mSharableFileArgs.append(file); - XQSERVICE_DEBUG_PRINT("XQServiceRequest::sharable file added"); - } - } - - if (!ret) - { - mData->mRequestUtil.mSharableFileArgs.clear(); - } - - return ret; -} - - -/*! - Serializes all the arguments from the service request. - \param action Defines the request having arguments to be serialized. - \return Serialized arguments in byte array. -*/ -QByteArray XQServiceRequest::serializeArguments(const XQServiceRequest &action) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::serializeArguments"); - QByteArray ret; - QBuffer *buffer = new QBuffer(&ret); - buffer->open(QIODevice::WriteOnly); - QDataStream stream(buffer); - stream << action.mData->mArguments; - - delete buffer; - return ret; -} -/*! - Deserializes all the arguments from the byte array to service request. - \param action Defines the request where arguments are deserialized. - \param data Defines the byte array of serialized arguments. -*/ -void XQServiceRequest::deserializeArguments(XQServiceRequest &action, - const QByteArray &data) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::deserializeArguments"); - QDataStream stream(data); - stream >> action.mData->mArguments; -} - -/*! - Serializes this request to the stream. - \param stream Defines stream this request is serialized to. -*/ -template void XQServiceRequest::serialize(Stream &stream) const -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::serialize"); - stream << mData->mArguments; - stream << mData->mService; - stream << mData->mMessage; - stream << mData->mSynchronous; -} - -/*! - Deserializes this request from the stream. - \param stream Defines the stream this request is deserialized from. -*/ -template void XQServiceRequest::deserialize(Stream &stream) -{ - XQSERVICE_DEBUG_PRINT("XQServiceRequest::deserialize"); - stream >> mData->mArguments; - stream >> mData->mService; - stream >> mData->mMessage; - stream >> mData->mSynchronous; -} - -Q_IMPLEMENT_USER_METATYPE(XQServiceRequest)