Removed execute permissions from non-executable files.
[platform/upstream/iotivity.git] / service / things-manager / sdk / src / ThingsConfiguration.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 /// @file    ThingsConfiguration.cpp
22 /// @brief
23
24 #include <OCApi.h>
25 #include <OCPlatform.h>
26 #include <cstdlib>
27 #include <algorithm>
28 #include "ThingsConfiguration.h"
29
30 using namespace OC;
31
32 const int SUCCESS_RESPONSE = 0;
33 int cnt = 0;
34
35 std::map< std::string, ConfigurationRequestEntry > configurationRequestTable;
36
37 ThingsConfiguration* ThingsConfiguration::thingsConfigurationInstance = NULL;
38
39 ConfigurationCallback g_bootstrapCallback;
40
41 ThingsConfiguration* ThingsConfiguration::getInstance()
42 {
43     if (thingsConfigurationInstance == NULL)
44     {
45         thingsConfigurationInstance = new ThingsConfiguration();
46     }
47     return thingsConfigurationInstance;
48 }
49
50 void ThingsConfiguration::deleteInstance()
51 {
52     if (thingsConfigurationInstance)
53     {
54         delete thingsConfigurationInstance;
55         thingsConfigurationInstance = NULL;
56     }
57 }
58
59 std::string ThingsConfiguration::getAttributeByConfigurationName(ConfigurationName name)
60 {
61     for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
62     {
63         if ((*it).m_name == name)
64             return (*it).m_attribute;
65     }
66
67     return "";
68 }
69
70 std::string ThingsConfiguration::getUriByConfigurationName(ConfigurationName name)
71 {
72     for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
73     {
74         if ((*it).m_name == name)
75             return (*it).m_uri;
76     }
77
78     return "";
79 }
80
81 std::string ThingsConfiguration::getUpdateVal(std::string conf)
82 {
83     std::map< std::string, ConfigurationRequestEntry >::iterator it =
84             configurationRequestTable.find(conf);
85
86     if (it == configurationRequestTable.end())
87         return NULL;
88     else
89         return it->second.m_updateVal;
90
91 }
92 std::shared_ptr< OCResource > ThingsConfiguration::getResource(std::string conf)
93 {
94     std::map< std::string, ConfigurationRequestEntry >::iterator it =
95             configurationRequestTable.find(conf);
96
97     if (it == configurationRequestTable.end())
98         return NULL;
99     else
100         return it->second.m_resource;
101 }
102
103 ConfigurationCallback ThingsConfiguration::getCallback(std::string conf)
104 {
105     std::map< std::string, ConfigurationRequestEntry >::iterator it =
106             configurationRequestTable.find(conf);
107
108     if (it == configurationRequestTable.end())
109         return NULL;
110     else
111         return it->second.m_callback;
112 }
113
114 std::string ThingsConfiguration::getListOfSupportedConfigurationUnits()
115 {
116     std::string res;
117
118     res = "{\"Configuration Units\":[";
119
120     auto it = ConfigurationUnitTable.begin();
121     while (1)
122     {
123         res = res + (*it).getJSON();
124         it++;
125
126         if (it == ConfigurationUnitTable.end())
127             break;
128         else
129             res += ",";
130     }
131
132     res += "]}";
133
134     return res;
135 }
136
137 std::string ThingsConfiguration::getHostFromURI(std::string oldUri)
138 {
139     size_t f;
140     std::string newUri;
141
142     if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
143         newUri = oldUri.replace(f, oldUri.size(), "");
144     else if ((f = oldUri.find("/oic/")) != string::npos)
145         newUri = oldUri.replace(f, oldUri.size(), "");
146
147     return newUri;
148 }
149
150 void ThingsConfiguration::onDeleteActionSet(const HeaderOptions& headerOptions,
151         const OCRepresentation& rep, const int eCode, std::string conf)
152 {
153     std::shared_ptr < OCResource > resource = getResource(conf);
154
155     std::cout << __func__ << std::endl;
156
157     if (resource)
158     {
159         QueryParamsMap query;
160
161         // After deletion of the left action set, find target child resource's URIs by sending GET
162         // message. Note that, this resource is surely a collection resource which has child
163         // resources.
164         resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
165                 std::function<
166                         void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
167                                 const int eCode) >(
168                         std::bind(&ThingsConfiguration::onGetChildInfoForUpdate, this,
169                                 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
170                                 conf)));
171
172     }
173
174 }
175
176 void ThingsConfiguration::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
177         const OCRepresentation& rep, const int eCode, std::string conf)
178 {
179     if (eCode == SUCCESS_RESPONSE)
180     {
181         std::cout << "GET request was successful" << std::endl;
182
183         std::cout << "\tResource URI: " << rep.getUri() << std::endl;
184
185         std::vector < OCRepresentation > children = rep.getChildren();
186         for (auto oit = children.begin(); oit != children.end(); ++oit)
187         {
188             std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
189         }
190
191         // Get information by using configuration name(conf)
192         std::shared_ptr < OCResource > resource = getResource(conf);
193         std::string actionstring = conf;
194         std::string uri = getUriByConfigurationName(conf);
195         std::string attr = getAttributeByConfigurationName(conf);
196
197         if (uri == "")
198             return;
199
200         if (resource)
201         {
202             // In this nest, we create a new action set of which name is the configuration name.
203             // Required information consists of a host address, URI, attribute key, and attribute
204             // value.
205             ActionSet *newActionSet = new ActionSet();
206             newActionSet->actionsetName = conf;
207
208             for (auto oit = children.begin(); oit != children.end(); ++oit)
209             {
210                 Action *newAction = new Action();
211
212                 // oit->getUri() includes a host address as well as URI.
213                 // We should split these to each other and only use the host address to create
214                 // a child resource's URI. Note that the collection resource and its child resource
215                 // are located in same host.
216                 newAction->target = getHostFromURI(oit->getUri()) + uri;
217
218                 Capability *newCapability = new Capability();
219                 newCapability->capability = attr;
220                 newCapability->status = getUpdateVal(conf);
221
222                 newAction->listOfCapability.push_back(newCapability);
223                 newActionSet->listOfAction.push_back(newAction);
224             }
225
226             // Request to create a new action set by using the above actionSet
227             g_groupmanager->addActionSet(resource, newActionSet,
228                     std::function<
229                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
230                                     const int eCode) >(
231                             std::bind(&ThingsConfiguration::onCreateActionSet, this,
232                                     std::placeholders::_1, std::placeholders::_2,
233                                     std::placeholders::_3, conf)));
234         }
235
236     }
237     else
238     {
239         std::cout << "onPut Response error: " << eCode << std::endl;
240         std::exit(-1);
241     }
242 }
243
244 void ThingsConfiguration::onGetChildInfoForGet(const HeaderOptions& headerOptions,
245         const OCRepresentation& rep, const int eCode, std::string conf)
246 {
247     if (eCode == SUCCESS_RESPONSE)
248     {
249         std::cout << "GET request was successful" << std::endl;
250         std::cout << "\tResource URI: " << rep.getUri() << std::endl;
251
252         std::shared_ptr< OCResource > resource, tempResource;
253         std::vector < std::shared_ptr < OCResource >> p_resources;
254         std::vector < std::string > m_if;
255         std::string uri = getUriByConfigurationName(conf);
256
257         if (uri == "")
258             return;
259
260         if (uri == "/oic/con" || uri == "/factoryset" || uri == "/factoryset/oic/con")
261             m_if.push_back(BATCH_INTERFACE);
262         else
263             m_if.push_back(DEFAULT_INTERFACE);
264
265         std::vector < OCRepresentation > children = rep.getChildren();
266         for (auto oit = children.begin(); oit != children.end(); ++oit)
267         {
268             std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
269
270             // Using a host address and child URIs, we can dynamically create resource objects.
271             // Note that, the child resources have not found before, we have no resource objects.
272             // For this reason, we create the resource objects.
273
274             std::string host = getHostFromURI(oit->getUri());
275             tempResource = OCPlatform::constructResourceObject(host, uri, true,
276                     oit->getResourceTypes(), m_if);
277
278             p_resources.push_back(tempResource);
279         }
280
281         // Send GET messages to the child resources in turn.
282         for (unsigned int i = 0; i < p_resources.size(); ++i)
283         {
284             resource = p_resources.at(i);
285             if (resource)
286             {
287                 try
288                 {
289                     if (isSimpleResource(resource))
290                     {
291                         QueryParamsMap test;
292                         resource->get(test, getCallback(conf));
293                     }
294                     else
295                     {
296                         QueryParamsMap test;
297                         resource->get(resource->getResourceTypes().at(0), BATCH_INTERFACE, test,
298                                 getCallback(conf));
299                     }
300                 }
301                 catch (OCException& e)
302                 {
303                     std::cout << e.reason() << std::endl;
304                 }
305
306             }
307         }
308     }
309     else
310     {
311         std::cout << "onPut Response error: " << eCode << std::endl;
312         std::exit(-1);
313     }
314 }
315
316 void ThingsConfiguration::onCreateActionSet(const HeaderOptions& headerOptions,
317         const OCRepresentation& rep, const int eCode, std::string conf)
318 {
319     if (eCode == SUCCESS_RESPONSE)
320     {
321         std::cout << "PUT request was successful" << std::endl;
322
323         std::shared_ptr < OCResource > resource = getResource(conf);
324         if (resource)
325         {
326             // Now, it is time to execute the action set.
327             g_groupmanager->executeActionSet(resource, conf,
328                     std::function<
329                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
330                                     const int eCode) >(
331                             std::bind(&ThingsConfiguration::onExecuteForGroupAction, this,
332                                     std::placeholders::_1, std::placeholders::_2,
333                                     std::placeholders::_3, conf)));
334         }
335     }
336     else
337     {
338         std::cout << "onPut Response error: " << eCode << std::endl;
339         std::exit(-1);
340     }
341 }
342
343 void ThingsConfiguration::onExecuteForGroupAction(const HeaderOptions& headerOptions,
344         const OCRepresentation& rep, const int eCode, std::string conf)
345 {
346     if (eCode == SUCCESS_RESPONSE)
347     {
348         std::cout << "PUT request was successful" << std::endl;
349
350         getCallback(conf)(headerOptions, rep, eCode);
351     }
352     else
353     {
354         std::cout << "onPut Response error: " << eCode << std::endl;
355         std::exit(-1);
356     }
357 }
358
359 bool ThingsConfiguration::isSimpleResource(std::shared_ptr< OCResource > resource)
360 {
361     for (unsigned int i = 0; i < resource->getResourceInterfaces().size(); ++i)
362     {
363         if (resource->getResourceInterfaces().at(i) == BATCH_INTERFACE)
364             return false;
365     }
366     return true;
367 }
368
369 void ThingsConfiguration::onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
370         const int eCode, std::string conf)
371 {
372     if (eCode == SUCCESS_RESPONSE)
373     {
374         std::cout << "Get request was successful" << std::endl;
375
376         getCallback(conf)(headerOptions, rep, eCode);
377     }
378     else
379     {
380         std::cout << "onPut Response error: " << eCode << std::endl;
381         std::exit(-1);
382     }
383 }
384
385 void ThingsConfiguration::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
386         const int eCode, std::string conf)
387 {
388     if (eCode == SUCCESS_RESPONSE)
389     {
390         std::cout << "PUT request was successful" << std::endl;
391
392         // Callback
393         getCallback(conf)(headerOptions, rep, eCode);
394     }
395     else
396     {
397         std::cout << "onPut Response error: " << eCode << std::endl;
398         std::exit(-1);
399     }
400 }
401
402 OCStackResult ThingsConfiguration::updateConfigurations(std::shared_ptr< OCResource > resource,
403         std::map< ConfigurationName, ConfigurationValue > configurations,
404         ConfigurationCallback callback)
405 {
406     // For M2, # of configurations is 1
407     // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
408     if (configurations.size() == 0)
409     {
410         std::cout << "# of request configuration is 0" << std::endl;
411         return OC_STACK_ERROR;
412     }
413
414     if (!resource)
415     {
416         std::cout << "resource is NULL\n";
417         return OC_STACK_ERROR;
418     }
419
420     std::map< ConfigurationName, ConfigurationValue >::iterator it = configurations.begin();
421     std::string conf = it->first; // configuration name
422     std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
423
424     // Check the request queue if a previous request is still left. If so, remove it.
425     std::map< std::string, ConfigurationRequestEntry >::iterator iter =
426             configurationRequestTable.find(conf);
427     if (iter != configurationRequestTable.end())
428         configurationRequestTable.erase(iter);
429
430     // Create new request entry stored in the queue
431     ConfigurationRequestEntry newCallback(conf, callback, resource, it->second);
432     configurationRequestTable.insert(std::make_pair(conf, newCallback));
433
434     OCRepresentation rep;
435     QueryParamsMap query;
436     if (isSimpleResource(resource))
437     {
438         // This resource does not need to use a group manager. Just send a PUT message
439         rep.setValue(getAttributeByConfigurationName(conf), getUpdateVal(conf));
440         return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
441                 std::function<
442                         void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
443                                 const int eCode) >(
444                         std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
445                                 std::placeholders::_2, std::placeholders::_3, conf)));
446     }
447     else
448     {
449         // This resource is a collection resource which uses group manager functionalities.
450         // First, delete an existing action set of which name is same as a current action set name.
451         // As of now, the name is determined by "Configuration Name" which a user just specifies.
452         return g_groupmanager->deleteActionSet(resource, conf,
453                 std::function<
454                         void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
455                                 const int eCode) >(
456                         std::bind(&ThingsConfiguration::onDeleteActionSet, this,
457                                 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
458                                 conf)));
459     }
460 }
461
462 OCStackResult ThingsConfiguration::getConfigurations(std::shared_ptr< OCResource > resource,
463         std::vector< ConfigurationName > configurations, ConfigurationCallback callback)
464 {
465     // For M2, # of configurations is 1
466     // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
467     if (configurations.size() == 0)
468     {
469         std::cout << "# of request configuration is 0" << std::endl;
470         return OC_STACK_ERROR;
471     }
472     if (!resource)
473     {
474         std::cout << "resource is NULL\n";
475         return OC_STACK_ERROR;
476     }
477
478     std::vector< ConfigurationName >::iterator it = configurations.begin();
479     std::string conf = (*it); // configuration name
480     std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
481
482     // Check the request queue if a previous request is still left. If so, remove it.
483     std::map< std::string, ConfigurationRequestEntry >::iterator iter =
484             configurationRequestTable.find(conf);
485     if (iter != configurationRequestTable.end())
486         configurationRequestTable.erase(iter);
487
488     // Create new request entry stored in the queue
489     ConfigurationRequestEntry newCallback(conf, callback, resource, conf);
490     configurationRequestTable.insert(std::make_pair(conf, newCallback));
491
492     QueryParamsMap query;
493     OCRepresentation rep;
494
495     if (isSimpleResource(resource))
496     {
497         // This resource is a simple resource. Just send a PUT message
498         return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
499                 std::function<
500                         void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
501                                 const int eCode) >(
502                         std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
503                                 std::placeholders::_2, std::placeholders::_3, conf)));
504     }
505     else
506     {
507         // This resource is a collection resource. On the contrary of a update, it does not use
508         // group manager functionality. It just acquires child resource's URI and send GET massages
509         // to the child resources in turn.
510         // First, request the child resources's URI.
511         return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
512                 std::function<
513                         void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
514                                 const int eCode) >(
515                         std::bind(&ThingsConfiguration::onGetChildInfoForGet, this,
516                                 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
517                                 conf)));
518     }
519
520 }
521
522 // callback handler on GET request
523 void ThingsConfiguration::onGetBootstrapInformation(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
524 {
525     if(eCode == SUCCESS_RESPONSE)
526     {
527         std::cout << "GET request was successful" << std::endl;
528
529         std::cout << "\tResource URI: " << rep.getUri() << std::endl;
530         g_bootstrapCallback(headerOptions, rep,  eCode);
531     }
532
533     else
534     {
535         std::cout << "onGET Response error: " << eCode << std::endl;
536         std::exit(-1);
537     }
538 }
539
540 void ThingsConfiguration::onFoundBootstrapServer(std::vector< std::shared_ptr< OCResource > > resources)
541 {
542     std::string resourceURI;
543     std::string hostAddress;
544
545     try
546     {
547         // Do some operations with resource object.
548         for (unsigned int i = 0; i < resources.size(); ++i)
549         {
550             std::shared_ptr < OCResource > resource = resources.at(i);
551
552             if (resource)
553             {
554                 std::cout << "DISCOVERED Resource:" << std::endl;
555                 // Get the resource URI
556                 resourceURI = resource->uri();
557                 std::cout << "\tURI of the resource: " << resourceURI << std::endl;
558
559                 // Get the resource host address
560                 hostAddress = resource->host();
561                 std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
562
563                 // Get the resource types
564                 std::cout << "\tList of resource types: " << std::endl;
565                 for (auto &resourceTypes : resource->getResourceTypes())
566                 {
567                     std::cout << "\t\t" << resourceTypes << std::endl;
568                 }
569
570                 // Get the resource interfaces
571                 cout << "\tList of resource interfaces: " << endl;
572                 for (auto &resourceInterfaces : resource->getResourceInterfaces())
573                 {
574                     cout << "\t\t" << resourceInterfaces << endl;
575                 }
576
577                 // Request configuration resources
578                 std::cout << "Getting bootstrap server representation on: "<< DEFAULT_INTERFACE << std::endl;
579
580                 resource->get("bootstrap", DEFAULT_INTERFACE, QueryParamsMap(), &onGetBootstrapInformation);
581
582             }
583             else
584             {
585                 // Resource is invalid
586                 std::cout << "Resource is invalid" << std::endl;
587             }
588         }
589
590     }
591     catch (std::exception& e)
592     {
593         //log(e.what());
594     }
595 }
596
597 OCStackResult ThingsConfiguration::doBootstrap(ConfigurationCallback callback)
598 {
599     g_bootstrapCallback = callback;
600
601     // Find bootstrap server.
602     std::vector<std::string> type;
603     type.push_back("bootstrap");
604
605     std::cout << "Finding Bootstrap Server resource... " << std::endl;
606     return g_groupmanager->findCandidateResources(type, &onFoundBootstrapServer);
607 }