blob: da535333713195aeebcf1094e015a8293b1184d5 [file] [log] [blame]
/*
* 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 <axiom_data_handler.h>
#include <stdio.h>
#include <sys/stat.h>
#include <axiom_mime_part.h>
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 */
int 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 int 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,
int *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,
int 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;
}