summaryrefslogtreecommitdiffstats
path: root/src/serviceframework/qserviceinterfacedescriptor.cpp
blob: a9b9f40b95ed176f2682c97e0ec8ccc2ced44947 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSystems module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qserviceinterfacedescriptor_p.h"
#ifndef QT_NO_DATASTREAM
#include <qdatastream.h>
#endif

#include <QDebug>
#include <QStringList>

QT_BEGIN_NAMESPACE

/*!
    \class QServiceInterfaceDescriptor
    \ingroup servicefw
    \inmodule QtServiceFramework
    \brief The QServiceInterfaceDescriptor class identifies a service implementation.

    A service can implement multiple interfaces and each interface can have multiple implementations.
    The QServiceInterfaceDescriptor class enscapsulates this information, as illustrated
    by the diagram below.

    \image qserviceinterfacedescriptor.png Service-Interface-Implementation

    The major version tag indicates the interface version and the minor version tag identifies the implementation
    version. Subsequent versions of the same interface must be binary compatible to previous versions
    of the same interface.

    In the above example service A and B implement the interface \e com.nokia.qt.x.
    In fact Service A provides two different implementations for the very same interface.
    This is indicated by the changed minor version number. Although Service B is
    using the same interface it's implementation actually utilizes the second version of
    the interface \e com.nokia.qt.x. Binary compatibility guarantees that clients
    who know version 1 can utilize version 2. If an existing interface has to be changed
    in a non-compatible way a new interface (name) is required.

    \section1 Namespaces

    A QServiceInterfaceDescriptor (the quadruble of service name,
    interface name, interface version and implementation version) uniquely
    identifies a service implementation on a device. Interface names follow
    the java namespace convention.

    The namespace \e com.nokia.qt.* is reserved for future Qt development.

    \sa QServiceFilter, QServiceManager
*/

/*!
    \enum QServiceInterfaceDescriptor::Attribute

    This enum describes the possible attribute types which can be attached
    to a QServiceInterfaceDescriptor.

    \value      Capabilities            The capabilities attribute is a QStringList and
                                        describes the capabilities that a service client
                                        would require to use the service if capability
                                        checks are enforced.
    \value      Location                This attribute points to either the location
                                        where the plug-in providing this service is stored or
                                        where the name of the service IPC path is found.
                                        If the service is plug-in based the location is the
                                        name and/or path of the plugin. If the service is
                                        IPC based the location is the name of the socket address.
    \value      ServiceDescription      This attribute provides a general description for
                                        the service.
    \value      InterfaceDescription    This attribute provides a description for the interface
                                        implementation.
    \value      ServiceType             This attribute specifies the QService::Type that the
                                        service is being provided.
*/

/*!
    Creates a new QServiceInterfaceDescriptor.
*/
QServiceInterfaceDescriptor::QServiceInterfaceDescriptor()
    :  d(0)
{
}

/*!
    Destroys the QServiceInterfaceDescriptor object.
*/
QServiceInterfaceDescriptor::~QServiceInterfaceDescriptor()
{
    if (d)
        delete d;
}

/*!
    Creates a copy of QServiceInterfaceDescriptor contained in \a other.
*/
QServiceInterfaceDescriptor::QServiceInterfaceDescriptor(const QServiceInterfaceDescriptor& other)
    : d(0)
{
    (*this) = other; //use assignment operator
}

/*!
    \fn  QServiceInterfaceDescriptor& QServiceInterfaceDescriptor::operator=(const QServiceInterfaceDescriptor& other)

    Copies the content of the QServiceInterfaceDescriptor object contained
    in \a other into this one.
*/
QServiceInterfaceDescriptor& QServiceInterfaceDescriptor::operator=(const QServiceInterfaceDescriptor& other)
{
    if (&other == this)
        return *this;

    if ( !other.isValid() ) {
        if (d)
            delete d;
        d = 0;
        return *this;
    }

    if (!d)
        d = new QServiceInterfaceDescriptorPrivate;

    (*d) = *(other.d);
    return *this;
}

/*!
    \fn bool QServiceInterfaceDescriptor::operator==(const QServiceInterfaceDescriptor& other) const

    Compares a QServiceInterfaceDescriptor to \a other. Returns true if they
    are equal and false otherwise.
*/
bool QServiceInterfaceDescriptor::operator==(const QServiceInterfaceDescriptor& other) const
{
    if (isValid() ^ other.isValid())
        return false;

    if (!d)
        return true;

    if ((*d) == *(other.d))
        return true;
    return false;
}

/*!
    \fn bool QServiceInterfaceDescriptor::operator!=(const QServiceInterfaceDescriptor& other) const

    Compares a QServiceInterfaceDescriptor to \a other. Returns true
    if they are not equal and false otherwise.
*/

/*!
    \fn bool QServiceInterfaceDescriptor::isValid() const

    Returns true if this descriptor is valid; otherwise returns false.
*/
bool QServiceInterfaceDescriptor::isValid() const
{
    return d ? true : false;
}

/*!
    \fn  bool QServiceInterfaceDescriptor::scope() const

    Returns true if this implementation is provided for all users on the system.

    \sa QService::Scope
*/
QService::Scope QServiceInterfaceDescriptor::scope() const
{
    return d ? d->scope : QService::UserScope;
}

/*!
    \fn  QString QServiceInterfaceDescriptor::serviceName() const

    Returns the name of service that provides this implementation.
*/
QString QServiceInterfaceDescriptor::serviceName() const
{
    return d ? d->serviceName : QString();
}

