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/foreach.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>
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 #include <wrt_plugin_export.h>
43 #include <plugin_path.h>
44 #include <installer_log.h>
46 using namespace WrtDB;
48 #define SET_PLUGIN_INSTALL_PROGRESS(step, desc) \
49 m_context->installerTask->UpdateProgress( \
50 PluginInstallerContext::step, desc);
52 #define DISABLE_IF_PLUGIN_WITHOUT_LIB() \
53 if (m_pluginInfo.m_libraryName.empty()) \
55 _W("Plugin without library."); \
60 namespace PluginInstall {
61 PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) :
62 DPL::TaskDecl<PluginInstallTask>(this),
65 m_dataFromConfigXML(true)
67 AddStep(&PluginInstallTask::stepCheckPluginPath);
68 AddStep(&PluginInstallTask::stepParseConfigFile);
69 AddStep(&PluginInstallTask::stepFindPluginLibrary);
70 AddStep(&PluginInstallTask::stepCheckIfAlreadyInstalled);
71 AddStep(&PluginInstallTask::stepLoadPluginLibrary);
72 AddStep(&PluginInstallTask::stepRegisterPlugin);
73 AddStep(&PluginInstallTask::stepRegisterFeatures);
74 AddStep(&PluginInstallTask::stepRegisterPluginObjects);
75 AddStep(&PluginInstallTask::stepResolvePluginDependencies);
77 SET_PLUGIN_INSTALL_PROGRESS(START, "Installation initialized");
80 PluginInstallTask::~PluginInstallTask()
83 void PluginInstallTask::stepCheckPluginPath()
85 _D("Plugin installation: step CheckPluginPath");
87 if(!m_context->pluginFilePath.Exists()){
88 ThrowMsg(Exceptions::PluginPathFailed,
92 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Path to plugin verified");
95 void PluginInstallTask::stepParseConfigFile()
97 _D("Plugin installation: step parse config file");
99 if(!m_context->pluginFilePath.getMetaFile().Exists()){
100 m_dataFromConfigXML = false;
104 _D("Plugin Config file::%s", m_context->pluginFilePath.getMetaFile().Fullpath().c_str());
108 PluginMetafileReader reader;
109 reader.initialize(m_context->pluginFilePath.getMetaFile());
110 reader.read(m_pluginInfo);
112 FOREACH(it, m_pluginInfo.m_featureContainer)
114 _D("Parsed feature : %s", it->m_name.c_str());
115 FOREACH(devCap, it->m_deviceCapabilities) {
116 _D(" | DevCap : %s", (*devCap).c_str());
120 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Config file analyzed");
122 Catch(ValidationCore::ParserSchemaException::Base)
124 _E("Error during file processing %s", m_context->pluginFilePath.getMetaFile().Fullpath().c_str());
125 ThrowMsg(Exceptions::PluginMetafileFailed,
130 void PluginInstallTask::stepFindPluginLibrary()
132 if (m_dataFromConfigXML) {
135 _D("Plugin installation: step find plugin library");
136 _D("Plugin .so: %s", m_context->pluginFilePath.getLibraryName().c_str());
137 m_pluginInfo.m_libraryName = m_context->pluginFilePath.getLibraryName();
140 void PluginInstallTask::stepCheckIfAlreadyInstalled()
142 if (PluginDAO::isPluginInstalled(m_pluginInfo.m_libraryName)) {
143 ThrowMsg(Exceptions::PluginAlreadyInstalled,
144 "Plugin already installed");
147 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_EXISTS_CHECK, "Check if plugin exist");
150 void PluginInstallTask::stepLoadPluginLibrary()
152 _D("Plugin installation: step load library");
154 DISABLE_IF_PLUGIN_WITHOUT_LIB()
156 _D("Loading plugin: %s", m_context->pluginFilePath.getLibraryName().c_str());
158 fprintf(stderr, " - Try to dlopen() : [%s] ", m_context->pluginFilePath.getLibraryPath().Fullpath().c_str());
160 void *dlHandle = dlopen( m_context->pluginFilePath.getLibraryPath().Fullpath().c_str(), RTLD_LAZY);
161 if (dlHandle == NULL) {
162 const char* error = (const char*)dlerror();
165 (error != NULL ? error : "unknown"));
166 _E("Failed to load plugin: %s. Reason: %s",
167 m_context->pluginFilePath.getLibraryName().c_str(), (error != NULL ? error : "unknown"));
168 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
171 fprintf(stderr, "-> Done.\n");
173 const js_entity_definition_t *rawEntityList = NULL;
174 get_widget_entity_map_proc *getWidgetEntityMapProcPtr = NULL;
176 getWidgetEntityMapProcPtr =
177 reinterpret_cast<get_widget_entity_map_proc *>(dlsym(dlHandle,
178 PLUGIN_GET_CLASS_MAP_PROC_NAME));
180 if (getWidgetEntityMapProcPtr) {
181 rawEntityList = (*getWidgetEntityMapProcPtr)();
184 static_cast<const js_entity_definition_t *>(dlsym(dlHandle,
185 PLUGIN_CLASS_MAP_NAME));
188 if (rawEntityList == NULL) {
190 _E("Failed to read class name %s", m_context->pluginFilePath.getLibraryName().c_str());
191 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
194 if (!m_dataFromConfigXML) {
195 on_widget_init_proc *onWidgetInitProc =
196 reinterpret_cast<on_widget_init_proc *>(
197 dlsym(dlHandle, PLUGIN_WIDGET_INIT_PROC_NAME));
199 if (NULL == onWidgetInitProc) {
201 _E("Failed to read onWidgetInit symbol %s", m_context->pluginFilePath.getLibraryName().c_str());
202 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
205 // obtain feature -> dev-cap mapping
206 feature_mapping_interface_t mappingInterface = { NULL, NULL, NULL };
207 (*onWidgetInitProc)(&mappingInterface);
209 if (!mappingInterface.featGetter || !mappingInterface.release ||
210 !mappingInterface.dcGetter)
212 _E("Failed to obtain mapping interface from .so");
213 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
216 feature_mapping_t* devcapMapping = mappingInterface.featGetter();
218 _D("Getting mapping from features to device capabilities");
220 for (size_t i = 0; i < devcapMapping->featuresCount; ++i) {
221 PluginMetafileData::Feature feature;
222 feature.m_name = devcapMapping->features[i].feature_name;
224 _D("Feature: %s", feature.m_name.c_str());
226 const devcaps_t* dc =
227 mappingInterface.dcGetter(
229 devcapMapping->features[i].
233 _D("devcaps count: %d", dc->devCapsCount);
235 for (size_t j = 0; j < dc->devCapsCount; ++j) {
236 _D("devcap: %s", dc->deviceCaps[j]);
237 feature.m_deviceCapabilities.insert(dc->deviceCaps[j]);
241 m_pluginInfo.m_featureContainer.insert(feature);
244 mappingInterface.release(devcapMapping);
247 m_libraryObjects = PluginObjectsPtr(new PluginObjects());
248 const js_entity_definition_t *rawEntityListIterator = rawEntityList;
251 _D("##### Plugin: %s supports new plugin API",
252 m_context->pluginFilePath.getLibraryName().c_str());
255 while (rawEntityListIterator->parent_name != NULL &&
256 rawEntityListIterator->object_name != NULL)
258 _D("##### [%s]: ", rawEntityListIterator->object_name);
259 _D("##### Parent: %s", rawEntityListIterator->parent_name);
262 m_libraryObjects->addObjects(rawEntityListIterator->parent_name,
263 rawEntityListIterator->object_name);
265 ++rawEntityListIterator;
269 if (dlclose(dlHandle) != 0) {
270 _E("Cannot close plugin handle");
272 _D("Library is unloaded");
276 _D("Library successfuly loaded and parsed");
278 SET_PLUGIN_INSTALL_PROGRESS(LOADING_LIBRARY, "Library loaded and analyzed");
281 void PluginInstallTask::stepRegisterPlugin()
283 _D("Plugin installation: step register Plugin");
286 PluginDAO::registerPlugin(m_pluginInfo, m_context->pluginFilePath.Fullpath());
288 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_PLUGIN, "Plugin registered");
291 void PluginInstallTask::stepRegisterFeatures()
293 _D("Plugin installation: step register features");
295 FOREACH(it, m_pluginInfo.m_featureContainer)
297 _D("PluginHandle: %d", m_pluginHandle);
298 FeatureDAO::RegisterFeature(*it, m_pluginHandle);
300 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_FEATURES, "Features registered");
303 void PluginInstallTask::stepRegisterPluginObjects()
305 _D("Plugin installation: step register objects");
307 DISABLE_IF_PLUGIN_WITHOUT_LIB()
309 //register implemented objects
310 PluginObjects::ObjectsPtr objects =
311 m_libraryObjects->getImplementedObject();
313 FOREACH(it, *objects)
315 PluginDAO::registerPluginImplementedObject(*it, m_pluginHandle);
318 //register requiredObjects
319 objects = m_libraryObjects->getDependentObjects();
321 FOREACH(it, *objects)
323 if (m_libraryObjects->hasObject(*it)) {
324 _D("Dependency from the same library. ignored");
328 PluginDAO::registerPluginRequiredObject(*it, m_pluginHandle);
331 SET_PLUGIN_INSTALL_PROGRESS(REGISTER_OBJECTS, "Plugin Objects registered");
334 void PluginInstallTask::stepResolvePluginDependencies()
336 _D("Plugin installation: step resolve dependencies ");
338 //DISABLE_IF_PLUGIN_WITHOUT_LIB
339 if (m_pluginInfo.m_libraryName.empty()) {
340 PluginDAO::setPluginInstallationStatus(
343 INSTALLATION_COMPLETED);
344 //Installation completed
345 m_context->pluginHandle = m_pluginHandle;
346 m_context->installationCompleted = true;
347 _W("Plugin without library.");
351 PluginHandleSetPtr handles = PluginHandleSetPtr(new PluginHandleSet);
353 DbPluginHandle handle = INVALID_PLUGIN_HANDLE;
355 //register requiredObjects
356 FOREACH(it, *(m_libraryObjects->getDependentObjects()))
358 if (m_libraryObjects->hasObject(*it)) {
359 _D("Dependency from the same library. ignored");
363 handle = PluginDAO::getPluginHandleForImplementedObject(*it);
364 if (handle == INVALID_PLUGIN_HANDLE) {
365 _E("Library implementing: %s NOT FOUND", (*it).c_str());
366 PluginDAO::setPluginInstallationStatus(
368 PluginDAO::INSTALLATION_WAITING);
372 handles->insert(handle);
375 PluginDAO::registerPluginLibrariesDependencies(m_pluginHandle, handles);
377 PluginDAO::setPluginInstallationStatus(m_pluginHandle,
378 PluginDAO::INSTALLATION_COMPLETED);
380 //Installation completed
381 m_context->pluginHandle = m_pluginHandle;
382 m_context->installationCompleted = true;
384 SET_PLUGIN_INSTALL_PROGRESS(RESOLVE_DEPENDENCIES, "Dependencies resolved");
387 #undef SET_PLUGIN_INSTALL_PROGRESS
389 } //namespace PluginInstall