upload tizen1.0 source
[framework/web/wrt-installer.git] / src / jobs / plugin_install / plugin_install_task.cpp
1 /*
2  * Copyright (c) 2011 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    install_one_task.cpp
18  * @author  Pawel Sikorski (p.sikorski@samgsung.com)
19  * @author  Grzegorz Krawczyk (g.krawczyk@samgsung.com)
20  * @version
21  * @brief
22  */
23
24 //SYSTEM INCLUDES
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <dlfcn.h>
28
29 //WRT INCLUDES
30 #include <dpl/log/log.h>
31 #include <dpl/foreach.h>
32 #include <job.h>
33 #include "plugin_install_task.h"
34 #include "job_plugin_install.h"
35 #include "plugin_installer_errors.h"
36 #include "plugin_metafile_reader.h"
37 #include <dpl/wrt-dao-ro/global_config.h>
38 //#include <plugin.h>
39 #include <wrt_common_types.h>
40 #include <dpl/wrt-dao-rw/feature_dao.h>
41 #include <dpl/wrt-dao-rw/plugin_dao.h>
42 #include "plugin_objects.h"
43
44 using namespace WrtDB;
45
46 namespace {
47 const std::string DIRECTORY_SEPARATOR = std::string("/");
48 }
49
50 #define SET_PLUGIN_INSTALL_PROGRESS(step, desc)              \
51     m_context->installerTask->UpdateProgress(               \
52         PluginInstallerContext::step, desc);
53
54 #define DISABLE_IF_PLUGIN_WITHOUT_LIB()        \
55     if(m_pluginMetafile.m_libraryName.empty()) \
56     {                                          \
57         LogWarning("Plugin without library."); \
58         return;                                \
59     }
60
61 namespace Jobs {
62 namespace PluginInstall {
63 PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) :
64     DPL::TaskDecl<PluginInstallTask>(this),
65     m_context(inCont)
66 {
67     AddStep(&PluginInstallTask::stepCheckPluginPath);
68     AddStep(&PluginInstallTask::stepParseConfigFile);
69     AddStep(&PluginInstallTask::stepCheckIfAlreadyInstalled);
70     AddStep(&PluginInstallTask::stepLoadPluginLibrary);
71     AddStep(&PluginInstallTask::stepRegisterPlugin);
72     AddStep(&PluginInstallTask::stepRegisterFeatures);
73     AddStep(&PluginInstallTask::stepRegisterPluginObjects);
74     AddStep(&PluginInstallTask::stepResolvePluginDependencies);
75
76     SET_PLUGIN_INSTALL_PROGRESS(START, "Installation initialized");
77 }
78
79 PluginInstallTask::~PluginInstallTask()
80 {
81 }
82
83 void PluginInstallTask::stepCheckPluginPath()
84 {
85     LogInfo("Plugin installation: step CheckPluginPath");
86
87     struct stat tmp;
88
89     if (-1 == stat(m_context->pluginFilePath.c_str(), &tmp)) {
90         ThrowMsg(Exceptions::PluginPathFailed,
91                  "Stat function failed");
92     }
93
94     if (!S_ISDIR(tmp.st_mode)) {
95         ThrowMsg(Exceptions::PluginPathFailed,
96                  "Invalid Directory");
97     }
98
99     SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Path to plugin verified");
100 }
101
102 void PluginInstallTask::stepParseConfigFile()
103 {
104     LogInfo("Plugin installation: step parse config file");
105
106     std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
107         std::string(GlobalConfig::GetPluginMetafileName());
108
109     LogInfo("Plugin Config file::" << filename);
110
111     Try
112     {
113         PluginMetafileReader reader;
114         reader.initialize(filename);
115         reader.read(m_pluginMetafile);
116
117         FOREACH(it, m_pluginMetafile.m_featureContainer)
118         {
119             LogDebug("Parsed feature : " << it->m_name);
120             FOREACH (devCap, it->m_deviceCapabilities) {
121                 LogDebug("  |  DevCap : " << *devCap);
122             }
123         }
124
125         SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Config file analyzed");
126     }
127     Catch(ValidationCore::ParserSchemaException::Base)
128     {
129         LogError("Error during file processing " << filename);
130         ThrowMsg(Exceptions::PluginMetafileFailed,
131                  "Metafile error");
132     }
133 }
134
135 void PluginInstallTask::stepCheckIfAlreadyInstalled()
136 {
137     if (PluginDAO::isPluginInstalled(m_pluginMetafile.m_libraryName)) {
138         ThrowMsg(Exceptions::PluginAlreadyInstalled,
139                  "Plugin already installed");
140     }
141
142     SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_EXISTS_CHECK, "Check if plugin exist");
143 }
144
145 void PluginInstallTask::stepLoadPluginLibrary()
146 {
147     LogInfo("Plugin installation: step load library");
148
149     DISABLE_IF_PLUGIN_WITHOUT_LIB()
150
151     std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
152         m_pluginMetafile.m_libraryName;
153
154     LogDebug("Loading plugin: " << filename);
155
156     void *dlHandle = dlopen(filename.c_str(), RTLD_LAZY);
157     if (dlHandle == NULL ) {
158         LogError(
159                 "Failed to load plugin: " << filename <<
160                 ". Reason: " << dlerror());
161         ThrowMsg(Exceptions::PluginLibraryError, "Library error");
162     }
163
164     const class_definition_t *rawClassList = NULL;
165     get_widget_class_map_proc *getWidgetClassMapProcPtr = NULL;
166
167     getWidgetClassMapProcPtr =
168         reinterpret_cast<get_widget_class_map_proc *>(dlsym(dlHandle,
169                     PLUGIN_GET_CLASS_MAP_PROC_NAME));
170
171     if (getWidgetClassMapProcPtr) {
172         rawClassList = (*getWidgetClassMapProcPtr)();
173     } else {
174         rawClassList =
175             static_cast<const class_definition_t *>(dlsym(dlHandle,
176                         PLUGIN_CLASS_MAP_NAME));
177     }
178
179     if (rawClassList == NULL) {
180         dlclose(dlHandle);
181         LogError("Failed to read class name" << filename);
182         ThrowMsg(Exceptions::PluginLibraryError, "Library error");
183     }
184
185     m_libraryObjects = PluginObjectsPtr(new PluginObjects());
186     const class_definition_t *rawClassListIterator = rawClassList;
187
188     LogInfo("#####");
189     LogInfo("##### Plugin: " << filename << " supports new plugin API");
190     LogInfo("#####");
191
192     while (rawClassListIterator->parent_name != NULL &&
193             rawClassListIterator->object_name != NULL &&
194             rawClassListIterator->js_class_template != NULL) {
195         LogInfo("#####     [" << rawClassListIterator->object_name << "]: ");
196         LogInfo("#####     Parent: " << rawClassListIterator->parent_name);
197         LogInfo("#####");
198
199         m_libraryObjects->addObjects(rawClassListIterator->parent_name,
200                 rawClassListIterator->object_name);
201
202         ++rawClassListIterator;
203 }
204
205 // Unload library
206 if (dlclose(dlHandle) != 0) {
207     LogError("Cannot close plugin handle");
208 } else {
209     LogDebug("Library is unloaded");
210 }
211
212     // Load export table
213     LogDebug("Library successfuly loaded and parsed");
214
215     SET_PLUGIN_INSTALL_PROGRESS(LOADING_LIBRARY, "Library loaded and analyzed");
216     //TODO unload library;
217 }
218
219 void PluginInstallTask::stepRegisterPlugin()
220 {
221     LogInfo("Plugin installation: step register Plugin");
222
223     m_pluginHandle =
224         PluginDAO::registerPlugin(m_pluginMetafile, m_context->pluginFilePath);
225
226     SET_PLUGIN_INSTALL_PROGRESS(REGISTER_PLUGIN, "Plugin registered");
227 }
228
229 void PluginInstallTask::stepRegisterFeatures()
230 {
231     LogInfo("Plugin installation: step register features");
232
233     FOREACH(it, m_pluginMetafile.m_featureContainer)
234     {
235         LogError("PluginHandle: " << m_pluginHandle);
236         FeatureDAO::RegisterFeature(*it, m_pluginHandle);
237     }
238     SET_PLUGIN_INSTALL_PROGRESS(REGISTER_FEATURES, "Features registered");
239 }
240
241 void PluginInstallTask::stepRegisterPluginObjects()
242 {
243     LogInfo("Plugin installation: step register objects");
244
245     DISABLE_IF_PLUGIN_WITHOUT_LIB()
246
247     //register implemented objects
248     PluginObjects::ObjectsPtr objects =
249         m_libraryObjects->getImplementedObject();
250
251     FOREACH(it, *objects)
252     {
253         PluginDAO::registerPluginImplementedObject(*it, m_pluginHandle);
254     }
255
256     //register requiredObjects
257     objects = m_libraryObjects->getDependentObjects();
258
259     FOREACH(it, *objects)
260     {
261         if (m_libraryObjects->hasObject(*it)) {
262             LogDebug("Dependency from the same library. ignored");
263             continue;
264         }
265
266         PluginDAO::registerPluginRequiredObject(*it, m_pluginHandle);
267     }
268
269     SET_PLUGIN_INSTALL_PROGRESS(REGISTER_OBJECTS, "Plugin Objects registered");
270 }
271
272 void PluginInstallTask::stepResolvePluginDependencies()
273 {
274     LogInfo("Plugin installation: step resolve dependencies ");
275
276     //DISABLE_IF_PLUGIN_WITHOUT_LIB
277     if(m_pluginMetafile.m_libraryName.empty())
278     {
279         PluginDAO::setPluginInstallationStatus(m_pluginHandle,
280                                            PluginDAO::INSTALLATION_COMPLETED);
281         //Installation completed
282         m_context->pluginHandle = m_pluginHandle;
283         m_context->installationCompleted = true;
284         LogWarning("Plugin without library.");
285         return;
286     }
287
288     PluginHandleSetPtr handles = PluginHandleSetPtr(new PluginHandleSet);
289
290     DbPluginHandle handle = INVALID_PLUGIN_HANDLE;
291
292     //register requiredObjects
293     FOREACH(it, *(m_libraryObjects->getDependentObjects()))
294     {
295         if (m_libraryObjects->hasObject(*it)) {
296             LogDebug("Dependency from the same library. ignored");
297             continue;
298         }
299
300         handle = PluginDAO::getPluginHandleForImplementedObject(*it);
301         if (handle == INVALID_PLUGIN_HANDLE) {
302             LogError("Library implementing: " << *it << " NOT FOUND");
303             PluginDAO::setPluginInstallationStatus(
304                 m_pluginHandle,
305                 PluginDAO::INSTALLATION_WAITING);
306             return;
307         }
308
309         handles->insert(handle);
310     }
311
312     PluginDAO::registerPluginLibrariesDependencies(m_pluginHandle, handles);
313
314     PluginDAO::setPluginInstallationStatus(m_pluginHandle,
315                                            PluginDAO::INSTALLATION_COMPLETED);
316
317     //Installation completed
318     m_context->pluginHandle = m_pluginHandle;
319     m_context->installationCompleted = true;
320
321     SET_PLUGIN_INSTALL_PROGRESS(RESOLVE_DEPENDENCIES, "Dependencies resolved");
322 }
323
324 #undef SET_PLUGIN_INSTALL_PROGRESS
325 } //namespace Jobs
326 } //namespace PluginInstall