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
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
|
/*
* Copyright (C) 2005-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#pragma once
#include "JSONUtils.h"
#include "utils/Variant.h"
#include <limits>
#include <memory>
#include <string>
#include <vector>
namespace JSONRPC
{
class JSONSchemaTypeDefinition;
typedef std::shared_ptr<JSONSchemaTypeDefinition> JSONSchemaTypeDefinitionPtr;
/*!
\ingroup jsonrpc
\brief Class for a parameter of a
json rpc method.
Represents a parameter of a defined
json rpc method and is used to verify
and extract the value of the parameter
in a method call.
*/
class JSONSchemaTypeDefinition : protected CJSONUtils
{
public:
JSONSchemaTypeDefinition();
bool Parse(const CVariant &value, bool isParameter = false);
JSONRPC_STATUS Check(const CVariant& value, CVariant& outputValue, CVariant& errorData) const;
void Print(bool isParameter, bool isGlobal, bool printDefault, bool printDescriptions, CVariant &output) const;
void ResolveReference();
std::string missingReference;
/*!
\brief Name of the parameter (for
by-name calls)
*/
std::string name;
/*!
\brief Id of the type (for
referenced types)
Renamed from "id" because of possible
issues with Objective-C.
*/
std::string ID;
/*!
\brief Referenced object
*/
JSONSchemaTypeDefinitionPtr referencedType;
/*!
\brief Whether the type has been set
based on the referenced type
*/
bool referencedTypeSet = false;
/*!
\brief Array of reference types
which are extended by this type.
*/
std::vector<JSONSchemaTypeDefinitionPtr> extends;
/*!
\brief Description of the parameter
*/
std::string description;
/*!
\brief JSON schema type of the parameter's value
*/
JSONSchemaType type = AnyValue;
/*!
\brief JSON schema type definitions in case
of a union type
*/
std::vector<JSONSchemaTypeDefinitionPtr> unionTypes;
/*!
\brief Whether or not the parameter is
optional
*/
bool optional = true;
/*!
\brief Default value of the parameter
(only needed when it is optional)
*/
CVariant defaultValue;
/*!
\brief Minimum value for Integer
or Number types
*/
double minimum;
/*!
\brief Maximum value for Integer or Number types
*/
double maximum;
/*!
\brief Whether to exclude the defined Minimum
value from the valid range or not
*/
bool exclusiveMinimum = false;
/*!
\brief Whether to exclude the defined Maximum
value from the valid range or not
*/
bool exclusiveMaximum = false;
/*!
\brief Integer by which the value (of type
Integer) must be divisible without rest
*/
unsigned int divisibleBy = 0;
/*!
\brief Minimum length for String types
*/
int minLength = -1;
/*!
\brief Maximum length for String types
*/
int maxLength = -1;
/*!
\brief (Optional) List of allowed values
for the type
*/
std::vector<CVariant> enums;
/*!
\brief List of possible values in an array
*/
std::vector<JSONSchemaTypeDefinitionPtr> items;
/*!
\brief Minimum amount of items in the array
*/
unsigned int minItems = 0;
/*!
\brief Maximum amount of items in the array
*/
unsigned int maxItems = 0;
/*!
\brief Whether every value in the array
must be unique or not
*/
bool uniqueItems = false;
/*!
\brief List of json schema definitions for
additional items in an array with tuple
typing (defined schemas in "items")
*/
std::vector<JSONSchemaTypeDefinitionPtr> additionalItems;
/*!
\brief Maps a properties name to its
json schema type definition
*/
class CJsonSchemaPropertiesMap
{
public:
CJsonSchemaPropertiesMap();
void add(const JSONSchemaTypeDefinitionPtr& property);
typedef std::map<std::string, JSONSchemaTypeDefinitionPtr>::const_iterator JSONSchemaPropertiesIterator;
JSONSchemaPropertiesIterator begin() const;
JSONSchemaPropertiesIterator find(const std::string& key) const;
JSONSchemaPropertiesIterator end() const;
unsigned int size() const;
private:
std::map<std::string, JSONSchemaTypeDefinitionPtr> m_propertiesmap;
};
/*!
\brief List of properties of the parameter (only needed when the
parameter is an object)
*/
CJsonSchemaPropertiesMap properties;
/*!
\brief Whether the type can have additional properties
or not
*/
bool hasAdditionalProperties = false;
/*!
\brief Type definition for additional properties
*/
JSONSchemaTypeDefinitionPtr additionalProperties;
};
/*!
\ingroup jsonrpc
\brief Structure for a published json
rpc method.
Represents a published json rpc method
and is used to verify an incoming json
rpc request against a defined method.
*/
class JsonRpcMethod : protected CJSONUtils
{
public:
JsonRpcMethod();
bool Parse(const CVariant &value);
JSONRPC_STATUS Check(const CVariant &requestParameters, ITransportLayer *transport, IClient *client, bool notification, MethodCall &methodCall, CVariant &outputParameters) const;
std::string missingReference;
/*!
\brief Name of the represented method
*/
std::string name;
/*!
\brief Pointer tot he implementation
of the represented method
*/
MethodCall method;
/*!
\brief Definition of the type of
request/response
*/
TransportLayerCapability transportneed = Response;
/*!
\brief Definition of the permissions needed
to execute the method
*/
OperationPermission permission = ReadData;
/*!
\brief Description of the method
*/
std::string description;
/*!
\brief List of accepted parameters
*/
std::vector<JSONSchemaTypeDefinitionPtr> parameters;
/*!
\brief Definition of the return value
*/
JSONSchemaTypeDefinitionPtr returns;
private:
bool parseParameter(const CVariant& value, const JSONSchemaTypeDefinitionPtr& parameter);
bool parseReturn(const CVariant &value);
static JSONRPC_STATUS checkParameter(const CVariant& requestParameters,
const JSONSchemaTypeDefinitionPtr& type,
unsigned int position,
CVariant& outputParameters,
unsigned int& handled,
CVariant& errorData);
};
/*!
\ingroup jsonrpc
\brief Structure mapping a json rpc method
definition to an actual method implementation.
*/
typedef struct
{
/*!
\brief Name of the json rpc method.
*/
std::string name;
/*!
\brief Pointer to the actual
implementation of the json rpc
method.
*/
MethodCall method;
} JsonRpcMethodMap;
/*!
\ingroup jsonrpc
\brief Helper class for json schema service descriptor based
service descriptions for the json rpc API
Provides static functions to parse a complete json schema
service descriptor of a published service containing json rpc
methods, print the json schema service descriptor representation
into a string (mainly for output purposes) and evaluate and verify
parameters provided in a call to one of the publish json rpc methods
against a parameter definition parsed from a json schema service
descriptor.
*/
class CJSONServiceDescription : public CJSONUtils
{
friend class JSONSchemaTypeDefinition;
friend class JsonRpcMethod;
public:
/*!
\brief Parses the given json schema description and evaluates
and stores the defined type
\param jsonType json schema description to parse
\return True if the json schema description has been parsed successfully otherwise false
*/
static bool AddType(const std::string &jsonType);
/*!
\brief Parses the given json schema description and evaluates
and stores the defined method
\param jsonMethod json schema description to parse
\param method pointer to the implementation
\return True if the json schema description has been parsed successfully otherwise false
*/
static bool AddMethod(const std::string &jsonMethod, MethodCall method);
/*!
\brief Parses the given json schema description and evaluates
and stores the defined builtin method
\param jsonMethod json schema description to parse
\return True if the json schema description has been parsed successfully otherwise false
*/
static bool AddBuiltinMethod(const std::string &jsonMethod);
/*!
\brief Parses the given json schema description and evaluates
and stores the defined notification
\param jsonNotification json schema description to parse
\return True if the json schema description has been parsed successfully otherwise false
*/
static bool AddNotification(const std::string &jsonNotification);
static bool AddEnum(const std::string &name, const std::vector<CVariant> &values, CVariant::VariantType type = CVariant::VariantTypeNull, const CVariant &defaultValue = CVariant::ConstNullVariant);
static bool AddEnum(const std::string &name, const std::vector<std::string> &values);
static bool AddEnum(const std::string &name, const std::vector<int> &values);
/*!
\brief Gets the version of the json
schema description
\return Version of the json schema description
*/
static const char* GetVersion();
/*!
\brief Prints the json schema description into the given result object
\param result Object into which the json schema description is printed
\param transport Transport layer capabilities
\param client Client requesting a print
\param printDescriptions Whether to print descriptions or not
\param printMetadata Whether to print XBMC specific data or not
\param filterByTransport Whether to filter by transport or not
*/
static JSONRPC_STATUS Print(CVariant &result, ITransportLayer *transport, IClient *client, bool printDescriptions = true, bool printMetadata = false, bool filterByTransport = true, const std::string &filterByName = "", const std::string &filterByType = "", bool printReferences = true);
/*!
\brief Checks the given parameters from the request against the
json schema description for the given method
\param method Called method
\param requestParameters Parameters from the request
\param client Client who sent the request
\param notification Whether the request was sent as a notification or not
\param methodCall Object which will contain the actual C/C++ method to be called
\param outputParameters Cleaned up parameter list
\return OK if the validation of the request succeeded otherwise an appropriate error code
Checks if the given method is a valid json rpc method, if the client has the permission
to call this method, if the method can be called as a notification or not, assigns the
actual C/C++ implementation of the method to the "methodCall" parameter and checks the
given parameters from the request against the json schema description for the given method.
*/
static JSONRPC_STATUS CheckCall(const char* method, const CVariant &requestParameters, ITransportLayer *transport, IClient *client, bool notification, MethodCall &methodCall, CVariant &outputParameters);
static JSONSchemaTypeDefinitionPtr GetType(const std::string &identification);
static void ResolveReferences();
static void Cleanup();
private:
static bool prepareDescription(std::string &description, CVariant &descriptionObject, std::string &name);
static bool addMethod(const std::string &jsonMethod, MethodCall method);
static void parseHeader(const CVariant &descriptionObject);
static bool parseJSONSchemaType(const CVariant &value, std::vector<JSONSchemaTypeDefinitionPtr>& typeDefinitions, JSONSchemaType &schemaType, std::string &missingReference);
static void addReferenceTypeDefinition(const JSONSchemaTypeDefinitionPtr& typeDefinition);
static void removeReferenceTypeDefinition(const std::string &typeID);
static void getReferencedTypes(const JSONSchemaTypeDefinitionPtr& type,
std::vector<std::string>& referencedTypes);
class CJsonRpcMethodMap
{
public:
CJsonRpcMethodMap();
void add(const JsonRpcMethod &method);
typedef std::map<std::string, JsonRpcMethod>::const_iterator JsonRpcMethodIterator;
JsonRpcMethodIterator begin() const;
JsonRpcMethodIterator find(const std::string& key) const;
JsonRpcMethodIterator end() const;
void clear();
private:
std::map<std::string, JsonRpcMethod> m_actionmap;
};
static CJsonRpcMethodMap m_actionMap;
static std::map<std::string, JSONSchemaTypeDefinitionPtr> m_types;
static std::map<std::string, CVariant> m_notifications;
static JsonRpcMethodMap m_methodMaps[];
typedef enum SchemaDefinition
{
SchemaDefinitionType,
SchemaDefinitionMethod
} SchemaDefinition;
typedef struct IncompleteSchemaDefinition
{
std::string Schema;
SchemaDefinition Type;
MethodCall Method;
} IncompleteSchemaDefinition;
typedef std::map<std::string, std::vector<IncompleteSchemaDefinition> > IncompleteSchemaDefinitionMap;
static IncompleteSchemaDefinitionMap m_incompleteDefinitions;
};
}
|