/* * 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 #define MAX_SIZE 1024 #define MAX_ALLOC (MAX_SIZE * 64) axis2_char_t * axutil_properties_read( FILE *input, const axutil_env_t *env); axis2_char_t * axutil_properties_read_next( axis2_char_t *cur); axis2_char_t * axutil_properties_trunk_and_dup( axis2_char_t *start, axis2_char_t *end, const axutil_env_t *env); struct axutil_properties { axutil_hash_t *prop_hash; }; AXIS2_EXTERN axutil_properties_t *AXIS2_CALL axutil_properties_create( const axutil_env_t *env) { axutil_properties_t *properties = NULL; AXIS2_ENV_CHECK(env, NULL); properties = (axutil_properties_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_properties_t)); if(!properties) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Not enough memory"); return NULL; } properties->prop_hash = axutil_hash_make(env); return properties; } AXIS2_EXTERN void AXIS2_CALL axutil_properties_free( axutil_properties_t *properties, const axutil_env_t *env) { axis2_char_t *key = NULL; axis2_char_t *value = NULL; axutil_hash_index_t *hi = NULL; if(properties->prop_hash) { for(hi = axutil_hash_first(properties->prop_hash, env); hi; hi = axutil_hash_next(env, hi)) { axutil_hash_this(hi, (void *)&key, NULL, (void *)&value); if(key) { AXIS2_FREE(env->allocator, key); } if(value) { AXIS2_FREE(env->allocator, value); } } axutil_hash_free(properties->prop_hash, env); } if(properties) { AXIS2_FREE(env->allocator, properties); } return; } AXIS2_EXTERN axis2_char_t *AXIS2_CALL axutil_properties_get_property( axutil_properties_t *properties, const axutil_env_t *env, axis2_char_t *key) { AXIS2_PARAM_CHECK(env->error, key, NULL); return axutil_hash_get(properties->prop_hash, key, AXIS2_HASH_KEY_STRING); } AXIS2_EXTERN axis2_status_t AXIS2_CALL axutil_properties_set_property( axutil_properties_t *properties, const axutil_env_t *env, axis2_char_t *key, axis2_char_t *value) { axis2_char_t *old = NULL; AXIS2_PARAM_CHECK(env->error, key, AXIS2_FAILURE); old = axutil_properties_get_property(properties, env, key); if(old) { AXIS2_FREE(env->allocator, old); axutil_hash_set(properties->prop_hash, key, AXIS2_HASH_KEY_STRING, axutil_strdup(env, value)); return AXIS2_SUCCESS; } axutil_hash_set(properties->prop_hash, axutil_strdup(env, key), AXIS2_HASH_KEY_STRING, axutil_strdup(env, value)); return AXIS2_SUCCESS; } AXIS2_EXTERN axutil_hash_t *AXIS2_CALL axutil_properties_get_all( axutil_properties_t *properties, const axutil_env_t *env) { return properties->prop_hash; } AXIS2_EXTERN axis2_status_t AXIS2_CALL axutil_properties_store( axutil_properties_t *properties, const axutil_env_t *env, FILE *output) { axutil_hash_index_t *hi = NULL; axis2_char_t *key = NULL; axis2_char_t *value = NULL; AXIS2_PARAM_CHECK(env->error, output, AXIS2_FAILURE); if(properties->prop_hash) { for(hi = axutil_hash_first(properties->prop_hash, env); hi; hi = axutil_hash_next(env, hi)) { axutil_hash_this(hi, (void *)&key, NULL, (void *)&value); if(key) { if(!value) { value = axutil_strdup(env, ""); } fprintf(output, "%s=%s\n", key, value); } } } return AXIS2_SUCCESS; } AXIS2_EXTERN axis2_status_t AXIS2_CALL axutil_properties_load( axutil_properties_t *properties, const axutil_env_t *env, axis2_char_t *input_filename) { FILE *input = NULL; axis2_char_t *cur = NULL; axis2_char_t *tag = NULL; const int LINE_STARTED = -1; const int LINE_MIDWAY = 0; const int EQUAL_FOUND = 1; const int LINE_HALFWAY = 2; int status = LINE_STARTED; axis2_char_t *key = NULL; axutil_hash_t *prop_hash = NULL; axis2_char_t *buffer = NULL; axis2_char_t loginfo[1024]; AXIS2_PARAM_CHECK(env->error, input_filename, AXIS2_FAILURE); prop_hash = properties->prop_hash; input = fopen(input_filename, "r+"); if(!input) { return AXIS2_FAILURE; } buffer = axutil_properties_read(input, env); if(!buffer) { sprintf(loginfo, "error in reading file\n"); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, loginfo); AXIS2_FREE(env->allocator, buffer); return AXIS2_FAILURE; } for(cur = axutil_properties_read_next(buffer); *cur; cur = axutil_properties_read_next(++cur)) { if(*cur == '\r') { *cur = '\0'; } else if(*cur != '\0' && *cur != '\n' && status == LINE_STARTED) { tag = cur; status = LINE_MIDWAY; } /* equal found just create a property */ else if(*cur == '=' && status == LINE_MIDWAY) { *cur = '\0'; if(status != LINE_MIDWAY) { sprintf(loginfo, "equal apear in wrong place around %s\n", tag); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, loginfo); AXIS2_FREE(env->allocator, buffer); return AXIS2_FAILURE; } status = EQUAL_FOUND; key = axutil_properties_trunk_and_dup(tag, cur, env); } /* right next to the equal found */ else if(status == EQUAL_FOUND) { tag = cur; status = LINE_HALFWAY; } else if(*cur == '\n') { *cur = '\0'; if(status == LINE_HALFWAY) { tag = axutil_properties_trunk_and_dup(tag, cur, env); axutil_hash_set(prop_hash, key, AXIS2_HASH_KEY_STRING, tag); } status = LINE_STARTED; } } if(status == LINE_HALFWAY) { *cur = '\0'; tag = axutil_properties_trunk_and_dup(tag, cur, env); axutil_hash_set(prop_hash, key, AXIS2_HASH_KEY_STRING, tag); status = LINE_STARTED; } if(status != LINE_STARTED) { sprintf(loginfo, "error parsing properties\n"); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, loginfo); AXIS2_FREE(env->allocator, buffer); return AXIS2_FAILURE; } if(input) { fclose(input); } AXIS2_FREE(env->allocator, buffer); return AXIS2_SUCCESS; } axis2_char_t * axutil_properties_read_next( axis2_char_t *cur) { /* ignore comment */ if(*cur == '#') { for(; *cur != '\n' && *cur != '\0'; cur++) ; } /* check '\\''\n' case */ if(*cur == '\\' && *(cur + 1) == '\n') { /* ignore two axis2_char_ts */ *(cur++) = ' '; *(cur++) = ' '; } return cur; } axis2_char_t * axutil_properties_trunk_and_dup( axis2_char_t *start, axis2_char_t *end, const axutil_env_t *env) { for(; *start == ' '; start++) ; /* remove front spaces */ for(end--; *end == ' '; end--) ; /* remove rear spaces */ *(++end) = '\0'; start = (axis2_char_t *)axutil_strdup(env, start); return start; } axis2_char_t * axutil_properties_read( FILE *input, const axutil_env_t *env) { size_t nread = 0; axis2_char_t *out_stream = NULL; size_t ncount = 0; size_t curr_alloc = MAX_SIZE * 2; size_t total_alloc = curr_alloc; out_stream = (axis2_char_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * curr_alloc); if(!out_stream) { return NULL; } do { nread = fread(out_stream + ncount, sizeof(axis2_char_t), MAX_SIZE, input); ncount += nread; if(ncount + MAX_SIZE > total_alloc) { axis2_char_t *new_stream = NULL; if(curr_alloc < MAX_ALLOC) { curr_alloc *= 2; } total_alloc += curr_alloc; new_stream = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * total_alloc); if(!new_stream) { if(out_stream) { AXIS2_FREE(env->allocator, out_stream); } return NULL; } memcpy(new_stream, out_stream, sizeof(axis2_char_t) * ncount); if(out_stream) { AXIS2_FREE(env->allocator, out_stream); } out_stream = new_stream; } } while(nread == MAX_SIZE); out_stream[ncount] = '\0'; return out_stream; }