f821907bacee8ddb91390e1e5e61187b9b627173
[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 "core.h"
23 #include <json.h>
24 #include <iostream>
25 #include <stdexcept>
26 #include <boost/concept_check.hpp>
27 //#include <json-glib/json-glib.h>
28
29
30 using namespace std;
31
32 std::string get_file_contents(const char *filename)
33 {
34         //FILE *in = fopen(filename,"r");
35
36         std::ifstream in(filename, std::ios::in);
37         std::string output;
38         std::string line;
39         while(in.good())
40         {
41                 getline(in,line);
42                 output.append(line);
43         }
44         return output;
45 }
46 PluginLoader::PluginLoader(string configFile, int argc, char** argv): f_create(NULL), routingEngine(nullptr), mMainLoop(nullptr)
47 {
48         DebugOut()<<"Loading config file: "<<configFile<<endl;
49         json_object *rootobject;
50         json_tokener *tokener = json_tokener_new();
51         std::string configBuffer = get_file_contents(configFile.c_str());
52         if(configBuffer == "")
53         {
54                 throw std::runtime_error("No config or config empty");
55         }
56         enum json_tokener_error err;
57         do
58         {
59                 rootobject = json_tokener_parse_ex(tokener, configBuffer.c_str(),configBuffer.length());
60         } while ((err = json_tokener_get_error(tokener)) == json_tokener_continue);
61         if (err != json_tokener_success)
62         {
63                 fprintf(stderr, "Error: %s\n", json_tokener_error_desc(err));
64                 // Handle errors, as appropriate for your application.
65                 throw std::runtime_error("Invalid config");
66         }
67         if (tokener->char_offset < configFile.length()) // XXX shouldn't access internal fields
68         {
69                 // Handle extra characters after parsed object as desired.
70                 // e.g. issue an error, parse another object from that point, etc...
71         }
72
73         json_object *coreobject = json_object_object_get(rootobject,"routingEngine");
74         if (coreobject)
75         {
76                 /// there is a mainloop entry.  Load the plugin:
77
78                 string restr = string(json_object_get_string(coreobject));
79
80                 routingEngine = loadRoutingEngine(restr);
81
82                 if(!routingEngine)
83                 {
84                         DebugOut(DebugOut::Warning)<<"Failed to load routing engine plugin: "<<restr<<endl;
85                 }
86         }
87
88         if(!routingEngine)
89         {
90                 /// there is no mainloop entry, use default glib
91                 DebugOut()<<"No routing engine specified in config.  Using built-in 'core' routing engine by default."<<endl;
92
93                 /// core wants some specific configuration settings:
94                 std::map<std::string,std::string> settings;
95
96                 json_object *lpq = json_object_object_get(rootobject,"lowPriorityQueueSize");
97                 if (lpq)
98                 {
99                         /// there is a mainloop entry.  Load the plugin:
100
101                         string restr = string(json_object_get_string(lpq));
102                         settings["lowPriorityQueueSize"] = restr;
103                 }
104
105                 json_object *npq = json_object_object_get(rootobject,"normalPriorityQueueSize");
106                 if (npq)
107                 {
108                         /// there is a mainloop entry.  Load the plugin:
109
110                         string restr = string(json_object_get_string(npq));
111                         settings["normalPriorityQueueSize"] = restr;
112                 }
113
114                 json_object *hpq = json_object_object_get(rootobject,"highPriorityQueueSize");
115                 if (hpq)
116                 {
117                         /// there is a mainloop entry.  Load the plugin:
118
119                         string restr = string(json_object_get_string(hpq));
120                         settings["highPriorityQueueSize"] = restr;
121                 }
122
123                 routingEngine = new Core(settings);
124         }
125
126
127
128         json_object *mainloopobject = json_object_object_get(rootobject,"mainloop");
129         if (mainloopobject)
130         {
131                 /// there is a mainloop entry.  Load the plugin:
132
133                 string mainloopstr = string(json_object_get_string(mainloopobject));
134
135                 mMainLoop = loadMainLoop(mainloopstr,argc, argv);
136
137                 if(!mMainLoop)
138                 {
139                         DebugOut(DebugOut::Warning)<<"Failed to load main loop plugin."<<endl;
140                 }
141         }
142         else if(!mMainLoop)
143         {
144                 /// there is no mainloop entry, use default glib
145                 DebugOut()<<"No mainloop specified in config.  Using glib by default."<<endl;
146                 mMainLoop = new GlibMainLoop(argc,argv);
147         }
148
149         json_object *sourcesobject = json_object_object_get(rootobject,"sources");
150
151         if(!sourcesobject)
152         {
153                 DebugOut()<<"Error getting sources member: "<<endl;
154                 throw std::runtime_error("Error getting sources member");
155         }
156
157         //g_assert(json_reader_is_array(reader));
158         g_assert(json_object_get_type(sourcesobject)==json_type_array);
159
160
161         array_list *sourceslist = json_object_get_array(sourcesobject);
162         if (!sourceslist)
163         {
164                 DebugOut() << "Error getting source list" << endl;
165                 throw std::runtime_error("Error getting sources list");
166         }
167
168         for(int i=0; i < array_list_length(sourceslist); i++)
169         {
170                 json_object *obj = (json_object*)array_list_get_idx(sourceslist,i); //This is an object
171
172                 std::map<std::string, std::string> configurationMap;
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                 string path = configurationMap["path"];
181
182                 AbstractSource* plugin = loadPlugin<AbstractSource*>(path,configurationMap);
183
184                 if(plugin != nullptr)
185                 {
186                         mSources.push_back(plugin);
187                 }
188         }
189
190         //json_object_put(sourcesobject);
191         ///read the sinks:
192
193         json_object *sinksobject = json_object_object_get(rootobject,"sinks");
194
195         if (!sinksobject)
196         {
197                 DebugOut() << "Error getting sink object" << endl;
198                 throw std::runtime_error("Error getting sink object");
199         }
200
201         array_list *sinkslist = json_object_get_array(sinksobject);
202
203
204         if (!sinkslist)
205         {
206                 DebugOut() << "Error getting sink list" << endl;
207                 throw std::runtime_error("Error getting sink list");
208         }
209
210
211         for(int i=0; i < array_list_length(sinkslist); i++)
212         {
213                 json_object *obj = (json_object*)array_list_get_idx(sinkslist,i);
214
215                 std::map<std::string, std::string> configurationMap;
216
217                 json_object_object_foreach(obj, key, val)
218                 {
219                         string valstr = json_object_get_string(val);
220                         DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
221                         configurationMap[key] = valstr;
222                 }
223
224
225                 string path = configurationMap["path"];
226
227                 AbstractSinkManager* plugin = loadPlugin<AbstractSinkManager*>(path, configurationMap);
228
229                 if(plugin == nullptr)
230                 {
231                         DebugOut()<<"plugin is not a SinkManager"<<endl;
232
233                         AbstractSink* sink = loadPlugin<AbstractSink*>(path, configurationMap);
234
235                         if(!sink)
236                         {
237                                 DebugOut(DebugOut::Warning)<<"plugin seems to be invalid: "<<path<<endl;
238                         }
239                 }
240                 else
241                 {
242                         mSinkManagers.push_back(plugin);
243                 }
244         }
245
246         //json_object_put(sinksobject);
247         json_object_put(rootobject);
248         json_tokener_free(tokener);
249
250         Core* core = static_cast<Core*>(routingEngine);
251         if( core != nullptr )
252         {
253                 core->inspectSupported();
254         }
255 }
256
257 PluginLoader::~PluginLoader()
258 {
259         for(auto i :mSinkManagers)
260         {
261                 delete i;
262         }
263
264         for(auto handle : openHandles)
265                 dlclose(handle);
266 }
267
268 IMainLoop *PluginLoader::mainloop()
269 {
270         return mMainLoop;
271 }
272
273 SourceList PluginLoader::sources()
274 {
275         return mSources;
276 }
277
278 std::string PluginLoader::errorString()
279 {
280         return mErrorString;
281 }
282