~ubuntu-branches/ubuntu/oneiric/libapache-mod-jk/oneiric

« back to all changes in this revision

Viewing changes to jk/native/common/jk_map.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2006-08-05 16:30:53 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060805163053-myf66gm6j1a21ps6
Tags: 1:1.2.18-1ubuntu1
Merge from Debian unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright 1999-2004 The Apache Software Foundation
3
 
 *
4
 
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 
 *  you may not use this file except in compliance with the License.
6
 
 *  You may obtain a copy of the License at
7
 
 *
8
 
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 
 *
10
 
 *  Unless required by applicable law or agreed to in writing, software
11
 
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 
 *  See the License for the specific language governing permissions and
14
 
 *  limitations under the License.
15
 
 */
16
 
 
17
 
/***************************************************************************
18
 
 * Description: General purpose map object                                 *
19
 
 * Author:      Gal Shachor <shachor@il.ibm.com>                           *
20
 
 * Author:      Mladen Turk <mturk@apache.org>                             *
21
 
 * Version:     $Revision: 1.36 $                                          *
22
 
 ***************************************************************************/
23
 
#ifdef AS400
24
 
#include "apr_xlate.h"
25
 
#endif
26
 
 
27
 
#include "jk_global.h"
28
 
#include "jk_map.h"
29
 
#include "jk_pool.h"
30
 
#include "jk_map.h"
31
 
#include "jk_util.h"
32
 
#include "jk_shm.h"
33
 
 
34
 
#define CAPACITY_INC_SIZE (50)
35
 
#define LENGTH_OF_LINE    (8192)
36
 
 
37
 
#ifdef AS400
38
 
#define CASE_MASK 0xbfbfbfbf
39
 
#else
40
 
#define CASE_MASK 0xdfdfdfdf
41
 
#endif
42
 
 
43
 
/* Compute the "checksum" for a key, consisting of the first
44
 
 * 4 bytes, normalized for case-insensitivity and packed into
45
 
 * an int...this checksum allows us to do a single integer
46
 
 * comparison as a fast check to determine whether we can
47
 
 * skip a strcasecmp
48
 
 */
49
 
#define COMPUTE_KEY_CHECKSUM(key, checksum)    \
50
 
{                                              \
51
 
    const char *k = (key);                     \
52
 
    unsigned int c = (unsigned int)*k;         \
53
 
    (checksum) = c;                            \
54
 
    (checksum) <<= 8;                          \
55
 
    if (c) {                                   \
56
 
        c = (unsigned int)*++k;                \
57
 
        checksum |= c;                         \
58
 
    }                                          \
59
 
    (checksum) <<= 8;                          \
60
 
    if (c) {                                   \
61
 
        c = (unsigned int)*++k;                \
62
 
        checksum |= c;                         \
63
 
    }                                          \
64
 
    (checksum) <<= 8;                          \
65
 
    if (c) {                                   \
66
 
        c = (unsigned int)*++k;                \
67
 
        checksum |= c;                         \
68
 
    }                                          \
69
 
    checksum &= CASE_MASK;                     \
70
 
}
71
 
 
72
 
struct jk_map
73
 
{
74
 
    jk_pool_t p;
75
 
    jk_pool_atom_t buf[SMALL_POOL_SIZE];
76
 
 
77
 
    const char **names;
78
 
    const void **values;
79
 
    unsigned int *keys;
80
 
 
81
 
    unsigned int capacity;
82
 
    unsigned int size;
83
 
};
84
 
 
85
 
static void trim_prp_comment(char *prp);
86
 
static size_t trim(char *s);
87
 
static int map_realloc(jk_map_t *m);
88
 
 
89
 
int jk_map_alloc(jk_map_t **m)
90
 
{
91
 
    if (m) {
92
 
        return jk_map_open(*m = (jk_map_t *)malloc(sizeof(jk_map_t)));
93
 
    }
94
 
 
95
 
    return JK_FALSE;
96
 
}
97
 
 
98
 
int jk_map_free(jk_map_t **m)
99
 
{
100
 
    int rc = JK_FALSE;
101
 
 
102
 
    if (m && *m) {
103
 
        jk_map_close(*m);
104
 
        free(*m);
105
 
        *m = NULL;
106
 
    }
107
 
 
108
 
    return rc;
109
 
}
110
 
 
111
 
int jk_map_open(jk_map_t *m)
112
 
