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