198dead00e5d452ce8cc5ff774e9e89a5ac41941
[profile/ivi/layer-management.git] / LayerManagerBase / src / PluginManager.cpp
1 /***************************************************************************
2  *
3  * Copyright 2012 BMW Car IT GmbH
4  *
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  ****************************************************************************/
19
20 #include "PluginManager.h"
21 #include "Configuration.h"
22 #include "Log.h"
23 #include "IPlugin.h"
24 #include <IScene.h>
25
26 #include <dirent.h>
27 #include <errno.h>
28 #include <dlfcn.h>
29 #include <stdlib.h>
30
31 StaticPluginCreateFuncList PluginManager::mStaticPluginCreateFuncList;
32
33 //===========================================================================
34 // register statically linked plugins (configured by build system)
35 //===========================================================================
36 STATIC_PLUGIN_REGISTRATION
37
38 //===========================================================================
39 // class implementation
40 //===========================================================================
41 PluginManager::PluginManager(ICommandExecutor& executor, Configuration& config)
42 : mExecutor(executor)
43 , mConfiguration(config)
44 {
45     LOG_DEBUG("PluginManager", "loading plugins from " << mConfiguration.getPluginPath());
46
47     // create static plugins
48     createStaticallyLinkedPlugins();
49
50 #ifndef WITH_STATIC_LIBRARIES
51     // create dynamic plugins
52     getAllFilesInPluginPath(mConfiguration.getPluginPath());
53     createDynamicallyLinkedPlugins();
54 #endif
55
56     LOG_INFO("PluginManager", "created " << mPluginList.size() << " plugins");
57 }
58
59 PluginManager::~PluginManager()
60 {
61     PluginList::iterator iter = mPluginList.begin();
62     PluginList::iterator iterEnd = mPluginList.end();
63
64     for (; iter != iterEnd; ++iter)
65     {
66         IPlugin* plugin = *iter;
67         if (plugin)
68         {
69             LOG_INFO("PluginManager", "plugin " << plugin->pluginGetName() << " destroyed");
70             delete plugin;
71         }
72     }
73     mPluginList.clear();
74 }
75
76 void PluginManager::getRendererList(RendererList& list)
77 {
78     PluginList::const_iterator iter = mPluginList.begin();
79     PluginList::const_iterator iterEnd = mPluginList.end();
80
81     for (; iter != iterEnd; ++iter)
82     {
83         IPlugin* plugin = *iter;
84         ilmPluginApi api = plugin->pluginGetApi();
85         if (PLUGIN_IS_RENDERER(api))
86         {
87             IRenderer* renderer = dynamic_cast<IRenderer*>(plugin);
88             list.push_back(renderer);
89         }
90     }
91 }
92
93 void PluginManager::getHealthMonitorList(HealthMonitorList& list)
94 {
95     PluginList::const_iterator iter = mPluginList.begin();
96     PluginList::const_iterator iterEnd = mPluginList.end();
97
98     for (; iter != iterEnd; ++iter)
99     {
100         IPlugin* plugin = *iter;
101         ilmPluginApi api = plugin->pluginGetApi();
102         if (PLUGIN_IS_HEALTHMONITOR(api))
103         {
104             IHealthMonitor* monitor = dynamic_cast<IHealthMonitor*>(plugin);
105             if (monitor)
106             {
107                 list.push_back(monitor);
108             }
109         }
110     }
111 }
112
113 void PluginManager::getSceneProviderList(SceneProviderList& list)
114 {
115     PluginList::const_iterator iter = mPluginList.begin();
116     PluginList::const_iterator iterEnd = mPluginList.end();
117
118     for (; iter != iterEnd; ++iter)
119     {
120         IPlugin* plugin = *iter;
121         ilmPluginApi api = plugin->pluginGetApi();
122         if (PLUGIN_IS_SCENEPROVIDER(api))
123         {
124             ISceneProvider* sceneprovider = dynamic_cast<ISceneProvider*>(plugin);
125             list.push_back(sceneprovider);
126         }
127     }
128 }
129
130 void PluginManager::getCommunicatorList(CommunicatorList& list)
131 {
132     PluginList::const_iterator iter = mPluginList.begin();
133     PluginList::const_iterator iterEnd = mPluginList.end();
134
135     for (; iter != iterEnd; ++iter)
136     {
137         IPlugin* plugin = *iter;
138         ilmPluginApi api = plugin->pluginGetApi();
139         if (PLUGIN_IS_COMMUNICATOR(api))
140         {
141             ICommunicator* comm = dynamic_cast<ICommunicator*>(plugin);
142             list.push_back(comm);
143         }
144     }
145 }
146
147
148 bool PluginManager::registerStaticPluginCreateFunction(StaticPluginCreateFunc func)
149 {
150     bool result = false;
151     if (func)
152     {
153         mStaticPluginCreateFuncList.push_back(func);
154         result = true;
155     }
156     return result;
157 }
158
159 void PluginManager::createStaticallyLinkedPlugins()
160 {
161     StaticPluginCreateFuncList::iterator iter = mStaticPluginCreateFuncList.begin();
162     StaticPluginCreateFuncList::iterator iterEnd = mStaticPluginCreateFuncList.end();
163
164     for (; iter != iterEnd; ++iter)
165     {
166         StaticPluginCreateFunc func = *iter;
167         IPlugin* plugin = (*func)(mExecutor, mConfiguration);
168         LOG_INFO("PluginManager", "creating plugin " << plugin->pluginGetName() << " (static linking)");
169         mPluginList.push_back(plugin);
170     }
171 }
172
173 void PluginManager::getAllFilesInPluginPath(std::string path)
174 {
175     DIR *directory = opendir(path.c_str());
176     struct dirent *itemInDirectory = 0;
177
178     while (directory && (itemInDirectory = readdir(directory)))
179     {
180         unsigned char entryType = itemInDirectory->d_type;
181         std::string entryName = itemInDirectory->d_name;
182         std::string fullPath = path + "/" + entryName;
183
184         if (entryName.at(0) == '.')
185         {
186             continue;
187         }
188
189         switch (entryType)
190         {
191         case DT_REG:
192         case DT_LNK:
193         case DT_UNKNOWN:
194             mFileList.push_back(fullPath);
195             LOG_DEBUG("PluginManager", "considering File " << fullPath);
196             break;
197
198         case DT_DIR:
199             getAllFilesInPluginPath(fullPath);
200             break;
201
202         default:
203             LOG_DEBUG("PluginManager", "ignored file " << fullPath);
204             break;
205         }
206     }
207
208     closedir(directory);
209 }
210
211 void PluginManager::createDynamicallyLinkedPlugins()
212 {
213     FileList::const_iterator iter = mFileList.begin();
214     FileList::const_iterator iterEnd = mFileList.end();
215
216     for (; iter != iterEnd; ++iter)
217     {
218         IPlugin* plugin = createDynamicallyLinkedPlugin(*iter);
219         if (plugin)
220         {
221             mPluginList.push_back(plugin);
222         }
223     }
224 }
225
226 IPlugin* PluginManager::createDynamicallyLinkedPlugin(std::string path)
227 {
228     IPlugin* returnValue = NULL;
229
230     // open library
231     void *libraryHandle;
232     dlerror(); // Clear any existing error
233     libraryHandle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);
234     const char* dlopen_error = dlerror();
235     if (dlopen_error)
236     {
237         LOG_DEBUG("PluginManager", "not a shared library: " << dlopen_error);
238         return NULL;
239     }
240
241     // load entry point
242     union
243     {
244         void* data;
245         IPlugin* (*createFunc)(ICommandExecutor&, Configuration&);
246     } convertUnion;
247
248     int cutBegin = path.find_last_of('/') + 4;      // remove '*/lib' from name
249     int cutEnd = path.find_first_of('.', cutBegin); // remove '.extension' from name
250
251     std::string createFunctionName = "create";
252     createFunctionName += path.substr(cutBegin, cutEnd - cutBegin);
253
254     convertUnion.data = dlsym(libraryHandle, createFunctionName.c_str());
255
256     // create plugin instance from entry point
257     const char* dlsym_error = dlerror();
258     if (convertUnion.data && !dlsym_error)
259     {
260         returnValue = convertUnion.createFunc(mExecutor, mConfiguration);
261         LOG_INFO("PluginManager", "creating plugin " << returnValue->pluginGetName() << " (dynamic linking)");
262     }
263     else
264     {
265         LOG_DEBUG("PluginManager", "not a valid Plugin: " << path << ": " << dlsym_error);
266         dlclose(libraryHandle);
267         returnValue = NULL;
268     }
269
270     return returnValue;
271 }