support resource manager API. 18/40218/2
authorJiwoong Im <jiwoong.im@samsung.com>
Mon, 1 Jun 2015 05:23:24 +0000 (14:23 +0900)
committerJiwoong Im <jiwoong.im@samsung.com>
Mon, 1 Jun 2015 06:41:53 +0000 (23:41 -0700)
Provides interfaces to check and insert resource.xml and get resource
data of specific package from db.

JIRA ticket : TC-2491

Change-Id: Ibd30c9840af30e877caec8d2cf4ba73c72092b45
Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
12 files changed:
CMakeLists.txt
include/pkgmgrinfo_resource.h [new file with mode: 0755]
packaging/pkgmgr-info.spec
parser/CMakeLists.txt
parser/pkgmgr_parser.h
parser/pkgmgr_parser_db.c
parser/pkgmgr_parser_resource.c [new file with mode: 0755]
parser/pkgmgr_parser_resource.h [new file with mode: 0755]
parser/pkgmgr_parser_resource_db.c [new file with mode: 0755]
parser/pkgmgr_parser_resource_db.h [new file with mode: 0755]
parser/res.xsd.in [new file with mode: 0755]
src/pkgmgrinfo_resource.c [new file with mode: 0644]

index 7b9f75d..450a6a1 100644 (file)
@@ -18,14 +18,14 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src ${CMAKE_
 
 ### Required packages
 INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack)
+pkg_check_modules(pkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack bundle)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
 
-pkg_check_modules(libpkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack)
+pkg_check_modules(libpkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack bundle)
 
 FOREACH(flag ${libpkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
@@ -46,7 +46,7 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
 add_subdirectory(parser)
 
 ## build pkgmgr-info library
-add_library(pkgmgr-info SHARED src/pkgmgr-info.c src/pkgmgr-info-internal.c)
+add_library(pkgmgr-info SHARED src/pkgmgr-info.c src/pkgmgr-info-internal.c src/pkgmgrinfo_resource.c)
 
 
 SET_TARGET_PROPERTIES(pkgmgr-info PROPERTIES SOVERSION ${VERSION_MAJOR})
@@ -62,6 +62,7 @@ configure_file(tag_parser_list.txt.in tag_parser_list.txt @ONLY)
 INSTALL(TARGETS pkgmgr-info DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-info.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/pkgmgr-info.h DESTINATION include)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/pkgmgrinfo_resource.h DESTINATION include)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/parser_path.conf DESTINATION ${SYSCONFDIR}/package-manager/)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mdparser_list.txt DESTINATION ${SYSCONFDIR}/package-manager/parserlib/metadata)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/category_parser_list.txt DESTINATION ${SYSCONFDIR}/package-manager/parserlib/category)
