From 8e67894c06153657c6c891a88e7afd34f16db9d8 Mon Sep 17 00:00:00 2001 From: Youmin Ha Date: Tue, 17 Mar 2015 13:47:33 +0900 Subject: [PATCH] Allow optional elements in tpk manifest xml Some xml elements are optional, thus they can be omitted in the tizen-manifest.xml. This patch allows those elements to be omitted. In addition, null checking routine in common/step/step_generate_xml.cc is added, because if there is no description in tizen-manifest.xml, manifest_x->description will be nullptr. Change-Id: Ie37236b472011c9d516840cc9cda86b777a6a474 Signed-Off-By: Youmin Ha --- src/common/step/step_generate_xml.cc | 78 ++++++++++-------- src/tpk/step/step_parse.cc | 155 ++++++++++++++++++++++------------- src/tpk/step/step_parse.h | 5 +- src/tpk/step/step_symbolic_link.cc | 4 +- src/tpk/task.cc | 16 ++-- src/tpk/task.h | 6 +- 6 files changed, 158 insertions(+), 106 deletions(-) diff --git a/src/common/step/step_generate_xml.cc b/src/common/step/step_generate_xml.cc index c0f3df5..351b95d 100644 --- a/src/common/step/step_generate_xml.cc +++ b/src/common/step/step_generate_xml.cc @@ -73,7 +73,8 @@ Step::Status StepGenerateXml::process() { xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST context_->manifest_data()->version); - if ( context_->manifest_data()->description->name ) + if ( context_->manifest_data()->description && + context_->manifest_data()->description->name ) xmlTextWriterWriteFormatElement(writer, BAD_CAST "description", "%s", BAD_CAST context_->manifest_data()->description->name); else @@ -114,7 +115,7 @@ Step::Status StepGenerateXml::process() { fs::path icon = fs::path(ui->appid) += fs::path(".png"); - if (ui->icon->name) { + if (ui->icon && ui->icon->name) { fs::path app_icon = fs::path(context_->pkg_path()) / fs::path(ui->appid) / fs::path(ui->icon->name); if (fs::exists(app_icon)) @@ -132,20 +133,24 @@ Step::Status StepGenerateXml::process() { for (; appc_ui != nullptr; appc_ui = appc_ui->next) { xmlTextWriterStartElement(writer, BAD_CAST "app-control"); - xmlTextWriterStartElement(writer, BAD_CAST "operation"); - xmlTextWriterWriteAttribute(writer, BAD_CAST "name", - BAD_CAST appc_ui->operation->name); - xmlTextWriterEndElement(writer); - - xmlTextWriterStartElement(writer, BAD_CAST "uri"); - xmlTextWriterWriteAttribute(writer, BAD_CAST "name", - BAD_CAST appc_ui->uri->name); - xmlTextWriterEndElement(writer); - - xmlTextWriterStartElement(writer, BAD_CAST "mime"); - xmlTextWriterWriteAttribute(writer, BAD_CAST "name", - BAD_CAST appc_ui->mime->name); - xmlTextWriterEndElement(writer); + if (appc_ui->operation) { + xmlTextWriterStartElement(writer, BAD_CAST "operation"); + xmlTextWriterWriteAttribute(writer, BAD_CAST "name", + BAD_CAST appc_ui->operation->name); + xmlTextWriterEndElement(writer); + } + if (appc_ui->uri) { + xmlTextWriterStartElement(writer, BAD_CAST "uri"); + xmlTextWriterWriteAttribute(writer, BAD_CAST "name", + BAD_CAST appc_ui->uri->name); + xmlTextWriterEndElement(writer); + } + if (appc_ui->mime) { + xmlTextWriterStartElement(writer, BAD_CAST "mime"); + xmlTextWriterWriteAttribute(writer, BAD_CAST "name", + BAD_CAST appc_ui->mime->name); + xmlTextWriterEndElement(writer); + } xmlTextWriterEndElement(writer); } @@ -168,9 +173,10 @@ Step::Status StepGenerateXml::process() { BAD_CAST exec_path.string().c_str()); xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST svc->type); - - xmlTextWriterWriteFormatElement(writer, BAD_CAST "label", - "%s", BAD_CAST svc->label->name); + if (svc->label) { + xmlTextWriterWriteFormatElement(writer, BAD_CAST "label", + "%s", BAD_CAST svc->label->name); + } // the icon is renamed to // and located in TZ_USER_ICON/TZ_SYS_ICON @@ -179,7 +185,7 @@ Step::Status StepGenerateXml::process() { utils::CreateDir(icon_path_); fs::path icon = fs::path(svc->appid) += fs::path(".png"); - if (svc->icon->name) { + if (svc->icon && svc->icon->name) { fs::path app_icon = fs::path(context_->pkg_path()) / fs::path(svc->appid) / fs::path(svc->icon->name); if (fs::exists(app_icon)) @@ -194,20 +200,24 @@ Step::Status StepGenerateXml::process() { for (; appc_svc != nullptr; appc_svc = appc_svc->next) { xmlTextWriterStartElement(writer, BAD_CAST "app-control"); - xmlTextWriterStartElement(writer, BAD_CAST "operation"); - xmlTextWriterWriteAttribute(writer, BAD_CAST "name", - BAD_CAST appc_svc->operation->name); - xmlTextWriterEndElement(writer); - - xmlTextWriterStartElement(writer, BAD_CAST "uri"); - xmlTextWriterWriteAttribute(writer, BAD_CAST "name", - BAD_CAST appc_svc->uri->name); - xmlTextWriterEndElement(writer); - - xmlTextWriterStartElement(writer, BAD_CAST "mime"); - xmlTextWriterWriteAttribute(writer, BAD_CAST "name", - BAD_CAST appc_svc->mime->name); - xmlTextWriterEndElement(writer); + if (appc_svc->operation) { + xmlTextWriterStartElement(writer, BAD_CAST "operation"); + xmlTextWriterWriteAttribute(writer, BAD_CAST "name", + BAD_CAST appc_svc->operation->name); + xmlTextWriterEndElement(writer); + } + if (appc_svc->uri) { + xmlTextWriterStartElement(writer, BAD_CAST "uri"); + xmlTextWriterWriteAttribute(writer, BAD_CAST "name", + BAD_CAST appc_svc->uri->name); + xmlTextWriterEndElement(writer); + } + if (appc_svc->mime) { + xmlTextWriterStartElement(writer, BAD_CAST "mime"); + xmlTextWriterWriteAttribute(writer, BAD_CAST "name", + BAD_CAST appc_svc->mime->name); + xmlTextWriterEndElement(writer); + } xmlTextWriterEndElement(writer); } diff --git a/src/tpk/step/step_parse.cc b/src/tpk/step/step_parse.cc index 85de2f7..830c882 100644 --- a/src/tpk/step/step_parse.cc +++ b/src/tpk/step/step_parse.cc @@ -26,13 +26,22 @@ namespace { XmlElement* parent, const string element_name) { vector v = tree->Children(parent, element_name); if (v.size() < 1) { - LOG(ERROR) << element_name << " is not found as a child of " << + LOG(INFO) << 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()) { + LOG(DEBUG) << "it is null_string"; + return nullptr; + } + return strdup(s.c_str()); + } + } // namespace @@ -52,6 +61,7 @@ Status StepParse::process() { if (!mPath) { return Status::ERROR; } + LOG(INFO) << "Parse " << mPath->c_str(); XmlParser parser; std::unique_ptr tree(parser.ParseAndGetNewTree(mPath->c_str())); @@ -90,7 +100,10 @@ bool StepParse::SetContextByManifestParser(XmlTree* tree) { * ui_application, * label; // manifest - if (nullptr == (manifest = tree->GetRootElement())) return false; + if (nullptr == (manifest = tree->GetRootElement())) { + LOG(ERROR) << "No mandatory manifest element in xml"; + return false; + } LOG(DEBUG) << "Getting manifest xml data"; LOG(DEBUG) << "manifest: xmlns='" << manifest->attr("xmlns") << @@ -100,86 +113,110 @@ bool StepParse::SetContextByManifestParser(XmlTree* tree) { // ui_application if (nullptr == (ui_application = Get1stChild(tree, - manifest, "ui-application"))) return false; - if (nullptr == (label = Get1stChild(tree, ui_application, "label"))) + manifest, "ui-application"))) { + LOG(ERROR) << "No mandatory ui-application element in manifest xml"; return false; + } + if (nullptr == (label = Get1stChild(tree, ui_application, "label"))) { + LOG(ERROR) << "No mandatory label element in manifest xml"; + return false; + } // set context_ context_->config_data()->set_application_name(label->content()); context_->config_data()->set_required_version(manifest->attr("api_version")); context_->set_pkgid(manifest->attr("package")); + context_->set_manifest(static_cast( + calloc(1, sizeof(manifest_x)))); // set context_->manifest_data() return SetPkgInfoManifest(context_->manifest_data(), tree, manifest); } + bool StepParse::SetPkgInfoManifest(manifest_x* m, XmlTree* tree, XmlElement* manifest) { + // Get required elements - XmlElement* ui_application, * label, * icon, * description; - if (nullptr == (ui_application = Get1stChild(tree, - manifest, "ui-application"))) return false; - if (nullptr == (label = Get1stChild(tree, ui_application, "label"))) - return false; - if (nullptr == (icon = Get1stChild(tree, ui_application, "icon"))) + XmlElement* ui_application = Get1stChild(tree, manifest, "ui-application"); + if (!ui_application) { + LOG(ERROR) << "No mandatory ui-application element in manifest xml"; return false; - if (nullptr == (description = Get1stChild(tree, - ui_application, "description"))) return false; - - // Common values - m->label = static_cast - (calloc(1, sizeof(label_x))); - m->description = static_cast - (calloc(1, sizeof(description_x))); - m->privileges = static_cast - (calloc(1, sizeof(privileges_x))); - m->privileges->next = nullptr; - m->privileges->privilege = nullptr; - - // Basic values - m->package = strdup(manifest->attr("package").c_str()); + } + + // manifest's attribute + m->package = string_strdup(manifest->attr("package")); m->type = strdup("tpk"); - m->version = strdup(manifest->attr("version").c_str()); - m->label->name = strdup(label->content().c_str()); - m->description->name = strdup(description->content().c_str()); - m->mainapp_id = strdup(ui_application->attr("appid").c_str()); + m->version = string_strdup(manifest->attr("version")); + m->mainapp_id = string_strdup(ui_application->attr("appid")); + + // manifest' attribute from children's values + XmlElement* label = Get1stChild(tree, ui_application, "label"); + if (label) { + m->label = static_cast(calloc(1, sizeof(label_x))); + m->label->name = string_strdup(label->content()); + } + XmlElement* description = Get1stChild(tree, manifest, "description"); + if (description) { + m->description = static_cast + (calloc(1, sizeof(description_x))); + m->description->name = string_strdup(description->content()); + } + + // Set children elements + return SetPkgInfoChildren(m, tree, manifest); +} + +bool StepParse::SetPkgInfoChildren(manifest_x *m, + XmlTree *tree, XmlElement* manifest) { // Privileges - XmlElement* privileges; - if (nullptr == (privileges = Get1stChild(tree, manifest, "privileges"))) { - return false; - } - vector v_priv = tree->Children(privileges, "privilege"); - for (auto& privilege : v_priv) { - privilege_x *p = - static_cast(calloc(1, sizeof(privilege_x))); - // privilege data text - p->text = strdup(privilege->content().c_str()); - LISTADD(m->privileges->privilege, p); - LOG(INFO) << "Add a privilege: " << p->text; + XmlElement* privileges = Get1stChild(tree, manifest, "privileges"); + if (privileges) { + m->privileges = static_cast + (calloc(1, sizeof(privileges_x))); + + vector v_priv = tree->Children(privileges, "privilege"); + for (auto& privilege : v_priv) { + privilege_x *p = + static_cast(calloc(1, sizeof(privilege_x))); + // privilege data text + p->text = string_strdup(privilege->content()); + LISTADD(m->privileges->privilege, p); + LOG(INFO) << "Add a privilege: " << p->text; + } } - // Other app data (null initialization) + // service-application m->serviceapplication = nullptr; // NOTE: ignore service application - m->uiapplication = static_cast - (calloc (1, sizeof(uiapplication_x))); - m->uiapplication->icon = static_cast - (calloc(1, sizeof(icon_x))); - m->uiapplication->label = static_cast - (calloc(1, sizeof(label_x))); - m->description = static_cast - (calloc(1, sizeof(description_x))); - m->uiapplication->appcontrol = nullptr; - - m->uiapplication->appid = strdup(ui_application->attr("appid").c_str()); - m->uiapplication->exec = strdup(ui_application->attr("exec").c_str()); - m->uiapplication->type = strdup(ui_application->attr("type").c_str()); - - m->uiapplication->label->name = strdup(label->content().c_str()); - m->uiapplication->icon->name = strdup(icon->content().c_str()); - m->uiapplication->next = nullptr; + // ui-application + XmlElement* ui_application = Get1stChild(tree, manifest, "ui-application"); + if (ui_application) { + m->uiapplication = static_cast + (calloc (1, sizeof(uiapplication_x))); + + m->uiapplication->appid = string_strdup(ui_application->attr("appid")); + m->uiapplication->exec = string_strdup(ui_application->attr("exec")); + m->uiapplication->type = string_strdup(ui_application->attr("type")); + + LOG(DEBUG) << "appid=" << m->uiapplication->appid << + ", exec=" << m->uiapplication->exec << + ", type=" << m->uiapplication->type; + XmlElement* label = Get1stChild(tree, ui_application, "label"); + if (label) { + m->uiapplication->label = static_cast + (calloc(1, sizeof(label_x))); + m->uiapplication->label->name = string_strdup(label->content()); + } + XmlElement* icon = Get1stChild(tree, ui_application, "icon"); + if (icon) { + m->uiapplication->icon = static_cast + (calloc(1, sizeof(icon_x))); + m->uiapplication->icon->name = string_strdup(icon->content()); + } + } return true; } diff --git a/src/tpk/step/step_parse.h b/src/tpk/step/step_parse.h index 84e48cb..f0c2017 100644 --- a/src/tpk/step/step_parse.h +++ b/src/tpk/step/step_parse.h @@ -23,8 +23,9 @@ class StepParse : public common_installer::Step { const boost::filesystem::path& dir); bool SetContextByManifestParser(xml_parser::XmlTree* tree); bool SetPkgInfoManifest(manifest_x* m, - xml_parser::XmlTree* tree, - xml_parser::XmlElement* manifest); + xml_parser::XmlTree* tree, xml_parser::XmlElement* manifest); + bool SetPkgInfoChildren(manifest_x *m, + xml_parser::XmlTree *tree, xml_parser::XmlElement* manifest); }; } // namespace step diff --git a/src/tpk/step/step_symbolic_link.cc b/src/tpk/step/step_symbolic_link.cc index 5e2f61b..38f1181 100644 --- a/src/tpk/step/step_symbolic_link.cc +++ b/src/tpk/step/step_symbolic_link.cc @@ -35,7 +35,7 @@ bool CreateSymLink(T *app, ContextInstaller* context) { // Make a symlink with the name of appid, pointing exec file fs::path symlink_path = bindir / fs::path(app->appid); - LOG(INFO) << "Creating symlink pointing " << symlink_path << " to " << + LOG(INFO) << "Creating symlink " << symlink_path << " pointing " << app->exec; fs::create_symlink(fs::path(app->exec), symlink_path, error); if (error) { @@ -90,9 +90,9 @@ Status StepSymbolicLink::process() { LOG(ERROR) << "Neither ui-application nor service-application exists"; return Status::ERROR; } + if (!CreateSymLink(uiapp, context_)) return Status::ERROR; if (!CreateSymLink(svcapp, context_)) return Status::ERROR; - return Status::OK; } diff --git a/src/tpk/task.cc b/src/tpk/task.cc index 892c043..53db317 100644 --- a/src/tpk/task.cc +++ b/src/tpk/task.cc @@ -69,7 +69,7 @@ bool Task::Init(int argc, char** argv) { bool Task::Run() { - bool ret = false; + int ret = 0; switch (request_) { case PKGMGR_REQ_INSTALL: ret = Install(); @@ -81,10 +81,14 @@ bool Task::Run() { ret = Reinstall(); break; } - return ret; + if (ret != 0) { + LOG(ERROR) << "Got error from AppInstaler: error code " << ret; + return false; + } + return true; } -bool Task::Install() { +int Task::Install() { ci::AppInstaller ai(pi_, kPkgType); ai.AddStep(); @@ -100,7 +104,7 @@ bool Task::Install() { return ai.Run(); } -bool Task::Uninstall() { +int Task::Uninstall() { ci::AppInstaller ai(pi_, kPkgType); ai.AddStep(); @@ -112,8 +116,8 @@ bool Task::Uninstall() { return ai.Run(); } -bool Task::Reinstall() { - return false; +int Task::Reinstall() { + return 0; } } // namespace tpk diff --git a/src/tpk/task.h b/src/tpk/task.h index 8af9e0f..cb71c40 100644 --- a/src/tpk/task.h +++ b/src/tpk/task.h @@ -19,9 +19,9 @@ class Task { private: - bool Install(); - bool Uninstall(); - bool Reinstall(); + int Install(); + int Uninstall(); + int Reinstall(); pkgmgr_installer* pi_; int request_; -- 2.7.4