{
113
 
    int rc = JK_FALSE;
114
 
 
115
 
    if (m) {
116
 
        jk_open_pool(&m->p, m->buf, sizeof(jk_pool_atom_t) * SMALL_POOL_SIZE);
117
 
        m->capacity = 0;
118
 
        m->size = 0;
119
 
        m->keys  = NULL;
120
 
        m->names = NULL;
121
 
        m->values = NULL;
122
 
        rc = JK_TRUE;
123
 
    }
124
 
 
125
 
    return rc;
126
 
}
127
 
 
128
 
int jk_map_close(jk_map_t *m)
129
 
{
130
 
    int rc = JK_FALSE;
131
 
 
132
 
    if (m) {
133
 
        jk_close_pool(&m->p);
134
 
        rc = JK_TRUE;
135
 
    }
136
 
 
137
 
    return rc;
138
 
}
139
 
 
140
 
void *jk_map_get(jk_map_t *m, const char *name, const void *def)
141
 
{
142
 
    const void *rc = (void *)def;
143
 
 
144
 
    if (m && name) {
145
 
        unsigned int i;
146
 
        unsigned int key;
147
 
        COMPUTE_KEY_CHECKSUM(name, key)
148
 
        for (i = 0; i < m->size; i++) {
149
 
            if (m->keys[i] == key && strcasecmp(m->names[i], name) == 0) {
150
 
                rc = m->values[i];
151
 
                break;
152
 
            }
153
 
        }
154
 
    }
155
 
 
156
 
    return (void *)rc;          /* DIRTY */
157
 
}
158
 
 
159
 
int jk_map_get_id(jk_map_t *m, const char *name)
160
 
{
161
 
    int rc = -1;
162
 
    if (m && name) {
163
 
        unsigned int i;
164
 
        unsigned int key;
165
 
        COMPUTE_KEY_CHECKSUM(name, key)
166
 
        for (i = 0; i < m->size; i++) {
167
 
            if (m->keys[i] == key && strcasecmp(m->names[i], name) == 0) {
168
 
                rc = i;
169
 
                break;
170
 
            }
171
 
        }
172
 
    }
173
 
 
174
 
    return rc;
175
 
}
176
 
 
177
 
const char *jk_map_get_string(jk_map_t *m, const char *name, const char *def)
178
 
{
179
 
    const char *rc = def;
180
 
 
181
 
    if (m && name) {
182
 
        unsigned int i;
183
 
        unsigned int key;
184
 
        COMPUTE_KEY_CHECKSUM(name, key)
185
 
        for (i = 0; i < m->size; i++) {
186
 
            if (m->keys[i] == key && strcasecmp(m->names[i], name) == 0) {
187
 
                rc = m->values[i];
188
 
                break;
189
 
            }
190
 
        }
191
 
    }
192
 
 
193
 
    return rc;
194
 
}
195
 
 
196
 
 
197
 
int jk_map_get_int(jk_map_t *m, const char *name, int def)
198
 
{
199
 
    char buf[100];
200
 
    const char *rc;
201
 
    size_t len;
202
 
    int int_res;
203
 
    int multit = 1;
204
 
 
205
 
    sprintf(buf, "%d", def);
206
 
    rc = jk_map_get_string(m, name, buf);
207
 
 
208
 
    len = strlen(rc);
209
 
    if (len) {
210
 
        char *lastchar = &buf[0] + len - 1;
211
 
        strcpy(buf, rc);
212
 
        if ('m' == *lastchar || 'M' == *lastchar) {
213
 
            *lastchar = '\0';
214
 
            multit = 1024 * 1024;
215
 
        }
216
 
        else if ('k' == *lastchar || 'K' == *lastchar) {
217
 
            *lastchar = '\0';
218
 
            multit = 1024;
219
 
        }
220
 
        int_res = atoi(buf);
221
 
    }
222
 
    else
223
 
        int_res = def;
224
 
 
225
 
    return int_res * multit;
226
 
}
227
 
 
228
 
double jk_map_get_double(jk_map_t *m, const char *name, double def)
229
 
{
230
 
    char buf[100];
231
 
    const char *rc;
232
 
 
233
 
    sprintf(buf, "%f", def);
234
 
    rc = jk_map_get_string(m, name, buf);
235
 
 
236
 
    return atof(rc);
237
 
}
238
 
 
239
 
