blob: 6cae42e4b58fb40b1de9a9aa8910df42b6a3fa04 [file] [log] [blame]
/*
* 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 <axutil_stream.h>
#include <axiom_node.h>
#include <axiom_element.h>
#include <axiom_attribute.h>
#include <json.h>
#include "axis2_json_reader.h"
#define AXIS2_JSON_XSI_URI "http://www.w3.org/2001/XMLSchema-instance"
struct axis2_json_reader
{
json_object* json_obj;
axiom_node_t* axiom_node;
};
const char* json_tokener_error_to_str(enum json_tokener_error error)
{
switch (error)
{
case json_tokener_success:
return "success";
case json_tokener_continue:
return "continue";
case json_tokener_error_depth:
return "error_depth";
case json_tokener_error_parse_eof:
return "error_parse_eof";
case json_tokener_error_parse_unexpected:
return "error_parse_unexpected";
case json_tokener_error_parse_null:
return "error_parse_null";
case json_tokener_error_parse_boolean:
return "error_parse_boolean";
case json_tokener_error_parse_number:
return "error_parse_number";
case json_tokener_error_parse_array:
return "error_parse_array";
case json_tokener_error_parse_object_key_name:
return "error_parse_object_key_name";
case json_tokener_error_parse_object_key_sep:
return "error_parse_object_key_sep";
case json_tokener_error_parse_object_value_sep:
return "error_parse_object_value_sep";
case json_tokener_error_parse_string:
return "error_parse_string";
case json_tokener_error_parse_comment:
return "error_parse_comment";
}
return "UNKNOWN";
}
axis2_status_t
axis2_json_read_node(
json_object* parent,
const char* name,
axiom_node_t** om_node,
const axutil_env_t* env);
axis2_status_t
axis2_json_read_child_node(
json_object* child_object,
const char* child_name,
axiom_node_t* om_node,
const axutil_env_t* env)
{
axiom_node_t* child_node = NULL;
switch (json_object_get_type(child_object))
{
case json_type_object:
{
if (axis2_json_read_node(child_object, child_name, &child_node, env) != AXIS2_SUCCESS)
return AXIS2_FAILURE;
if (axiom_node_add_child(om_node, env, child_node) != AXIS2_SUCCESS)
return AXIS2_FAILURE;
break;
}
case json_type_array:
{
int i;
int array_len = json_object_array_length(child_object);
for (i = 0; i < array_len; ++i)
{
if (axis2_json_read_child_node(json_object_array_get_idx(child_object, i),
child_name, om_node, env) != AXIS2_SUCCESS)
return AXIS2_FAILURE;
}
break;
}
case json_type_int:
case json_type_boolean:
case json_type_double:
case json_type_string:
{
axiom_node_t* om_child_node = NULL;
axiom_node_t* om_text_node = NULL;
if (!axiom_element_create(env, NULL, child_name, NULL, &om_child_node))
return AXIS2_FAILURE;
if (!axiom_text_create(env, om_child_node, json_object_get_string(child_object),
&om_text_node))
return AXIS2_FAILURE;
if (axiom_node_add_child(om_node, env, om_child_node) != AXIS2_SUCCESS)
{
axiom_node_free_tree(om_text_node, env);
return AXIS2_FAILURE;
}
break;
}
case json_type_null:
{
axiom_element_t* om_child_elem = NULL;
axiom_node_t* om_child_node = NULL;
/* handle as nillable */
axiom_attribute_t* attr;
axiom_namespace_t* ns =
axiom_namespace_create(env, AXIS2_JSON_XSI_URI, "xsi");
if (!ns)
return AXIS2_FAILURE;
om_child_elem = axiom_element_create(env, NULL, child_name, NULL, &om_child_node);
if (!om_child_elem)
{
axiom_namespace_free(ns, env);
return AXIS2_FAILURE;
}
if (axiom_node_add_child(om_node, env, om_child_node) != AXIS2_SUCCESS)
{
axiom_namespace_free(ns, env);
axiom_node_free_tree(om_child_node, env);
return AXIS2_FAILURE;
}
attr = axiom_attribute_create(env, "nil", "true", ns);
if (!attr)
{
axiom_attribute_free(attr, env);
return AXIS2_FAILURE;
}
if (axiom_element_add_attribute(om_child_elem, env, attr,
om_child_node) != AXIS2_SUCCESS)
{
axiom_attribute_free(attr, env);
return AXIS2_FAILURE;
}
break;
}
}
return AXIS2_SUCCESS;
}
axis2_status_t
axis2_json_read_node(
json_object* parent,
const char* name,
axiom_node_t** om_node,
const axutil_env_t* env)
{
if (!json_object_is_type(parent, json_type_object))
return AXIS2_FAILURE;
axiom_element_create(env, NULL, name, NULL, om_node);
json_object_object_foreach(parent, child_name, child_object)
{
if (axis2_json_read_child_node(child_object, child_name, *om_node, env) != AXIS2_SUCCESS)
return AXIS2_FAILURE;
}
return AXIS2_SUCCESS;
}
AXIS2_EXTERN axis2_json_reader_t* AXIS2_CALL
axis2_json_reader_create_for_stream(
const axutil_env_t* env,
axutil_stream_t* stream)
{
axis2_json_reader_t* reader =
(axis2_json_reader_t*)AXIS2_MALLOC(env->allocator,
sizeof(struct axis2_json_reader));
if (reader)
{
axis2_char_t buffer[512];
int readed;
struct json_tokener* tokener = json_tokener_new();
enum json_tokener_error error;
json_object* json_obj = NULL;
reader->json_obj = NULL;
reader->axiom_node = NULL;
do
{
readed = axutil_stream_read(stream, env, &buffer, sizeof(buffer));
if (readed < 0)
break;
json_obj = json_tokener_parse_ex(tokener, buffer, readed);
} while ((error = json_tokener_get_error(tokener)) == json_tokener_continue);
if (error != json_tokener_success)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_STATE_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Failed to parse JSON request: %s",
json_tokener_error_to_str(tokener->err));
if (json_obj)
json_object_put(json_obj);
json_tokener_free(tokener);
free(reader);
return NULL;
}
reader->json_obj = json_obj;
json_tokener_free(tokener);
}
return reader;
}
AXIS2_EXTERN axis2_json_reader_t* AXIS2_CALL
axis2_json_reader_create_for_memory(
const axutil_env_t* env,
const axis2_char_t* json_string,
int json_string_size)
{
axis2_json_reader_t* reader =
(axis2_json_reader_t*)AXIS2_MALLOC(env->allocator,
sizeof(struct axis2_json_reader));
if (reader)
{
struct json_tokener* tokener = json_tokener_new();
reader->axiom_node = NULL;
reader->json_obj = json_tokener_parse_ex(tokener, json_string, json_string_size);
if (tokener->err != json_tokener_success)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_STATE_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Failed to parse JSON request: %s",
json_tokener_error_to_str(tokener->err));
if (reader->json_obj)
json_object_put(reader->json_obj);
json_tokener_free(tokener);
free(reader);
return NULL;
}
json_tokener_free(tokener);
}
return reader;
}
AXIS2_EXTERN void AXIS2_CALL
axis2_json_reader_free(
axis2_json_reader_t* reader,
const axutil_env_t* env)
{
if (reader->json_obj)
json_object_put(reader->json_obj);
AXIS2_FREE(env->allocator, reader);
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_json_reader_read(
axis2_json_reader_t* reader,
const axutil_env_t* env)
{
json_object* json_root = NULL;
const char* json_root_name = NULL;
/* free existing om tree */
if (reader->axiom_node)
axiom_node_free_tree(reader->axiom_node, env);
reader->axiom_node = NULL;
/* get first child */
json_object_object_foreach(reader->json_obj, key, value)
{
json_root = value;
json_root_name = key;
break;
}
if (!json_root || !json_root_name)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_STATE_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Failed find root JSON node");
return AXIS2_FAILURE;
}
return axis2_json_read_node(json_root, json_root_name, &reader->axiom_node, env);
}
AXIS2_EXTERN axiom_node_t* AXIS2_CALL
axis2_json_reader_get_root_node(
axis2_json_reader_t* reader,
const axutil_env_t* env)
{
(void)env;
return reader->axiom_node;
}