Merge "Fixing issues found by prevent2 (49866)"
[framework/web/wrt-installer.git] / src / jobs / plugin_install / plugin_install_task.cpp
index 218e10b..65333ba 100644 (file)
@@ -28,6 +28,7 @@
 
 //WRT INCLUDES
 #include <dpl/log/log.h>
+#include <dpl/foreach.h>
 #include <job.h>
 #include "plugin_install_task.h"
 #include "job_plugin_install.h"
@@ -39,6 +40,7 @@
 #include <dpl/wrt-dao-rw/feature_dao.h>
 #include <dpl/wrt-dao-rw/plugin_dao.h>
 #include "plugin_objects.h"
+#include <wrt_plugin_export.h>
 
 using namespace WrtDB;
 
@@ -50,14 +52,24 @@ const std::string DIRECTORY_SEPARATOR = std::string("/");
     m_context->installerTask->UpdateProgress(               \
         PluginInstallerContext::step, desc);
 
+#define DISABLE_IF_PLUGIN_WITHOUT_LIB()        \
+    if (m_pluginInfo.m_libraryName.empty()) \
+    {                                          \
+        LogWarning("Plugin without library."); \
+        return;                                \
+    }
+
 namespace Jobs {
 namespace PluginInstall {
 PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) :
     DPL::TaskDecl<PluginInstallTask>(this),
-    m_context(inCont)
+    m_context(inCont),
+    m_pluginHandle(0),
+    m_dataFromConfigXML(true)
 {
     AddStep(&PluginInstallTask::stepCheckPluginPath);
     AddStep(&PluginInstallTask::stepParseConfigFile);
+    AddStep(&PluginInstallTask::stepFindPluginLibrary);
     AddStep(&PluginInstallTask::stepCheckIfAlreadyInstalled);
     AddStep(&PluginInstallTask::stepLoadPluginLibrary);
     AddStep(&PluginInstallTask::stepRegisterPlugin);
@@ -69,8 +81,7 @@ PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) :
 }
 
 PluginInstallTask::~PluginInstallTask()
-{
-}
+{}
 
 void PluginInstallTask::stepCheckPluginPath()
 {
@@ -95,16 +106,31 @@ void PluginInstallTask::stepParseConfigFile()
 {
     LogInfo("Plugin installation: step parse config file");
 
+    struct stat tmp;
+
     std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
         std::string(GlobalConfig::GetPluginMetafileName());
 
+    if (-1 == stat(filename.c_str(), &tmp)) {
+        m_dataFromConfigXML = false;
+        return;
+    }
+
     LogInfo("Plugin Config file::" << filename);
 
     Try
     {
         PluginMetafileReader reader;
         reader.initialize(filename);
-        reader.read(m_pluginMetafile);
+        reader.read(m_pluginInfo);
+
+        FOREACH(it, m_pluginInfo.m_featureContainer)
+        {
+            LogDebug("Parsed feature : " << it->m_name);
+            FOREACH(devCap, it->m_deviceCapabilities) {
+                LogDebug("  |  DevCap : " << *devCap);
+            }
+        }
 
         SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Config file analyzed");
     }
@@ -116,9 +142,31 @@ void PluginInstallTask::stepParseConfigFile()
     }
 }
 
