From 0425aadc78680e53000fd0108b540d6eca048516 Mon Sep 17 00:00:00 2001 From: gmcdonald Date: Sat, 13 Feb 2010 01:32:03 +0000 Subject: Moving axis svn, part of TLP move INFRA-2441 git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68 --- axiom/src/attachments/data_handler.c | 572 +++++++++++++++++++++++++++++++++++ 1 file changed, 572 insertions(+) create mode 100644 axiom/src/attachments/data_handler.c (limited to 'axiom/src/attachments/data_handler.c') diff --git a/axiom/src/attachments/data_handler.c b/axiom/src/attachments/data_handler.c new file mode 100644 index 0000000..3be8a9d --- /dev/null +++ b/axiom/src/attachments/data_handler.c @@ -0,0 +1,572 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 +#include +#include +#include + +struct axiom_data_handler +{ + /* The content type */ + axis2_char_t *mime_type; + + /* If in a file then the file name*/ + axis2_char_t *file_name; + + /* If it is in a buffer then the buffer */ + axis2_byte_t *buffer; + + /* The length of the buffer */ + size_t buffer_len; + + /* Is this a data_handler with a file name or a buffer*/ + axiom_data_handler_type_t data_handler_type; + + /* When parsing whether we have cached it or not */ + axis2_bool_t cached; + + /* The Content Id */ + axis2_char_t *mime_id; + + /* In the case of sending callback this is required */ + void *user_param; + +}; + +/* Creates the data_handler. The file name is not mandatory */ + +AXIS2_EXTERN axiom_data_handler_t *AXIS2_CALL +axiom_data_handler_create( + const axutil_env_t *env, + const axis2_char_t *file_name, + const axis2_char_t *mime_type) +{ + axiom_data_handler_t *data_handler = NULL; + + AXIS2_ENV_CHECK(env, NULL); + data_handler = (axiom_data_handler_t *)AXIS2_MALLOC(env->allocator, + sizeof(axiom_data_handler_t)); + + if(!data_handler) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create data handler"); + return NULL; + } + + data_handler->mime_type = NULL; + data_handler->file_name = NULL; + data_handler->buffer = NULL; + data_handler->buffer_len = 0; + /* By default, a Data Handler is of type Buffer */ + data_handler->data_handler_type = AXIOM_DATA_HANDLER_TYPE_BUFFER; + data_handler->cached = AXIS2_FALSE; + data_handler->mime_id = NULL; + data_handler->user_param = NULL; + + if(mime_type) + { + data_handler->mime_type = axutil_strdup(env, mime_type); + if(!(data_handler->mime_type)) + { + axiom_data_handler_free(data_handler, env); + return NULL; + } + } + if(file_name) + { + data_handler->file_name = axutil_strdup(env, file_name); + if(!(data_handler->file_name)) + { + axiom_data_handler_free(data_handler, env); + return NULL; + } + data_handler->data_handler_type = AXIOM_DATA_HANDLER_TYPE_FILE; + } + + return data_handler; +} + +AXIS2_EXTERN void AXIS2_CALL +axiom_data_handler_free( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + if(data_handler->file_name) + { + AXIS2_FREE(env->allocator, data_handler->file_name); + } + + if(data_handler->mime_type) + { + AXIS2_FREE(env->allocator, data_handler->mime_type); + } + + if(data_handler->buffer) + { + AXIS2_FREE(env->allocator, data_handler->buffer); + } + + if(data_handler->mime_id) + { + AXIS2_FREE(env->allocator, data_handler->mime_id); + } + + if(data_handler) + { + AXIS2_FREE(env->allocator, data_handler); + } + + return; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axiom_data_handler_get_content_type( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + return data_handler->mime_type; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axiom_data_handler_set_content_type( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + const axis2_char_t *mime_type) +{ + if(data_handler->mime_type) + { + AXIS2_FREE(env->allocator, data_handler->mime_type); + } + data_handler->mime_type = axutil_strdup(env, mime_type); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axiom_data_handler_get_cached( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + return data_handler->cached; +} + +AXIS2_EXTERN void AXIS2_CALL +axiom_data_handler_set_cached( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + axis2_bool_t cached) +{ + data_handler->cached = cached; +} + +AXIS2_EXTERN axis2_byte_t *AXIS2_CALL +axiom_data_handler_get_input_stream( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + return data_handler->buffer; +} + +AXIS2_EXTERN size_t AXIS2_CALL +axiom_data_handler_get_input_stream_len( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + return data_handler->buffer_len; +} + +/* With MTOM caching support this function is no longer used + * Because this will load whole file in to buffer. So for large + * attachment this is not wise */ + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axiom_data_handler_read_from( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + axis2_byte_t **output_stream, + size_t *output_stream_size) +{ + if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_BUFFER) + { + *output_stream = data_handler->buffer; + *output_stream_size = data_handler->buffer_len; + } + else if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_FILE + && data_handler->file_name) + { + FILE *f = NULL; + axis2_byte_t *byte_stream = NULL; + axis2_byte_t *temp_byte_stream = NULL; + axis2_byte_t *read_stream = NULL; + int byte_stream_size = 0; + int temp_byte_stream_size = 0; + int read_stream_size = 0; + int count = 0; + struct stat stat_p; + + f = fopen(data_handler->file_name, "rb"); + if(!f) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error opening file %s for reading", + data_handler->file_name); + return AXIS2_FAILURE; + } + + if(stat(data_handler->file_name, &stat_p) == -1) + { + fclose(f); + return AXIS2_FAILURE; + } + else if(stat_p.st_size == 0) + { + fclose(f); + *output_stream = NULL; + *output_stream_size = 0; + return AXIS2_SUCCESS; + } + + do + { + read_stream_size = stat_p.st_size; + read_stream = AXIS2_MALLOC(env->allocator, (read_stream_size) * sizeof(axis2_byte_t)); + if(!read_stream) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create binary stream"); + if(byte_stream) + { + AXIS2_FREE(env->allocator, byte_stream); + } + fclose(f); + return AXIS2_FAILURE; + } + count = (int)fread(read_stream, 1, read_stream_size, f); + /* The count lies within the int range */ + if(ferror(f)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in reading file %s", + data_handler->file_name); + if(byte_stream) + { + AXIS2_FREE(env->allocator, byte_stream); + } + if(read_stream) + { + AXIS2_FREE(env->allocator, read_stream); + } + fclose(f); + return AXIS2_FAILURE; + } + + /* copy the read bytes */ + if(count > 0) + { + if(byte_stream) + { + temp_byte_stream = byte_stream; + temp_byte_stream_size = byte_stream_size; + byte_stream_size = temp_byte_stream_size + count; + byte_stream = AXIS2_MALLOC(env->allocator, (byte_stream_size) + * sizeof(axis2_byte_t)); + if(!byte_stream) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "No memory. Cannot create binary stream"); + if(read_stream) + { + AXIS2_FREE(env->allocator, read_stream); + } + if(temp_byte_stream) + { + AXIS2_FREE(env->allocator, temp_byte_stream); + } + fclose(f); + return AXIS2_FAILURE; + } + + memcpy(byte_stream, temp_byte_stream, temp_byte_stream_size); + memcpy(byte_stream + temp_byte_stream_size, read_stream, count); + + if(read_stream) + { + AXIS2_FREE(env->allocator, read_stream); + read_stream_size = 0; + } + if(temp_byte_stream) + { + AXIS2_FREE(env->allocator, temp_byte_stream); + temp_byte_stream = NULL; + temp_byte_stream_size = 0; + } + } + else + { + byte_stream = read_stream; + byte_stream_size = read_stream_size; + read_stream = NULL; + read_stream_size = 0; + } + } + else if(read_stream) + { + AXIS2_FREE(env->allocator, read_stream); + } + } + while(!feof(f)); + + fclose(f); + data_handler->buffer = byte_stream; + data_handler->buffer_len = byte_stream_size; + *output_stream = byte_stream; + *output_stream_size = byte_stream_size; + } + else + { + /* Data Handler File Name is missing */ + return AXIS2_FAILURE; + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axiom_data_handler_set_binary_data( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + axis2_byte_t *input_stream, + size_t input_stream_len) +{ + data_handler->buffer = input_stream; + data_handler->buffer_len = input_stream_len; + return AXIS2_SUCCESS; +} + +/* This function will write the data in the buffer + * to a file. When caching is being used this will + * not be called , because the parser it self cache + * the attachment while parsing */ + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axiom_data_handler_write_to( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + if(data_handler->file_name) + { + FILE *f = NULL; + int count = 0; + + f = fopen(data_handler->file_name, "wb"); + if(!f) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error opening file %s for writing", + data_handler->file_name); + return AXIS2_FAILURE; + } + + count = (int)fwrite(data_handler->buffer, 1, data_handler->buffer_len, f); + /* The count lies within the int range */ + + if(ferror(f)) + { + fclose(f); + return AXIS2_FAILURE; + } + fflush(f); + fclose(f); + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axiom_data_handler_set_file_name( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + axis2_char_t *file_name) +{ + if(data_handler->file_name) + { + AXIS2_FREE(env->allocator, data_handler->file_name); + data_handler->file_name = NULL; + } + + if(file_name) + { + data_handler->file_name = axutil_strdup(env, file_name); + if(!(data_handler->file_name)) + { + return AXIS2_FAILURE; + } + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axiom_data_handler_get_file_name( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + if(data_handler->file_name) + { + return data_handler->file_name; + } + else + { + return NULL; + } +} + +/* This method will add the data_handler binary data to the array_list. + * If it is a buffer the part type is buffer. otherwise it is a file. In the + * case of file the array_list have just the file name and the size. The content + * is not loaded to the memory. + */ + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axiom_data_handler_add_binary_data( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + axutil_array_list_t *list) + +{ + axiom_mime_part_t *binary_part = NULL; + + binary_part = axiom_mime_part_create(env); + + if(!binary_part) + { + return AXIS2_FAILURE; + } + + if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_BUFFER) + { + binary_part->part = (axis2_byte_t *)AXIS2_MALLOC(env->allocator, (data_handler->buffer_len) + * sizeof(axis2_byte_t)); + memcpy(binary_part->part, data_handler->buffer, data_handler->buffer_len); + + binary_part->part_size = data_handler->buffer_len; + binary_part->type = AXIOM_MIME_PART_BUFFER; + } + + /* In the case of file we first calculate the file size + * and then add the file name */ + + else if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_FILE + && data_handler->file_name) + { + struct stat stat_p; + + if(stat(data_handler->file_name, &stat_p) == -1) + { + return AXIS2_FAILURE; + } + else if(stat_p.st_size == 0) + { + return AXIS2_SUCCESS; + } + else + { + binary_part->file_name = (axis2_char_t *)axutil_strdup(env, data_handler->file_name); + binary_part->part_size = stat_p.st_size; + binary_part->type = AXIOM_MIME_PART_FILE; + } + } + /* In the case of Callback the user should specify the callback name in the + * configuration file. We just set the correct type. Inside the transport + * it will load the callback and send the attachment appropriately */ + + else if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_CALLBACK) + { + binary_part->type = AXIOM_MIME_PART_CALLBACK; + binary_part->user_param = data_handler->user_param; + } + + else + { + /* Data Handler File Name is missing */ + return AXIS2_FAILURE; + } + + /* Finaly we add the binary details to the list */ + + axutil_array_list_add(list, env, binary_part); + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axiom_data_handler_get_mime_id( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + return data_handler->mime_id; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axiom_data_handler_set_mime_id( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + const axis2_char_t *mime_id) +{ + if(data_handler->mime_id) + { + AXIS2_FREE(env->allocator, data_handler->mime_id); + } + data_handler->mime_id = axutil_strdup(env, mime_id); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axiom_data_handler_type_t AXIS2_CALL +axiom_data_handler_get_data_handler_type( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + return data_handler->data_handler_type; +} + +AXIS2_EXTERN void AXIS2_CALL +axiom_data_handler_set_data_handler_type( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + axiom_data_handler_type_t data_handler_type) +{ + data_handler->data_handler_type = data_handler_type; + return; +} + +AXIS2_EXTERN void *AXIS2_CALL +axiom_data_handler_get_user_param( + axiom_data_handler_t *data_handler, + const axutil_env_t *env) +{ + return data_handler->user_param; +} + +AXIS2_EXTERN void AXIS2_CALL +axiom_data_handler_set_user_param( + axiom_data_handler_t *data_handler, + const axutil_env_t *env, + void *user_param) +{ + data_handler->user_param = user_param; + return; +} + -- cgit v1.1-32-gdbae