int jk_map_get_bool(jk_map_t *m, const char *name, int def)
240
 
{
241
 
    char buf[100];
242
 
    size_t len;
243
 
    const char *rc;
244
 
    int rv = 0;
245
 
 
246
 
    sprintf(buf, "%d", def);
247
 
    rc = jk_map_get_string(m, name, buf);
248
 
 
249
 
    len = strlen(rc);
250
 
    if (len) {
251
 
        if (strcasecmp(rc, "true") == 0 ||
252
 
            *rc == 'Y' || *rc == 'y' || *rc == '1') {
253
 
            rv = 1;
254
 
        }
255
 
    }
256
 
    return rv;
257
 
}
258
 
 
259
 
char **jk_map_get_string_list(jk_map_t *m,
260
 
                              const char *name,
261
 
                              unsigned *list_len, const char *def)
262
 
{
263
 
    const char *l = jk_map_get_string(m, name, def);
264
 
    char **ar = NULL;
265
 
 
266
 
#if defined(AS400) || defined(_REENTRANT)
267
 
    char *lasts;
268
 
#endif
269
 
 
270
 
    *list_len = 0;
271
 
 
272
 
    if (l) {
273
 
        unsigned capacity = 0;
274
 
        unsigned idex = 0;
275
 
        char *p;
276
 
        char *v = jk_pool_strdup(&m->p, l);
277
 
 
278
 
        if (!v) {
279
 
            return NULL;
280
 
        }
281
 
 
282
 
        /*
283
 
         * GS, in addition to VG's patch, we now need to
284
 
         * strtok also by a "*"
285
 
         */
286
 
#if defined(AS400) || defined(_REENTRANT)
287
 
        for (p = strtok_r(v, " \t,", &lasts);
288
 
             p; p = strtok_r(NULL, " \t,", &lasts))
289
 
#else
290
 
        for (p = strtok(v, " \t,"); p; p = strtok(NULL, " \t,"))
291
 
#endif
292
 
 
293
 
        {
294
 
 
295
 
            if (idex == capacity) {
296
 
                ar = jk_pool_realloc(&m->p,
297
 
                                     sizeof(char *) * (capacity + 5),
298
 
                                     ar, sizeof(char *) * capacity);
299
 
                if (!ar) {
300
 
                    return JK_FALSE;
301
 
                }
302
 
                capacity += 5;
303
 
            }
304
 
            ar[idex] = jk_pool_strdup(&m->p, p);
305
 
            idex++;
306
 
        }
307
 
 
308
 
        *list_len = idex;
309
 
    }
310
 
 
311
 
    return ar;
312
 
}
313
 
 
314
 
int jk_map_put(jk_map_t *m, const char *name, const void *value, void **old)
315
 
{
316
 
    int rc = JK_FALSE;
317
 
 
318
 
    if (m && name) {
319
 
        unsigned int i;
320
 
        unsigned int key;
321
 
        COMPUTE_KEY_CHECKSUM(name, key)
322
 
        for (i = 0; i < m->size; i++) {
323
 
            if (m->keys[i] == key && strcasecmp(m->names[i], name) == 0) {
324
 
                break;
325
 
            }
326
 
        }
327
 
 
328
 
        if (i < m->size) {
329
 
            if (old)
330
 
                *old = (void *)m->values[i];        /* DIRTY */
331
 
            m->values[i] = value;
332
 
            rc = JK_TRUE;
333
 
        }
334
 
        else {
335
 
            map_realloc(m);
336
 
 
337
 
            if (m->size < m->capacity) {
338
 
                m->values[m->size] = value;
339
 
                m->names[m->size] = jk_pool_strdup(&m->p, name);
340
 
                m->keys[m->size] = key;
341
 
                m->size++;
342
 
                rc = JK_TRUE;
343
 
            }
344
 
        }
345
 
    }
346
 
 
347
 
    return rc;
348
 
}
349
 
 
350
 
int jk_map_read_property(jk_map_t *m, const char *str)
351
 
