Merge branch 'master' of github.com:otcshare/automotive-message-broker
[profile/ivi/automotive-message-broker.git] / ambd / pluginloader.cpp
1 /*
2 Copyright (C) 2012 Intel Corporation
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19
20 #include "pluginloader.h"
21 #include "glibmainloop.h"
22 #include <json.h>
23 #include <iostream>
24 #include <stdexcept>
25 #include <boost/concept_check.hpp>
26 //#include <json-glib/json-glib.h>
27
28
29 using namespace std;
30
31 /********************************************
32  * Example JSON config:
33  * {
34  *      sources: [ path1, path2, path3 ]
35  *      sinks: [ path1, path2, path3 ]
36  * }
37  * 
38 **********************************************/
39
40 std::string get_file_contents(const char *filename)
41 {
42   //FILE *in = fopen(filename,"r");
43   
44   std::ifstream in(filename, std::ios::in);
45   std::string output;
46   std::string line;
47   while(in.good())
48   {
49     getline(in,line);
50     output.append(line);
51   }
52   return output;
53 }
54 PluginLoader::PluginLoader(string configFile, AbstractRoutingEngine* re, int argc, char** argv): f_create(NULL), routingEngine(re), mMainLoop(nullptr)
55 {
56   
57         DebugOut()<<"Loading config file: "<<configFile<<endl;
58         json_object *rootobject;
59         json_tokener *tokener = json_tokener_new();
60         std::string configBuffer = get_file_contents(configFile.c_str());
61         enum json_tokener_error err;
62         do
63         {
64                 rootobject = json_tokener_parse_ex(tokener, configBuffer.c_str(),configBuffer.length());
65         } while ((err = json_tokener_get_error(tokener)) == json_tokener_continue);
66         if (err != json_tokener_success)
67         {
68                 fprintf(stderr, "Error: %s\n", json_tokener_error_desc(err));
69                 // Handle errors, as appropriate for your application.
70         }
71         if (tokener->char_offset < configFile.length()) // XXX shouldn't access internal fields
72         {
73                 // Handle extra characters after parsed object as desired.
74                 // e.g. issue an error, parse another object from that point, etc...
75         }
76         
77         //DebugOut()<<"Config members: "<<json_reader_count_members(reader)<<endl;
78         json_object *mainloopobject = json_object_object_get(rootobject,"mainloop");
79         if (mainloopobject)
80         {
81                 /// there is a mainloop entry.  Load the plugin:
82
83                 string mainloopstr = string(json_object_get_string(mainloopobject));
84
85                 mMainLoop = loadMainLoop(mainloopstr,argc, argv);
86
87                 if(!mMainLoop)
88                 {
89                         DebugOut(0)<<"Failed to load main loop plugin."<<endl;
90                 }
91         }
92         else if(!mMainLoop)
93         {
94                 /// there is no mainloop entry, use default glib
95                 DebugOut()<<"No mainloop specified in config.  Using glib by default."<<endl;
96                 mMainLoop = new GlibMainLoop(argc,argv);
97         }
98         
99         json_object *sourcesobject = json_object_object_get(rootobject,"sources");
100
101         if(!sourcesobject)
102         {
103                 DebugOut()<<"Error getting sources member: "<<endl;
104                 throw std::runtime_error("Error getting sources member");
105         }
106         
107         //g_assert(json_reader_is_array(reader));
108         g_assert(json_object_get_type(sourcesobject)==json_type_array);
109         
110         
111         array_list *sourceslist = json_object_get_array(sourcesobject);
112         if (!sourceslist)
113         {
114           DebugOut() << "Error getting source list" << endl;
115           throw std::runtime_error("Error getting sources list");
116         }
117         
118         for(int i=0; i < array_list_length(sourceslist); i++)
119         {
120                 json_object *obj = (json_object*)array_list_get_idx(sourceslist,i); //This is an object
121                 
122                 std::map<std::string, std::string> configurationMap;
123                 json_object_object_foreach(obj, key, val)
124                 {
125                         string valstr = json_object_get_string(val);
126                         DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
127                         configurationMap[key] = valstr;
128                 }
129                 json_object *pathobject = json_object_object_get(obj,"path");
130                 string path = string(json_object_get_string(pathobject));
131
132                 AbstractSource* plugin = loadPlugin<AbstractSource*>(path,configurationMap);
133                 
134                 if(plugin != nullptr)
135                 {
136                         mSources.push_back(plugin);
137                 }
138                 json_object_put(pathobject);
139         }
140         DebugOut() << "Trying to free list" << endl;
141         array_list_free(sourceslist);
142         DebugOut() << "Trying to free obj" << endl;
143         //json_object_put(sourcesobject);
144         DebugOut() << "Done first" << endl;
145         ///read the sinks:
146         
147         json_object *sinksobject = json_object_object_get(rootobject,"sinks");
148         
149         if (!sinksobject)
150         {
151           DebugOut() << "Error getting sink object" << endl;
152           throw std::runtime_error("Error getting sink object");
153         }
154         
155         
156         
157         array_list *sinkslist = json_object_get_array(sinksobject);
158         
159         
160         if (!sinkslist)
161         {
162           DebugOut() << "Error getting sink list" << endl;
163           throw std::runtime_error("Error getting sink list");
164         }
165         
166         
167         for(int i=0; i < array_list_length(sinkslist); i++)
168         {
169                 json_object *obj = (json_object*)array_list_get_idx(sinkslist,i);
170
171                 std::map<std::string, std::string> configurationMap;
172
173                 json_object_object_foreach(obj, key, val)
174                 {
175                         string valstr = json_object_get_string(val);
176                         DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
177                         configurationMap[key] = valstr;
178                 }
179
180                 
181                 json_object *pathobject = json_object_object_get(obj,"path");
182                 string path = string(json_object_get_string(pathobject));
183
184                 AbstractSinkManager* plugin = loadPlugin<AbstractSinkManager*>(path, configurationMap);
185
186                 if(plugin == nullptr)
187                 {
188                         throw std::runtime_error("plugin is not a SinkManager");
189                 }
190                 json_object_put(pathobject);
191                 //json_object_put(obj);
192
193         }
194         DebugOut() << "Trying to free list" << endl;
195         array_list_free(sinkslist);
196         DebugOut() << "Trying to free obj" << endl;
197         //json_object_put(sinksobject);
198         DebugOut() << "Done" << endl;
199                 
200         
201         ///TODO: this will probably explode:
202         
203         //if(error) g_error_free(error);
204         
205         //g_object_unref(reader);
206         //g_object_unref(parser);
207         //*/
208 }
209
210 PluginLoader::~PluginLoader()
211 {
212         for(auto itr = mSinks.begin(); itr != mSinks.end(); itr++)
213         {
214                 delete *itr;
215         }
216
217         for(auto itr = mSources.begin(); itr != mSources.end(); itr++)
218         {
219                 delete *itr;
220         }
221 }
222
223 SinkList PluginLoader::sinks()
224 {
225         return mSinks;
226 }
227
228 IMainLoop *PluginLoader::mainloop()
229 {
230         return mMainLoop;
231 }
232
233 SourceList PluginLoader::sources()
234 {
235         return mSources;
236 }
237
238
239
240 std::string PluginLoader::errorString()
241 {
242         return mErrorString;
243 }
244