Add an exception handling about out of memory
[platform/core/appfw/aul-1.git] / src / aul_rsc_mgr_internal.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <glib.h>
22 #include <libxml/tree.h>
23 #include <libxml/xmlschemas.h>
24
25 #include <dlog.h>
26 #include <bundle.h>
27
28 #include "aul_rsc_mgr_internal.h"
29 #include "aul_rsc_mgr_schema.h"
30
31 static char *__get_attribute(xmlNode *xml_node, const char *name)
32 {
33         xmlChar *val;
34         char *attr = NULL;
35
36         val = xmlGetProp(xml_node, (const xmlChar *)name);
37         if (val) {
38                 attr = strdup((const char *)val);
39                 xmlFree(val);
40         }
41
42         return attr;
43 }
44
45 static void __get_attribute_into_bundle(xmlNode *xml_node, const char *name,
46                 bundle *b)
47 {
48         char *attr;
49
50         attr = __get_attribute(xml_node, name);
51         if (attr) {
52                 bundle_add_str(b, name, attr);
53                 free(attr);
54         }
55 }
56
57 static int __parse_node(xmlNode *xml_node, GList **nodes)
58 {
59         resource_node_t *node;
60
61         if (strcmp((char *)xml_node->name, "node"))
62                 return -1;
63
64         node = calloc(1, sizeof(resource_node_t));
65         if (!node) {
66                 LOGE("Out of memory");
67                 return -1;
68         }
69
70         node->folder = __get_attribute(xml_node, "folder");
71         /* why we should use bundle here? */
72         node->attr = bundle_create();
73         if (node->attr == NULL) {
74                 LOGE("Out of memory");
75                 free(node->folder);
76                 free(node);
77                 return -1;
78         }
79
80         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_DPI,
81                         node->attr);
82         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_DPI_RANGE,
83                         node->attr);
84         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE,
85                         node->attr);
86         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_LARGE,
87                         node->attr);
88         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_BPP,
89                         node->attr);
90         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_PLATFORM_VER,
91                         node->attr);
92         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_LANGUAGE,
93                         node->attr);
94
95         *nodes = g_list_append(*nodes, node);
96
97         return 0;
98 }
99
100 static char *_get_group_type(xmlNode *xml_node)
101 {
102         static const char delim[] = "-";
103         char *str;
104         char *tok;
105         char *ptr;
106
107         /* copy original string */
108         str = strdup((const char *)xml_node->name);
109         if (str == NULL) {
110                 LOGE("Out of memory");
111                 return NULL;
112         }
113
114         tok = strtok_r(str, delim, &ptr);
115         /* not a group element */
116         if (tok == NULL || strcmp(tok, "group"))
117                 return NULL;
118         tok = strtok_r(NULL, delim, &ptr);
119         /* invalid element */
120         if (tok == NULL)
121                 return NULL;
122         ptr = strdup(tok);
123         free(str);
124
125         return ptr;
126 }
127
128 static int __parse_group(xmlNode *xml_node, GList **groups)
129 {
130         xmlNode *tmp;
131         char *type;
132         resource_group_t *group;
133
134         type = _get_group_type(xml_node);
135         if (type == NULL)
136                 return -1;
137
138         group = calloc(1, sizeof(resource_group_t));
139         if (group == NULL) {
140                 LOGE("Out of memory");
141                 return -1;
142         }
143
144         group->type = type;
145         group->folder = __get_attribute(xml_node, "folder");
146
147         for (tmp = xml_node->children; tmp; tmp = tmp->next) {
148                 if (xml_node->type != XML_ELEMENT_NODE)
149                         continue;
150                 if (__parse_node(tmp, &group->node_list))
151                         continue;
152         }
153
154         *groups = g_list_append(*groups, group);
155
156         return 0;
157 }
158
159 static int __parse_resource(xmlNode *xml_node, resource_data_t **data)
160 {
161         xmlNode *tmp;
162
163         *data = calloc(1, sizeof(resource_data_t));
164         if (*data == NULL) {
165                 LOGE("out of memory");
166                 return -1;
167         }
168
169         for (tmp = xml_node->children; tmp; tmp = tmp->next) {
170                 if (tmp->type != XML_ELEMENT_NODE)
171                         continue;
172                 __parse_group(tmp, &(*data)->group_list);
173         }
174
175         return 0;
176 }
177
178 static int __validate_schema(const char *path)
179 {
180         xmlSchemaParserCtxt *parser_ctxt;
181         xmlSchema *schema;
182         xmlSchemaValidCtxt *valid_ctxt;
183         int ret;
184
185         parser_ctxt = xmlSchemaNewMemParserCtxt(res_schema, sizeof(res_schema));
186         if (parser_ctxt == NULL) {
187                 LOGE("failed to create parser context");
188                 return -1;
189         }
190
191         schema = xmlSchemaParse(parser_ctxt);
192         if (schema == NULL) {
193                 LOGE("failed to create schema");
194                 xmlSchemaFreeParserCtxt(parser_ctxt);
195                 return -1;
196         }
197
198         valid_ctxt = xmlSchemaNewValidCtxt(schema);
199         if (valid_ctxt == NULL) {
200                 LOGE("failed to create valid context");
201                 xmlSchemaFree(schema);
202                 xmlSchemaFreeParserCtxt(parser_ctxt);
203                 return -1;
204         }
205
206         ret = xmlSchemaValidateFile(valid_ctxt, path, 0);
207         if (ret)
208                 LOGE("%s: validation failed(%d)", path, ret);
209
210         xmlSchemaFreeValidCtxt(valid_ctxt);
211         xmlSchemaFree(schema);
212         xmlSchemaFreeParserCtxt(parser_ctxt);
213
214         return ret;
215 }
216
217 int _resource_open(const char *path, resource_data_t **data)
218 {
219         int ret;
220         xmlDoc *doc;
221         xmlNode *root;
222
223         if (__validate_schema(path))
224                 return -1;
225         doc = xmlReadFile(path, NULL, 0);
226         if (doc == NULL)
227                 return -1;
228         root = xmlDocGetRootElement(doc);
229
230         ret = __parse_resource(root, data);
231
232         xmlFreeDoc(doc);
233
234         return ret;
235 }
236
237 static void __free_resource_node(gpointer data)
238 {
239         resource_node_t *node = (resource_node_t *)data;
240
241         free(node->folder);
242         bundle_free(node->attr);
243         free(node);
244 }
245
246 static void __free_resource_group(gpointer data)
247 {
248         resource_group_t *group = (resource_group_t *)data;
249
250         free(group->folder);
251         free(group->type);
252
253         g_list_free_full(group->node_list, __free_resource_node);
254
255         free(group);
256 }
257
258 int _resource_close(resource_data_t *data)
259 {
260         /*
261         free(data->package);
262         */
263         g_list_free_full(data->group_list, __free_resource_group);
264
265         free(data);
266
267         return 0;
268 }