{
352
 
    int rc = JK_TRUE;
353
 
    char buf[LENGTH_OF_LINE + 1];
354
 
    char *prp = &buf[0];
355
 
 
356
 
    if (strlen(str) > LENGTH_OF_LINE)
357
 
        return JK_FALSE;
358
 
 
359
 
    strcpy(prp, str);
360
 
    if (trim(prp)) {
361
 
        char *v = strchr(prp, '=');
362
 
        if (v) {
363
 
            *v = '\0';
364
 
            v++;
365
 
            trim(prp);
366
 
            trim(v);
367
 
            if (strlen(v) && strlen(prp)) {
368
 
                const char *oldv = jk_map_get_string(m, prp, NULL);
369
 
                v = jk_map_replace_properties(v, m);
370
 
                if (oldv && jk_is_unique_property(prp) == JK_FALSE) {
371
 
                    char *tmpv = jk_pool_alloc(&m->p,
372
 
                                       strlen(v) + strlen(oldv) + 3);
373
 
                    if (tmpv) {
374
 
                        char sep = '*';
375
 
                        if (jk_is_path_poperty(prp))
376
 
                            sep = PATH_SEPERATOR;
377
 
                        else if (jk_is_cmd_line_poperty(prp))
378
 
                            sep = ' ';
379
 
                        else if (!strcasecmp(prp, "worker.list"))
380
 
                            sep = ',';
381
 
                        sprintf(tmpv, "%s%c%s", oldv, sep, v);
382
 
                    }
383
 
                    v = tmpv;
384
 
                }
385
 
                else {
386
 
                    v = jk_pool_strdup(&m->p, v);
387
 
                }
388
 
                if (v) {
389
 
                    jk_map_put(m, prp, v, NULL);
390
 
                }
391
 
                else {
392
 
                    rc = JK_FALSE;
393
 
                }
394
 
            }
395
 
        }
396
 
    }
397
 
    return rc;
398
 
}
399
 
 
400
 
 
401
 
int jk_map_read_properties(jk_map_t *m, const char *f, time_t *modified)
402
 
{
403
 
    int rc = JK_FALSE;
404
 
 
405
 
    if (m && f) {
406
 
        struct stat statbuf;
407
 
        FILE *fp;
408
 
        if ((rc = stat(f, &statbuf)) == -1)
409
 
            return JK_FALSE;
410
 
#ifdef AS400
411
 
        fp = fopen(f, "r, o_ccsid=0");
412
 
#else
413
 
        fp = fopen(f, "r");
414
 
#endif
415
 
 
416
 
        if (fp) {
417
 
            char buf[LENGTH_OF_LINE + 1];
418
 
            char *prp;
419
 
 
420
 
            rc = JK_TRUE;
421
 
 
422
 
            while (NULL != (prp = fgets(buf, LENGTH_OF_LINE, fp))) {
423
 
                trim_prp_comment(prp);
424
 
                if (*prp) {
425
 
                    if ((rc =jk_map_read_property(m, prp)) == JK_FALSE)
426
 
                        break;
427
 
                }
428
 
            }
429
 
            fclose(fp);
430
 
            if (modified)
431
 
                *modified = statbuf.st_mtime;
432
 
        }
433
 
    }
434
 
 
435
 
    return rc;
436
 
}
437
 
 
438
 
 
439
 
int jk_map_size(jk_map_t *m)
440
 
{
441
 
    if (m) {
442
 
        return m->size;
443
 
    }
444
 
 
445
 
    return -1;
446
 
}
447
 
 
448
 
const char *jk_map_name_at(jk_map_t *m, int idex)
449
 
{
450
 
    if (m && idex >= 0) {
451
 
        return m->names[idex];  /* DIRTY */
452
 
    }
453
 
 
454
 
    return NULL;
455
 
}
456
 
 
457
 
void *jk_map_value_at(jk_map_t *m, int idex)
458
 
{
459
 
    if (m && idex >= 0) {
460
 
        return (void *)m->values[idex]; /* DIRTY */
461
 
    }
462
 
 
463
 
    return NULL;
464
 
}
465
 
 
466
 
static void trim_prp_comment(char *prp)
467
 
{
468
 
#ifdef AS400
469
 
    char *comment;
470
 
    /* lots of lines that translate a '#' realtime deleted   */
471
 
    comment = strchr(prp, *APR_NUMBERSIGN);
472
 
#else
473
 
    char *comment = strchr(prp, '#');
474
 
#endif
475
 
    if (comment) {
476
 
        *comment = '\0';
477
 
    }
478
 
}
479
 
 
480
 
static size_t trim(char *s)
481
 
