[Feature] Integration step_parse for TPK tizen_manifest.xml file with manifest_parser 17/46517/12
authorMaciej Socha <m.socha@samsung.com>
Thu, 20 Aug 2015 12:25:48 +0000 (14:25 +0200)
committerPawel Sikorski <p.sikorski@samsung.com>
Thu, 1 Oct 2015 08:46:31 +0000 (01:46 -0700)
Change-Id: I109956932b81e8af4fe2cbe54b5525292754555f

CMakeLists.txt
src/tpk/CMakeLists.txt
src/tpk/step/step_parse.cc
src/tpk/step/step_parse.h

index 5ef2690..af8c94a 100644 (file)
@@ -47,6 +47,7 @@ PKG_CHECK_MODULES(TZPLATFORM_CONFIG_DEPS REQUIRED libtzplatform-config)
 PKG_CHECK_MODULES(SECURITY_MANAGER_DEPS REQUIRED security-manager)
 PKG_CHECK_MODULES(MANIFEST_PARSER_DEPS REQUIRED manifest-parser)
 PKG_CHECK_MODULES(MANIFEST_HANDLERS_DEPS REQUIRED manifest-handlers)
+PKG_CHECK_MODULES(TPK_MANIFEST_HANDLERS_DEPS REQUIRED tpk-manifest-handlers)
 PKG_CHECK_MODULES(CERT_SVC_DEPS_VCORE REQUIRED cert-svc-vcore)
 PKG_CHECK_MODULES(PKGMGR_PARSER_DEPS REQUIRED pkgmgr-parser)
 PKG_CHECK_MODULES(PKGMGR_INFO_DEPS REQUIRED pkgmgr-info)