diff --git a/include/pkgmgrinfo_resource.h b/include/pkgmgrinfo_resource.h
new file mode 100755 (executable)
index 0000000..95d2b17
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef __PKGMGRINFO_RESOURCE_H_
+#define __PKGMGRINFO_RESOURCE_H_
+
+#include <glib.h>
+#include <bundle.h>
+
+#define RSC_GROUP_TYPE_IMAGE "image"
+#define RSC_GROUP_TYPE_LAYOUT "layout"
+#define RSC_GROUP_TYPE_SOUND "sound"
+#define RSC_GROUP_TYPE_BIN "bin"
+
+#define RSC_NODE_ATTR_SCREEN_DPI "screen-dpi"
+#define RSC_NODE_ATTR_SCREEN_DPI_RANGE "screen-dpi-range"
+#define RSC_NODE_ATTR_SCREEN_WIDTH_RANGE "screen-width-range"
+#define RSC_NODE_ATTR_SCREEN_LARGE "screen-large"
+#define RSC_NODE_ATTR_SCREEN_BPP "screen-bpp"
+#define RSC_NODE_ATTR_PLATFORM_VER "platform-version"
+#define RSC_NODE_ATTR_LANGUAGE "language"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+       char *folder;
+       bundle *attr;
+} resource_node_t;
+
+typedef struct {
+       char *folder;
+       char *type;
+       GList *node_list;
+} resource_group_t;
+
+typedef struct {
+       char *package;
+       GList *group_list;
+} resource_data_t;
+
+/**
+ * @fn int pkgmgrinfo_resource_close(resource_data_t data)
+ * @brief      This API frees given data and its own variables
+ *
+ * @par                This API is for capi-appfw-application.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  data    structure of resource_data_t
+ * @return     0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+int pkgmgrinfo_resource_close(resource_data_t *data);
+
+/**
+ * @fn int pkgmgrinfo_resource_open(const char *package, resource_data_t **data)
+ * @brief      This API will get resource data of specific package from db
+ *
+ * @par                This API is for capi-appfw-application.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  package packageID
+ * @param[out]data     resource_data type structure. it will filled with resource data
+ * @return     0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+int pkgmgrinfo_resource_open(const char *package, resource_data_t **data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
index 16a87b2..4fb3c65 100644 (file)
@@ -16,6 +16,7 @@ BuildRequires: pkgconfig(dbus-1)
 BuildRequires: pkgconfig(dbus-glib-1)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(libsmack)
+BuildRequires: pkgconfig(bundle)
 
 %description
 Packager Manager infomation api for packaging
@@ -76,6 +77,7 @@ chsmack -a '*' %{TZ_SYS_RW_PACKAGES}
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
 %{_includedir}/pkgmgr-info.h
+%{_includedir}/pkgmgrinfo_resource.h
 %{_libdir}/pkgconfig/pkgmgr-info.pc
 %{_libdir}/libpkgmgr-info.so
 
@@ -86,6 +88,7 @@ chsmack -a '*' %{TZ_SYS_RW_PACKAGES}
 %config %{_sysconfdir}/package-manager/preload/preload_list.txt
 %config %{_sysconfdir}/package-manager/preload/manifest.xsd
 %config %{_sysconfdir}/package-manager/preload/xml.xsd
+%config %{_sysconfdir}/package-manager/preload/res.xsd
 %config %{_sysconfdir}/package-manager/parser_path.conf
 %config %{_sysconfdir}/package-manager/parserlib/metadata/mdparser_list.txt
 %config %{_sysconfdir}/package-manager/parserlib/category/category_parser_list.txt
@@ -96,5 +99,6 @@ chsmack -a '*' %{TZ_SYS_RW_PACKAGES}
 %defattr(-,root,root,-)
 %{_includedir}/pkgmgr/pkgmgr_parser.h
 %{_includedir}/pkgmgr/pkgmgr_parser_db.h
+%{_includedir}/pkgmgr/pkgmgr_parser_resource.h
 %{_libdir}/pkgconfig/pkgmgr-parser.pc
 %{_libdir}/libpkgmgr_parser.so
index 8904ecc..54075ca 100644 (file)
@@ -26,7 +26,7 @@ message(STATUS "version/major : ${VERSION} / ${VERSION_MAJOR}")
 ### Get required CFLAGS, LDFLAGS from pkg-config
 
 include(FindPkgConfig)
-pkg_check_modules(parser_pkgs REQUIRED dlog libxml-2.0 glib-2.0 sqlite3 db-util vconf)
+pkg_check_modules(parser_pkgs REQUIRED dlog libxml-2.0 glib-2.0 sqlite3 db-util vconf bundle)
 
 foreach(flag ${parser_pkgs_CFLAGS})
        set(parser_pkgs_CFLAGS_str "${parser_pkgs_CFLAGS_str} ${flag}")
@@ -45,7 +45,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
 
 ## pkgmgr_parser object (by sewook.park)
 # This library is for installer backend
-add_library(pkgmgr_parser SHARED pkgmgr_parser.c pkgmgr_parser_db.c pkgmgr_parser_signature.c)
+add_library(pkgmgr_parser SHARED pkgmgr_parser.c pkgmgr_parser_db.c pkgmgr_parser_signature.c pkgmgr_parser_resource_db.c pkgmgr_parser_resource.c)
 #add_library(pkgmgr_parser SHARED pkgmgr_parser.c)
 set_target_properties(pkgmgr_parser PROPERTIES SOVERSION ${VERSION_MAJOR})
 set_target_properties(pkgmgr_parser PROPERTIES VERSION ${VERSION})
@@ -57,6 +57,7 @@ configure_file(pkgmgr-parser.pc.in ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-parser.pc
 configure_file(preload_list.txt.in preload_list.txt @ONLY)
 configure_file(manifest.xsd.in manifest.xsd @ONLY)
 configure_file(xml.xsd.in xml.xsd @ONLY)
+configure_file(res.xsd.in res.xsd @ONLY)
 
 ## Install
 INSTALL(TARGETS
@@ -69,7 +70,9 @@ INSTALL(FILES
 INSTALL(FILES
                        pkgmgr_parser_db.h
                DESTINATION include/pkgmgr)
-
+INSTALL(FILES
+                       pkgmgr_parser_resource.h
+               DESTINATION include/pkgmgr)
 INSTALL(FILES
                ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-parser.pc
                DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
@@ -77,3 +80,4 @@ INSTALL(FILES
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/preload_list.txt DESTINATION ${SYSCONFDIR}/package-manager/preload/)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/xml.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/res.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/)
index cbbf806..6328f73 100644 (file)
@@ -59,6 +59,14 @@ extern "C" {
 #define PKGMGR_PARSER_EMPTY_STR                ""
 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
 
+/**
+ * @brief API return values
+ */
+enum {
+       PM_PARSER_R_EINVAL = -2,                /**< Invalid argument */
+       PM_PARSER_R_ERROR = -1,         /**< General error */
+       PM_PARSER_R_OK = 0                      /**< General success */
+};
 
 /**
  * @brief List definitions.
index 83383f5..b34ae43 100644 (file)
@@ -255,6 +255,18 @@ sqlite3 *pkgmgr_cert_db;
                                                "FOREIGN KEY(app_id) " \
                                                "REFERENCES package_app_info(app_id) " \
                                                "ON DELETE CASCADE)"
+#define QUERY_CREATE_TABLE_PACKAGE_RESOURCE_INFO "CREATE TABLE IF NOT EXISTS package_resource_info" \
+                                               "(pkg_id text NOT NULL," \
+                                               "group_folder text NOT NULL," \
+                                               "group_type text NOT NULL," \
+                                               "PRIMARY KEY(pkg_id, group_type))"
+
+#define QUERY_CREATE_TABLE_PACKAGE_RESOURCE_DATA "CREATE TABLE IF NOT EXISTS package_resource_data" \
+                                               "(id integer REFERENCES package_resource_info(rowid)," \
+                                               "node_folder text NOT NULL," \
+                                               "attr_name text NOT NULL," \
+                                               "attr_value test NOT NULL," \
+                                               "PRIMARY KEY(id, node_folder, attr_name))"
 
 static int __insert_uiapplication_info(manifest_x *mfx);
 static int __insert_serviceapplication_info(manifest_x *mfx);
@@ -2172,6 +2184,17 @@ API int pkgmgr_parser_initialize_db(void)
                _LOGD("package cert index info DB initialization failed\n");
                return ret;
        }
+       /*resource DB*/
+       ret = __initialize_db(pkgmgr_parser_db, QUERY_CREATE_TABLE_PACKAGE_RESOURCE_INFO);
+       if (ret == -1) {
+               _LOGD("package resource info DB initialization failed\n");
+               return ret;
+       }
+       ret = __initialize_db(pkgmgr_parser_db, QUERY_CREATE_TABLE_PACKAGE_RESOURCE_DATA);
+       if (ret == -1) {
+               _LOGD("package resource data DB initialization failed\n");
+               return ret;
+       }
 
        return 0;
 }
