jk_uri_worker_map.c

来自「精通tomcat书籍原代码,希望大家共同学习」· C语言 代码 · 共 628 行 · 第 1/2 页

C
628
字号
/*
 *  Copyright 1999-2004 The Apache Software Foundation
 *
 *  Licensed 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: URI to worker map object.                                  *
 *                                                                         *
 * Author:      Gal Shachor <shachor@il.ibm.com>                           *
 * Author:      Mladen Turk <mturk@apache.org>                             *
 * Version:     $Revision: 386282 $                                          *
 ***************************************************************************/

#include "jk_pool.h"
#include "jk_util.h"
#include "jk_map.h"
#include "jk_mt.h"
#include "jk_uri_worker_map.h"

#ifdef WIN32
#define JK_STRCMP   strcasecmp
#define JK_STRNCMP  strnicmp
#else
#define JK_STRCMP   strcmp
#define JK_STRNCMP  strncmp
#endif


/*
 * Given context uri, count the number of path tokens.
 *
 * Servlet specification 2.4, SRV.11.1 says

 *   The container will recursively try tomatch the longest
 *   path-prefix. This is done by stepping down the path tree a
 *   directory at a time, using the / character as a path
 *   separator. The longest match determines the servlet selected.
 *
 * The implication seems to be `most uri path elements is most exact'.
 * This is a little helper function to count uri tokens, so we can
 * keep the worker map sorted with most specific first.
 */
static int worker_count_context_uri_tokens(const char * context)
{
    const char * c = context;
    int count = 0;
    while (c && *c) {
        if ('/' == *c++)
            count++;
    }
    return count;
}

static int worker_compare(const void *elem1, const void *elem2)
{
    uri_worker_record_t *e1 = *(uri_worker_record_t **)elem1;
    uri_worker_record_t *e2 = *(uri_worker_record_t **)elem2;
    int e1_tokens = 0;
    int e2_tokens = 0;

    e1_tokens = worker_count_context_uri_tokens(e1->context);
    e2_tokens = worker_count_context_uri_tokens(e2->context);

    if (e1_tokens != e2_tokens) {
        return (e2_tokens - e1_tokens);
    }
    /* given the same number of URI tokens, use character
     * length as a tie breaker
     */
    return ((int)e2->context_len - (int)e1->context_len);
}

static void worker_qsort(jk_uri_worker_map_t *uw_map)
{

   /* Sort remaining args using Quicksort algorithm: */
   qsort((void *)uw_map->maps, uw_map->size,
         sizeof(uri_worker_record_t *), worker_compare );

}

/* Match = 0, NoMatch = 1, Abort = -1
 * Based loosely on sections of wildmat.c by Rich Salz
 */
static int wildchar_match(const char *str, const char *exp, int icase)
{
    int x, y;

    for (x = 0, y = 0; exp[y]; ++y, ++x) {
        if (!str[x] && exp[y] != '*')
            return -1;
        if (exp[y] == '*') {
            while (exp[++y] == '*');
            if (!exp[y])
                return 0;
            while (str[x]) {
                int ret;
                if ((ret = wildchar_match(&str[x++], &exp[y], icase)) != 1)
                    return ret;
            }
            return -1;
        }
        else if (exp[y] != '?') {
            if (icase && (tolower(str[x]) != tolower(exp[y])))
                return 1;
            else if (!icase && str[x] != exp[y])
                return 1;
        }
    }
    return (str[x] != '\0');
}

int uri_worker_map_alloc(jk_uri_worker_map_t **uw_map,
                         jk_map_t *init_data, jk_logger_t *l)
{
    JK_TRACE_ENTER(l);

    if (uw_map) {
        int rc;
        *uw_map = (jk_uri_worker_map_t *)calloc(1, sizeof(jk_uri_worker_map_t));

        JK_INIT_CS(&((*uw_map)->cs), rc);
        if (rc == JK_FALSE) {
            jk_log(l, JK_LOG_ERROR,
                   "creating thread lock errno=%d",
                   errno);
            JK_TRACE_EXIT(l);
            return JK_FALSE;
        }
        if (init_data)
            rc = uri_worker_map_open(*uw_map, init_data, l);
        JK_TRACE_EXIT(l);
        return rc;
    }

    JK_LOG_NULL_PARAMS(l);
    JK_TRACE_EXIT(l);

    return JK_FALSE;
}

static int uri_worker_map_close(jk_uri_worker_map_t *uw_map, jk_logger_t *l)
{
    JK_TRACE_ENTER(l);

    if (uw_map) {
        int i;
        JK_DELETE_CS(&(uw_map->cs), i);
        jk_close_pool(&uw_map->p);
        JK_TRACE_EXIT(l);
        return JK_TRUE;
    }

    JK_LOG_NULL_PARAMS(l);
    JK_TRACE_EXIT(l);
    return JK_FALSE;
}