/*!
    \fn  QString QServiceInterfaceDescriptor::interfaceName() const

    Returns the name of the interface that is implemented.
*/
QString QServiceInterfaceDescriptor::interfaceName() const
{
    return d ? d->interfaceName : QString();
}

/*!
    \fn  int QServiceInterfaceDescriptor::majorVersion() const

    Returns the version of the interface.

    Subsequent versions of an interface are binary compatible
    to previous versions of the same interface. If an interface
    is broken it must use a new interface name.
*/
int QServiceInterfaceDescriptor::majorVersion() const
{
    return d ? d->major : -1;
}

/*!
    \fn  int QServiceInterfaceDescriptor::minorVersion() const

    Returns the version of the implementation.
*/
int QServiceInterfaceDescriptor::minorVersion() const
{
    return d ? d->minor : -1;
}

/*!
    \fn  QVariant QServiceInterfaceDescriptor::attribute(QServiceInterfaceDescriptor::Attribute which) const

    Returns the value for the attribute \a which; otherwise returns
    an invalid QVariant.
*/
QVariant QServiceInterfaceDescriptor::attribute(QServiceInterfaceDescriptor::Attribute which) const
{
    if (d)
        return d->attributes.value(which);
    return QVariant();
}

/*!
    \fn  QString QServiceInterfaceDescriptor::customAttribute(const QString& which) const

    Returns the value for the custom attribute \a which; otherwise
    returns a null string.
*/
QString QServiceInterfaceDescriptor::customAttribute(const QString& which) const
{
    if (d)
        return d->customAttributes[which];
    return QString();
}

/*!
  Returns a list of custom attributes attached to the service.
 */
QStringList QServiceInterfaceDescriptor::customAttributes() const
{
    if (d)
        return d->customAttributes.keys();
    return QStringList();
}

#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QServiceInterfaceDescriptor &desc)
{
    if (desc.isValid()) {
        QString serviceInterface = QString(QLatin1String("%1 %2.%3")).arg(desc.interfaceName())
                .arg(desc.majorVersion() < 0 ? '?' : desc.majorVersion())
                .arg(desc.minorVersion() < 0 ? '?' : desc.minorVersion());
        dbg.nospace() << "QServiceInterfaceDescriptor(";
        dbg.nospace() << "service=" << desc.serviceName() << ", ";
        dbg.nospace() << "interface=" << serviceInterface;
        dbg.nospace() << ")";
    } else {
        dbg.nospace() << "QServiceInterfaceDescriptor(invalid)";
    }
    return dbg.space();
}
#endif

#ifndef QT_NO_DATASTREAM

QDataStream &operator<<(QDataStream &out, const QServiceInterfaceDescriptor::Attribute &k)
{
    out << qint8(k);
    return out;
}

QDataStream &operator>>(QDataStream &in, QServiceInterfaceDescriptor::Attribute &k)
{
    quint8 key;
    in >> key;
    k = (QServiceInterfaceDescriptor::Attribute)key;
    return in;
}
/*!
    \fn QDataStream &operator<<(QDataStream &out, const QServiceInterfaceDescriptor &dc)
    \relates QServiceInterfaceDescriptor

    Writes service interface descriptor \a dc to the stream \a out and returns a reference
    to the stream.
*/

QDataStream &operator<<(QDataStream &out, const QServiceInterfaceDescriptor &dc)
{
    const quint32 magicNumber = 0x77AFAFA;
    const quint16 majorVersion = 1;
    const quint16 minorVersion = 0;
    const qint8 valid = dc.isValid();
    out << magicNumber << majorVersion << minorVersion;
    out << valid;
    if (valid) {
       out << dc.d->serviceName;
       out << dc.d->interfaceName;
       out << dc.d->major;
       out << dc.d->minor;
       out << dc.d->attributes;
       out << dc.d->customAttributes;
       out << (qint8)dc.d->scope;
    }
    return out;
}

/*!
    \fn QDataStream &operator>>(QDataStream &in, QServiceInterfaceDescriptor &dc)
    \relates QServiceInterfaceDescriptor

    Reads a service interface descriptor into \a dc from the stream \a in and returns a
    reference to the stream.
*/
QDataStream &operator>>(QDataStream &in, QServiceInterfaceDescriptor &dc)
{
    const quint32 magicNumber = 0x77AFAFA;
    quint32 storedMagicNumber;
    in >> storedMagicNumber;
    if (storedMagicNumber != magicNumber) {
        qWarning() << "Datastream doesn't provide searialized QServiceInterfaceDescriptor";
        return in;
    }

    const quint16 currentMajorVersion = 1;
    quint16 majorVersion = 0;
    quint16 minorVersion = 0;

    in >> majorVersion >> minorVersion;
    if (majorVersion != currentMajorVersion) {
        qWarning() << "Unknown serialization format for QServiceInterfaceDescriptor.";
        return in;
    }
    //Allow all minor versions.

    qint8 valid;
    in >> valid;
    if (valid) {
        if (!dc.isValid())
            dc.d = new QServiceInterfaceDescriptorPrivate;
        in >> dc.d->serviceName;
        in >> dc.d->interfaceName;
        in >> dc.d->major;
        in >> dc.d->minor;
        in >> dc.d->attributes;
        in >> dc.d->customAttributes;
        in >> valid;
        dc.d->scope = (QService::Scope) valid;
    } else { //input stream contains invalid descriptor
        //use assignment operator
        dc = QServiceInterfaceDescriptor();
    }

    return in;
}
#endif //QT_NO_DATASTREAM



QT_END_NAMESPACE