Initialize Tizen 2.3
[framework/web/wrt-plugins-common.git] / src_mobile / plugins-api-support / PluginRegistry.cpp
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /**
17  * @file    PluginRegistry.h
18  * @author  Grzegorz Krawczyk (g.krawczyk@samgsung.com)
19  * @version
20  * @brief
21  */
22 #include "PluginRegistry.h"
23 #include "PluginRegistration.h"
24 #include "PluginRegistrationImpl.h"
25 #include "ExportedApi.h"
26
27 #include <dlfcn.h>
28 #include <cstdio>
29 #include <cstdlib>
30 #include <string>
31 #include <algorithm>
32
33 #include <dpl/log/log.h>
34 #include <dpl/log/secure_log.h>
35 #include <dpl/foreach.h>
36 #include <dpl/scope_guard.h>
37
38 namespace WrtPluginsApi {
39 void PluginRegistry::AddPlugin(const std::string& libraryName,
40                                Plugin& plugin)
41 {
42     LogDebug("Adding plugin for library: " << libraryName);
43
44     auto libraryIt = m_plugins.find(libraryName);
45     if (m_plugins.end() == libraryIt) {
46         m_plugins[libraryName] = &plugin;
47     }
48 }
49
50 Plugin* PluginRegistry::GetPlugin(const std::string& libraryName)
51 {
52     auto it = m_plugins.find(libraryName);
53     if (it == m_plugins.end()) {
54         if (!LoadFromFile(libraryName)) {
55             LogError("Failed to load lib" << libraryName);
56             ThrowMsg(PluginNotFound, "Failed to load plugin");
57         }
58
59         return m_plugins[libraryName];
60     }
61
62     return it->second;
63 }
64
65 void PluginRegistry::RemovePlugin(const std::string& libraryName,
66                                   Plugin& plugin)
67 {
68     auto it = m_plugins.find(libraryName);
69     if (it != m_plugins.end()) {
70         if (&plugin == it->second) {
71             m_plugins.erase(it);
72         }
73     }
74 }
75
76 void PluginRegistry::UnloadAll()
77 {
78     LogDebug("Unload all plugins");
79
80     typedef void (*UnregisterFunction)(PluginRegistration&, Plugin&);
81
82     FOREACH(libraryIt, m_libraries)
83     {
84         auto pluginIt = m_plugins.find(libraryIt->first);
85         if (m_plugins.end() != pluginIt) {
86             void* handle = dlopen(libraryIt->first.c_str(), RTLD_NOW);
87             if (!handle) {
88                 const char* error = (const char*)dlerror();
89                 LogError("Error: " << (error != NULL ? error : "unknown"));
90                 continue;
91             }
92             DPL_SCOPE_EXIT(handle) {
93                 if (dlclose(handle) != 0) {
94                     const char* error = dlerror();
95                     if (error != NULL)
96                     {
97                         std::string errstr{error};
98                         _E("%s", errstr.c_str());
99                     }
100                     else
101                     {
102                         _E("unknown error while closing plug-in library");
103                     }
104                 }
105             };
106
107             ExportedApi* entryPoint =
108                 static_cast<ExportedApi*>
109                 (dlsym(handle, GetExportedSymbolName()));
110             if (NULL == entryPoint) {
111                 const char* error = (const char*)dlerror();
112                 LogError("Error: " << (error != NULL ? error : "unknown"));
113                 continue;
114             }
115             if (entryPoint->Unregister == NULL) {
116                 LogError("Error Unregister function not set");
117                 continue;
118             }
119
120             PluginRegistration registration(
121                 new PluginRegistration::Impl(*this, libraryIt->first));
122
123             entryPoint->Unregister(registration, (pluginIt->second));
124
125             m_plugins.erase(pluginIt);
126         }
127         dlclose(libraryIt->second);
128     }
129 }
130
131 bool PluginRegistry::LoadFromFile(const std::string& libraryName)
132 {
133     void* handle = dlopen(libraryName.c_str(), RTLD_NOW);
134     if (!handle) {
135         const char* error = (const char*)dlerror();
136         LogError("Error: " << (error != NULL ? error : "unknown"));
137         return false;
138     }
139     m_libraries[libraryName] = handle;
140
141     ExportedApi* entryPoint =
142         static_cast<ExportedApi*>(dlsym(handle, GetExportedSymbolName()));
143     if (NULL == entryPoint) {
144         const char* error = (const char*)dlerror();
145         LogError("Error: " << (error != NULL ? error : "unknown"));
146         return false;
147     }
148
149     if (entryPoint->Register == NULL) {
150         LogError("Error Register function not set");
151         return false;
152     }
153     if (entryPoint->Unregister == NULL) {
154         LogError("Error Unregister function not set");
155         return false;
156     }
157
158     PluginRegistration registration(
159         new PluginRegistration::Impl(*this, libraryName));
160     entryPoint->Register(registration);
161
162     return true;
163 }
164
165 PluginRegistry::~PluginRegistry()
166 {
167     //TODO discuss ... when the unload should be called
168     //    UnloadAll();
169 }
170 }