+void PluginInstallTask::stepFindPluginLibrary()
+{
+    if (m_dataFromConfigXML) {
+        return;
+    }
+    LogDebug("Plugin installation: step find plugin library");
+    std::string pluginPath = m_context->pluginFilePath;
+    size_t indexpos = pluginPath.find_last_of('/');
+
+    if (std::string::npos == indexpos) {
+        indexpos = 0;
+    } else {
+        indexpos += 1;  // move after '/'
+    }
+
+    std::string libName = pluginPath.substr(indexpos);
+    libName = GlobalConfig::GetPluginPrefix() + libName +
+        GlobalConfig::GetPluginSuffix();
+    LogDebug("Plugin .so: " << libName);
+    m_pluginInfo.m_libraryName = libName;
+}
+
 void PluginInstallTask::stepCheckIfAlreadyInstalled()
 {
-    if (PluginDAO::isPluginInstalled(m_pluginMetafile.m_libraryName)) {
+    if (PluginDAO::isPluginInstalled(m_pluginInfo.m_libraryName)) {
         ThrowMsg(Exceptions::PluginAlreadyInstalled,
                  "Plugin already installed");
     }
@@ -130,72 +178,129 @@ void PluginInstallTask::stepLoadPluginLibrary()
 {
     LogInfo("Plugin installation: step load library");
 
+    DISABLE_IF_PLUGIN_WITHOUT_LIB()
+
     std::string filename = m_context->pluginFilePath + DIRECTORY_SEPARATOR +
-        m_pluginMetafile.m_libraryName;
+        m_pluginInfo.m_libraryName;
 
     LogDebug("Loading plugin: " << filename);
 
     void *dlHandle = dlopen(filename.c_str(), RTLD_LAZY);
-    if (dlHandle == NULL ) {
+    if (dlHandle == NULL) {
+        const char* error = (const char*)dlerror();
         LogError(
-                "Failed to load plugin: " << filename <<
-                ". Reason: " << dlerror());
+            "Failed to load plugin: " << filename <<
+            ". Reason: " << (error != NULL ? error : "unknown"));
         ThrowMsg(Exceptions::PluginLibraryError, "Library error");
     }
 
-    const class_definition_t *rawClassList = NULL;
-    get_widget_class_map_proc *getWidgetClassMapProcPtr = NULL;
+    const js_entity_definition_t *rawEntityList = NULL;
+    get_widget_entity_map_proc *getWidgetEntityMapProcPtr = NULL;
 
-    getWidgetClassMapProcPtr =
-        reinterpret_cast<get_widget_class_map_proc *>(dlsym(dlHandle,
-                    PLUGIN_GET_CLASS_MAP_PROC_NAME));
+    getWidgetEntityMapProcPtr =
+        reinterpret_cast<get_widget_entity_map_proc *>(dlsym(dlHandle,
+                                                             PLUGIN_GET_CLASS_MAP_PROC_NAME));
 
-    if (getWidgetClassMapProcPtr) {
-        rawClassList = (*getWidgetClassMapProcPtr)();
+    if (getWidgetEntityMapProcPtr) {
+        rawEntityList = (*getWidgetEntityMapProcPtr)();
     } else {
-        rawClassList =
-            static_cast<const class_definition_t *>(dlsym(dlHandle,
-                        PLUGIN_CLASS_MAP_NAME));
+        rawEntityList =
+            static_cast<const js_entity_definition_t *>(dlsym(dlHandle,
+                                                              PLUGIN_CLASS_MAP_NAME));
     }
 
-    if (rawClassList == NULL) {
+    if (rawEntityList == NULL) {
         dlclose(dlHandle);
         LogError("Failed to read class name" << filename);
         ThrowMsg(Exceptions::PluginLibraryError, "Library error");
     }
 
+    if (!m_dataFromConfigXML) {
+        on_widget_init_proc *onWidgetInitProc =
+            reinterpret_cast<on_widget_init_proc *>(
+                dlsym(dlHandle, PLUGIN_WIDGET_INIT_PROC_NAME));
+
+        if (NULL == onWidgetInitProc) {
+            dlclose(dlHandle);
+            LogError("Failed to read onWidgetInit symbol" << filename);
+            ThrowMsg(Exceptions::PluginLibraryError, "Library error");
+        }
+
+        // obtain feature -> dev-cap mapping
+        feature_mapping_interface_t mappingInterface = { NULL, NULL, NULL };
+        (*onWidgetInitProc)(&mappingInterface);
+
+        if (!mappingInterface.featGetter || !mappingInterface.release ||
+            !mappingInterface.dcGetter)
+        {
+            LogError("Failed to obtain mapping interface from .so");
+            ThrowMsg(Exceptions::PluginLibraryError, "Library error");
+        }
+
+        feature_mapping_t* devcapMapping = mappingInterface.featGetter();
+
+        LogDebug("Getting mapping from features to device capabilities");
+
+        for (size_t i = 0; i < devcapMapping->featuresCount; ++i) {
+            PluginMetafileData::Feature feature;
+            feature.m_name = devcapMapping->features[i].feature_name;
+
+            LogDebug("Feature: " << feature.m_name);
+
+            const devcaps_t* dc =
+                mappingInterface.dcGetter(
+                    devcapMapping,
+                    devcapMapping->features[i].
+                        feature_name);
+
+            LogDebug("device=cap: " << dc);
+
+            if (dc) {
+                LogDebug("devcaps count: " << dc->devCapsCount);
+
+                for (size_t j = 0; j < dc->devCapsCount; ++j) {
+                    LogDebug("devcap: " << dc->deviceCaps[j]);
+                    feature.m_deviceCapabilities.insert(dc->deviceCaps[j]);
+                }
+            }
+
+            m_pluginInfo.m_featureContainer.insert(feature);
+        }
+
+        mappingInterface.release(devcapMapping);
+    }
+
     m_libraryObjects = PluginObjectsPtr(new PluginObjects());
-    const class_definition_t *rawClassListIterator = rawClassList;
+    const js_entity_definition_t *rawEntityListIterator = rawEntityList;
 
     LogInfo("#####");
     LogInfo("##### Plugin: " << filename << " supports new plugin API");
     LogInfo("#####");
 
-    while (rawClassListIterator->parent_name != NULL &&
-            rawClassListIterator->object_name != NULL &&
-            rawClassListIterator->js_class_template != NULL) {
-        LogInfo("#####     [" << rawClassListIterator->object_name << "]: ");
-        LogInfo("#####     Parent: " << rawClassListIterator->parent_name);
+    while (rawEntityListIterator->parent_name != NULL &&
+           rawEntityListIterator->object_name != NULL)
+    {
+        LogInfo("#####     [" << rawEntityListIterator->object_name << "]: ");
+        LogInfo("#####     Parent: " << rawEntityListIterator->parent_name);
         LogInfo("#####");
 
-        m_libraryObjects->addObjects(rawClassListIterator->parent_name,
-                rawClassListIterator->object_name);
+        m_libraryObjects->addObjects(rawEntityListIterator->parent_name,
+                                     rawEntityListIterator->object_name);
 
-        ++rawClassListIterator;
-}
+        ++rawEntityListIterator;
+    }
 
-// Unload library
-if (dlclose(dlHandle) != 0) {
-    LogError("Cannot close plugin handle");
-} else {
-    LogDebug("Library is unloaded");
-}
+    // Unload library
+    if (dlclose(dlHandle) != 0) {
+        LogError("Cannot close plugin handle");
+    } else {
+        LogDebug("Library is unloaded");
+    }
 
     // Load export table
     LogDebug("Library successfuly loaded and parsed");
 
     SET_PLUGIN_INSTALL_PROGRESS(LOADING_LIBRARY, "Library loaded and analyzed");
-    //TODO unload library;
 }
 
 void PluginInstallTask::stepRegisterPlugin()
@@ -203,7 +308,7 @@ void PluginInstallTask::stepRegisterPlugin()
     LogInfo("Plugin installation: step register Plugin");
 
     m_pluginHandle =
-        PluginDAO::registerPlugin(m_pluginMetafile, m_context->pluginFilePath);
+        PluginDAO::registerPlugin(m_pluginInfo, m_context->pluginFilePath);
 
     SET_PLUGIN_INSTALL_PROGRESS(REGISTER_PLUGIN, "Plugin registered");
 }
@@ -212,7 +317,7 @@ void PluginInstallTask::stepRegisterFeatures()
 {
     LogInfo("Plugin installation: step register features");
 
-    FOREACH(it, m_pluginMetafile.m_featureContainer)
+    FOREACH(it, m_pluginInfo.m_featureContainer)
     {
         LogError("PluginHandle: " << m_pluginHandle);
         FeatureDAO::RegisterFeature(*it, m_pluginHandle);
@@ -224,6 +329,8 @@ void PluginInstallTask::stepRegisterPluginObjects()
 {
     LogInfo("Plugin installation: step register objects");
 
+    DISABLE_IF_PLUGIN_WITHOUT_LIB()
+
     //register implemented objects
     PluginObjects::ObjectsPtr objects =
         m_libraryObjects->getImplementedObject();
@@ -253,6 +360,19 @@ void PluginInstallTask::stepResolvePluginDependencies()
 {
     LogInfo("Plugin installation: step resolve dependencies ");
 
+    //DISABLE_IF_PLUGIN_WITHOUT_LIB
+    if (m_pluginInfo.m_libraryName.empty()) {
+        PluginDAO::setPluginInstallationStatus(
+            m_pluginHandle,
+            PluginDAO::
+                INSTALLATION_COMPLETED);
+        //Installation completed
+        m_context->pluginHandle = m_pluginHandle;
+        m_context->installationCompleted = true;
+        LogWarning("Plugin without library.");
+        return;
+    }
+
     PluginHandleSetPtr handles = PluginHandleSetPtr(new PluginHandleSet);
 
     DbPluginHandle handle = INVALID_PLUGIN_HANDLE;