1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtSystems module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include <QRegExp>
35#include <QStringList>
36#include <QDebug>
37#ifndef QT_NO_DATASTREAM
38#include <qdatastream.h>
39#endif
40
41#include "qservicefilter.h"
42
43QT_BEGIN_NAMESPACE
44
45class QServiceFilterPrivate
46{
47public:
48 QString interface;
49 QString service;
50 int majorVersion;
51 int minorVersion;
52 QServiceFilter::VersionMatchRule matchingRule;
53 QHash<QString,QString> customAttributes;
54 QStringList capabilities;
55 QServiceFilter::CapabilityMatchRule capMatchingRule;
56};
57
58
59/*!
60 \class QServiceFilter
61
62 \ingroup servicefw
63 \inmodule QtServiceFramework
64 \brief The QServiceFilter class defines criteria for defining a sub-set of
65 all available services.
66
67 A QServiceFilter can be used to constrain the number of services when searching
68 for services. Only those services that match all filter criteria are returned
69 by \l QServiceManager::findInterfaces().
70
71
72 \sa QServiceInterfaceDescriptor, QServiceManager
73*/
74
75/*!
76 \enum QServiceFilter::VersionMatchRule
77
78 This enum describes how interface version matching is performed.
79
80 \value ExactVersionMatch The filter matches any interface implementation that implements
81 the exact version provided.
82 \value MinimumVersionMatch The filter matches any interface implementation that implements
83 either the given major/minor version or any subsequent version.
84*/
85
86/*!
87 \enum QServiceFilter::CapabilityMatchRule
88
89 This enum describes the capability/permission matching rules. Some platforms restrict what services clients
90 can access using "capabilities" or permissions. Services with more capabilities require
91 more privileged clients. Platforms without capabilities may ignore this type of matching
92 rule as the default behavior is to ignore any capability restrictions.
93
94 This is a brief example. Assuming that the system knows the services S1 - S6 which require capabilities as stated below:
95 \table
96 \header \li Service \li Required capabilities
97 \row \li S1 \li \{\}
98 \row \li S2 \li \{A\}
99 \row \li S3 \li \{A,B\}
100 \row \li S4 \li \{A,B,C,D\}
101 \row \li S5 \li \{A,D\}
102 \row \li S6 \li \{F\}
103 \endtable
104
105 The matching rules would apply as follows:
106
107 \table
108 \header \li Matching rule \li Filter's capabilities \li Matching services
109 \row \li MatchLoadable \li \{\} \li S1
110 \row \li MatchLoadable \li \{A\} \li S1, S2
111 \row \li MatchLoadable \li \{A,B,C\} \li S1, S2, S3
112 \row \li MatchMinimum \li \{\} \li S1, S2, S3, S4, S5, S6
113 \row \li MatchMinimum \li \{A\} \li S2, S3, S4, S5
114 \row \li MatchMinimum \li \{A,B,C\} \li S4
115 \endtable
116
117 \value MatchMinimum The filter matches any service that requires at least the given
118 filter capabilities. This may mean that the returned services
119 may require more capabilities than the specified ones.
120 Such a search is equivalent to a wildcard match if the passed filter's capability list is empty. In mathematical set notation
121 this rule is equivalent to Cap\sub{(Filter)} \\ Cap\sub{(Service)} = {}. This is the default matching rule.
122 \value MatchLoadable The filter matches any service that could be loaded by the client.
123 Using this matching rule guarantees that the returned services do not
124 require more capabilites than specified by this rule. It includes services
125 with no capability requirements. If this rule
126 is provided alongside an empty capability search list the returned
127 services do not require any capabilities and thus can be accessed
128 by any client. The equivalent set notation is Cap\sub{(Service)} \\ Cap\sub{(Filter)} = {}.
129*/
130
131/*!
132 Creates a new filter object that matches all service implementations.
133*/
134QServiceFilter::QServiceFilter()
135{
136 d = new QServiceFilterPrivate();
137 d->majorVersion = -1;
138 d->minorVersion = -1;
139 d->matchingRule = QServiceFilter::MinimumVersionMatch;
140 d->capMatchingRule = QServiceFilter::MatchMinimum;
141}
142
143/*!
144 Creates a copy of QServiceFilter object contained in \a other.
145*/
146QServiceFilter::QServiceFilter(const QServiceFilter& other)
147{
148 d = new QServiceFilterPrivate();
149 (*this) = other;
150}
151
152/*!
153 \fn QServiceFilter::QServiceFilter(const QString& interfaceName, const QString& version, QServiceFilter::VersionMatchRule rule)
154
155 Creates a new filter object that matches all service
156 implementations implementing \a interfaceName that match the specified
157 \a version using the given \a rule.
158*/
159QServiceFilter::QServiceFilter(const QString& interfaceName, const QString& version, QServiceFilter::VersionMatchRule rule)
160{
161 d = new QServiceFilterPrivate();
162 d->majorVersion = -1;
163 d->minorVersion = -1;
164 d->matchingRule = QServiceFilter::MinimumVersionMatch;
165 d->capMatchingRule = QServiceFilter::MatchMinimum;
166 setInterface(interfaceName, version, rule);
167}
168
169/*!
170 Destroys this instance of QServiceFilter.
171*/
172QServiceFilter::~QServiceFilter()
173{
174 delete d;
175}
176
177/*!
178 \fn QServiceFilter& QServiceFilter::operator=(const QServiceFilter& other)
179
180 Copies the content of the QServiceFilter object contained in
181 \a other into this one.
182*/
183QServiceFilter& QServiceFilter::operator=(const QServiceFilter& other)
184{
185 if (&other == this)
186 return *this;
187
188 d->interface = other.d->interface;
189 d->service = other.d->service;
190 d->majorVersion = other.d->majorVersion;
191 d->minorVersion = other.d->minorVersion;
192 d->matchingRule = other.d->matchingRule;
193 d->customAttributes = other.d->customAttributes;
194 d->capabilities = other.d->capabilities;
195 d->capMatchingRule = other.d->capMatchingRule;
196
197 return *this;
198}
199
200/*!
201 \fn void QServiceFilter::setServiceName(const QString& serviceName)
202
203 The filter only matches implementations which are provided by the service
204 specified by \a serviceName.
205
206 If the \a serviceName is empty the filter matches any service.
207*/
208void QServiceFilter::setServiceName(const QString& serviceName)
209{
210 d->service = serviceName;
211}
212
213/*!
214 \fn void QServiceFilter::setInterface(const QString &interfaceName, const QString& version, QServiceFilter::VersionMatchRule rule)
215
216 Sets the filter to match any interface implementation that implements
217 \a interfaceName with version \a version. The version is matched
218 according to the given \a rule. If \a version is not set, the filter matches any version of the
219 interface implementation.
220
221 This method does nothing if \a version is not a valid version string or
222 if \a interfaceName is empty.
223
224 A valid version string has the format x.y whereby x and y are positive integer
225 numbers.
226*/
227void QServiceFilter::setInterface(const QString &interfaceName, const QString& version, QServiceFilter::VersionMatchRule rule)
228{
229 //unset interface name
230 if (interfaceName.isEmpty() && version.isEmpty())
231 {
232 d->interface = interfaceName;
233 d->majorVersion = d->minorVersion = -1;
234 d->matchingRule = rule;
235 return;
236 }
237
238 if (interfaceName.isEmpty()) {
239 qWarning() << "Empty interface name. Ignoring filter details";
240 return;
241 }
242
243 if (version.isEmpty()) {
244 d->majorVersion = d->minorVersion = -1;
245 d->matchingRule = rule;
246 d->interface = interfaceName;
247 return;
248 }
249
250 // Match x.y as version format.
251 // This differs from regex in servicemetadata in that 0.x versions are
252 // accepted for the search filter.
253 QRegExp rx(QLatin1String("^(0+|[1-9][0-9]*)\\.(0+|[1-9][0-9]*)$"));
254 int pos = rx.indexIn(str: version);
255 QStringList list = rx.capturedTexts();
256 bool success = false;
257 int temp_major = -1;
258 int temp_minor = -1;
259 if (pos == 0 && list.count() == 3
260 && rx.matchedLength() == version.length() )
261 {
262 temp_major = list[1].toInt(ok: &success);
263 if ( success ) {
264 temp_minor = list[2].toInt(ok: &success);
265 }
266 }
267
268 if (success) {
269 d->majorVersion = temp_major;
270 d->minorVersion = temp_minor;
271 d->interface = interfaceName;
272 d->matchingRule = rule;
273 } else {
274 qWarning() << "Invalid version tag" << version << ". Ignoring filter details.";
275 }
276}
277
278/*!
279 \fn QString QServiceFilter::serviceName() const
280
281 Returns the service name for this filter.
282
283 \sa setServiceName()
284*/
285QString QServiceFilter::serviceName() const
286{
287 return d->service;
288}
289
290/*!
291 \fn QString QServiceFilter::interfaceName() const
292
293 Returns the interface name for this filter.
294
295 \sa setInterface()
296*/
297QString QServiceFilter::interfaceName() const
298{
299 return d->interface;
300}
301
302/*!
303 \fn int QServiceFilter::majorVersion() const
304
305 Returns the major interface version for this filter.
306
307 \sa setInterface()
308*/
309int QServiceFilter::majorVersion() const
310{
311 return d->majorVersion;
312}
313
314/*!
315 \fn int QServiceFilter::minorVersion() const
316
317 Returns the minor interface version for this filter.
318
319 \sa setInterface()
320*/
321int QServiceFilter::minorVersion() const
322{
323 return d->minorVersion;
324}
325
326/*!
327 \fn void QServiceFilter::setCustomAttribute(const QString& key, const QString& value)
328
329 The filter only matches implementations which have the custom attribute
330 \a key with the given \a value. Such constraints are specified via the
331 \e{<customproperty>} tag within the service xml.
332
333 \sa customAttribute(), clearCustomAttribute()
334*/
335void QServiceFilter::setCustomAttribute(const QString& key, const QString& value)
336{
337 d->customAttributes.insert(akey: key, avalue: value);
338}
339
340/*!
341 \fn QString QServiceFilter::customAttribute(const QString& key) const
342
343 Returns the value for the custom attribute \a key; otherwise
344 returns a null string.
345
346 \sa setCustomAttribute(), clearCustomAttribute()
347*/
348QString QServiceFilter::customAttribute(const QString& key) const
349{
350 return d->customAttributes.value(akey: key);
351}
352
353/*!
354 \fn void QServiceFilter::clearCustomAttribute(const QString &key)
355
356 Clears the custom attribute \a key from the filter's set of constraints.
357 If \a key is empty all custom attributes are cleared.
358
359 \sa setCustomAttribute()
360*/
361void QServiceFilter::clearCustomAttribute(const QString &key)
362{
363 if (key.isEmpty())
364 d->customAttributes.clear();
365 else
366 d->customAttributes.remove(akey: key);
367}
368
369/*!
370 \fn QServiceFilter::VersionMatchRule QServiceFilter::versionMatchRule() const
371
372 Returns the version match rule for this filter.
373
374 \sa setInterface()
375*/
376QServiceFilter::VersionMatchRule QServiceFilter::versionMatchRule() const
377{
378 return d->matchingRule;
379}
380
381/*!
382 \fn QList<QString> QServiceFilter::customAttributes() const
383
384 Returns the list of custom keys which have been added to the filter.
385*/
386QStringList QServiceFilter::customAttributes() const
387{
388 return d->customAttributes.keys();
389}
390
391/*!
392 \fn void QServiceFilter::setCapabilities(QServiceFilter::CapabilityMatchRule rule, const QStringList& capabilities )
393
394 Sets the list of \a capabilities which are used to constrain
395 searches for services. The capabilities are matched according
396 to the given \a rule.
397
398 \sa capabilities()
399*/
400void QServiceFilter::setCapabilities(QServiceFilter::CapabilityMatchRule rule, const QStringList& capabilities )
401{
402 d->capMatchingRule = rule;
403 d->capabilities = capabilities;
404}
405
406/*!
407 \fn QStringList QServiceFilter::capabilities() const
408
409 Returns the list of capabilities which are used to limit services searches.
410
411 The filter matches any services that requires the given or less
412 capabilities and thus enabling clients to query for services
413 for which they have the required capabilties.
414
415 \sa setCapabilities(), capabilityMatchRule()
416*/
417QStringList QServiceFilter::capabilities() const
418{
419 return d->capabilities;
420}
421
422/*!
423 Returns the capability matching rule for this filter.
424
425 \sa setCapabilities(), capabilities()
426*/
427QServiceFilter::CapabilityMatchRule QServiceFilter::capabilityMatchRule() const
428{
429 return d->capMatchingRule;
430}
431
432#ifndef QT_NO_DATASTREAM
433/*!
434 \fn QDataStream &operator<<(QDataStream &out, const QServiceFilter &sf)
435 \relates QServiceFilter
436
437 Writes service filter \a sf to the stream \a out and returns a reference
438 to the stream.
439*/
440QDataStream &operator<<(QDataStream &out, const QServiceFilter &sf)
441{
442 const quint32 magicNumber = 0x78AFAFA;
443 const qint32 mj = sf.d->majorVersion;
444 const qint32 mn = sf.d->minorVersion;
445 const qint8 versionrule = (qint32) sf.d->matchingRule;
446 const qint8 caprule = (qint8) sf.d->capMatchingRule;
447 const quint16 majorVersion = 1;
448 const quint16 minorVersion = 0;
449
450 out << magicNumber
451 << majorVersion
452 << minorVersion
453 << sf.d->interface
454 << sf.d->service
455 << mj
456 << mn
457 << versionrule
458 << sf.d->customAttributes
459 << caprule
460 << sf.d->capabilities;
461 return out;
462}
463
464/*!
465 \fn QDataStream &operator>>(QDataStream &in, QServiceFilter &sf)
466 \relates QServiceFilter
467
468 Reads a service filter into \a sf from the stream \a in and returns a
469 reference to the stream.
470*/
471QDataStream &operator>>(QDataStream &in, QServiceFilter &sf)
472{
473 const quint32 magicNumber = 0x78AFAFA;
474 qint32 mj, mn;
475 qint8 versionrule, caprule;
476
477 quint32 storedMagicNumber;
478 in >> storedMagicNumber;
479 if (storedMagicNumber != magicNumber) {
480 qWarning() << Q_FUNC_INFO << "Datastream doesn't provide serialized QServiceFilter";
481 return in;
482 }
483
484 const quint16 currentMajorVersion = 1;
485 quint16 majorVersion = 0;
486 quint16 minorVersion = 0;
487
488 in >> majorVersion >> minorVersion;
489 if (majorVersion != currentMajorVersion) {
490 qWarning() << "Unknown serialization format for QServiceFilter.";
491 return in;
492 }
493 //Allow all minor versions.
494
495 in >> sf.d->interface
496 >> sf.d->service
497 >> mj
498 >> mn
499 >> versionrule
500 >> sf.d->customAttributes
501 >> caprule
502 >> sf.d->capabilities;
503
504 sf.d->majorVersion = mj;
505 sf.d->minorVersion = mn;
506 sf.d->matchingRule = (QServiceFilter::VersionMatchRule) versionrule;
507 sf.d->capMatchingRule = (QServiceFilter::CapabilityMatchRule) caprule;
508
509 return in;
510}
511#endif //QT_NO_DATASTREAM
512
513
514QT_END_NAMESPACE
515
516

source code of qtsystems/src/serviceframework/qservicefilter.cpp