{
482
 
    size_t i;
483
 
 
484
 
    /* check for empty strings */
485
 
    if (!(i = strlen(s)))
486
 
        return 0;
487
 
    for (i = i - 1; (i >= 0) &&
488
 
         isspace((int)((unsigned char)s[i])); i--);
489
 
 
490
 
    s[i + 1] = '\0';
491
 
 
492
 
    for (i = 0; ('\0' != s[i]) &&
493
 
         isspace((int)((unsigned char)s[i])); i++);
494
 
 
495
 
    if (i > 0) {
496
 
        strcpy(s, &s[i]);
497
 
    }
498
 
 
499
 
    return strlen(s);
500
 
}
501
 
 
502
 
static int map_realloc(jk_map_t *m)
503
 
{
504
 
    if (m->size == m->capacity) {
505
 
        char **names;
506
 
        void **values;
507
 
        unsigned int *keys;
508
 
        int capacity = m->capacity + CAPACITY_INC_SIZE;
509
 
 
510
 
        names = (char **)jk_pool_alloc(&m->p, sizeof(char *) * capacity);
511
 
        values = (void **)jk_pool_alloc(&m->p, sizeof(void *) * capacity);
512
 
        keys = (unsigned int *)jk_pool_alloc(&m->p, sizeof(unsigned int) * capacity);
513
 
 
514
 
        if (values && names) {
515
 
            if (m->capacity && m->names)
516
 
                memcpy(names, m->names, sizeof(char *) * m->capacity);
517
 
 
518
 
            if (m->capacity && m->values)
519
 
                memcpy(values, m->values, sizeof(void *) * m->capacity);
520
 
 
521
 
            if (m->capacity && m->keys)
522
 
                memcpy(keys, m->keys, sizeof(unsigned int) * m->capacity);
523
 
 
524
 
            m->names = (const char **)names;
525
 
            m->values = (const void **)values;
526
 
            m->keys = keys;
527
 
            m->capacity = capacity;
528
 
 
529
 
            return JK_TRUE;
530
 
        }
531
 
    }
532
 
 
533
 
    return JK_FALSE;
534
 
}
535
 
 
536
 
/**
537
 
 *  Replace $(property) in value.
538
 
 *
539
 
 */
540
 
char *jk_map_replace_properties(const char *value, jk_map_t *m)
541
 
{
542
 
    char *rc = (char *)value;
543
 
    char *env_start = rc;
544
 
    int rec = 0;
545
 
 
546
 
    while ((env_start = strstr(env_start, "$(")) != NULL) {
547
 
        char *env_end = strstr(env_start, ")");
548
 
        if (rec++ > 20)
549
 
            return rc;
550
 
        if (env_end) {
551
 
            char env_name[LENGTH_OF_LINE + 1] = "";
552
 
            const char *env_value;
553
 
#if defined(WIN32)
554
 
            char env_buf[LENGTH_OF_LINE + 1];
555
 
#endif
556
 
            *env_end = '\0';
557
 
            strcpy(env_name, env_start + 2);
558
 
            *env_end = ')';
559
 
 
560
 
            env_value = jk_map_get_string(m, env_name, NULL);
561
 
            if (!env_value) {
562
 
                env_value = getenv(env_name);
563
 
            }
564
 
#if defined(WIN32)
565
 
            if (!env_value) {
566
 
                /* Try the env block from calling process */
567
 
                if (GetEnvironmentVariable(env_name, env_buf,
568
 
                                           sizeof(env_buf)))
569
 
                    env_value = &env_buf[0];
570
 
            }
571
 
#endif
572
 
            if (env_value) {
573
 
                size_t offset = 0;
574
 
                char *new_value = jk_pool_alloc(&m->p,
575
 
                                                (sizeof(char) *
576
 
                                                (strlen(rc) +
577
 
                                                strlen(env_value))));
578
 
                if (!new_value) {
579
 
                    break;
580
 
                }
581
 
                *env_start = '\0';
582
 
                strcpy(new_value, rc);
583
 
                strcat(new_value, env_value);
584
 
                strcat(new_value, env_end + 1);
585
 
                offset = env_start - rc + strlen(env_value);
586
 
                rc = new_value;
587
 
                /* Avoid recursive subst */
588
 
                env_start = rc + offset;
589
 
            }
590
 
            else {
591
 
                env_start = env_end;
592
 
            }
593
 
        }
594
 
        else {
595
 
            break;
596
 
        }
597
 
    }
598
 
 
599
 
    return rc;
600
 
}