int uri_worker_map_free(jk_uri_worker_map_t **uw_map, jk_logger_t *l)
{
    JK_TRACE_ENTER(l);

    if (uw_map && *uw_map) {
        uri_worker_map_close(*uw_map, l);
        free(*uw_map);
        *uw_map = NULL;
        JK_TRACE_EXIT(l);
        return JK_TRUE;
    }
    else
        JK_LOG_NULL_PARAMS(l);

    JK_TRACE_EXIT(l);
    return JK_FALSE;
}

/*
 * Ensure there will be memory in context info to store Context Bases
 */

#define UW_INC_SIZE 4           /* 4 URI->WORKER STEP */

static int uri_worker_map_realloc(jk_uri_worker_map_t *uw_map)
{
    if (uw_map->size == uw_map->capacity) {
        uri_worker_record_t **uwr;
        int capacity = uw_map->capacity + UW_INC_SIZE;

        uwr =
            (uri_worker_record_t **) jk_pool_alloc(&uw_map->p,
                                                   sizeof(uri_worker_record_t
                                                          *) * capacity);

        if (!uwr)
            return JK_FALSE;

        if (uw_map->capacity && uw_map->maps)
            memcpy(uwr, uw_map->maps,
                   sizeof(uri_worker_record_t *) * uw_map->capacity);

        uw_map->maps = uwr;
        uw_map->capacity = capacity;
    }

    return JK_TRUE;
}


int uri_worker_map_add(jk_uri_worker_map_t *uw_map,
                       const char *puri, const char *worker, jk_logger_t *l)
{
    uri_worker_record_t *uwr = NULL;
    char *uri;
    unsigned int match_type = 0;
    unsigned int i;

    JK_TRACE_ENTER(l);

    if (*puri == '-') {
        /* Disable urimap.
         * This way you can disable already mounted
         * context.
         */
        match_type = MATCH_TYPE_DISABLED;
        puri++;
    }
    if (*puri == '!') {
        match_type |= MATCH_TYPE_NO_MATCH;
        puri++;
    }

    /* Find if duplicate entry */
    for (i = 0; i < uw_map->size; i++) {
        uwr = uw_map->maps[i];
        if (strcmp(uwr->uri, puri) == 0) {
            /* Update disabled flag */
            if (match_type & MATCH_TYPE_DISABLED)
                uwr->match_type |= MATCH_TYPE_DISABLED;
            else
                uwr->match_type &= ~MATCH_TYPE_DISABLED;
            if (strcmp(uwr->worker_name, worker) == 0) {
                jk_log(l, JK_LOG_DEBUG,
                       "map rule %s=%s already exists",
                       puri, worker);
                JK_TRACE_EXIT(l);
                return JK_TRUE;
            }
            else {
                jk_log(l, JK_LOG_DEBUG,
                       "changing map rule %s=%s ",
                       puri, worker);
                uwr->worker_name = jk_pool_strdup(&uw_map->p, worker);
                JK_TRACE_EXIT(l);
                return JK_TRUE;
            }
        }
    }
    if (uri_worker_map_realloc(uw_map) == JK_FALSE) {
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }
    uwr = (uri_worker_record_t *)jk_pool_alloc(&uw_map->p,
                                    sizeof(uri_worker_record_t));
    if (!uwr) {
        jk_log(l, JK_LOG_ERROR,
               "can't alloc map entry");
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    uri = jk_pool_strdup(&uw_map->p, puri);
    if (!uri || !worker) {
        jk_log(l, JK_LOG_ERROR,
               "can't alloc uri/worker strings");
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    if (*uri == '/') {
        if (strchr(uri, '*') ||
            strchr(uri, '?')) {
            /* Something like
             * /context/ * /user/ *
             * /context/ *.suffix
             */
            match_type |= MATCH_TYPE_WILDCHAR_PATH;
            jk_log(l, JK_LOG_DEBUG,
                    "wildchar rule %s=%s was added",
                    uri, worker);

        }
        else {
            /* Something like:  JkMount /login/j_security_check ajp13 */
            match_type |= MATCH_TYPE_EXACT;
            jk_log(l, JK_LOG_DEBUG,
                   "exact rule %s=%s was added",
                   uri, worker);
        }
        uwr->uri = uri;
        uwr->context = uri;
        uwr->worker_name = jk_pool_strdup(&uw_map->p, worker);
        uwr->context_len = strlen(uwr->context);
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?