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 {
64 PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) :
65 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()
86 void PluginInstallTask::stepCheckPluginPath()
88 LogInfo("Plugin installation: step CheckPluginPath");
92 if (-1 == stat(m_context->pluginFilePath.c_str(), &tmp)) {
93 ThrowMsg(Exceptions::PluginPathFailed,
94 "Stat function failed");
97 if (!S_ISDIR(tmp.st_mode)) {
98 ThrowMsg(Exceptions::PluginPathFailed,
102 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Path to plugin verified");
105 void PluginInstallTask::stepParseConfigFile()
107 LogInfo("Plugin installation: step parse config file");
111 std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
112 std::string(GlobalConfig::GetPluginMetafileName());
114 if (-1 == stat(filename.c_str(), &tmp)) {
115 m_dataFromConfigXML = false;
119 LogInfo("Plugin Config file::" << filename);
123 PluginMetafileReader reader;
124 reader.initialize(filename);
125 reader.read(m_pluginInfo);
127 FOREACH(it, m_pluginInfo.m_featureContainer)
129 LogDebug("Parsed feature : " << it->m_name);
130 FOREACH(devCap, it->m_deviceCapabilities) {
131 LogDebug(" | DevCap : " << *devCap);
135 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Config file analyzed");
137 Catch(ValidationCore::ParserSchemaException::Base)
139 LogError("Error during file processing " << filename);
140 ThrowMsg(Exceptions::PluginMetafileFailed,
145 void PluginInstallTask::stepFindPluginLibrary()
147 if (m_dataFromConfigXML) {
150 LogDebug("Plugin installation: step find plugin library");
151 std::string pluginPath = m_context->pluginFilePath;
152 size_t indexpos = pluginPath.find_last_of('/');
154 if (std::string::npos == indexpos) {
157 indexpos += 1; // move after '/'
160 std::string libName = pluginPath.substr(indexpos);
161 libName = GlobalConfig::GetPluginPrefix() + libName +
162 GlobalConfig::GetPluginSuffix();
163 LogDebug("Plugin .so: " << libName);
164 m_pluginInfo.m_libraryName = libName;
167 void PluginInstallTask::stepCheckIfAlreadyInstalled()
169 if (PluginDAO::isPluginInstalled(m_pluginInfo.m_libraryName)) {
170 ThrowMsg(Exceptions::PluginAlreadyInstalled,
171 "Plugin already installed");
174 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_EXISTS_CHECK, "Check if plugin exist");
177 void PluginInstallTask::stepLoadPluginLibrary()
179 LogInfo("Plugin installation: step load library");
181 DISABLE_IF_PLUGIN_WITHOUT_LIB()
183 std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
184 m_pluginInfo.m_libraryName;
186 LogDebug("Loading plugin: " << filename);
188 void *dlHandle = dlopen(filename.c_str(), RTLD_LAZY);
189 if (dlHandle == NULL) {
190 const char* error = (const char*)dlerror();
192 "Failed to load plugin: " << filename <<
193 ". Reason: " << (error != NULL ? error : "unknown"));
194 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
197 const js_entity_definition_t *rawEntityList = NULL;
198 get_widget_entity_map_proc *getWidgetEntityMapProcPtr = NULL;
200 getWidgetEntityMapProcPtr =
201 reinterpret_cast<get_widget_entity_map_proc *>(dlsym(dlHandle,
202 PLUGIN_GET_CLASS_MAP_PROC_NAME));
204 if (getWidgetEntityMapProcPtr) {
205 rawEntityList = (*getWidgetEntityMapProcPtr)();
208 static_cast<const js_entity_definition_t *>(dlsym(dlHandle,
209 PLUGIN_CLASS_MAP_NAME));
212 if (rawEntityList == NULL) {
214 LogError("Failed to read class name" << filename);
215 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
218 if (!m_dataFromConfigXML) {
219 on_widget_init_proc *onWidgetInitProc =
220 reinterpret_cast<on_widget_init_proc *>(
221 dlsym(dlHandle, PLUGIN_WIDGET_INIT_PROC_NAME));
223 if (NULL == onWidgetInitProc) {
225 LogError("Failed to read onWidgetInit symbol" << filename);
226 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
229 // obtain feature -> dev-cap mapping
230 feature_mapping_interface_t mappingInterface = { NULL, NULL, NULL };
231 (*onWidgetInitProc)(&mappingInterface);
233 if (!mappingInterface.featGetter || !mappingInterface.release ||
234 !mappingInterface.dcGetter)
236 LogError("Failed to obtain mapping interface from .so");
237 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
240 feature_mapping_t* devcapMapping = mappingInterface.featGetter();
242 LogDebug("Getting mapping from features to device capabilities");
244 for (size_t i = 0; i < devcapMapping->featuresCount; ++i) {
245 PluginMetafileData::Feature feature;
246 feature.m_name = devcapMapping->features[i].feature_name;
248 LogDebug("Feature: " << feature.m_name);
250 const devcaps_t* dc =
251 mappingInterface.dcGetter(
253 devcapMapping->features[i].
256 LogDebug("device=cap: " << dc);
259 LogDebug("devcaps count: " << dc->devCapsCount);
261 for (size_t j = 0; j < dc->devCapsCount; ++j) {
262 LogDebug("devcap: " << dc->deviceCaps[j]);
263 feature.m_deviceCapabilities.insert(dc->deviceCaps[j]);
267 m_pluginInfo.m_featureContainer.insert(feature);
270 mappingInterface.release(devcapMapping);
273 m_libraryObjects = PluginObjectsPtr(new PluginObjects());
274 const js_entity_definition_t *rawEntityListIterator = rawEntityList;
277 LogInfo("##### Plugin: " << filename << " supports new plugin API");
280 while (rawEntityListIterator->parent_name != NULL &&
281 rawEntityListIterator->object_name != NULL)
283 LogInfo("##### [" << rawEntityListIterator->object_name << "]: ");
284 LogInfo("##### Parent: " << rawEntityListIterator->parent_name);
287 m_libraryObjects->addObjects(rawEntityListIterator->parent_name,
288 rawEntityListIterator->object_name);
290 ++rawEntityListIterator;
294 if (dlclose(dlHandle) != 0) {
295 LogError("Cannot close plugin handle");
297 LogDebug("Library is unloaded");
301 LogDebug("Library successfuly loaded and parsed");
303 SET_PLUGIN_INSTALL_PROGRESS(LOADING_LIBRARY, "Library loaded and analyzed");
306 void PluginInstallTask::stepRegisterPlugin()
308 LogInfo("Plugin installation: step register Plugin");
311 PluginDAO::registerPlugin(m_pluginInfo, m_context->pluginFilePath);
313 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_PLUGIN, "Plugin registered");
316 void PluginInstallTask::stepRegisterFeatures()
318 LogInfo("Plugin installation: step register features");
320 FOREACH(it, m_pluginInfo.m_featureContainer)
322 LogError("PluginHandle: " << m_pluginHandle);
323 FeatureDAO::RegisterFeature(*it, m_pluginHandle);
325 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_FEATURES, "Features registered");
328 void PluginInstallTask::stepRegisterPluginObjects()
330 LogInfo("Plugin installation: step register objects");
332 DISABLE_IF_PLUGIN_WITHOUT_LIB()
334 //register implemented objects
335 PluginObjects::ObjectsPtr objects =
336 m_libraryObjects->getImplementedObject();
338 FOREACH(it, *objects)
340 PluginDAO::registerPluginImplementedObject(*it, m_pluginHandle);
343 //register requiredObjects
344 objects = m_libraryObjects->getDependentObjects();
346 FOREACH(it, *objects)
348 if (m_libraryObjects->hasObject(*it)) {
349 LogDebug("Dependency from the same library. ignored");
353 PluginDAO::registerPluginRequiredObject(*it, m_pluginHandle);
356 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_OBJECTS, "Plugin Objects registered");
359 void PluginInstallTask::stepResolvePluginDependencies()
361 LogInfo("Plugin installation: step resolve dependencies ");
363 //DISABLE_IF_PLUGIN_WITHOUT_LIB
364 if (m_pluginInfo.m_libraryName.empty()) {
365 PluginDAO::setPluginInstallationStatus(
368 INSTALLATION_COMPLETED);
369 //Installation completed
370 m_context->pluginHandle = m_pluginHandle;
371 m_context->installationCompleted = true;
372 LogWarning("Plugin without library.");
376 PluginHandleSetPtr handles = PluginHandleSetPtr(new PluginHandleSet);
378 DbPluginHandle handle = INVALID_PLUGIN_HANDLE;
380 //register requiredObjects
381 FOREACH(it, *(m_libraryObjects->getDependentObjects()))
383 if (m_libraryObjects->hasObject(*it)) {
384 LogDebug("Dependency from the same library. ignored");
388 handle = PluginDAO::getPluginHandleForImplementedObject(*it);
389 if (handle == INVALID_PLUGIN_HANDLE) {
390 LogError("Library implementing: " << *it << " NOT FOUND");
391 PluginDAO::setPluginInstallationStatus(
393 PluginDAO::INSTALLATION_WAITING);
397 handles->insert(handle);
400 PluginDAO::registerPluginLibrariesDependencies(m_pluginHandle, handles);
402 PluginDAO::setPluginInstallationStatus(m_pluginHandle,
403 PluginDAO::INSTALLATION_COMPLETED);
405 //Installation completed
406 m_context->pluginHandle = m_pluginHandle;
407 m_context->installationCompleted = true;
409 SET_PLUGIN_INSTALL_PROGRESS(RESOLVE_DEPENDENCIES, "Dependencies resolved");
412 #undef SET_PLUGIN_INSTALL_PROGRESS
414 } //namespace PluginInstall