2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file install_one_task.cpp
18 * @author Pawel Sikorski (p.sikorski@samgsung.com)
19 * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com)
25 #include <sys/types.h>
30 #include <dpl/log/log.h>
31 #include <dpl/foreach.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>
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 #include <wrt_plugin_export.h>
45 using namespace WrtDB;
48 const std::string DIRECTORY_SEPARATOR = std::string("/");
51 #define SET_PLUGIN_INSTALL_PROGRESS(step, desc) \
52 m_context->installerTask->UpdateProgress( \
53 PluginInstallerContext::step, desc);
55 #define DISABLE_IF_PLUGIN_WITHOUT_LIB() \
56 if(m_pluginInfo.m_libraryName.empty()) \
58 LogWarning("Plugin without library."); \
63 namespace PluginInstall {
65 PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) :
66 DPL::TaskDecl<PluginInstallTask>(this),
68 m_dataFromConfigXML(true)
70 AddStep(&PluginInstallTask::stepCheckPluginPath);
71 AddStep(&PluginInstallTask::stepParseConfigFile);
72 AddStep(&PluginInstallTask::stepFindPluginLibrary);
73 AddStep(&PluginInstallTask::stepCheckIfAlreadyInstalled);
74 AddStep(&PluginInstallTask::stepLoadPluginLibrary);
75 AddStep(&PluginInstallTask::stepRegisterPlugin);
76 AddStep(&PluginInstallTask::stepRegisterFeatures);
77 AddStep(&PluginInstallTask::stepRegisterPluginObjects);
78 AddStep(&PluginInstallTask::stepResolvePluginDependencies);
80 SET_PLUGIN_INSTALL_PROGRESS(START, "Installation initialized");
83 PluginInstallTask::~PluginInstallTask()
87 void PluginInstallTask::stepCheckPluginPath()
89 LogInfo("Plugin installation: step CheckPluginPath");
93 if (-1 == stat(m_context->pluginFilePath.c_str(), &tmp)) {
94 ThrowMsg(Exceptions::PluginPathFailed,
95 "Stat function failed");
98 if (!S_ISDIR(tmp.st_mode)) {
99 ThrowMsg(Exceptions::PluginPathFailed,
100 "Invalid Directory");
103 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Path to plugin verified");
106 void PluginInstallTask::stepParseConfigFile()
108 LogInfo("Plugin installation: step parse config file");
112 std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
113 std::string(GlobalConfig::GetPluginMetafileName());
115 if (-1 == stat(filename.c_str(), &tmp)) {
116 m_dataFromConfigXML = false;
120 LogInfo("Plugin Config file::" << filename);
124 PluginMetafileReader reader;
125 reader.initialize(filename);
126 reader.read(m_pluginInfo);
128 FOREACH(it, m_pluginInfo.m_featureContainer)
130 LogDebug("Parsed feature : " << it->m_name);
131 FOREACH (devCap, it->m_deviceCapabilities) {
132 LogDebug(" | DevCap : " << *devCap);
136 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Config file analyzed");
138 Catch(ValidationCore::ParserSchemaException::Base)
140 LogError("Error during file processing " << filename);
141 ThrowMsg(Exceptions::PluginMetafileFailed,
146 void PluginInstallTask::stepFindPluginLibrary()
148 if (m_dataFromConfigXML)
152 LogDebug("Plugin installation: step find plugin library");
153 std::string pluginPath = m_context->pluginFilePath;
154 size_t indexpos = pluginPath.find_last_of('/');
156 if (std::string::npos == indexpos)
162 indexpos += 1; // move after '/'
165 std::string libName = pluginPath.substr(indexpos);
166 libName = GlobalConfig::GetPluginPrefix() + libName + GlobalConfig::GetPluginSuffix();
167 LogDebug("Plugin .so: " << libName);
168 m_pluginInfo.m_libraryName = libName;
171 void PluginInstallTask::stepCheckIfAlreadyInstalled()
173 if (PluginDAO::isPluginInstalled(m_pluginInfo.m_libraryName)) {
174 ThrowMsg(Exceptions::PluginAlreadyInstalled,
175 "Plugin already installed");
178 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_EXISTS_CHECK, "Check if plugin exist");
181 void PluginInstallTask::stepLoadPluginLibrary()
183 LogInfo("Plugin installation: step load library");
185 DISABLE_IF_PLUGIN_WITHOUT_LIB()
187 std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
188 m_pluginInfo.m_libraryName;
190 LogDebug("Loading plugin: " << filename);
192 void *dlHandle = dlopen(filename.c_str(), RTLD_NOW);
193 if (dlHandle == NULL ) {
195 "Failed to load plugin: " << filename <<
196 ". Reason: " << dlerror());
197 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
200 const js_entity_definition_t *rawEntityList = NULL;
201 get_widget_entity_map_proc *getWidgetEntityMapProcPtr = NULL;
203 getWidgetEntityMapProcPtr =
204 reinterpret_cast<get_widget_entity_map_proc *>(dlsym(dlHandle,
205 PLUGIN_GET_CLASS_MAP_PROC_NAME));
207 if (getWidgetEntityMapProcPtr) {
208 rawEntityList = (*getWidgetEntityMapProcPtr)();
211 static_cast<const js_entity_definition_t *>(dlsym(dlHandle,
212 PLUGIN_CLASS_MAP_NAME));
215 if (rawEntityList == NULL) {
217 LogError("Failed to read class name" << filename);
218 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
221 if (!m_dataFromConfigXML)
223 on_widget_init_proc *onWidgetInitProc =
224 reinterpret_cast<on_widget_init_proc *>(
225 dlsym(dlHandle, PLUGIN_WIDGET_INIT_PROC_NAME));
227 if (NULL == onWidgetInitProc)
230 LogError("Failed to read onWidgetInit symbol" << filename);
231 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
234 // obtain feature -> dev-cap mapping
235 feature_mapping_interface_t mappingInterface = { NULL, NULL, NULL };
236 (*onWidgetInitProc)(&mappingInterface);
238 if (!mappingInterface.featGetter || !mappingInterface.release ||
239 !mappingInterface.dcGetter)
241 LogError("Failed to obtain mapping interface from .so");
242 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
245 feature_mapping_t* devcapMapping = mappingInterface.featGetter();
247 LogDebug("Getting mapping from features to device capabilities");
249 for (size_t i = 0; i < devcapMapping->featuresCount; ++i)
251 PluginMetafileData::Feature feature;
252 feature.m_name = devcapMapping->features[i].feature_name;
254 LogDebug("Feature: " << feature.m_name);
256 const devcaps_t* dc =
257 mappingInterface.dcGetter(devcapMapping,
258 devcapMapping->features[i].feature_name);
260 LogDebug("device=cap: " << dc);
264 LogDebug("devcaps count: " << dc->devCapsCount);
266 for (size_t j = 0; j < dc->devCapsCount; ++j)
268 LogDebug("devcap: " << dc->deviceCaps[j]);
269 feature.m_deviceCapabilities.insert(dc->deviceCaps[j]);
273 m_pluginInfo.m_featureContainer.insert(feature);
276 mappingInterface.release(devcapMapping);
279 m_libraryObjects = PluginObjectsPtr(new PluginObjects());
280 const js_entity_definition_t *rawEntityListIterator = rawEntityList;
283 LogInfo("##### Plugin: " << filename << " supports new plugin API");
286 while (rawEntityListIterator->parent_name != NULL &&
287 rawEntityListIterator->object_name != NULL)
289 LogInfo("##### [" << rawEntityListIterator->object_name << "]: ");
290 LogInfo("##### Parent: " << rawEntityListIterator->parent_name);
293 m_libraryObjects->addObjects(rawEntityListIterator->parent_name,
294 rawEntityListIterator->object_name);
296 ++rawEntityListIterator;
300 if (dlclose(dlHandle) != 0) {
301 LogError("Cannot close plugin handle");
303 LogDebug("Library is unloaded");
307 LogDebug("Library successfuly loaded and parsed");
309 SET_PLUGIN_INSTALL_PROGRESS(LOADING_LIBRARY, "Library loaded and analyzed");
312 void PluginInstallTask::stepRegisterPlugin()
314 LogInfo("Plugin installation: step register Plugin");
317 PluginDAO::registerPlugin(m_pluginInfo, m_context->pluginFilePath);
319 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_PLUGIN, "Plugin registered");
322 void PluginInstallTask::stepRegisterFeatures()
324 LogInfo("Plugin installation: step register features");
326 FOREACH(it, m_pluginInfo.m_featureContainer)
328 LogError("PluginHandle: " << m_pluginHandle);
329 FeatureDAO::RegisterFeature(*it, m_pluginHandle);
331 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_FEATURES, "Features registered");
334 void PluginInstallTask::stepRegisterPluginObjects()
336 LogInfo("Plugin installation: step register objects");
338 DISABLE_IF_PLUGIN_WITHOUT_LIB()
340 //register implemented objects
341 PluginObjects::ObjectsPtr objects =
342 m_libraryObjects->getImplementedObject();
344 FOREACH(it, *objects)
346 PluginDAO::registerPluginImplementedObject(*it, m_pluginHandle);
349 //register requiredObjects
350 objects = m_libraryObjects->getDependentObjects();
352 FOREACH(it, *objects)
354 if (m_libraryObjects->hasObject(*it)) {
355 LogDebug("Dependency from the same library. ignored");
359 PluginDAO::registerPluginRequiredObject(*it, m_pluginHandle);
362 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_OBJECTS, "Plugin Objects registered");
365 void PluginInstallTask::stepResolvePluginDependencies()
367 LogInfo("Plugin installation: step resolve dependencies ");
369 //DISABLE_IF_PLUGIN_WITHOUT_LIB
370 if(m_pluginInfo.m_libraryName.empty())
372 PluginDAO::setPluginInstallationStatus(m_pluginHandle,
373 PluginDAO::INSTALLATION_COMPLETED);
374 //Installation completed
375 m_context->pluginHandle = m_pluginHandle;
376 m_context->installationCompleted = true;
377 LogWarning("Plugin without library.");
381 PluginHandleSetPtr handles = PluginHandleSetPtr(new PluginHandleSet);
383 DbPluginHandle handle = INVALID_PLUGIN_HANDLE;
385 //register requiredObjects
386 FOREACH(it, *(m_libraryObjects->getDependentObjects()))
388 if (m_libraryObjects->hasObject(*it)) {
389 LogDebug("Dependency from the same library. ignored");
393 handle = PluginDAO::getPluginHandleForImplementedObject(*it);
394 if (handle == INVALID_PLUGIN_HANDLE) {
395 LogError("Library implementing: " << *it << " NOT FOUND");
396 PluginDAO::setPluginInstallationStatus(
398 PluginDAO::INSTALLATION_WAITING);
402 handles->insert(handle);
405 PluginDAO::registerPluginLibrariesDependencies(m_pluginHandle, handles);
407 PluginDAO::setPluginInstallationStatus(m_pluginHandle,
408 PluginDAO::INSTALLATION_COMPLETED);
410 //Installation completed
411 m_context->pluginHandle = m_pluginHandle;
412 m_context->installationCompleted = true;
414 SET_PLUGIN_INSTALL_PROGRESS(RESOLVE_DEPENDENCIES, "Dependencies resolved");
417 #undef SET_PLUGIN_INSTALL_PROGRESS
419 } //namespace PluginInstall