summaryrefslogtreecommitdiffstats
path: root/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_map.c
diff options
context:
space:
mode:
Diffstat (limited to 'rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_map.c')
-rw-r--r--rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_map.c889
1 files changed, 889 insertions, 0 deletions
diff --git a/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_map.c b/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_map.c
new file mode 100644
index 00000000..4b025425
--- /dev/null
+++ b/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_map.c
@@ -0,0 +1,889 @@
+/*
+ * 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.
+ */
+
+/***************************************************************************
+ * Description: General purpose map object *
+ * Author: Gal Shachor <shachor@il.ibm.com> *
+ * Author: Mladen Turk <mturk@apache.org> *
+ * Version: $Revision: 1042364 $ *
+ ***************************************************************************/
+#if defined(AS400) && !defined(AS400_UTF8)
+#include "apr_xlate.h"
+#endif
+
+#include "jk_global.h"
+#include "jk_pool.h"
+#include "jk_util.h"
+#include "jk_map.h"
+
+#define CAPACITY_INC_SIZE (50)
+#define LENGTH_OF_LINE (8192)
+#define JK_MAP_RECURSION (20)
+#define JK_MAP_REFERENCE (".reference")
+#define JK_MAP_REFERENCE_SZ (strlen(JK_MAP_REFERENCE))
+
+/* Compute the "checksum" for a key, consisting of the first
+ * 4 bytes, packed into an int.
+ * This checksum allows us to do a single integer
+ * comparison as a fast check to determine whether we can
+ * skip a strcmp
+ */
+#define COMPUTE_KEY_CHECKSUM(key, checksum) \
+{ \
+ const char *k = (key); \
+ unsigned int c = (unsigned int)*k; \
+ (checksum) = c; \
+ (checksum) <<= 8; \
+ if (c) { \
+ c = (unsigned int)*++k; \
+ checksum |= c; \
+ } \
+ (checksum) <<= 8; \
+ if (c) { \
+ c = (unsigned int)*++k; \
+ checksum |= c; \
+ } \
+ (checksum) <<= 8; \
+ if (c) { \
+ c = (unsigned int)*++k; \
+ checksum |= c; \
+ } \
+}
+
+struct jk_map
+{
+ jk_pool_t p;
+ jk_pool_atom_t buf[SMALL_POOL_SIZE];
+
+ const char **names;
+ const void **values;
+ unsigned int *keys;
+
+ unsigned int capacity;
+ unsigned int size;
+};
+
+static void trim_prp_comment(char *prp);
+static size_t trim(char *s);
+static int map_realloc(jk_map_t *m);
+static char *jk_map_replace_properties(jk_map_t *m, jk_map_t *env, char *value);
+
+int jk_map_alloc(jk_map_t **m)
+{
+ if (m) {
+ return jk_map_open(*m = (jk_map_t *)malloc(sizeof(jk_map_t)));
+ }
+
+ return JK_FALSE;
+}
+
+int jk_map_free(jk_map_t **m)
+{
+ int rc = JK_FALSE;
+
+ if (m && *m) {
+ jk_map_close(*m);
+ free(*m);
+ *m = NULL;
+ }
+
+ return rc;
+}
+
+int jk_map_open(jk_map_t *m)
+{
+ int rc = JK_FALSE;
+
+ if (m) {
+ jk_open_pool(&m->p, m->buf, sizeof(jk_pool_atom_t) * SMALL_POOL_SIZE);
+ m->capacity = 0;
+ m->size = 0;
+ m->keys = NULL;
+ m->names = NULL;
+ m->values = NULL;
+ rc = JK_TRUE;
+ }
+
+ return rc;
+}
+
+int jk_map_close(jk_map_t *m)
+{
+ int rc = JK_FALSE;
+
+ if (m) {
+ jk_close_pool(&m->p);
+ rc = JK_TRUE;
+ }
+
+ return rc;
+}
+
+void *jk_map_get(jk_map_t *m, const char *name, const void *def)
+{
+ const void *rc = (void *)def;
+
+ if (m && name) {
+ unsigned int i;
+ unsigned int key;
+ COMPUTE_KEY_CHECKSUM(name, key)
+ for (i = 0; i < m->size; i++) {
+ if (m->keys[i] == key && strcmp(m->names[i], name) == 0) {
+ rc = m->values[i];
+ break;
+ }
+ }
+ }
+
+ return (void *)rc; /* DIRTY */
+}
+
+int jk_map_get_id(jk_map_t *m, const char *name)
+{
+ int rc = -1;
+ if (m && name) {
+ unsigned int i;
+ unsigned int key;
+ COMPUTE_KEY_CHECKSUM(name, key)
+ for (i = 0; i < m->size; i++) {
+ if (m->keys[i] == key && strcmp(m->names[i], name) == 0) {
+ rc = i;
+ break;
+ }
+ }
+ }
+
+ return rc;
+}
+
+const char *jk_map_get_string(jk_map_t *m, const char *name, const char *def)
+{
+ const char *rc = def;
+
+ if (m && name) {
+ unsigned int i;
+ unsigned int key;
+ COMPUTE_KEY_CHECKSUM(name, key)
+ for (i = 0; i < m->size; i++) {
+ if (m->keys[i] == key && strcmp(m->names[i], name) == 0) {
+ rc = m->values[i];
+ break;
+ }
+ }
+ }
+
+ return rc;
+}
+
+
+int jk_map_get_int(jk_map_t *m, const char *name, int def)
+{
+ char buf[100];
+ const char *rc;
+ size_t len;
+ int int_res;
+ int multit = 1;
+
+ sprintf(buf, "%d", def);
+ rc = jk_map_get_string(m, name, buf);
+
+ len = strlen(rc);
+ if (len) {
+ char *lastchar = &buf[0] + len - 1;
+ strcpy(buf, rc);
+ if ('m' == *lastchar || 'M' == *lastchar) {
+ *lastchar = '\0';
+ multit = 1024 * 1024;
+ }
+ else if ('k' == *lastchar || 'K' == *lastchar) {
+ *lastchar = '\0';
+ multit = 1024;
+ }
+ int_res = atoi(buf);
+ }
+ else
+ int_res = def;
+
+ return int_res * multit;
+}
+
+double jk_map_get_double(jk_map_t *m, const char *name, double def)
+{
+ char buf[100];
+ const char *rc;
+
+ sprintf(buf, "%f", def);
+ rc = jk_map_get_string(m, name, buf);
+
+ return atof(rc);
+}
+
+int jk_map_get_bool(jk_map_t *m, const char *name, int def)
+{
+ char buf[100];
+ const char *rc;
+
+ sprintf(buf, "%d", def);
+ rc = jk_map_get_string(m, name, buf);
+
+ return jk_get_bool_code(rc, def);
+}
+
+char **jk_map_get_string_list(jk_map_t *m,
+ const char *name,
+ unsigned int *list_len, const char *def)
+{
+ const char *l = jk_map_get_string(m, name, def);
+ char **ar = NULL;
+
+#ifdef _MT_CODE_PTHREAD
+ char *lasts;
+#endif
+
+ *list_len = 0;
+
+ if (l) {
+ unsigned capacity = 0;
+ unsigned idex = 0;
+ char *p;
+ char *v = jk_pool_strdup(&m->p, l);
+
+ if (!v) {
+ return NULL;
+ }
+
+ /*
+ * GS, in addition to VG's patch, we now need to
+ * strtok also by a "*"
+ */
+#ifdef _MT_CODE_PTHREAD
+ for (p = strtok_r(v, " \t,", &lasts);
+ p; p = strtok_r(NULL, " \t,", &lasts))
+#else
+ for (p = strtok(v, " \t,"); p; p = strtok(NULL, " \t,"))
+#endif
+
+ {
+
+ if (idex == capacity) {
+ ar = jk_pool_realloc(&m->p,
+ sizeof(char *) * (capacity + 5),
+ ar, sizeof(char *) * capacity);
+ if (!ar) {
+ return JK_FALSE;
+ }
+ capacity += 5;
+ }
+ ar[idex] = jk_pool_strdup(&m->p, p);
+ idex++;
+ }
+
+ *list_len = idex;
+ }
+
+ return ar;
+}
+
+int jk_map_get_int_list(jk_map_t *m,
+ const char *name,
+ int *list,
+ unsigned int list_len,
+ const char *def)
+{
+ const char *l = jk_map_get_string(m, name, def);
+
+#ifdef _MT_CODE_PTHREAD
+ char *lasts;
+#endif
+
+ if (!list_len)
+ return 0;
+
+ if (l) {
+ unsigned int capacity = list_len;
+ unsigned int index = 0;
+ char *p;
+ char *v = jk_pool_strdup(&m->p, l);
+
+ if (!v) {
+ return 0;
+ }
+
+ /*
+ * GS, in addition to VG's patch, we now need to
+ * strtok also by a "*"
+ */
+#ifdef _MT_CODE_PTHREAD
+ for (p = strtok_r(v, " \t,", &lasts);
+ p; p = strtok_r(NULL, " \t,", &lasts))
+#else
+ for (p = strtok(v, " \t,"); p; p = strtok(NULL, " \t,"))
+#endif
+
+ {
+ if (index < capacity) {
+ list[index] = atoi(p);
+ index++;
+ }
+ else
+ break;
+ }
+ return index;
+ }
+ return 0;
+}
+
+int jk_map_add(jk_map_t *m, const char *name, const void *value)
+{
+ int rc = JK_FALSE;
+
+ if (m && name) {
+ unsigned int key;
+ COMPUTE_KEY_CHECKSUM(name, key)
+ map_realloc(m);
+
+ if (m->size < m->capacity) {
+ m->values[m->size] = value;
+ m->names[m->size] = jk_pool_strdup(&m->p, name);
+ m->keys[m->size] = key;
+ m->size++;
+ rc = JK_TRUE;
+ }
+ }
+
+ return rc;
+}
+
+int jk_map_put(jk_map_t *m, const char *name, const void *value, void **old)
+{
+ int rc = JK_FALSE;
+
+ if (m && name) {
+ unsigned int i;
+ unsigned int key;
+ COMPUTE_KEY_CHECKSUM(name, key)
+ for (i = 0; i < m->size; i++) {
+ if (m->keys[i] == key && strcmp(m->names[i], name) == 0) {
+ break;
+ }
+ }
+
+ if (i < m->size) {
+ if (old)
+ *old = (void *)m->values[i]; /* DIRTY */
+ m->values[i] = value;
+ rc = JK_TRUE;
+ }
+ else {
+ rc = jk_map_add(m, name, value);
+ }
+ }
+
+ return rc;
+}
+
+
+static int jk_map_validate_property(char *prp, jk_logger_t *l)
+{
+ /* check the worker properties */
+ if (!jk_is_valid_property(prp)) {
+ jk_log(l, JK_LOG_ERROR,
+ "The attribute '%s' is not supported - please check"
+ " the documentation for the supported attributes.",
+ prp);
+ return JK_FALSE;
+ }
+ if (jk_is_deprecated_property(prp)) {
+ jk_log(l, JK_LOG_WARNING,
+ "The attribute '%s' is deprecated - please check"
+ " the documentation for the correct replacement.",
+ prp);
+ }
+ return JK_TRUE;
+}
+
+static int jk_map_handle_duplicates(jk_map_t *m, const char *prp, char **v,
+ int treatment, jk_logger_t *l)
+{
+ const char *oldv = jk_map_get_string(m, prp, NULL);
+ if (oldv) {
+ if ((treatment == JK_MAP_HANDLE_DUPLICATES)
+ && jk_is_unique_property(prp) == JK_FALSE) {
+ char *tmpv = jk_pool_alloc(&m->p,
+ strlen(*v) + strlen(oldv) + 3);
+ if (tmpv) {
+ char sep = '*';
+ if (jk_is_path_property(prp))
+ sep = PATH_SEPERATOR;
+ else if (jk_is_cmd_line_property(prp))
+ sep = ' ';
+ else if (jk_is_list_property(prp))
+ sep = ',';
+ sprintf(tmpv, "%s%c%s", oldv, sep, *v);
+ }
+ *v = tmpv;
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "Concatenated value is: %s -> %s",
+ prp, *v);
+ return JK_FALSE;
+ }
+ else {
+ jk_log(l, JK_LOG_WARNING,
+ "Duplicate key '%s' detected - previous value '%s'"
+ " will be overwritten with '%s'.",
+ prp, oldv ? oldv : "(null)", v ? *v : "(null)");
+ return JK_TRUE;
+ }
+ }
+ else {
+ return JK_TRUE;
+ }
+}
+
+int jk_map_read_property(jk_map_t *m, jk_map_t *env, const char *str,
+ int treatment, jk_logger_t *l)
+{
+ int rc = JK_TRUE;
+ char buf[LENGTH_OF_LINE + 1];
+ char *prp = &buf[0];
+
+ if (strlen(str) > LENGTH_OF_LINE) {
+ jk_log(l, JK_LOG_WARNING,
+ "Line to long (%d > %d), ignoring entry",
+ strlen(str), LENGTH_OF_LINE);
+ return JK_FALSE;
+ }
+
+ strcpy(prp, str);
+ if (trim(prp)) {
+ char *v = strchr(prp, '=');
+ if (v) {
+ *v = '\0';
+ v++;
+ if (trim(v) && trim(prp)) {
+ if (treatment == JK_MAP_HANDLE_RAW) {
+ v = jk_pool_strdup(&m->p, v);
+ }
+ else {
+ if (jk_map_validate_property(prp, l) == JK_FALSE)
+ return JK_FALSE;
+ v = jk_map_replace_properties(m, env, v);
+ if (jk_map_handle_duplicates(m, prp, &v, treatment, l) == JK_TRUE)
+ v = jk_pool_strdup(&m->p, v);
+ }
+ if (v) {
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "Adding property '%s' with value '%s' to map.",
+ prp, v);
+ jk_map_put(m, prp, v, NULL);
+ }
+ else {
+ JK_LOG_NULL_PARAMS(l);
+ rc = JK_FALSE;
+ }
+ }
+ }
+ }
+ return rc;
+}
+
+
+int jk_map_read_properties(jk_map_t *m, jk_map_t *env, const char *f, time_t *modified,
+ int treatment, jk_logger_t *l)
+{
+ int rc = JK_FALSE;
+
+ if (m && f) {
+ struct stat statbuf;
+ FILE *fp;
+ if (jk_stat(f, &statbuf) == -1)
+ return JK_FALSE;
+#if defined(AS400) && !defined(AS400_UTF8)
+ fp = fopen(f, "r, o_ccsid=0");
+#else
+ fp = fopen(f, "r");
+#endif
+
+ if (fp) {
+ char buf[LENGTH_OF_LINE + 1];
+ char *prp;
+
+ rc = JK_TRUE;
+
+ while (NULL != (prp = fgets(buf, LENGTH_OF_LINE, fp))) {
+ trim_prp_comment(prp);
+ if (*prp) {
+ if ((rc = jk_map_read_property(m, env, prp, treatment, l)) == JK_FALSE)
+ break;
+ }
+ }
+ fclose(fp);
+ if (modified)
+ *modified = statbuf.st_mtime;
+ }
+ }
+
+ return rc;
+}
+
+
+int jk_map_size(jk_map_t *m)
+{
+ if (m) {
+ return m->size;
+ }
+
+ return -1;
+}
+
+const char *jk_map_name_at(jk_map_t *m, int idex)
+{
+ if (m && idex >= 0) {
+ return m->names[idex]; /* DIRTY */
+ }
+
+ return NULL;
+}
+
+void *jk_map_value_at(jk_map_t *m, int idex)
+{
+ if (m && idex >= 0) {
+ return (void *)m->values[idex]; /* DIRTY */
+ }
+
+ return NULL;
+}
+
+void jk_map_dump(jk_map_t *m, jk_logger_t *l)
+{
+ if (m) {
+ int s = jk_map_size(m);
+ int i;
+ for (i=0;i<s;i++) {
+ if (!jk_map_name_at(m, i)) {
+ jk_log(l, JK_LOG_WARNING,
+ "Map contains empty name at index %d\n", i);
+ }
+ if (!jk_map_value_at(m, i)) {
+ jk_log(l, JK_LOG_WARNING,
+ "Map contains empty value for name '%s' at index %d\n",
+ jk_map_name_at(m, i), i);
+ }
+ if (JK_IS_DEBUG_LEVEL(l)) {
+ jk_log(l, JK_LOG_DEBUG,
+ "Dump of map: '%s' -> '%s'",
+ jk_map_name_at(m, i) ? jk_map_name_at(m, i) : "(null)",
+ jk_map_value_at(m, i) ? jk_map_value_at(m, i) : "(null)");
+ }
+ }
+ }
+}
+
+int jk_map_copy(jk_map_t *src, jk_map_t *dst)
+{
+ int sz = jk_map_size(src);
+ int i;
+ for (i = 0; i < sz; i++) {
+ const char *name = jk_map_name_at(src, i);
+ if (jk_map_get(dst, name, NULL) == NULL) {
+ if (!jk_map_put(dst, name,
+ jk_pool_strdup(&dst->p, jk_map_get_string(src, name, NULL)),
+ NULL)) {
+ return JK_FALSE;
+ }
+ }
+ }
+ return JK_TRUE;
+}
+
+
+static void trim_prp_comment(char *prp)
+{
+#if defined(AS400) && !defined(AS400_UTF8)
+ char *comment;
+ /* lots of lines that translate a '#' realtime deleted */
+ comment = strchr(prp, *APR_NUMBERSIGN);
+#else
+ char *comment = strchr(prp, '#');
+#endif
+ if (comment) {
+ *comment = '\0';
+ }
+}
+
+static size_t trim(char *s)
+{
+ size_t first;
+ size_t len;
+
+ /* check for empty strings */
+ if (!(len = strlen(s)))
+ return 0;
+ for (len = len - 1; (len > 0) &&
+ isspace((int)((unsigned char)s[len])); len--);
+ if ((len > 0) || !isspace((int)((unsigned char)s[len]))) {
+ len++;
+ }
+
+ s[len] = '\0';
+ len++;
+
+ for (first = 0; (s[first] != '\0') &&
+ isspace((int)((unsigned char)s[first])); first++);
+
+ if (first > 0) {
+ memmove(s, s + first, len - first);
+ }
+
+ return len;
+}
+
+static int map_realloc(jk_map_t *m)
+{
+ if (m->size == m->capacity) {
+ char **names;
+ void **values;
+ unsigned int *keys;
+ int capacity = m->capacity + CAPACITY_INC_SIZE;
+
+ names = (char **)jk_pool_alloc(&m->p, sizeof(char *) * capacity);
+ values = (void **)jk_pool_alloc(&m->p, sizeof(void *) * capacity);
+ keys = (unsigned int *)jk_pool_alloc(&m->p, sizeof(unsigned int) * capacity);
+
+ if (values && names) {
+ if (m->capacity && m->names)
+ memcpy(names, m->names, sizeof(char *) * m->capacity);
+
+ if (m->capacity && m->values)
+ memcpy(values, m->values, sizeof(void *) * m->capacity);
+
+ if (m->capacity && m->keys)
+ memcpy(keys, m->keys, sizeof(unsigned int) * m->capacity);
+
+ m->names = (const char **)names;
+ m->values = (const void **)values;
+ m->keys = keys;
+ m->capacity = capacity;
+
+ return JK_TRUE;
+ }
+ }
+
+ return JK_FALSE;
+}
+
+/**
+ * Replace $(property) in value.
+ *
+ */
+static char *jk_map_replace_properties(jk_map_t *m, jk_map_t *env, char *value)
+{
+ char *rc = value;
+ char *env_start = rc;
+ int rec = 0;
+
+ while ((env_start = strstr(env_start, "$(")) != NULL) {
+ char *env_end = strstr(env_start, ")");
+ if (rec++ > 20)
+ return rc;
+ if (env_end) {
+ char env_name[LENGTH_OF_LINE + 1] = "";
+ const char *env_value;
+#if defined(WIN32)
+ char env_buf[LENGTH_OF_LINE + 1];
+#endif
+ *env_end = '\0';
+ strcpy(env_name, env_start + 2);
+ *env_end = ')';
+
+ env_value = jk_map_get_string(m, env_name, NULL);
+ if (!env_value) {
+ env_value = getenv(env_name);
+ }
+ if (!env_value && env) {
+ /* Search inside local environment table */
+ env_value = jk_map_get_string(env, env_name, NULL);
+ }
+
+#if defined(WIN32)
+ if (!env_value) {
+ /* Try the env block from calling process */
+ if (GetEnvironmentVariable(env_name, env_buf,
+ sizeof(env_buf)))
+ env_value = &env_buf[0];
+ }
+#endif
+ if (env_value) {
+ size_t offset = 0;
+ char *new_value = jk_pool_alloc(&m->p,
+ (sizeof(char) *
+ (strlen(rc) +
+ strlen(env_value))));
+ if (!new_value) {
+ break;
+ }
+ *env_start = '\0';
+ strcpy(new_value, rc);
+ strcat(new_value, env_value);
+ strcat(new_value, env_end + 1);
+ offset = env_start - rc + strlen(env_value);
+ rc = new_value;
+ /* Avoid recursive subst */
+ env_start = rc + offset;
+ }
+ else {
+ env_start = env_end;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Resolve references
+ *
+ */
+int jk_map_resolve_references(jk_map_t *m, const char *prefix,
+ int wildcard, int depth, jk_logger_t *l)
+{
+ int rc = JK_FALSE;
+
+ JK_TRACE_ENTER(l);
+
+ if (m && prefix) {
+ if (depth <= JK_MAP_RECURSION) {
+ size_t prelen = strlen(prefix);
+ unsigned int i;
+ rc = JK_TRUE;
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "Checking for references with prefix %s with%s wildcard (recursion %d)",
+ prefix, wildcard? "" : "out", depth);
+ for (i = 0; i < m->size; i++) {
+ char *v = (char *)m->values[i];
+ if (v && *v &&
+ !strncmp(m->names[i], prefix, prelen)) {
+ size_t remain = strlen(m->names[i]) - prelen;
+ if ((remain == JK_MAP_REFERENCE_SZ ) || (wildcard && remain > JK_MAP_REFERENCE_SZ)) {
+ remain = strlen(m->names[i]) - JK_MAP_REFERENCE_SZ;
+ if (!strncmp(m->names[i] + remain, JK_MAP_REFERENCE, JK_MAP_REFERENCE_SZ)) {
+ char *from = jk_pool_alloc(&m->p,
+ (sizeof(char) *
+ (strlen(v) + 2)));
+ char *to = jk_pool_alloc(&m->p,
+ (sizeof(char) *
+ (remain + 2)));
+ if (!from || !to) {
+ jk_log(l, JK_LOG_ERROR,
+ "Error in string allocation");
+ rc = JK_FALSE;
+ break;
+ }
+ strcpy(from, v);
+ *(from+strlen(v)) = '.';
+ *(from+strlen(v)+1) = '\0';
+ strncpy(to, m->names[i], remain);
+ *(to+remain) = '.';
+ *(to+remain+1) = '\0';
+
+ rc = jk_map_resolve_references(m, v, 0, depth+1, l);
+ if (rc == JK_FALSE) {
+ break;
+ }
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "Copying values from %s to %s",
+ from, to);
+ rc = jk_map_inherit_properties(m, from, to, l);
+ if (rc == JK_FALSE) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ jk_log(l, JK_LOG_ERROR,
+ "Recursion limit %d for worker references with prefix '%s' reached",
+ JK_MAP_RECURSION, prefix);
+ }
+ }
+ else {
+ JK_LOG_NULL_PARAMS(l);
+ }
+ JK_TRACE_EXIT(l);
+ return rc;
+}
+
+/**
+ * Inherit properties
+ *
+ */
+int jk_map_inherit_properties(jk_map_t *m, const char *from, const char *to, jk_logger_t *l)
+{
+ int rc = JK_FALSE;
+ const char *prp;
+ char *to_prp;
+
+ if (m && from && to) {
+ unsigned int i;
+ for (i = 0; i < m->size; i++) {
+ if (!strncmp(m->names[i], from, strlen(from))) {
+ rc = JK_TRUE;
+ prp = m->names[i] + strlen(from);
+ to_prp = jk_pool_alloc(&m->p,
+ (sizeof(char) *
+ (strlen(to) +
+ strlen(prp) + 1)));
+ if (!to_prp) {
+ jk_log(l, JK_LOG_ERROR,
+ "Error in string allocation for attribute '%s.%s'",
+ to, prp);
+ rc = JK_FALSE;
+ break;
+ }
+ strcpy(to_prp, to);
+ strcat(to_prp, prp);
+ if (jk_map_get_id(m, to_prp) < 0 ) {
+ rc = jk_map_add(m, to_prp, m->values[i]);
+ if (rc == JK_FALSE) {
+ jk_log(l, JK_LOG_ERROR,
+ "Error when adding attribute '%s'",
+ to_prp);
+ break;
+ }
+ }
+ }
+ }
+ if ( rc == JK_FALSE) {
+ jk_log(l, JK_LOG_ERROR,
+ "Reference '%s' not found",
+ from);
+ }
+ }
+ else {
+ JK_LOG_NULL_PARAMS(l);
+ }
+ return rc;
+}