diff --git a/parser/pkgmgr_parser_resource.c b/parser/pkgmgr_parser_resource.c
new file mode 100755 (executable)
index 0000000..e749ffd
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * pkgmgr-info
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
+ * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <db-util.h>
+#include <glib.h>
+#include <dlfcn.h>
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlschemas.h>
+#include <bundle.h>
+#include "pkgmgr-info.h"
+#include "pkgmgr-info-debug.h"
+#include "pkgmgr_parser_resource.h"
+#include "pkgmgr_parser_resource_db.h"
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "PKGMGR_PARSER"
+
+#define XMLCHAR(s) (const xmlChar *)s
+#define ASCII(s) (char *)s
+
+#define FREE_AND_NULL(ptr) do { \
+               if (ptr) { \
+                       free((void *)ptr); \
+                       ptr = NULL; \
+               } \
+       } while (0)
+
+
+#define RSC_XML_QUALIFIER "res"
+#define RSC_GROUP_NAME_SEPERATOR '-'
+#define RSC_GROUP "group"
+#define RSC_GROUP_ATTR_FOLDER "folder"
+#define RSC_GROUP_ATTR_TYPE "type"
+#define RSC_NODE "node"
+#define RSC_MANIFEST_SCHEMA_FILE "/etc/package-manager/preload/res.xsd"
+
+static int __next_child_element(xmlTextReaderPtr reader, int depth)
+{
+       int ret = xmlTextReaderRead(reader);
+       int cur = xmlTextReaderDepth(reader);
+       while (ret == 1) {
+               switch (xmlTextReaderNodeType(reader)) {
+               case XML_READER_TYPE_ELEMENT:
+                       if (cur == depth + 1)
+                               return 1;
+                       break;
+               case XML_READER_TYPE_TEXT:
+                       /*text is handled by each function separately*/
+                       if (cur == depth + 1)
+                               return 0;
+                       break;
+               case XML_READER_TYPE_END_ELEMENT:
+                       if (cur == depth)
+                               return 0;
+                       break;
+               default:
+                       if (cur <= depth)
+                               return 0;
+                       break;
+               }
+               ret = xmlTextReaderRead(reader);
+               cur = xmlTextReaderDepth(reader);
+       }
+       return ret;
+}
+
+static void _free_node_list(void *data, void *user_data)
+{
+       resource_node_t *tmp_node = (resource_node_t *)data;
+
+       if (tmp_node == NULL) {
+               _LOGE("node list's element is NULL");
+               return;
+       }
+
+       FREE_AND_NULL(tmp_node->folder);
+       if (tmp_node->attr != NULL) {
+               bundle_free(tmp_node->attr);
+               tmp_node->attr = NULL;
+       }
+}
+
+static void _free_group_list(void *data, void *user_data)
+{
+       resource_group_t *tmp_group = (resource_group_t *)data;
+
+       if (tmp_group == NULL) {
+               _LOGE("group list's element is NULL");
+               return;
+       }
+
+       FREE_AND_NULL(tmp_group->folder);
+       FREE_AND_NULL(tmp_group->type);
+
+       g_list_free_full(tmp_group->node_list, (GDestroyNotify)_free_node_list);
+}
+
+static void __save_resource_attribute_into_bundle(xmlTextReaderPtr reader, char *attribute, bundle **b)
+{
+       xmlChar *attr_val = xmlTextReaderGetAttribute(reader, XMLCHAR(attribute));
+
+       if (attr_val)
+               bundle_add_str(*b, attribute, (char *)attr_val);
+}
+
+static void __save_resource_attribute(xmlTextReaderPtr reader, char *attribute, char **xml_attribute, char *default_value)
+{
+       xmlChar *attrib_val = xmlTextReaderGetAttribute(reader, XMLCHAR(attribute));
+
+       if (attrib_val)
+               *xml_attribute = strdup(ASCII(attrib_val));
+       else {
+               if (default_value != NULL)
+                       *xml_attribute = strdup(default_value);
+       }
+}
+
+
+static void __psp_process_node(xmlTextReaderPtr reader, resource_node_t **res_node)
+{
+       char *node_folder = NULL;
+
+       __save_resource_attribute(reader, "folder", &node_folder, NULL);
+       bundle *b = NULL;
+       (*res_node)->folder = node_folder;
+
+       /*retrieve node's attribute and put it into bundle*/
+       b = bundle_create();
+
+       __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_DPI, &b);
+       __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_DPI_RANGE, &b);
+       __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE, &b);
+       __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_LARGE, &b);
+       __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_BPP, &b);
+       __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_PLATFORM_VER, &b);
+       __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_LANGUAGE, &b);
+
+       (*res_node)->attr = b;
+}
+
+static int __psp_process_group(xmlTextReaderPtr reader, resource_group_t **res_group, char *group_type)
+{
+       int depth = -1;
+       int ret = -1;
+       resource_group_t *tmp_group = NULL;
+       resource_node_t *res_node = NULL;
+       const xmlChar *node;
+       char *folder = NULL;
+
+       if (reader == NULL || *res_group == NULL || group_type == NULL) {
+               _LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       tmp_group = *res_group;
+       /*handle group's own attribute*/
+       __save_resource_attribute(reader, RSC_GROUP_ATTR_FOLDER, &folder, NULL);
+       tmp_group->folder = folder;
+       tmp_group->type = group_type;
+
+       depth = xmlTextReaderDepth(reader);
+       while ((ret = __next_child_element(reader, depth))) {
+               node = xmlTextReaderConstName(reader);
+               if (!node) {
+                       _LOGE("xmlTextReaderConstName value is NULL");
+                       return PMINFO_R_ERROR;
+               }
+
+               res_node = NULL;
+               if (!strcmp(ASCII(node), RSC_NODE)) {
+                       res_node = malloc(sizeof(resource_node_t));
+                       if (res_node == NULL) {
+                               _LOGE("malloc failed");
+                               return -1;
+                       }
+                       tmp_group->node_list = g_list_append(tmp_group->node_list, res_node);
+                       __psp_process_node(reader, &res_node);
+               } else {
+                       _LOGE("unidentified node has found[%s]", ASCII(node));
+                       return PMINFO_R_ERROR;
+               }
+       }
+       return ret;
+}
+
+static int __is_group(char *node, char **type)
+{
+       char *tmp = NULL;
+
+       if (node == NULL) {
+               _LOGE("node is null");
+               return PMINFO_R_EINVAL;
+       }
+
+       tmp = strchr(node, RSC_GROUP_NAME_SEPERATOR);
+       tmp = tmp + 1; /*remove dash seperator*/
+       if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_IMAGE))
+               *type = strdup(tmp);
+       else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_LAYOUT))
+               *type = strdup(tmp);
+       else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_SOUND))
+               *type = strdup(tmp);
+       else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_BIN))
+               *type = strdup(tmp);
+       else
+               return PMINFO_R_ERROR;
+
+       if (*type == NULL) {
+               _LOGE("strdup failed with node[%s]", node);
+               return PMINFO_R_ERROR;
+       }
+
+       return PMINFO_R_OK;
+}
+
+static int __start_resource_process(xmlTextReaderPtr reader, GList **list)
+{
+       GList *tmp_list = NULL;
+       const xmlChar *node;
+       char *group_type = NULL;
+       int ret = -1;
+       int depth = -1;
+       resource_group_t *res_group = NULL;
+
+       if (reader == NULL) {
+               _LOGE("reader is null");
+               return PMINFO_R_EINVAL;
+       }
+
+       depth = xmlTextReaderDepth(reader);
+       while ((ret = __next_child_element(reader, depth))) {
+               node = xmlTextReaderConstName(reader);
+               if (!node) {
+                       _LOGE("xmlTextReaderConstName value is null");
+                       return -1;
+               }
+
+               group_type = NULL;
+               ret = __is_group(ASCII(node), &group_type);
+               if (ret) {
+                       _LOGE("unidentified node[%s] has found with error[%d]", ASCII(node), ret);
+                       return ret;
+               }
+               res_group = NULL;
+               res_group = malloc(sizeof(resource_group_t));
+               if (res_group == NULL) {
+                       _LOGE("malloc failed");
+                       return -1;
+               }
+               memset(res_group, '\0', sizeof(resource_group_t));
+               tmp_list = g_list_append(tmp_list, res_group);
+               ret = __psp_process_group(reader, &res_group, group_type);
+               if (ret != 0) {
+                       FREE_AND_NULL(res_group);
+                       return PMINFO_R_ERROR;
+               }
+       }
+
+       *list = g_list_first(tmp_list);
+       return ret;
+}
+
+static int __process_resource_manifest(xmlTextReaderPtr reader, resource_data_t *data)
+{
+       const xmlChar *node;
+       int ret = PMINFO_R_ERROR;
+
+       if (reader == NULL)
+               return PMINFO_R_ERROR;
+
+       ret = __next_child_element(reader, -1);
+       if (ret) {
+               node = xmlTextReaderConstName(reader);
+               retvm_if(!node, PMINFO_R_ERROR, "xmlTextReaderConstName value is NULL\n");
+
+               if (!strcmp(ASCII(node), RSC_XML_QUALIFIER)) {
+                       ret = __start_resource_process(reader, &data->group_list);
+                       if (data->group_list == NULL)
+                               _LOGE("__process_resource_manifest about to end but group list is null[%d]", ret);
+               } else {
+                       _LOGE("no manifest element[res] has found");
+                       return PMINFO_R_ERROR;
+               }
+       }
+       return ret;
+}
+
+static resource_data_t *_pkgmgr_resource_parser_process_manifest_xml(const char *manifest)
+{
+       xmlTextReaderPtr reader;
+       resource_data_t *rsc_data = NULL;
+
+       reader = xmlReaderForFile(manifest, NULL, 0);
+       if (reader) {
+               rsc_data = malloc(sizeof(resource_data_t));
+               if (rsc_data == NULL) {
+                       _LOGE("memory allocation failed");
+                       return NULL;
+               }
+
+               memset(rsc_data, '\0', sizeof(resource_data_t));
+               if (__process_resource_manifest(reader, rsc_data) < 0) {
+                       _LOGE("parsing failed with given manifest[%s]", manifest);
+                       if (pkgmgr_resource_parser_close(rsc_data) != 0)
+                               _LOGE("closing failed");
+                       rsc_data = NULL;
+               } else
+                       _LOGE("parsing succeed");
+
+               xmlFreeTextReader(reader);
+       } else {
+               _LOGE("creating xmlreader failed");
+               FREE_AND_NULL(rsc_data);
+       }
+       return rsc_data;
+}
+
+API int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data)
+{
+       resource_data_t *rsc_data = NULL;
+       int ret = -1;
+
+       if (package == NULL || strlen(package) == 0) {
+               _LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       ret = pkgmgr_parser_resource_db_load(package, &rsc_data);
+       if (ret != 0) {
+               _LOGE("get resource data from db failed");
+               return ret;
+       }
+
+       *data = rsc_data;
+       return ret;
+}
+
+API int pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data)
+{
+       resource_data_t *rsc_data = NULL;
+       int ret = PMINFO_R_ERROR;
+
+       if (fname == NULL || access(fname, R_OK) != 0) {
+               _LOGE("filename is null or cannot access file");
+               return PMINFO_R_EINVAL;
+       }
+       xmlInitParser();
+       rsc_data = _pkgmgr_resource_parser_process_manifest_xml(fname);
+       if (rsc_data == NULL) {
+               _LOGE("parsing failed");
+               goto catch;
+       }
+       rsc_data->package = strdup(package);
+
+       *data = rsc_data;
+       ret = PMINFO_R_OK;
+catch:
+       xmlCleanupParser();
+       return ret;
+}
+
+API int pkgmgr_resource_parser_close(resource_data_t *data)
+{
+       if (data == NULL) {
+               _LOGE("parameter is NULL");
+               return PMINFO_R_EINVAL;
+       }
+
+       FREE_AND_NULL(data->package);
+       g_list_free_full(data->group_list, (GDestroyNotify)_free_group_list);
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgr_resource_parser_insert_into_db(resource_data_t *data)
+{
+       if (data == NULL) {
+               _LOGE("parameter is NULL");
+               return PMINFO_R_EINVAL;
+       }
+
+       return pkgmgr_parser_resource_db_save(data->package, data);
+}
+
+API int pkgmgr_resource_parser_delete_from_db(const char *package)
+{
+       if (package == NULL) {
+               _LOGE("parameter is NULL");
+               return PMINFO_R_EINVAL;
+       }
+
+       return pkgmgr_parser_resource_db_remove(package);
+}
+
+API int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile)
+{
+       if (xmlfile == NULL) {
+               _LOGE("manifest file is NULL\n");
+               return PM_PARSER_R_EINVAL;
+       }
+       int ret = PM_PARSER_R_OK;
+       xmlSchemaParserCtxtPtr ctx = NULL;
+       xmlSchemaValidCtxtPtr vctx = NULL;
+       xmlSchemaPtr xschema = NULL;
+       ctx = xmlSchemaNewParserCtxt(RSC_MANIFEST_SCHEMA_FILE);
+       if (ctx == NULL) {
+               _LOGE("xmlSchemaNewParserCtxt() Failed\n");
+               return PM_PARSER_R_ERROR;
+       }
+       xschema = xmlSchemaParse(ctx);
+       if (xschema == NULL) {
+               _LOGE("xmlSchemaParse() Failed\n");
+               ret = PM_PARSER_R_ERROR;
+               goto cleanup;
+       }
+       vctx = xmlSchemaNewValidCtxt(xschema);
+       if (vctx == NULL) {
+               _LOGE("xmlSchemaNewValidCtxt() Failed\n");
+               return PM_PARSER_R_ERROR;
+       }
+       xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr);
+       ret = xmlSchemaValidateFile(vctx, xmlfile, 0);
+       if (ret == -1) {
+               _LOGE("xmlSchemaValidateFile() failed\n");
+               ret = PM_PARSER_R_ERROR;
+               goto cleanup;
+       } else if (ret == 0) {
+               _LOGE("Manifest is Valid\n");
+               ret = PM_PARSER_R_OK;
+               goto cleanup;
+       } else {
+               _LOGE("Manifest Validation Failed with error code %d\n", ret);
+               ret = PM_PARSER_R_ERROR;
+               goto cleanup;
+       }
+
+cleanup:
+       if(vctx != NULL)
+               xmlSchemaFreeValidCtxt(vctx);
+
+       if(ctx != NULL)
+               xmlSchemaFreeParserCtxt(ctx);
+
+       if(xschema != NULL)
+               xmlSchemaFree(xschema);
+
+       return ret;
+}
diff --git a/parser/pkgmgr_parser_resource.h b/parser/pkgmgr_parser_resource.h
new file mode 100755 (executable)
index 0000000..6f9d6bc
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __PKGMGR_PARSER_RESOURCE_H_
+#define __PKGMGR_PARSER_RESOURCE_H_
+
+#include <bundle.h>
+#include <glib.h>
+#include "pkgmgr_parser.h"
+#include "pkgmgrinfo_resource.h"
+
+#define PKGMGR_RSC_GROUP_TYPE_IMAGE "image"
+#define PKGMGR_RSC_GROUP_TYPE_LAYOUT "layout"
+#define PKGMGR_RSC_GROUP_TYPE_SOUND "sound"
+#define PKGMGR_RSC_GROUP_TYPE_BIN "bin"
+
+#define RSC_NODE_ATTR_SCREEN_DPI "screen-dpi"
+#define RSC_NODE_ATTR_SCREEN_DPI_RANGE "screen-dpi-range"
+#define RSC_NODE_ATTR_SCREEN_WIDTH_RANGE "screen-width-range"
+#define RSC_NODE_ATTR_SCREEN_LARGE "screen-large"
+#define RSC_NODE_ATTR_SCREEN_BPP "screen-bpp"
+#define RSC_NODE_ATTR_PLATFORM_VER "platform-version"
+#define RSC_NODE_ATTR_LANGUAGE "language"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @fn int *pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data)
+ * @brief      This API initialize parses res.xml which identified by fname and package and put it into data.
+ *
+ * @par                This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  fname           pointer to xml filename
+ * @param[in]  pacakage        pointer to packageID
+ * @param[out]data             pointer of      pointer to resource_data type structure.
+ * @return     0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data);
+
+/**
+ * @fn int pkgmgr_resource_parser_close(resource_data_t data)
+ * @brief      This API frees given data and its own variables
+ *
+ * @par                This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  data    structure of resource_data_t
+ * @return     0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_close(resource_data_t *data);
+
+/**
+ * @fn int pkgmgr_resource_parser_insert_into_db(resource_data_t *data)
+ * @brief      This API will put given data into db
+ *
+ * @par                This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  data    structure to be inserted into db
+ * @return     0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_insert_into_db(resource_data_t *data);
+
+/**
+ * @fn int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data)
+ * @brief      This API will get resource data of specific package from db
+ *
+ * @par                This API is for applications.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  package packageID
+ * @param[out]data     resource_data type structure. it will filled with resource data
+ * @return     0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data);
+
+/**
+ * @fn int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile)
+ * @brief      This API will validates given resource manifest file
+ *
+ * @par                This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  manifest        manifest filepath to be validated
+ * @return     0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile);
+
+/**
+ * @fn int pkgmgr_resource_parser_delete_from_db(const char *package)
+ * @brief      This API will remove resource data from package_resource_info, package_resource_data
+ *
+ * @par                This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  package packageID
+ * @return     0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_delete_from_db(const char *package);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/parser/pkgmgr_parser_resource_db.c b/parser/pkgmgr_parser_resource_db.c
new file mode 100755 (executable)
index 0000000..1c0dec3
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+ * pkgmgr-info
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
+ * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <db-util.h>
+#include <glib.h>
+#include <dlfcn.h>
+#include <bundle.h>
+
+#include "pkgmgr-info.h"
+#include "pkgmgr-info-debug.h"
+#include "pkgmgr_parser_db.h"
+#include "pkgmgr_parser_internal.h"
+#include "pkgmgr_parser_resource.h"
+#include "pkgmgr_parser_resource_db.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "PKGMGR_PARSER"
+
+#define BUF_SIZE 1024
+#define PKGMGR_PARSER_DB_FILE tzplatform_mkpath(TZ_USER_DB, ".pkgmgr_parser.db")
+
+enum {
+       NODE_ATTR_MIN = 0,
+       NODE_ATTR_SCREEN_DPI,
+       NODE_ATTR_SCREEN_DPI_RANGE,
+       NODE_ATTR_SCREEN_WIDTH_RANGE,
+       NODE_ATTR_SCREEN_LARGE,
+       NODE_ATTR_SCREEN_BPP,
+       NODE_ATTR_PLATFORM_VER,
+       NODE_ATTR_LANGUAGE,
+       NODE_ATTR_MAX,
+};
+
+static int _get_attr_val(bundle *b, char **attr_name, const char **attr_val, int attr_index)
+{
+       char *buf = NULL;
+       if (b == NULL) {
+               _LOGE("bundle is null");
+               return PMINFO_R_EINVAL;
+       }
+
+       buf = malloc(BUF_SIZE);
+       if (buf == NULL) {
+               _LOGE("malloc failed");
+               return PMINFO_R_ERROR;
+       }
+       memset(buf, '\0', BUF_SIZE);
+       switch (attr_index) {
+       case NODE_ATTR_SCREEN_DPI:
+               snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_DPI);
+               *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_DPI);
+               break;
+       case NODE_ATTR_SCREEN_DPI_RANGE:
+               snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_DPI_RANGE);
+               *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_DPI_RANGE);
+               break;
+       case NODE_ATTR_SCREEN_WIDTH_RANGE:
+               snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_WIDTH_RANGE);
+               *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE);
+               break;
+       case NODE_ATTR_SCREEN_LARGE:
+               snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_LARGE);
+               *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_LARGE);
+               break;
+       case NODE_ATTR_SCREEN_BPP:
+               snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_BPP);
+               *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_BPP);
+               break;
+       case NODE_ATTR_PLATFORM_VER:
+               snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_PLATFORM_VER);
+               *attr_val = bundle_get_val(b, RSC_NODE_ATTR_PLATFORM_VER);
+               break;
+       case NODE_ATTR_LANGUAGE:
+               snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_LANGUAGE);
+               *attr_val = bundle_get_val(b, RSC_NODE_ATTR_LANGUAGE);
+               break;
+       default:
+               _LOGE("unidentified index[%d]", attr_index);
+               free(buf);
+               buf = NULL;
+               return PMINFO_R_ERROR;
+       }
+
+       if (buf != NULL && strlen(buf) != 0)
+               *attr_name = buf;
+
+       return PMINFO_R_OK;
+}
+
+static int _insert_node_data_into_db(sqlite3 *pkginfo, const char *package, char *group_type, GList *node_list)
+{
+       char *query = NULL;
+       resource_node_t *rsc_node = NULL;
+       GList *tmp_node_list = NULL;
+       bundle *b = NULL;
+       const char *attr_val = NULL;
+       char *attr_name = NULL;
+       int i;
+       int ret = -1;
+
+       if (pkginfo == NULL || package == NULL || strlen(package) == 0 || group_type == NULL || strlen(group_type) == 0 || node_list == NULL)
+               return PMINFO_R_EINVAL;
+
+       tmp_node_list = g_list_first(node_list);
+
+       if (tmp_node_list == NULL) {
+               _LOGE("list is null");
+               return PMINFO_R_ERROR;
+       }
+
+       while (tmp_node_list != NULL) {
+               rsc_node = (resource_node_t *)tmp_node_list->data;
+               if (rsc_node == NULL) {
+                       _LOGE("node is null");
+                       return PMINFO_R_ERROR;
+               }
+
+               /*get bundle for each nodes*/
+               b = rsc_node->attr;
+               if (b == NULL) {
+                       _LOGE("bundle is null");
+                       return PMINFO_R_ERROR;
+               }
+
+               for (i = NODE_ATTR_MIN + 1; i < NODE_ATTR_MAX; i++) {
+                       ret = _get_attr_val(b, &attr_name, &attr_val, i);
+                       if (ret != 0) {
+                               _LOGE("get attribute from bundle failed");
+                               return ret;
+                       }
+
+                       if (attr_name == NULL || attr_val == NULL)
+                               continue;
+                       query = sqlite3_mprintf("insert into package_resource_data(id, node_folder, attr_name, attr_value) VALUES(" \
+                               "(select rowid from package_resource_info where pkg_id=%Q and group_type=%Q), %Q, %Q, %Q)", package, group_type, rsc_node->folder, attr_name, attr_val);
+
+                       /*Begin transaction*/
+                       ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL);
+                       if (ret != SQLITE_OK)
+                               _LOGE("Failed to insert into package_resource_data, attr_name[%s], attr_val[%s]", attr_name, attr_val);
+                       sqlite3_free(query);
+                       query = NULL;
+                       free(attr_name);
+                       attr_name = NULL;
+                       attr_val = NULL;
+               }
+               tmp_node_list = g_list_next(tmp_node_list);
+       }
+
+       return ret;
+}
+
+int pkgmgr_parser_resource_db_remove(const char *package)
+{
+       sqlite3 *pkginfo = NULL;
+       char *query = NULL;
+       int ret = -1;
+
+       if (package == NULL) {
+               _LOGE("parameter is NULL");
+               return PMINFO_R_EINVAL;
+       }
+
+       /*db open*/
+       ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0);
+       retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE);
+
+       /*Begin transaction*/
+       ret = sqlite3_exec(pkginfo, "BEGIN EXCLUSIVE", NULL, NULL, NULL);
+       tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to begin transaction\n");
+       _LOGD("Transaction Begin\n");
+
+       /*delete data from package_resource_data*/
+       query = sqlite3_mprintf("delete from package_resource_data where id in (select rowid from package_resource_info where pkg_id=%Q)", package);
+       ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL);
+       tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to delete from package_resource_info");
+       sqlite3_free(query);
+       query = NULL;
+
+       /*delete data from package_resource_info*/
+       query = sqlite3_mprintf("delete from package_resource_info where pkg_id=%Q", package);
+       ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL);
+       tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to delete from package_resource_info");
+
+       /*Commit transaction*/
+       ret = sqlite3_exec(pkginfo, "COMMIT", NULL, NULL, NULL);
+       if (ret != SQLITE_OK) {
+               _LOGE("Failed to commit transaction. Rollback now\n");
+               ret = sqlite3_exec(pkginfo, "ROLLBACK", NULL, NULL, NULL);
+               tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query);
+       }
+       _LOGD("Transaction Commit and End\n");
+
+       ret = PMINFO_R_OK;
+catch:
+       sqlite3_close(pkginfo);
+       sqlite3_free(query);
+
+       return ret;
+}
+
+int pkgmgr_parser_resource_db_save(const char *package, resource_data_t *data)
+{
+       sqlite3 *pkginfo = NULL;
+       char *query = NULL;
+       int ret = -1;
+       GList *group_list = NULL;
+       GList *node_list = NULL;
+       resource_group_t *rsc_group = NULL;
+
+       if (package == NULL || strlen(package) == 0 || data == NULL) {
+               _LOGE("invalid parameter");
+               return -1;
+       }
+
+       ret = pkgmgr_parser_check_and_create_db(getuid());
+       if (ret == 0)
+               ret = pkgmgr_parser_initialize_db();
+       if (ret < 0) {
+               _LOGE("db initialization failed");
+               goto catch;
+       }
+
+
+       group_list = g_list_first(data->group_list);
+       /*db open*/
+       ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0);
+       retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE);
+
+       /*Begin transaction*/
+       ret = sqlite3_exec(pkginfo, "BEGIN EXCLUSIVE", NULL, NULL, NULL);
+       tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to begin transaction\n");
+       _LOGD("Transaction Begin\n");
+
+       while (group_list != NULL) {
+               rsc_group = NULL;
+               node_list = NULL;
+
+               rsc_group = (resource_group_t *)group_list->data;
+               node_list = g_list_first(rsc_group->node_list);
+
+               if (rsc_group == NULL || node_list == NULL) {
+                       _LOGE("value is null");
+                       ret = -1;
+                       goto catch;
+               }
+
+               query = sqlite3_mprintf("insert into package_resource_info(pkg_id, group_folder, group_type) VALUES(%Q, %Q, %Q)", \
+                       package, rsc_group->folder, rsc_group->type);
+
+               /*Begin transaction*/
+               ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL);
+               tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to insert into package_resource_info");
+               sqlite3_free(query);
+               query = NULL;
+
+               ret = _insert_node_data_into_db(pkginfo, package, rsc_group->type, node_list);
+
+               group_list = g_list_next(group_list);
+       }
+
+       /*Commit transaction*/
+       ret = sqlite3_exec(pkginfo, "COMMIT", NULL, NULL, NULL);
+       if (ret != SQLITE_OK) {
+               _LOGE("Failed to commit transaction. Rollback now\n");
+               ret = sqlite3_exec(pkginfo, "ROLLBACK", NULL, NULL, NULL);
+               tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query);
+       }
+       _LOGD("Transaction Commit and End\n");
+
+       ret = PMINFO_R_OK;
+
+
+catch:
+       pkgmgr_parser_close_db();
+       sqlite3_close(pkginfo);
+       sqlite3_free(query);
+
+       return ret;
+
+}
+
+static gint _find_group_type(void *group, void *data)
+{
+       resource_group_t *rsc_group = (resource_group_t *)group;
+
+       return strcmp(rsc_group->type, (char *)data);
+}
+
+static gint _find_node_folder(void *node, void *data)
+{
+       resource_node_t *rsc_node = (resource_node_t *)node;
+       char *str = (char *)data;
+
+       return strcmp(rsc_node->folder, str);
+}
+
+static int _init_node(char *node_folder, resource_node_t **rsc_node)
+{
+       resource_node_t *tmp_node = NULL;
+
+       if (node_folder == NULL) {
+               _LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       tmp_node = malloc(sizeof(resource_node_t));
+       if (tmp_node == NULL) {
+               _LOGE("malloc failed");
+               return PMINFO_R_ERROR;
+       }
+
+       tmp_node->folder = strdup(node_folder);
+       tmp_node->attr = bundle_create();
+       *rsc_node = tmp_node;
+
+       return PMINFO_R_OK;
+}
+
+static int _init_group(char *group_type, resource_group_t **rsc_group)
+{
+       resource_group_t *tmp_group = NULL;
+
+       if (group_type == NULL) {
+               _LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       tmp_group = malloc(sizeof(resource_group_t));
+       if (tmp_group == NULL) {
+               _LOGE("malloc failed");
+               return PMINFO_R_ERROR;
+       }
+
+       tmp_group->type = strdup(group_type);
+       tmp_group->node_list = NULL;
+       *rsc_group = tmp_group;
+
+       return PMINFO_R_OK;
+}
+
+int pkgmgr_parser_resource_db_load(const char *package, resource_data_t **data)
+{
+       sqlite3 *pkginfo = NULL;
+       sqlite3_stmt *stmt = NULL;
+       char *query = NULL;
+       char *colname = NULL;
+       char *group_type = NULL;
+       char *group_folder = NULL;
+       char *node_folder = NULL;
+       char *attr_name = NULL;
+       char *attr_value = NULL;
+       int ret = -1;
+       int cols = 0;
+       int i;
+       resource_data_t *rsc_data = NULL;
+       resource_group_t *rsc_group = NULL;
+       resource_node_t *rsc_node = NULL;
+       GList *group_list = NULL;
+       GList *node_list = NULL;
+       GList *tmp_group_list = NULL;
+       GList *tmp_node_list = NULL;
+
+       ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0);
+       retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE);
+       query = sqlite3_mprintf("select " \
+               "package_resource_info.group_type, package_resource_info.group_folder, package_resource_data.node_folder, package_resource_data.attr_name, package_resource_data.attr_value " \
+               "from package_resource_info, package_resource_data where " \
+               "package_resource_info.rowid=package_resource_data.id and " \
+               "package_resource_info.pkg_id=%Q order by package_resource_data.rowid asc", \
+               package);
+       ret = sqlite3_prepare_v2(pkginfo, query, strlen(query), &stmt, NULL);
+       tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "sqlite3_prepare_v2 query = %s\n", query);
+       cols = sqlite3_column_count(stmt);
+
+       while (1) {
+               ret = sqlite3_step(stmt);
+               if (ret != SQLITE_ROW)
+                       break;
+               tmp_group_list = NULL;
+               tmp_node_list = NULL;
+               rsc_group = NULL;
+               rsc_node = NULL;
+
+               for (i = 0; i < cols; i++) {
+                       colname = (char *)sqlite3_column_name(stmt, i);
+                       if (strcmp(colname, "group_type") == 0) {
+                               /*group_type*/
+                               group_type = (char *)sqlite3_column_text(stmt, i);
+                               tmp_group_list = g_list_find_custom(group_list, group_type, (GCompareFunc)_find_group_type);
+                               if (tmp_group_list == NULL) {
+                                       ret = _init_group(group_type, &rsc_group);
+                                       if (ret != PMINFO_R_OK) {
+                                               _LOGE("group initialization failed[%d]", ret);
+                                               goto catch;
+                                       }
+                                       group_list = g_list_append(group_list, rsc_group);
+                                       node_list = NULL;
+                               } else {
+                                       rsc_group = (resource_group_t *)tmp_group_list->data;
+                                       node_list = rsc_group->node_list;
+                               }
+                       } else if (strcmp(colname, "group_folder") == 0) {
+                               /*group_folder*/
+                               group_folder = (char *)sqlite3_column_text(stmt, i);
+                               if (rsc_group->folder != NULL && strcmp(rsc_group->folder, group_folder) == 0)
+                                       continue;
+                               else if (rsc_group != NULL && group_folder != NULL)
+                                       rsc_group->folder = strdup(group_folder);
+                               else {
+                                       _LOGE("rsc_group and group_folder should not be null");
+                                       ret = PMINFO_R_ERROR;
+                                       goto catch;
+                               }
+                       } else if (strcmp(colname, "node_folder") == 0) {
+                               /*node_folder*/
+                               node_folder = (char *)sqlite3_column_text(stmt, i);
+                               tmp_node_list = g_list_find_custom(node_list, node_folder, (GCompareFunc)_find_node_folder);
+                               if (tmp_node_list == NULL) {
+                                       ret = _init_node(node_folder, &rsc_node);
+                                       /*initialize new node*/
+                                       if (ret != PMINFO_R_OK) {
+                                               _LOGE("node initialization failed[%d]", ret);
+                                               goto catch;
+                                       }
+                                       node_list = g_list_append(node_list, rsc_node);
+                                       if (rsc_group->node_list == NULL)
+                                               rsc_group->node_list = node_list;
+                               } else
+                                       rsc_node = (resource_node_t *)tmp_node_list->data;
+                       } else if (strcmp(colname, "attr_name") == 0) {
+                               /*attr_name*/
+                               attr_name = (char *)sqlite3_column_text(stmt, i);
+                       } else if (strcmp(colname, "attr_value") == 0) {
+                               /*attr_value*/
+                               attr_value = (char *)sqlite3_column_text(stmt, i);
+                               if (rsc_node != NULL && attr_name != NULL && attr_value != NULL) {
+                                       if (rsc_node->attr != NULL)
+                                               bundle_add(rsc_node->attr, attr_name, attr_value);
+                                       else {
+                                               _LOGE("bundle is not initialized");
+                                               ret = PMINFO_R_ERROR;
+                                               goto catch;
+                                       }
+                               } else {
+                                       _LOGE("error happened");
+                                       ret = PMINFO_R_ERROR;
+                                       goto catch;
+                               }
+                       } else {
+                               /*error handling*/
+                               _LOGE("unexpected column name detected:[%s]", colname);
+                               ret = PMINFO_R_ERROR;
+                               goto catch;
+                       }
+               }
+       }
+       if (ret == SQLITE_DONE)
+               ret = PMINFO_R_OK;
+
+       rsc_data = malloc(sizeof(resource_data_t));
+       if (rsc_data == NULL) {
+               _LOGD("malloc failed");
+               ret = PMINFO_R_ERROR;
+               goto catch;
+       }
+       rsc_data->group_list = group_list;
+       rsc_data->package = strdup(package);
+       /*set return data*/
+       *data = rsc_data;
+catch:
+       sqlite3_close(pkginfo);
+       sqlite3_free(query);
+
+       return ret;
+}
diff --git a/parser/pkgmgr_parser_resource_db.h b/parser/pkgmgr_parser_resource_db.h
new file mode 100755 (executable)
index 0000000..4476b7c
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __PKGMGR_PARSER_RESOURCE_DB_H_
+#define __PKGMGR_PARSER_RESOURCE_DB_H_
+
+#include "pkgmgrinfo_resource.h"
+#include "pkgmgr_parser.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int pkgmgr_parser_resource_db_save(const char *package, resource_data_t *data);
+int pkgmgr_parser_resource_db_load(const char *package, resource_data_t **data);
+int pkgmgr_parser_resource_db_remove(const char *package);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/parser/res.xsd.in b/parser/res.xsd.in
new file mode 100755 (executable)
index 0000000..fed6b3f
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
+       targetNamespace="http://tizen.org/ns/rm" xmlns:packages="http://tizen.org/ns/rm">
+       <xs:import namespace="http://www.w3.org/XML/1998/namespace"/>
+       <xs:element name="res">
+               <xs:complexType>
+                       <xs:all>
+                               <xs:element name="group-image" type="packages:GroupContainer" maxOccurs="1" minOccurs="0"/>
+                               <xs:element name="group-layout" type="packages:GroupContainer" maxOccurs="1" minOccurs="0"/>
+                               <xs:element name="group-sound" type="packages:GroupContainer" maxOccurs="1" minOccurs="0"/>
+                               <xs:element name="group-bin" type="packages:GroupContainer" maxOccurs="1" minOccurs="0"/>
+                       </xs:all>
+               </xs:complexType>
+       </xs:element>
+
+       <xs:complexType name="GroupContainer">
+               <xs:sequence>
+                       <xs:element name="node" maxOccurs="unbounded" minOccurs="0">
+                               <xs:complexType>
+                                       <xs:attribute name="folder" type="xs:string" use="required"/>
+                                       <xs:attribute name="screen-dpi" type="xs:integer"/>
+                                       <xs:attribute name="screen-dpi-range" type="xs:string"/>
+                                       <xs:attribute name="screen-width-range" type="xs:string"/>
+                                       <xs:attribute name="screen-large" type="xs:boolean"/>
+                                       <xs:attribute name="screen-bpp" type="xs:integer"/>
+                                       <xs:attribute name="platform-version" type="xs:string"/>
+                                       <xs:attribute name="language" type="xs:string"/>
+                               </xs:complexType>
+                       </xs:element>
+               </xs:sequence>
+               <xs:attribute name="folder" type="xs:string" use="required"/>
+       </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git a/src/pkgmgrinfo_resource.c b/src/pkgmgrinfo_resource.c
new file mode 100644 (file)
index 0000000..35f76f6
--- /dev/null
@@ -0,0 +1,12 @@
+#include "pkgmgr_parser_resource.h"
+
+API int pkgmgrinfo_resource_open(const char *package, resource_data_t **data)
+{
+       return pkgmgr_resource_parser_open_from_db(package, data);
+}
+
+API int pkgmgrinfo_resource_close(resource_data_t *data)
+{
+       return pkgmgr_resource_parser_close(data);
+}
+