index 19c3260..d94af55 100644 (file)
@@ -15,6 +15,8 @@ TARGET_INCLUDE_DIRECTORIES(${TARGET_TPK_BACKEND} PUBLIC "${CMAKE_CURRENT_SOURCE_
 
 APPLY_PKG_CONFIG(${TARGET_LIBNAME_TPK}
   PUBLIC PKGMGR_DEPS
+  TPK_MANIFEST_HANDLERS_DEPS
+  MANIFEST_PARSER_DEPS
   Boost
 )
 TARGET_LINK_LIBRARIES(${TARGET_LIBNAME_TPK} PUBLIC ${TARGET_LIBNAME_COMMON})
index 78265df..96149a7 100644 (file)
-/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
-#include "tpk/step/step_parse.h"
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
 
-#include <boost/filesystem.hpp>
+#include "tpk/step/step_parse.h"
 
+#include <tpk_manifest_handlers/account_handler.h>
+#include <tpk_manifest_handlers/application_manifest_constants.h>
+#include <tpk_manifest_handlers/author_handler.h>
+#include <tpk_manifest_handlers/description_handler.h>
+#include <tpk_manifest_handlers/package_handler.h>
+#include <tpk_manifest_handlers/privileges_handler.h>
+#include <tpk_manifest_handlers/service_application_handler.h>
+#include <tpk_manifest_handlers/ui_application_handler.h>
+#include <manifest_parser/manifest_constants.h>
+
+#include <pkgmgr/pkgmgr_parser.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
 #include <memory>
+#include <set>
 #include <string>
 #include <vector>
 
+#include "common/app_installer.h"
 #include "common/context_installer.h"
 #include "common/step/step.h"
-
-using std::vector;
-using std::string;
-using xml_parser::XmlParser;
-using xml_parser::XmlTree;
-using xml_parser::XmlElement;
-
-namespace bf = boost::filesystem;
-namespace ci = common_installer;
+#include "utils/clist_helpers.h"
 
 namespace tpk {
-
 namespace parse {
 
-namespace {
-  const char kManifestFileName[] = "tizen-manifest.xml";
-
-  XmlElement* Get1stChild(XmlTree *tree,
-      XmlElement* parent, const string element_name) {
-    vector<XmlElement*> v = tree->Children(parent, element_name);
-    if (v.size() < 1) {
-      LOG(DEBUG) << element_name << " is not found as a child of " <<
-          parent->name();
-      return nullptr;
-    }
-    return v[0];  // Always return only the 1st child
-  }
-
-  const char* string_strdup(const string &s) {
-    static const string nullstr = XmlElement::null_string();
-    if (s == XmlElement::null_string()) {
-      return nullptr;
-    }
-    return strdup(s.c_str());
-  }
-
-  // Set child element's data structure, based on given parent and
-  // children name.
-  // setter's arguments
-  //     T*: Child data structure's pointer
-  //     L: setter function(XmlElement* element, T* child_struct)
-  //     tree: tree pointer
-  //     parent: parent XmlElement object
-  //     childName: child name
-  //     setter : child element setter (lambda function)
-  template <typename T, typename L>
-    bool SetChildren(T** listptr, XmlTree* tree, XmlElement* parent,
-        const char* childName, L setter) {
-      vector<XmlElement*> v = tree->Children(parent, childName);
-      for (auto& el : v) {
-        T* p = static_cast<T*>(calloc(1, sizeof(T)));
-        setter(el, p);
-        LISTADD(*listptr, p);
-      }
-      return true;
-    }
-
-}  // namespace
-
-/* short namespace/class name */
-typedef common_installer::Step::Status Status;
-using boost::filesystem::path;
+namespace app_keys = tpk::application_keys;
+namespace bf = boost::filesystem;
+namespace manifest_keys = tpk::manifest_keys;
 
-Status StepParse::precheck() {
+common_installer::Step::Status StepParse::precheck() {
   if (context_->unpacked_dir_path.get().empty()) {
-      LOG(ERROR) << "unpacked_dir_path attribute is empty";
-      return Step::Status::INVALID_VALUE;
+    LOG(ERROR) << "unpacked_dir_path attribute is empty";
+    return common_installer::Step::Status::INVALID_VALUE;
   }
   if (!boost::filesystem::exists(context_->unpacked_dir_path.get())) {
     LOG(ERROR) << "unpacked_dir_path ("
                << context_->unpacked_dir_path.get()
                << ") path does not exist";
-    return Step::Status::INVALID_VALUE;
+    return common_installer::Step::Status::INVALID_VALUE;
   }
 
   boost::filesystem::path tmp(context_->unpacked_dir_path.get());
-  tmp /= kManifestFileName;
+  tmp /= manifest_keys::kManifestFileName;
 
   if (!boost::filesystem::exists(tmp)) {
-    LOG(ERROR) << kManifestFileName << " not found from the package";
-    return Step::Status::INVALID_VALUE;
+    LOG(ERROR) << manifest_keys::kManifestFileName
+               << " not found from the package";
+    return common_installer::Step::Status::INVALID_VALUE;
   }
 
-  return Step::Status::OK;
+  return common_installer::Step::Status::OK;
 }
 
+// Locating tizen-manifest.xml file
+bool StepParse::LocateConfigFile() {
+  boost::filesystem::path manifest = context_->unpacked_dir_path.get();
+  manifest /= manifest_keys::kManifestFileName;
+
+  LOG(DEBUG) << "tizen_manifest.xml path: " << manifest;
+
+  if (!boost::filesystem::exists(manifest))
+    return false;
+
+  path_ = manifest;
+  return true;
+}
+
+// Function neded by step_recovery
 bf::path StepParse::LocateConfigFile() const {
   boost::filesystem::path path(context_->unpacked_dir_path.get());
-  path /= kManifestFileName;
+  path /= manifest_keys::kManifestFileName;
   return path;
 }
 
-/* process()
- * Parse tizen-manifest.xml and get the data from it
- * Store the data into the context_
- */
-Status StepParse::process() {
-  bf::path m_path = LocateConfigFile();
+// package info
+bool StepParse::FillPackageInfo(manifest_x* manifest) {
+  std::shared_ptr<const PackageInfo> app_info =
+      std::static_pointer_cast<const PackageInfo>(
+          parser_->GetManifestData(manifest_keys::kManifestKey));
+  if (!app_info) {
+    LOG(ERROR) << "Application info manifest data has not been found.";
+    return false;
+  }
 
-  LOG(INFO) << "Parse " << m_path.c_str();
+  std::shared_ptr<const UIApplicationInfoList> ui_application_list =
+      std::static_pointer_cast<const UIApplicationInfoList>(
+          parser_->GetManifestData(app_keys::kUIApplicationKey));
+  std::shared_ptr<const ServiceApplicationInfoList> service_application_list =
+      std::static_pointer_cast<const ServiceApplicationInfoList>(
+          parser_->GetManifestData(app_keys::kServiceApplicationKey));
+
+  // mandatory check
+  if (!ui_application_list && !service_application_list) {
+    LOG(ERROR) << "UI Application or Service Application "
+                  "are mandatory and has not been found.";
+    return false;
+  }
 
-  XmlParser parser;
-  std::unique_ptr<XmlTree> tree(parser.ParseAndGetNewTree(m_path.c_str()));
-  if (tree == nullptr) {
-    LOG(ERROR) << "Failure on parsing xml";
-    return Status::ERROR;
+  manifest->package = strdup(app_info->package().c_str());
+  manifest->type = strdup("tpk");
+  manifest->version = strdup(app_info->version().c_str());
+  manifest->installlocation = strdup(app_info->install_location().c_str());
+  manifest->api_version = strdup(app_info->api_version().c_str());
+
+  if (ui_application_list) {
+    manifest->mainapp_id =
+        strdup(ui_application_list->items[0].ui_info.appid().c_str());
+  } else {
+    manifest->mainapp_id =
+        strdup(service_application_list->items[0].sa_info.appid().c_str());
   }
-  if (!SetContextByManifestParser(tree.get())) {
-    return Status::ERROR;
+  return true;
+}
+
+// author
+bool StepParse::FillAuthorInfo(manifest_x* manifest) {
+  std::shared_ptr<const AuthorInfo> author_info =
+      std::static_pointer_cast<const AuthorInfo>(
+          parser_->GetManifestData(app_keys::kAuthorKey));
+
+  if (!author_info) {
+    LOG(ERROR) << "Author data has not been found.";
+    return false;
   }
-  return Status::OK;
+
+  author_x* author = reinterpret_cast<author_x*>(calloc(1, sizeof(author_x)));
+  author->text = strdup(author_info->name().c_str());
+  author->email = strdup(author_info->email().c_str());
+  author->href = strdup(author_info->href().c_str());
+  LISTADD(manifest->author, author);
+  return true;
 }
 
-/* Read manifest xml, and set up context_ object
- */
-bool StepParse::SetContextByManifestParser(XmlTree* tree) {
-  // Get required elements
-  XmlElement* manifest,
-      * ui_application, * service_application, * label;
+// description
+bool StepParse::FillDescription(manifest_x* manifest) {
+  std::shared_ptr<const DescriptionInfo> description_info =
+      std::static_pointer_cast<const DescriptionInfo>(
+          parser_->GetManifestData(app_keys::kDescriptionKey));
 
-  // manifest
-  if (nullptr == (manifest = tree->GetRootElement())) {
-    LOG(ERROR) << "No mandatory manifest element in xml";
+  if (!description_info) {
+    LOG(ERROR) << "Description data has not been found.";
     return false;
   }
 
-  LOG(DEBUG) << "Getting manifest xml data";
-  LOG(DEBUG) << "manifest: xmlns='" << manifest->attr("xmlns") <<
-                "' api-version='" << manifest->attr("api-version") <<
-                "' package='" << manifest->attr("package") <<
-                "' versionr='" << manifest->attr("version") << "'";
-
-  // At least one of ui_application or service_application must be given
-  ui_application = Get1stChild(tree, manifest, "ui-application");
-  service_application = Get1stChild(tree, manifest, "service-application");
-  if (nullptr == ui_application && nullptr == service_application) {
-    LOG(ERROR) << "Neither <ui-application> nor <service-application>" <<
-        " element is found in manifest xml";
+  description_x* description = reinterpret_cast<description_x*>
+      (calloc(1, sizeof(description_x)));
+  description->text = strdup(description_info->description().c_str());
+  description->lang = strdup(description_info->xml_lang().c_str());
+  LISTADD(manifest->description, description);
+  return true;
+}
+
+// privileges
+bool StepParse::FillPrivileges(manifest_x* manifest) {
+  std::shared_ptr<const PrivilegesInfo> perm_info =
+      std::static_pointer_cast<const PrivilegesInfo>(parser_->GetManifestData(
+          app_keys::kPrivilegeKey));
+  std::set<std::string> privileges;
+
+  if (perm_info) {
+    privileges = perm_info->GetPrivileges();
+  }
+
+  if (!privileges.empty()) {
+    privileges_x* privileges_x_list =
+        reinterpret_cast<privileges_x*> (calloc(1, sizeof(privileges_x)));
+    manifest->privileges = privileges_x_list;
+    for (const std::string& p : privileges) {
+      privilege_x* privilege_x_node =
+          reinterpret_cast<privilege_x*> (calloc(1, sizeof(privilege_x)));
+      privilege_x_node->text = strdup(p.c_str());
+      LISTADD(manifest->privileges->privilege, privilege_x_node);
+    }
+  }
+  return true;
+}
+
+// service application
+bool StepParse::FillServiceApplication(manifest_x* manifest) {
+  std::shared_ptr<const ServiceApplicationInfoList> service_application_list =
+      std::static_pointer_cast<const ServiceApplicationInfoList>(
+          parser_->GetManifestData(app_keys::kServiceApplicationKey));
+
+  if (!service_application_list) {
+    LOG(ERROR) << "Service Application data has not been found.";
     return false;
   }
-  // label must be given
-  label = ui_application ? Get1stChild(tree, ui_application, "label") :
-      Get1stChild(tree, service_application, "label");
-  if (nullptr == label) {
-    LOG(ERROR) << "No mandatory <label> element in manifest xml";
+
+  for (const auto& application : service_application_list->items) {
+    serviceapplication_x* service_app =
+                          static_cast<serviceapplication_x*>
+                          (calloc(1, sizeof(serviceapplication_x)));
+    service_app->appid = strdup(application.sa_info.appid().c_str());
+    service_app->autorestart =
+        strdup(application.sa_info.auto_restart().c_str());
+    service_app->exec = strdup(application.sa_info.exec().c_str());
+    service_app->onboot = strdup(application.sa_info.on_boot().c_str());
+    service_app->type = strdup(application.sa_info.type().c_str());
+    LISTADD(manifest->serviceapplication, service_app);
+
+    if (!FillAppControl(manifest->uiapplication->appcontrol,
+                        application.app_control))
+      return false;
+    if (!FillDataControl(manifest->uiapplication->datacontrol,
+                         application.data_control))
+      return false;
+    if (!FillApplicationIconPaths(manifest->uiapplication->icon,
+                                  application.app_icons))
+      return false;
+    if (!FillLabel(manifest->uiapplication->label,
+                   application.label))
+      return false;
+    if (!FillMetadata(manifest->uiapplication->metadata,
+                      application.meta_data))
+      return false;
+  }
+  return true;
+}
+
+// ui application
+bool StepParse::FillUIApplication(manifest_x* manifest) {
+  std::shared_ptr<const UIApplicationInfoList> ui_application_list =
+      std::static_pointer_cast<const UIApplicationInfoList>(
+          parser_->GetManifestData(app_keys::kUIApplicationKey));
+
+  if (!ui_application_list) {
+    LOG(ERROR) << "UI Application data has not been found.";
     return false;
   }
 
-  // set context_
-  context_->pkgid.set(manifest->attr("package"));
+  for (const auto& application : ui_application_list->items) {
+    uiapplication_x* ui_app =
+                       static_cast<uiapplication_x*>
+                       (calloc(1, sizeof(uiapplication_x)));
+    ui_app->appid = strdup(application.ui_info.appid().c_str());
+    ui_app->exec = strdup(application.ui_info.exec().c_str());
+    ui_app->multiple = strdup(application.ui_info.multiple().c_str());
+    ui_app->nodisplay = strdup(application.ui_info.nodisplay().c_str());
+    ui_app->taskmanage = strdup(application.ui_info.taskmanage().c_str());
+    ui_app->type = strdup(application.ui_info.type().c_str());
+    LISTADD(manifest->uiapplication, ui_app);
+
+    if (!FillAppControl(manifest->serviceapplication->appcontrol,
+                        application.app_control))
+      return false;
+    if (!FillDataControl(manifest->serviceapplication->datacontrol,
+                         application.data_control))
+      return false;
+    if (!FillApplicationIconPaths(manifest->serviceapplication->icon,
+                                  application.app_icons))
+      return false;
+    if (!FillLabel(manifest->serviceapplication->label,
+                   application.label))
+      return false;
+    if (!FillMetadata(manifest->serviceapplication->metadata,
+                      application.meta_data))
+      return false;
+  }
+  return true;
+}
 
-  // write pkgid for recovery file
-  if (context_->recovery_info.get().recovery_file) {
-    context_->recovery_info.get().recovery_file->set_pkgid(
-        manifest->attr("package"));
-    context_->recovery_info.get().recovery_file->WriteAndCommitFileContent();
+// app_control
+template <typename T1, typename T2>
+bool StepParse::FillAppControl(T1* manifest, const T2& app_control_list) {
+  if (!app_control_list.empty()) {
+    LOG(ERROR) << "App Control data has not been found.";
+    return false;
+  }
+
+  for (const auto& control : app_control_list) {
+    appcontrol_x* app_control =
+          static_cast<appcontrol_x*>(calloc(1, sizeof(appcontrol_x)));
+    app_control->operation = strdup(control.operation().c_str());
+    app_control->mime = strdup(control.mime().c_str());
+    app_control->uri = strdup(control.uri().c_str());
+    LISTADD(manifest, app_control);
   }
+  return true;
+}
 
-  context_->manifest_data.set(static_cast<manifest_x*>(
-      calloc(1, sizeof(manifest_x))));
+// datacontrol
+template <typename T1, typename T2>
+bool StepParse::FillDataControl(T1* manifest, const T2& data_control_list) {
+  if (!data_control_list.empty()) {
+    LOG(ERROR) << "Data Control has not been found.";
+    return false;
+  }
 
-  // set context_->manifest_data()
-  return SetPkgInfoManifest(context_->manifest_data.get(), tree, manifest);
+  for (const auto& control : data_control_list) {
+    datacontrol_x* data_control =
+          static_cast<datacontrol_x*>(calloc(1, sizeof(datacontrol_x)));
+    data_control->access = strdup(control.access().c_str());
+    data_control->providerid = strdup(control.providerid().c_str());
+    data_control->type = strdup(control.type().c_str());
+    LISTADD(manifest, data_control);
+  }
+  return true;
 }
 
+// icon
+template <typename T1, typename T2>
+bool StepParse::FillApplicationIconPaths(T1* manifest, const T2& icons_info) {
+  if (!icons_info.exists()) {
+    LOG(ERROR) << "Application icon has not been found.";
+    return false;
+  }
 
-bool StepParse::SetPkgInfoManifest(manifest_x* m,
-    XmlTree* tree,
-    XmlElement* manifest) {
+  for (auto& application_icon : icons_info.icons()) {
+    icon_x* icon = reinterpret_cast<icon_x*> (calloc(1, sizeof(icon_x)));
+    // NOTE: name is an attribute, but the xml writer uses it as text.
+    // This must be fixed in whole app-installer modules, including wgt.
+    // Current implementation is just for compatibility.
+    icon->text = strdup(application_icon.path().c_str());
+    icon->name = strdup(application_icon.path().c_str());
+    LISTADD(manifest, icon);
+  }
+  return true;
+}
 
-  // Get required elements
-  XmlElement* ui_application = Get1stChild(tree, manifest, "ui-application");
-  XmlElement* service_application = Get1stChild(tree, manifest,
-      "service-application");
-  if (!(ui_application || service_application)) {   // mandatory check
-    LOG(ERROR) << "Neither <ui-application> nor <service-application>" <<
-        " element is found in manifest xml";
+// label
+template <typename T1, typename T2>
+bool StepParse::FillLabel(T1* manifest, const T2& label_list) {
+  if (!label_list.empty()) {
+    LOG(ERROR) << "Label data has not been found.";
     return false;
   }
 
-  // manifest's attribute
-  m->package = string_strdup(manifest->attr("package"));
-  m->type = strdup("tpk");
-  m->version = string_strdup(manifest->attr("version"));
-  m->installlocation = string_strdup(manifest->attr("install-location"));
-  m->api_version = string_strdup(manifest->attr("api-version"));
-
-  // Choose main app among ui-application or service-application
-  // NOTE: main app must have appid attribute
-  XmlElement* main_app = ui_application ? ui_application : service_application;
-  m->mainapp_id = string_strdup(main_app->attr("appid"));
-
-  // manifest' attribute from children's values
-  XmlElement* label = Get1stChild(tree, main_app, "label");
-  if (label) {
-    m->label =  static_cast<label_x*>(calloc(1, sizeof(label_x)));
-    m->label->name = string_strdup(label->content());
+  for (const auto& control : label_list) {
+    label_x* label =
+          static_cast<label_x*>(calloc(1, sizeof(label_x)));
+    // NOTE: name is an attribute, but the xml writer uses it as text.
+    // This must be fixed in whole app-installer modules, including wgt.
+    // Current implementation is just for compatibility.
+    label->text = strdup(control.text().c_str());
+    label->name = strdup(control.name().c_str());
+    label->lang = strdup(control.xml_lang().c_str());
+    LISTADD(manifest, label);
+  }
+  return true;
+}
+
+// metadata
+template <typename T1, typename T2>
+bool StepParse::FillMetadata(T1* manifest, const T2& meta_data_list) {
+  if (!meta_data_list.empty()) {
+    LOG(ERROR) << "Metadata has not been found.";
+    return false;
   }
 
-  // Set children elements
-  return SetPkgInfoChildren(m, tree, manifest);
+  for (auto& meta : meta_data_list) {
+    metadata_x* metadata =
+        static_cast<metadata_x*>(calloc(1, sizeof(metadata_x)));
+    metadata->key = strdup(meta.key().c_str());
+    metadata->value = strdup(meta.val().c_str());
+    LISTADD(manifest, metadata);
+  }
+  return true;
 }
 
-// Read and fill struct hierarchy
-// The spec of tizen-manifest is referred from Tizen 2.2.1 header.
-bool StepParse::SetPkgInfoChildren(manifest_x* m,
-    XmlTree* tree, XmlElement* manifest) {
-  manifest_x* p = m;
-  XmlElement* el = manifest;
-
-  // author
-  SetChildren(&(p->author), tree, el, "author",
-      [&](XmlElement *el, author_x* p){
-    p->email = string_strdup(el->attr("email"));
-    p->href = string_strdup(el->attr("href"));
-    p->text = string_strdup(el->content());
-    // p->lang = string_strdup(el->attr("xml:lang")); // NOTE: not in spec
-  });
-
-  // description
-  SetChildren(&(p->description), tree, el, "description",
-      [&](XmlElement *el, description_x* p){
-    // p->name = string_strdup(el->attr("name"));  // NOTE: not in spec
-    p->text = string_strdup(el->content());
-    p->lang = string_strdup(el->attr("xml:lang"));  // NOTE: not in spec
-  });
-
-  // privileges
-  SetChildren(&(p->privileges), tree, el, "privileges",
-      [&](XmlElement *el, privileges_x* p){
-    // privilge
-    SetChildren(&(p->privilege), tree, el, "privilege",
-      [&](XmlElement *el, privilege_x* p){
-        p->text = string_strdup(el->content());
-        LOG(DEBUG) << "Add a privilege: " << p->text;
-    });
-  });
-
-  // service-application
-  SetChildren(&(p->serviceapplication), tree, el, "service-application",
-      [&](XmlElement *el, serviceapplication_x* p){
-    p->appid = string_strdup(el->attr("appid"));
-    p->autorestart = string_strdup(el->attr("auto-restart"));
-    p->exec = string_strdup(el->attr("exec"));
-    p->onboot = string_strdup(el->attr("on-boot"));
-    p->type = string_strdup(el->attr("type"));
-
-    // FIXME: temporary fix to avoid build break
-    // app-control
-    SetChildren(&(p->appcontrol), tree, el, "app-control",
-        [&](XmlElement *el, appcontrol_x* p){
-      vector<XmlElement*> v = tree->Children(el, "operation");
-      if (!v.empty())
-        p->operation = string_strdup(v.front()->attr("name"));
-      v = tree->Children(el, "uri");
-      if (!v.empty())
-        p->uri = string_strdup(v.front()->attr("name"));
-      v = tree->Children(el, "mime");
-      if (!v.empty())
-        p->mime = string_strdup(v.front()->attr("name"));
-    });
-
-    // datacontrol
-    SetChildren(&(p->datacontrol), tree, el, "datacontrol",
-        [&](XmlElement *el, datacontrol_x* p){
-      p->access = string_strdup(el->attr("access"));
-      p->providerid = string_strdup(el->attr("providerid"));
-      p->type = string_strdup(el->attr("type"));
-    });
-
-    // icon
-    SetChildren(&(p->icon), tree, el, "icon",
-        [&](XmlElement *el, icon_x* p) {  // NOLINT
-      p->text = string_strdup(el->content());
-      // NOTE: name is an attribute, but the xml writer uses it as text.
-      // This must be fixed in whole app-installer modules, including wgt.
-      // Current implementation is just for compatibility.
-      // p->name = string_strdup(el->attr("name"));
-      p->name = string_strdup(el->content());
-    });
-
-    // label
-    SetChildren(&(p->label), tree, el, "label",
-        [&](XmlElement *el, label_x* p) {
-      // NOTE: name is an attribute, but the xml writer uses it as text.
-      // This must be fixed in whole app-installer modules, including wgt.
-      // Current implementation is just for compatibility.
-      // p->name = string_strdup(el->attr("name"));
-      p->text = string_strdup(el->content());
-      p->name = string_strdup(el->content());
-      p->lang = string_strdup(el->attr("xml:lang"));
-    });
-
-    // metadata
-    SetChildren(&(p->metadata), tree, el, "metadata",
-        [&](XmlElement *el, metadata_x* p){
-      p->key = string_strdup(el->attr("key"));
-      p->value = string_strdup(el->attr("value"));
-    });
-  });
-
-  // ui-application
-  SetChildren(&(p->uiapplication), tree, el, "ui-application",
-      [&](XmlElement *el, uiapplication_x* p){
-    p->appid = string_strdup(el->attr("appid"));
-    p->exec = string_strdup(el->attr("exec"));
-    p->multiple = string_strdup(el->attr("multiple"));
-    p->nodisplay = string_strdup(el->attr("nodisplay"));
-    p->taskmanage = string_strdup(el->attr("taskmanage"));
-    p->type = string_strdup(el->attr("type"));
-    // NOTE: onboot and auto-restart are in spec, but not in uiapplication_x
-
-    // FIXME: temporary fix to avoid build break
-    // app-control
-    SetChildren(&(p->appcontrol), tree, el, "app-control",
-        [&](XmlElement *el, appcontrol_x* p){
-      vector<XmlElement*> v = tree->Children(el, "operation");
-      if (!v.empty())
-        p->operation = string_strdup(v.front()->attr("name"));
-      v = tree->Children(el, "uri");
-      if (!v.empty())
-        p->uri = string_strdup(v.front()->attr("name"));
-      v = tree->Children(el, "mime");
-      if (!v.empty())
-        p->mime = string_strdup(v.front()->attr("name"));
-    });
-
-    // datacontrol
-    SetChildren(&(p->datacontrol), tree, el, "datacontrol",
-        [&](XmlElement *el, datacontrol_x* p){
-      p->access = string_strdup(el->attr("access"));
-      p->providerid = string_strdup(el->attr("providerid"));
-      p->type = string_strdup(el->attr("type"));
-    });
-
-    // icon
-    SetChildren(&(p->icon), tree, el, "icon",
-        [&](XmlElement *el, icon_x* p){
-      // TODO(t.iwanek): icons are located in shared/res/ so preppending it.
-      // it should not be set in manifest_x probably but added elsewhere.
-      p->text = string_strdup(std::string("shared/res/") + el->content());
-      // NOTE: name is an attribute, but the xml writer uses it as text.
-      // This must be fixed in whole app-installer modules, including wgt.
-      // Current implementation is just for compatibility.
-      // p->name = string_strdup(el->attr("name"));
-      p->name = string_strdup(std::string("shared/res/") + el->content());
-    });
-
-    // label
-    SetChildren(&(p->label), tree, el, "label",
-        [&](XmlElement *el, label_x* p){
-      // NOTE: name is an attribute, but the xml writer uses it as text.
-      // This must be fixed in whole app-installer modules, including wgt.
-      // Current implementation is just for compatibility.
-      // p->name = string_strdup(el->attr("name"));
-      p->text = string_strdup(el->content());
-      p->name = string_strdup(el->content());
-      p->lang = string_strdup(el->attr("xml:lang"));
-    });
-
-    // metadata
-    SetChildren(&(p->metadata), tree, el, "metadata",
-        [&](XmlElement *el, metadata_x* p){
-      p->key = string_strdup(el->attr("key"));
-      p->value = string_strdup(el->attr("value"));
-    });
-  });
-
-  // account
-  ci::AccountInfo& account_info =
-      context_->manifest_plugins_data.get().account_info.get();
-  for (auto& account : tree->Children(el, "account")) {
-    for (auto& account_provider : tree->Children(account, "account-provider")) {
-      ci::SingleAccountInfo account;
-      account.appid = account_provider->attr("appid");
-      if (account.appid.empty()) {
-        LOG(ERROR) << "Failed to get appid of account-provider";
-        return false;
-      }
-      if (account_provider->attr("multiple-accounts-support") == "true") {
-        account.multiple_account_support = true;
-      } else if (account_provider->attr("multiple-accounts-support")
-                 == "false") {
-        account.multiple_account_support = false;
-      } else {
-        LOG(ERROR) << "Invalid value of multiple-accounts-support";
-        return false;
-      }
-
-      for (auto& icon : tree->Children(account_provider, "icon")) {
-        std::string section = icon->attr("section");
-        std::string icon_path = icon->content();
-        if (section != "account" && section != "account-small") {
-          LOG(ERROR) << "Invalid value of section of account-provider";
-          return false;
-        }
-        account.icon_paths.emplace_back(section, icon_path);
-      }
-
-      for (auto& name : tree->Children(account_provider, "label")) {
-        std::string lang = name->attr("xml:lang");
-        std::string label = name->content();
-        account.names.emplace_back(label, lang);
-      }
-
-      for (auto& cap : tree->Children(account_provider, "capability")) {
-        std::string capability = cap->content();
-        account.capabilities.push_back(capability);
-      }
-      account_info.set_account(account);
-    }
+// account
+bool StepParse::FillAccounts(void) {
+  std::shared_ptr<const AccountInfo> account_info =
+      std::static_pointer_cast<const AccountInfo>(parser_->GetManifestData(
+          app_keys::kAccountKey));
+  if (!account_info) {
+    LOG(ERROR) << "Account Info has not been found.";
+    return false;
   }
 
+  common_installer::AccountInfo info;
+  for (auto& account : account_info->accounts()) {
+    common_installer::SingleAccountInfo single_info;
+    single_info.capabilities = account.capabilities;
+    single_info.icon_paths = account.icon_paths;
+    single_info.multiple_account_support = account.multiple_account_support;
+    single_info.names = account.labels;
+    // appid has the same value as package
+    single_info.appid =  account.app_id;
+    info.set_account(single_info);
+  }
+  context_->manifest_plugins_data.get().account_info.set(info);
   return true;
 }
 
+bool StepParse::FillManifestX(manifest_x* manifest) {
+  if (!FillPackageInfo(manifest))
+    return false;
+  if (!FillServiceApplication(manifest) && !FillUIApplication(manifest))
+    return false;
+  FillPrivileges(manifest);
+  FillAccounts();
+  return true;
+}
+
+common_installer::Step::Status StepParse::process() {
+  if (!LocateConfigFile()) {
+    LOG(ERROR) << "No tizen_manifest.xml";
+    return common_installer::Step::Status::ERROR;
+  }
+  parser_.reset(new tpk::parse::TPKConfigParser());
+  if (!parser_->ParseManifest(path_)) {
+    LOG(ERROR) << "[Parse] Parse failed. " <<  parser_->GetErrorMessage();
+    return common_installer::Step::Status::ERROR;
+  }
+
+  const manifest_x* manifest = context_->manifest_data.get();
+  if (!FillManifestX(const_cast<manifest_x*>(manifest))) {
+    LOG(ERROR) << "[Parse] Storing manifest_x failed. "
+               <<  parser_->GetErrorMessage();
+    return common_installer::Step::Status::ERROR;
+  }
+
+  // Copy data from ManifestData to ContextInstaller
+  std::shared_ptr<const PackageInfo> info =
+      std::static_pointer_cast<const PackageInfo>(
+          parser_->GetManifestData(
+              manifest_keys::kManifestKey));
+
+  context_->pkgid.set(manifest->package);
+
+  // write pkgid for recovery file
+  if (context_->recovery_info.get().recovery_file) {
+    context_->recovery_info.get().recovery_file->set_pkgid(manifest->package);
+    context_->recovery_info.get().recovery_file->WriteAndCommitFileContent();
+  }
+
+  std::shared_ptr<const PrivilegesInfo> perm_info =
+      std::static_pointer_cast<const PrivilegesInfo>(
+          parser_->GetManifestData(
+              application_keys::kPrivilegeKey));
+  parser::PrivilegesSet privileges;
+  if (perm_info)
+    privileges = perm_info->GetPrivileges();
+
+  LOG(DEBUG) << " Read data -[ ";
+  LOG(DEBUG) << "App package: " << info->package();
+  LOG(DEBUG) << "  aplication version     = " <<  info->version();
+  LOG(DEBUG) << "  api_version = " <<  info->api_version();
+  LOG(DEBUG) << "  privileges -[";
+  for (const auto& p : privileges) {
+    LOG(DEBUG) << "    " << p;
+  }
+  LOG(DEBUG) << "  ]-";
+  LOG(DEBUG) << "]-";
+
+  return common_installer::Step::Status::OK;
+}
+
 }  // namespace parse
 }  // namespace tpk
index ab98cc6..4959d2b 100644 (file)
@@ -1,10 +1,22 @@
-/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
 #ifndef TPK_STEP_STEP_PARSE_H_
 #define TPK_STEP_STEP_PARSE_H_
 
+#include <boost/filesystem.hpp>
+#include <tpk_manifest_handlers/privileges_handler.h>
+#include <tpk_manifest_handlers/tpk_config_parser.h>
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "common/app_installer.h"
+#include "common/context_installer.h"
 #include "common/step/step.h"
 #include "common/utils/logging.h"
-#include "tpk/xml_parser/xml_parser.h"
 
 namespace tpk {
 namespace parse {
@@ -12,21 +24,41 @@ namespace parse {
 class StepParse : public common_installer::Step {
  public:
   using Step::Step;
+  explicit StepParse(common_installer::ContextInstaller* context,
+      bool check_start_file);
 
-  Status process()  override;
-  Status clean()    override { return Status::OK; };
-  Status undo()     override { return Status::OK; };
+  Status process() override;
+  Status clean() override { return Status::OK; }
+  Status undo() override { return Status::OK; }
   Status precheck() override;
 
  protected:
+  virtual bool LocateConfigFile();
+  // required by step_recovery
   virtual boost::filesystem::path LocateConfigFile() const;
+  boost::filesystem::path path_;
 
  private:
-  bool SetContextByManifestParser(xml_parser::XmlTree* tree);
-  bool SetPkgInfoManifest(manifest_x* m,
-      xml_parser::XmlTree* tree, xml_parser::XmlElement* manifest);
-  bool SetPkgInfoChildren(manifest_x *m,
-      xml_parser::XmlTree *tree, xml_parser::XmlElement* manifest);
+  bool FillPackageInfo(manifest_x* manifest);
+  bool FillAuthorInfo(manifest_x* manifest);
+  bool FillDescription(manifest_x* manifest);
+  bool FillPrivileges(manifest_x* manifest);
+  bool FillServiceApplication(manifest_x* manifest);
+  bool FillUIApplication(manifest_x* manifest);
+  template <typename T1, typename T2>
+      bool FillAppControl(T1* manifest, const T2& app_control_list);
+  template <typename T1, typename T2> bool
+      FillDataControl(T1* manifest, const T2& data_control_list);
+  template <typename T1, typename T2>
+      bool FillApplicationIconPaths(T1* manifest, const T2& icons_info);
+  template <typename T1, typename T2>
+      bool FillLabel(T1* manifest, const T2& label_list);
+  template <typename T1, typename T2>
+      bool FillMetadata(T1* manifest, const T2& meta_data_list);
+  bool FillAccounts(void);
+  bool FillManifestX(manifest_x* manifest);
+
+  std::unique_ptr<tpk::parse::TPKConfigParser> parser_;
 
   SCOPE_LOG_TAG(Parse)
 };