throw if config is bad
[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         if(configBuffer == "")
62         {
63                 throw std::runtime_error("No config or config empty");
64         }
65         enum json_tokener_error err;
66         do
67         {
68                 rootobject = json_tokener_parse_ex(tokener, configBuffer.c_str(),configBuffer.length());
69         } while ((err = json_tokener_get_error(tokener)) == json_tokener_continue);
70         if (err != json_tokener_success)
71         {
72                 fprintf(stderr, "Error: %s\n", json_tokener_error_desc(err));
73                 // Handle errors, as appropriate for your application.
74         }
75         if (tokener->char_offset < configFile.length()) // XXX shouldn't access internal fields
76         {
77                 // Handle extra characters after parsed object as desired.
78                 // e.g. issue an error, parse another object from that point, etc...
79         }
80         
81         //DebugOut()<<"Config members: "<<json_reader_count_members(reader)<<endl;
82         json_object *mainloopobject = json_object_object_get(rootobject,"mainloop");
83         if (mainloopobject)
84         {
85                 /// there is a mainloop entry.  Load the plugin:
86
87                 string mainloopstr = string(json_object_get_string(mainloopobject));
88
89                 mMainLoop = loadMainLoop(mainloopstr,argc, argv);
90
91                 if(!mMainLoop)
92                 {
93                         DebugOut(0)<<"Failed to load main loop plugin."<<endl;
94                 }
95         }
96         else if(!mMainLoop)
97         {
98                 /// there is no mainloop entry, use default glib
99                 DebugOut()<<"No mainloop specified in config.  Using glib by default."<<endl;
100                 mMainLoop = new GlibMainLoop(argc,argv);
101         }
102         
103         json_object *sourcesobject = json_object_object_get(rootobject,"sources");
104
105         if(!sourcesobject)
106         {
107                 DebugOut()<<"Error getting sources member: "<<endl;
108                 throw std::runtime_error("Error getting sources member");
109         }
110         
111         //g_assert(json_reader_is_array(reader));
112         g_assert(json_object_get_type(sourcesobject)==json_type_array);
113         
114         
115         array_list *sourceslist = json_object_get_array(sourcesobject);
116         if (!sourceslist)
117         {
118           DebugOut() << "Error getting source list" << endl;
119           throw std::runtime_error("Error getting sources list");
120         }
121         
122         for(int i=0; i < array_list_length(sourceslist); i++)
123         {
124                 json_object *obj = (json_object*)array_list_get_idx(sourceslist,i); //This is an object
125                 
126                 std::map<std::string, std::string> configurationMap;
127                 json_object_object_foreach(obj, key, val)
128                 {
129                         string valstr = json_object_get_string(val);
130                         DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
131                         configurationMap[key] = valstr;
132                 }
133                 json_object *pathobject = json_object_object_get(obj,"path");
134                 string path = string(json_object_get_string(pathobject));
135
136                 AbstractSource* plugin = loadPlugin<AbstractSource*>(path,configurationMap);
137                 
138                 if(plugin != nullptr)
139                 {
140                         mSources.push_back(plugin);
141                 }
142                 json_object_put(pathobject);
143         }
144         DebugOut() << "Trying to free list" << endl;
145         array_list_free(sourceslist);
146         DebugOut() << "Trying to free obj" << endl;
147         //json_object_put(sourcesobject);
148         DebugOut() << "Done first" << endl;
149         ///read the sinks:
150         
151         json_object *sinksobject = json_object_object_get(rootobject,"sinks");
152         
153         if (!sinksobject)
154         {
155           DebugOut() << "Error getting sink object" << endl;
156           throw std::runtime_error("Error getting sink object");
157         }
158         
159         
160         
161         array_list *sinkslist = json_object_get_array(sinksobject);
162         
163         
164         if (!sinkslist)
165         {
166           DebugOut() << "Error getting sink list" << endl;
167           throw std::runtime_error("Error getting sink list");
168         }
169         
170         
171         for(int i=0; i < array_list_length(sinkslist); i++)
172         {
173                 json_object *obj = (json_object*)array_list_get_idx(sinkslist,i);
174
175                 std::map<std::string, std::string> configurationMap;
176
177                 json_object_object_foreach(obj, key, val)
178                 {
179                         string valstr = json_object_get_string(val);
180                         DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
181                         configurationMap[key] = valstr;
182                 }
183
184                 
185                 json_object *pathobject = json_object_object_get(obj,"path");
186                 string path = string(json_object_get_string(pathobject));
187
188                 AbstractSinkManager* plugin = loadPlugin<AbstractSinkManager*>(path, configurationMap);
189
190                 if(plugin == nullptr)
191                 {
192                         throw std::runtime_error("plugin is not a SinkManager");
193                 }
194                 json_object_put(pathobject);
195                 //json_object_put(obj);
196
197         }
198         DebugOut() << "Trying to free list" << endl;
199         array_list_free(sinkslist);
200         DebugOut() << "Trying to free obj" << endl;
201         //json_object_put(sinksobject);
202         DebugOut() << "Done" << endl;
203                 
204         
205         ///TODO: this will probably explode:
206         
207         //if(error) g_error_free(error);
208         
209         //g_object_unref(reader);
210         //g_object_unref(parser);
211         //*/
212 }
213
214 PluginLoader::~PluginLoader()
215 {
216 }
217
218 SinkList PluginLoader::sinks()
219 {
220         return mSinks;
221 }
222
223 IMainLoop *PluginLoader::mainloop()
224 {
225         return mMainLoop;
226 }
227
228 SourceList PluginLoader::sources()
229 {
230         return mSources;
231 }
232
233
234
235 std::string PluginLoader::errorString()
236 {
237         return mErrorString;
238 }
239