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>
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"
43 #include <PluginRegistry.h>
45 #include <IObject_cast.h>
46 #include <SoFeatures.h>
47 #include <ExportedApi.h>
49 using namespace WrtDB;
50 using namespace WrtPluginsApi;
53 const std::string DIRECTORY_SEPARATOR = std::string("/");
56 #define SET_PLUGIN_INSTALL_PROGRESS(step, desc) \
57 m_context->installerTask->UpdateProgress( \
58 PluginInstallerContext::step, desc);
60 #define DISABLE_IF_PLUGIN_WITHOUT_LIB() \
61 if(m_pluginInfo.m_libraryName.empty()) \
63 LogWarning("Plugin without library."); \
68 namespace PluginInstall {
70 PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) :
71 DPL::TaskDecl<PluginInstallTask>(this),
73 m_dataFromConfigXML(true)
75 AddStep(&PluginInstallTask::stepCheckPluginPath);
76 AddStep(&PluginInstallTask::stepParseConfigFile);
77 AddStep(&PluginInstallTask::stepFindPluginLibrary);
78 AddStep(&PluginInstallTask::stepCheckIfAlreadyInstalled);
79 AddStep(&PluginInstallTask::stepLoadPluginLibrary);
80 AddStep(&PluginInstallTask::stepRegisterPlugin);
81 AddStep(&PluginInstallTask::stepRegisterFeatures);
82 AddStep(&PluginInstallTask::stepRegisterPluginObjects);
83 AddStep(&PluginInstallTask::stepResolvePluginDependencies);
85 SET_PLUGIN_INSTALL_PROGRESS(START, "Installation initialized");
88 PluginInstallTask::~PluginInstallTask()
92 void PluginInstallTask::stepCheckPluginPath()
94 LogInfo("Plugin installation: step CheckPluginPath");
98 if (-1 == stat(m_context->pluginFilePath.c_str(), &tmp)) {
99 ThrowMsg(Exceptions::PluginPathFailed,
100 "Stat function failed");
103 if (!S_ISDIR(tmp.st_mode)) {
104 ThrowMsg(Exceptions::PluginPathFailed,
105 "Invalid Directory");
108 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Path to plugin verified");
111 void PluginInstallTask::stepParseConfigFile()
113 LogInfo("Plugin installation: step parse config file");
117 std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
118 std::string(GlobalConfig::GetPluginMetafileName());
120 if (-1 == stat(filename.c_str(), &tmp)) {
121 m_dataFromConfigXML = false;
125 LogInfo("Plugin Config file::" << filename);
129 PluginMetafileReader reader;
130 reader.initialize(filename);
131 reader.read(m_pluginInfo);
133 FOREACH(it, m_pluginInfo.m_featureContainer)
135 LogDebug("Parsed feature : " << it->m_name);
136 FOREACH (devCap, it->m_deviceCapabilities) {
137 LogDebug(" | DevCap : " << *devCap);
141 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Config file analyzed");
143 Catch(ValidationCore::ParserSchemaException::Base)
145 LogError("Error during file processing " << filename);
146 ThrowMsg(Exceptions::PluginMetafileFailed,
151 void PluginInstallTask::stepFindPluginLibrary()
153 if (m_dataFromConfigXML)
157 LogDebug("Plugin installation: step find plugin library");
158 std::string pluginPath = m_context->pluginFilePath;
159 size_t indexpos = pluginPath.find_last_of('/');
161 if (std::string::npos == indexpos)
167 indexpos += 1; // move after '/'
170 std::string libName = pluginPath.substr(indexpos);
171 libName = GlobalConfig::GetPluginPrefix() + libName + GlobalConfig::GetPluginSuffix();
172 LogDebug("Plugin .so: " << libName);
173 m_pluginInfo.m_libraryName = libName;
176 void PluginInstallTask::stepCheckIfAlreadyInstalled()
178 if (PluginDAO::isPluginInstalled(m_pluginInfo.m_libraryName)) {
179 ThrowMsg(Exceptions::PluginAlreadyInstalled,
180 "Plugin already installed");
183 SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_EXISTS_CHECK, "Check if plugin exist");
186 void PluginInstallTask::stepLoadPluginLibrary()
188 LogInfo("Plugin installation: step load library");
190 DISABLE_IF_PLUGIN_WITHOUT_LIB()
192 std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
193 m_pluginInfo.m_libraryName;
195 LogDebug("Loading plugin: " << filename);
197 void *dlHandle = dlopen(filename.c_str(), RTLD_NOW);
198 if (dlHandle == NULL ) {
200 "Failed to load plugin: " << filename <<
201 ". Reason: " << dlerror());
202 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
206 PluginRegistry registry;
211 plugin = registry.GetPlugin(filename);
213 Catch(DPL::Exception)
215 LogError("Loading library failed " << filename);
216 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
221 LogError("Failed to open library" << filename);
222 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
225 m_libraryObjects = PluginObjectsPtr(new PluginObjects());
228 LogInfo("##### Plugin: " << filename << " supports new plugin API");
231 FOREACH(o, *plugin->GetObjects())
233 m_libraryObjects->addObjects(CAST(*o)->GetParentName(),
234 CAST(*o)->GetName());
236 LogDebug("[Parent << Object] " << CAST(*o)->GetParentName()
238 << CAST(*o)->GetName());
240 registerObjects(plugin->GetObjects());
244 if (!m_dataFromConfigXML)
246 ExportedApi* entryPoint =
247 static_cast<ExportedApi*>(dlsym(dlHandle, GetExportedSymbolName()));
248 if (NULL == entryPoint)
250 LogError("Error: " << dlerror());
251 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
254 // obtain feature -> dev-cap mapping
255 feature_mapping_interface_t mappingInterface = { NULL, NULL, NULL };
256 entryPoint->GetProvidedFeatures(&mappingInterface);
258 if (!mappingInterface.featGetter || !mappingInterface.release ||
259 !mappingInterface.dcGetter)
261 LogError("Failed to obtain mapping interface from .so");
262 ThrowMsg(Exceptions::PluginLibraryError, "Library error");
265 feature_mapping_t* devcapMapping = mappingInterface.featGetter();
267 LogDebug("Getting mapping from features to device capabilities");
269 for (size_t i = 0; i < devcapMapping->featuresCount; ++i)
271 PluginMetafileData::Feature feature;
272 feature.m_name = devcapMapping->features[i].feature_name;
274 LogDebug("Feature: " << feature.m_name);
276 const devcaps_t* dc =
277 mappingInterface.dcGetter(devcapMapping,
278 devcapMapping->features[i].feature_name);
280 LogDebug("device=cap: " << dc);
284 LogDebug("devcaps count: " << dc->devCapsCount);
286 for (size_t j = 0; j < dc->devCapsCount; ++j)
288 LogDebug("devcap: " << dc->deviceCaps[j]);
289 feature.m_deviceCapabilities.insert(dc->deviceCaps[j]);
293 m_pluginInfo.m_featureContainer.insert(feature);
296 mappingInterface.release(devcapMapping);
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 void PluginInstallTask::registerObjects(const IObjectsListPtr& objects)
419 LogDebug("registerObjects invoked");
423 auto children = CAST(*o)->GetChildren();
427 FOREACH(c, *children)
429 m_libraryObjects->addObjects(CAST(*o)->GetName(),
430 CAST(*c)->GetName());
432 LogDebug("[Parent << Object] " << CAST(*c)->GetName()
434 << CAST(*o)->GetName());
437 registerObjects(children);
442 #undef SET_PLUGIN_INSTALL_PROGRESS
444 } //namespace PluginInstall