Hi,

Some intro:

Here is the result of the previous discussions regarding using regular
expressions for uri mappings.
I didn't change or enable the conditional build (need some ideas how or
why to do that), although this was the +1 case, so I didn't commit
nothing, and will be pleased if someone can spare some time to test this
(on unix preferably). 

The reason for using pcre was simple (?). It is well tested library, and
our uri mapping code is basically tries to be something like that on the
lower scale, not to mention the  increased power.

How to compile:
1. replace the provided files
2. copy the pcre dir from apache2/srclib to the j-t-c/jk/native2
3. add the pcre to the include path 
4. build pcre
5. add the pcre.lib and pcreposix.lib to the mod_jk2

Win users can simply include the dftables.dsp, pcre.dsp, pcreposix.dsp
to the project, and add the reference to the pcre and pcreposix.

How to use:

It's very simple :-), use the regular expressions!

This is the same:
  [uri:/examples]
  info=Example webapp in the default context. 
  context=/examples
  debug=0


Instead of /* use the \w* (meaning) zero or more 'word' characters.

[uri:/examples/\w*]
info=Map the whole webapp

Here lies the real power!

[uri:/examples/(?!\w*\.(gif|jpg)$)]
info=Map the whole webapp except *.gif and *.jpg files

[uri:/\w+\.jsp$]
info=Map the extension

MT.
/* ========================================================================= *
 *                                                                           *
 *                 The Apache Software License,  Version 1.1                 *
 *                                                                           *
 *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
 *                           All rights reserved.                            *
 *                                                                           *
 * ========================================================================= *
 *                                                                           *
 * Redistribution and use in source and binary forms,  with or without modi- *
 * fication, are permitted provided that the following conditions are met:   *
 *                                                                           *
 * 1. Redistributions of source code  must retain the above copyright notice *
 *    notice, this list of conditions and the following disclaimer.          *
 *                                                                           *
 * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
 *    notice,  this list of conditions  and the following  disclaimer in the *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. The end-user documentation  included with the redistribution,  if any, *
 *    must include the following acknowlegement:                             *
 *                                                                           *
 *       "This product includes  software developed  by the Apache  Software *
 *        Foundation <http://www.apache.org/>."                              *
 *                                                                           *
 *    Alternately, this acknowlegement may appear in the software itself, if *
 *    and wherever such third-party acknowlegements normally appear.         *
 *                                                                           *
 * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
 *    Foundation"  must not be used  to endorse or promote  products derived *
 *    from this  software without  prior  written  permission.  For  written *
 *    permission, please contact <[EMAIL PROTECTED]>.                        *
 *                                                                           *
 * 5. Products derived from this software may not be called "Apache" nor may *
 *    "Apache" appear in their names without prior written permission of the *
 *    Apache Software Foundation.                                            *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
 * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
 * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
 * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
 * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
 * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
 * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
 * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
 * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
 * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
 * POSSIBILITY OF SUCH DAMAGE.                                               *
 *                                                                           *
 * ========================================================================= *
 *                                                                           *
 * This software  consists of voluntary  contributions made  by many indivi- *
 * duals on behalf of the  Apache Software Foundation.  For more information *
 * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
 *                                                                           *
 * ========================================================================= */

/**
 * URI enviroment. All properties associated with a particular URI will be
 * stored here. This coresponds to a per_dir structure in Apache. 
 *
 * Replaces uri_worker_map, etc.
 *
 * Author:      Costin Manolache
 */

#ifndef JK_URIENV_H
#define JK_URIENV_H

#include "jk_logger.h"
#include "jk_endpoint.h"
#include "jk_worker.h"
#include "jk_map.h"
#include "jk_uriMap.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

struct jk_worker;
struct jk_endpoint;
struct jk_env;
struct jk_uri_worker_map;
struct jk_map;
struct jk_webapp;

struct jk_uriEnv;
typedef struct jk_uriEnv jk_uriEnv_t;

/* Standard exact mapping */
#define MATCH_TYPE_EXACT    (0)

/* Standard prefix mapping */
#define MATCH_TYPE_PREFIX  (1)

/* Standard suffix mapping ( *.jsp ) */
#define MATCH_TYPE_SUFFIX   (2)

/* Special: match all URIs of the form *ext */
#define MATCH_TYPE_GENERAL_SUFFIX (3) 

/* Special: match all context path URIs with a path component suffix */
#define MATCH_TYPE_CONTEXT_PATH (4)

/* The uriEnv corresponds to a virtual host */
#define MATCH_TYPE_HOST  (5)

/* Top level context mapping. WEB-INF and META-INF will be checked,
   and the information will be passed to tomcat
*/
#define MATCH_TYPE_CONTEXT  (6)


struct jk_uriEnv {
    struct jk_bean *mbean;
    
    struct jk_pool *pool;
    
    struct jk_workerEnv *workerEnv;

    struct jk_uriMap *uriMap;

    /* Generic name/value properties. 
     */
    struct jk_map *properties;

    /* -------------------- Properties extracted from the URI name ---------- */
    /** Full name */
    char *name;
    
    /* Virtual server handled - NULL means 'global' ( visible in all
     * virtual servers ). Part of the uri name.
     */
    char *virtual;

    /* Original uri ( unparsed ). Part of the uri name.
     */
    char *uri;

    /* -------------------- Properties set using setAttribute ---------- */
    /** ContextPath. Set with 'context' attribute.
     */
    char *contextPath;
    int ctxt_len;
    
    /** ServletName. Set with 'servlet' attribute.
     */
    char *servlet;
    int servletId;

    /** Group, set with 'group' attribute. Defaults to 'lb'.
     */
    char *workerName; 
    struct jk_worker *worker;

    /** For MATCH_TYPE_HOST, the list of aliases for the virtual host.
     *  Set using (multi-value ) 'alias' attribute on vhost uris.
    */
    struct jk_map *aliases;

    /* If set we'll use apr_time to get the request time in microseconds and update
       the scoreboard to reflect that. 
    */
    int timing;
    
    /* Regular Expression structure
     */
    void *regexp;

    int uri_len;

    int match_type;

    /** For MATCH_TYPE_HOST, the list of webapps in that host
     */
    struct jk_map *webapps;

    /** For MATCH_TYPE_CONTEXT, the list of local mappings
     */
    struct jk_map *exactMatch;

    /** For MATCH_TYPE_CONTEXT, the config used to read properties
        for that context.
        For MATCH_TYPE_HOST, the config used to read contexts 
        For MATCH_TYPE_HOST/default it also contains all vhosts

        If NULL - no config was attached.
        ( this will be used in future for run-time deployment )
     */
    struct jk_config *config;

    /* -------------------- Other properties -------------------- */


    /** Different apps can have different loggers.
     */
    struct jk_logger *l;

    /* Environment variables support
     */
    int envvars_in_use;
    struct jk_map *envvars;

    int merged;
    
    /* Reverse mappings
     */
    int reverse;

    /** XXX .
     */
/*     int status; */
/*     int virtualPort; */

    /* -------------------- Methods -------------------- */

    int (*init)( struct jk_env *env, struct jk_uriEnv *_this);

};



#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* JK_URIENV_H */
/* ========================================================================= *
 *                                                                           *
 *                 The Apache Software License,  Version 1.1                 *
 *                                                                           *
 *          Copyright (c) 1999-2002 The Apache Software Foundation.          *
 *                           All rights reserved.                            *
 *                                                                           *
 * ========================================================================= *
 *                                                                           *
 * Redistribution and use in source and binary forms,  with or without modi- *
 * fication, are permitted provided that the following conditions are met:   *
 *                                                                           *
 * 1. Redistributions of source code  must retain the above copyright notice *
 *    notice, this list of conditions and the following disclaimer.          *
 *                                                                           *
 * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
 *    notice,  this list of conditions  and the following  disclaimer in the *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. The end-user documentation  included with the redistribution,  if any, *
 *    must include the following acknowlegement:                             *
 *                                                                           *
 *       "This product includes  software developed  by the Apache  Software *
 *        Foundation <http://www.apache.org/>."                              *
 *                                                                           *
 *    Alternately, this acknowlegement may appear in the software itself, if *
 *    and wherever such third-party acknowlegements normally appear.         *
 *                                                                           *
 * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
 *    Foundation"  must not be used  to endorse or promote  products derived *
 *    from this  software without  prior  written  permission.  For  written *
 *    permission, please contact <[EMAIL PROTECTED]>.                        *
 *                                                                           *
 * 5. Products derived from this software may not be called "Apache" nor may *
 *    "Apache" appear in their names without prior written permission of the *
 *    Apache Software Foundation.                                            *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
 * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
 * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
 * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
 * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
 * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
 * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
 * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
 * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
 * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
 * POSSIBILITY OF SUCH DAMAGE.                                               *
 *                                                                           *
 * ========================================================================= *
 *                                                                           *
 * This software  consists of voluntary  contributions made  by many indivi- *
 * duals on behalf of the  Apache Software Foundation.  For more information *
 * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
 *                                                                           *
 * ========================================================================= */

/**
 * Description: URI to worker map object.                          
 * Maps can be                                                     
 *                                                                 
 * Exact Context -> /exact/uri=worker e.g. /examples/do[STAR]=ajp12
 * Context Based -> /context/[STAR]=worker e.g. /examples/[STAR]=ajp12
 * Context and suffix ->/context/[STAR].suffix=worker e.g. /examples/[STAR].jsp=ajp12
 *                                                                         
 * This lets us either partition the work among the web server and the     
 * servlet container.                                                      
 *                                                                         
 * @author: Gal Shachor <[EMAIL PROTECTED]>
 * @author: Costin Manolache
 * @author: Mladen Turk
 */

#include "jk_pool.h"
#include "jk_env.h"
#include "jk_uriMap.h"
#include "jk_registry.h"

#include "apr_lib.h"
#include "apr_pools.h"
#include "apr_strings.h"
#include "pcreposix.h"

static jk_uriEnv_t *jk2_uriMap_mapUri(jk_env_t *env, jk_uriMap_t *uriMap,
                                      const char *vhost,
                                      const char *uri);

/*
 * Was: check_security_fraud
 */
static int jk2_uriMap_checkUri(jk_env_t *env, jk_uriMap_t *uriMap, 
                               const char *uri)
{
    /* Use the apr_uri */
    return JK_OK;
}


/** Add a uri mapping. Called during uri: initialization. Will just copy the
    uri in the table ( XXX use a map keyed on name ). In init() we process this
    and set the right structures.
 */
static int jk2_uriMap_addUriEnv( jk_env_t *env, jk_uriMap_t *uriMap, jk_uriEnv_t 
*uriEnv )
{
    uriMap->maps->put(env, uriMap->maps, uriEnv->name, uriEnv, NULL);
    if (uriMap->mbean->debug > 0) 
        env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                      "uriMap.addUriEnv() %s %s %s\n", uriEnv->name, 
                      uriEnv->virtual, uriEnv->uri);
    return JK_OK;
}

static int JK_METHOD jk2_uriMap_setProperty(jk_env_t *env, jk_bean_t *mbean,
                                  char *name, void *valueP)
{
    jk_uriMap_t *uriMap = mbean->object;
    char *value = valueP;
    
    return JK_OK;
}

static jk_uriEnv_t *jk2_uriMap_findMap(jk_env_t *env, jk_uriMap_t *uriMap,
                                         jk_map_t *mapTable, const char *uri, 
                                         int uriLen)
{
    int i;    
    int sz = mapTable->size(env, mapTable);
    
    for (i = 0; i < sz; i++) {
        jk_uriEnv_t *uwr=mapTable->valueAt(env, mapTable, i);

        if (uwr->regexp) {
            regex_t *r = (regex_t *)uwr->regexp;
            regmatch_t regm[10];
            if (!regexec(r, uri, r->re_nsub + 1, regm, 0)) {
                return uwr;
            }
        }
        else {
            if (uriLen != uwr->uri_len) 
                continue;
            if (strncmp(uri, uwr->uri, uwr->uri_len) == 0) {
                return uwr;
            }
        }
    }
    return NULL;
}


static jk_uriEnv_t *jk2_uriMap_prefixMap(jk_env_t *env, jk_uriMap_t *uriMap,
                                          jk_map_t *mapTable, const char *uri, 
                                          int uriLen)
{
    int best_match = 0;
    jk_uriEnv_t *match = NULL;
    int i;
    
    int sz = mapTable->size(env, mapTable);
    
    for (i = 0; i < sz; i++) {
        jk_uriEnv_t *uwr = mapTable->valueAt(env, mapTable, i);

        if (uriLen < uwr->uri_len)
            continue;
        if (strncmp(uri, uwr->uri, uwr->uri_len) == 0) {
            if (uwr->uri_len > best_match) {
                best_match = uwr->uri_len;
                match = uwr;
            }
        }
    }
    return match;
}

/* Find the vhost */
static jk_uriEnv_t *jk2_uriMap_hostMap(jk_env_t *env, jk_uriMap_t *uriMap,
                                       const char *vhost)
{
    int i;
    
    if( vhost != NULL) {
        int sz = uriMap->vhosts->size(env, uriMap->vhosts);
        for (i = 0; i < sz; i++) {
            char *name = uriMap->vhosts->nameAt(env, uriMap->vhosts, i);
            
            /* Host name is not case sensitive */
            if (strcasecmp(name, vhost) == 0) {
                return uriMap->vhosts->valueAt(env, uriMap->vhosts, i);
            }
        }
        /* Can't find vhost, return default */
    }
    return uriMap->defaultVhost;
}

static int jk2_uriMap_init(jk_env_t *env, jk_uriMap_t *uriMap)
{
    int rc = JK_OK;
    int i;
    jk_workerEnv_t *workerEnv = uriMap->workerEnv;
    jk_bean_t *mbean;
    jk_uriEnv_t *uriEnv;

    mbean=env->getBean2(env, "uri", "");
    if (mbean==NULL )
        mbean = env->createBean2(env, workerEnv->pool,"uri", "");
    if (mbean == NULL || mbean->object == NULL ) {
        env->l->jkLog(env, env->l, JK_LOG_ERROR,
                      "uriMap.factory() Fail to create default host\n");
        return JK_ERR;
    }
    uriMap->defaultVhost = mbean->object;
    
    if (uriMap->mbean->debug > 5) 
        env->l->jkLog(env, env->l, JK_LOG_DEBUG, "uriMap.init() set default host\n"); 

    /* Initialize the vhosts table */
    for (i = 0; i < uriMap->maps->size(env, uriMap->maps ); i++) {
        uriEnv = uriMap->maps->valueAt(env, uriMap->maps, i);

        if (uriEnv == NULL) 
            continue;
        if (uriEnv->match_type == MATCH_TYPE_HOST ) {
            jk2_map_default_create(env, &uriEnv->webapps, uriMap->pool);
            if (uriEnv->virtual != NULL) {
                uriMap->vhosts->put(env, uriMap->vhosts,
                                    uriEnv->virtual, uriEnv, NULL);
            }
            if (uriMap->mbean->debug > 5) 
                env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                              "uriMap.init() loaded host %s\n",uriEnv->virtual); 
        }
    }

    /* Add the vhost aliases ( for each vhost, by looking in the aliases ) */
    for (i = 0; i < uriMap->maps->size(env, uriMap->maps); i++) {
        uriEnv=uriMap->maps->valueAt( env, uriMap->maps, i );
        if (uriEnv->match_type == MATCH_TYPE_HOST &&
            uriEnv->virtual != NULL) {
            
            
            /* XXX TODO */
            
        }
    }    
    
    /** Make sure each vhost has a default context
     */
    for (i = 0; i < uriMap->vhosts->size(env, uriMap->vhosts); i++) {
        jk_uriEnv_t *hostEnv = uriMap->vhosts->valueAt(env, uriMap->vhosts, i);
        jk_uriEnv_t *rootCtx;
        char *uriPath;
        
        if (hostEnv->virtual != NULL) {
            uriPath=env->tmpPool->calloc(env, env->tmpPool,
                                         strlen(hostEnv->virtual) + 3);
            strcpy(uriPath, hostEnv->virtual);
            strcat(uriPath, "/");
        } else {
            uriPath="/";
        }
        
        rootCtx = env->getByName2(env, "uri", uriPath);
        if (rootCtx == NULL) {
            env->createBean2(env, uriMap->mbean->pool, "uri", uriPath);
            rootCtx=env->getByName2(env, "uri", uriPath);
            if (uriMap->mbean->debug > 0) 
                env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                              "uriMap.init() Create default context %s\n", uriPath);
            rootCtx->mbean->setAttribute(env, rootCtx->mbean, "context", "/");
        }
    }

    uriEnv=env->getByName2(env, "uri", "/");
    if (uriEnv == NULL) {
        env->createBean2(env, uriMap->mbean->pool, "uri", "/");
        uriEnv=env->getByName2(env, "uri", "/");
        if (uriMap->mbean->debug > 0) 
            env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                          "uriMap.init() Create default context / ( for default host 
)\n" );
        uriEnv->mbean->setAttribute(env, uriEnv->mbean, "context", "/");
    }
    
    /* Init all contexts */
    /* For each context, init the local uri maps */
    for (i = 0; i < uriMap->maps->size(env, uriMap->maps); i++) {
        jk_uriEnv_t *uriEnv = uriMap->maps->valueAt(env, uriMap->maps, i);
        char *uri;
        char *context;
        if (uriEnv == NULL ) {
            env->l->jkLog(env, env->l, JK_LOG_INFO,
                          "uriMap.init() NPE\n");
        }
        uri = uriEnv->uri;
        context = uriEnv->contextPath;

        if (uri != NULL && context != NULL && strcmp(uri, context) == 0) {
            char *vhost = uriEnv->virtual;
            jk_uriEnv_t *hostEnv=jk2_uriMap_hostMap(env, uriMap, vhost);

            if (uriMap->mbean->debug > 5) 
                env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                              "uriMap.init() loaded context %s %s uri %s %#lx %#lx 
%#lx\n",
                              uriEnv->virtual, context, uri, hostEnv, hostEnv->webapps,
                              uriMap->pool); 

            uriEnv->uri_len = strlen(context);
            uriEnv->match_type = MATCH_TYPE_CONTEXT;
            hostEnv->webapps->put(env, hostEnv->webapps, context, uriEnv, NULL);
            jk2_map_default_create(env, & uriEnv->exactMatch, uriMap->pool);
            /* add default mappings for WEB-INF, META-INF, servlet/, .jsp */
        }
    }

    if (uriMap->mbean->debug > 5) 
        env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                      "uriMap.init() processing mappings\n");

    /* All other mappings are added in the right context leaf.
       XXX We should also sort prefix mappings and maybe use binary search - but
       it won't have too bigger benefits, the number of mappings per ctx is typically 
       small
     */
    for(i = 0; i < uriMap->maps->size(env, uriMap->maps); i++) {
        jk_uriEnv_t *uriEnv = uriMap->maps->valueAt(env, uriMap->maps, i);

        char *vhost= uriEnv->virtual;
        jk_uriEnv_t *hostEnv = jk2_uriMap_hostMap(env, uriMap, vhost);
        
        char *uri = uriEnv->uri;
        jk_uriEnv_t *ctxEnv;

        if (uri == NULL) 
            continue;
        uriEnv->uriMap = uriMap;
        uriEnv->init(env, uriEnv);
        
        if (uriEnv->contextPath) {
            env->l->jkLog(env, env->l, JK_LOG_INFO, "uriMap.init() finding context 
%s\n", uriEnv->contextPath); 
            ctxEnv = hostEnv->webapps->get(env, hostEnv->webapps, uriEnv->contextPath);
        }
        else {
            env->l->jkLog(env, env->l, JK_LOG_INFO, "uriMap.init() prefixing context 
uri %s\n", uri); 
            ctxEnv=jk2_uriMap_prefixMap(env, uriMap, hostEnv->webapps, uri, 
strlen(uri));
        }
        if (ctxEnv == NULL) {
            env->l->jkLog(env, env->l, JK_LOG_INFO, "uriMap.init() no context for 
%s\n", uri); 
            return JK_ERR;
        }
        
        if (uriEnv->match_type == MATCH_TYPE_EXACT) {
            env->l->jkLog(env, env->l, JK_LOG_DEBUG, "uriMap adding exact %s\n", uri); 
            ctxEnv->exactMatch->add( env, ctxEnv->exactMatch, uri, uriEnv );
        }
    }
    return rc;
}

static void jk2_uriMap_destroy(jk_env_t *env, jk_uriMap_t *uriMap)
{

    if (uriMap->mbean->debug > 0) 
        env->l->jkLog(env, env->l, JK_LOG_DEBUG, "uriMap.destroy()\n"); 

    /* this can't be null ( or a NPE would have been generated */
    uriMap->pool->close(env, uriMap->pool);
}



#define SAFE_URI_SIZE 8192

static jk_uriEnv_t *jk2_uriMap_mapUri(jk_env_t *env, jk_uriMap_t *uriMap,
                                      const char *vhost, const char *uri)
{
    int best_match = -1;
    int longest_match = 0;
    char * clean_uri = NULL;
    char *url_rewrite = NULL;
    int uriLen;
    jk_uriEnv_t *hostEnv;
    jk_uriEnv_t *ctxEnv;
    jk_uriEnv_t *match;
    
    /* Ugly hack to avoid using non-thread safe code.
       Modify the uri in place for uri session encoding, then
       restore it to the original. That works since the processing
       happens in a single thred. A better solution is to allocate
       the jk_ws_service and it's pool and pass it as param */
    char origChar = '\0';
    
    /* XXX - need to make sure prefix match take precedence over
       extension match ( now it doesn't )
    */
    
    if (uriMap == NULL || uri==NULL) 
            return NULL;
    
    if (uriMap->mbean->debug > 1)
        env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                      "uriMap.mapUri() %s %s\n", vhost, uri);    

    if (uri[0] != '/') {
        env->l->jkLog(env, env->l, JK_LOG_ERROR,
                      "uriMap.mapUri() uri must start with /\n");
        return NULL;
    }

    hostEnv = jk2_uriMap_hostMap(env, uriMap, vhost);

    if (uriMap->mbean->debug > 1)
        env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                      "uriMap.mapUri() found host %s\n", hostEnv->virtual);    

    url_rewrite = strstr(uri, JK_PATH_SESSION_IDENTIFIER);
        
    if (url_rewrite) {
        origChar = *url_rewrite;
        *url_rewrite = '\0';
        if (uriMap->mbean->debug > 0)
            env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                          "uriMap.mapUri() rewrote uri %s \n",uri);
    }

    uriLen = strlen(uri);

    /* Map the context */
    ctxEnv = jk2_uriMap_prefixMap(env, uriMap, hostEnv->webapps, uri, uriLen);

    if( ctxEnv == NULL ) {
        env->l->jkLog(env, env->l, JK_LOG_INFO,
                      "uriMap.mapUri() no context %s\n", uri);    
        return NULL;
    }
    
    if (uriMap->mbean->debug > 1)
        env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                      "uriMap.mapUri() found ctx %s\n", ctxEnv->uri);    

    /* As per Servlet spec, do exact match first */
    match = jk2_uriMap_findMap(env, uriMap, ctxEnv->exactMatch, uri, uriLen);
    if (match != NULL) {
        /* restore */
        if (url_rewrite)
            *url_rewrite = origChar;
        if (uriMap->mbean->debug > 0)
            env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                          "uriMap.mapUri() exact match %s %s\n",
                          uri, match->workerName ); 
        return match;
    }
    
    /* restore */
    if (url_rewrite)
        *url_rewrite = origChar;
        
    if (uriMap->mbean->debug > 1)
        env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                      "uriMap.mapUri() no match found\n"); 

    return NULL;
}


int JK_METHOD jk2_uriMap_factory(jk_env_t *env, jk_pool_t *pool, jk_bean_t *result,
                                 const char *type, const char *name)
{
    jk_uriMap_t *uriMap;

    uriMap = (jk_uriMap_t *)pool->calloc(env, pool, sizeof(jk_uriMap_t));
    if (!uriMap) {
        env->l->jkLog(env, env->l, JK_LOG_ERROR,
                      "uriMap.factory() OutOfMemoryError\n");
        return JK_ERR;
    }

    uriMap->pool = pool;

    jk2_map_default_create(env, &uriMap->maps, pool);
    jk2_map_default_create(env, &uriMap->vhosts, pool);

    uriMap->init = jk2_uriMap_init;
    uriMap->destroy = jk2_uriMap_destroy;
    uriMap->addUriEnv = jk2_uriMap_addUriEnv;
    uriMap->checkUri = jk2_uriMap_checkUri;
    uriMap->mapUri = jk2_uriMap_mapUri;
            
    result->object = uriMap;
    result->setAttribute = jk2_uriMap_setProperty;
    uriMap->mbean = result;

    return JK_OK;
}

/* ========================================================================= *
 *                                                                           *
 *                 The Apache Software License,  Version 1.1                 *
 *                                                                           *
 *          Copyright (c) 1999-2002 The Apache Software Foundation.          *
 *                           All rights reserved.                            *
 *                                                                           *
 * ========================================================================= *
 *                                                                           *
 * Redistribution and use in source and binary forms,  with or without modi- *
 * fication, are permitted provided that the following conditions are met:   *
 *                                                                           *
 * 1. Redistributions of source code  must retain the above copyright notice *
 *    notice, this list of conditions and the following disclaimer.          *
 *                                                                           *
 * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
 *    notice,  this list of conditions  and the following  disclaimer in the *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. The end-user documentation  included with the redistribution,  if any, *
 *    must include the following acknowlegement:                             *
 *                                                                           *
 *       "This product includes  software developed  by the Apache  Software *
 *        Foundation <http://www.apache.org/>."                              *
 *                                                                           *
 *    Alternately, this acknowlegement may appear in the software itself, if *
 *    and wherever such third-party acknowlegements normally appear.         *
 *                                                                           *
 * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
 *    Foundation"  must not be used  to endorse or promote  products derived *
 *    from this  software without  prior  written  permission.  For  written *
 *    permission, please contact <[EMAIL PROTECTED]>.                        *
 *                                                                           *
 * 5. Products derived from this software may not be called "Apache" nor may *
 *    "Apache" appear in their names without prior written permission of the *
 *    Apache Software Foundation.                                            *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
 * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
 * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
 * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
 * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
 * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
 * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
 * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
 * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
 * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
 * POSSIBILITY OF SUCH DAMAGE.                                               *
 *                                                                           *
 * ========================================================================= *
 *                                                                           *
 * This software  consists of voluntary  contributions made  by many indivi- *
 * duals on behalf of the  Apache Software Foundation.  For more information *
 * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
 *                                                                           *
 * ========================================================================= */

/**
 * Location properties. UriEnv can be:
 *                                                                 
 * Exact Context -> /exact/uri=worker e.g. /examples/do[STAR]=ajp12
 * Context Based -> /context/[STAR]=worker e.g. /examples/[STAR]=ajp12
 * Context and suffix ->/context/[STAR].suffix=worker e.g. /examplesSTAR].jsp=ajp12
 *                                                                         
 */

#include "jk_pool.h"
#include "jk_env.h"
#include "jk_uriMap.h"
#include "jk_registry.h"

#include "apr_pools.h"
#include "apr_strings.h"
#include "pcreposix.h"


static apr_status_t regex_cleanup(void *preg)
{
    regfree((regex_t *) preg);
    return APR_SUCCESS;
}

static regex_t * jk2_pregcomp(jk_pool_t *p, const char *pattern, int cflags)
{
    regex_t *preg = (regex_t *)apr_palloc(p->_private, sizeof(regex_t));

    if (regcomp(preg, pattern, cflags)) {
            return NULL;
    }

    apr_pool_cleanup_register(p->_private, (void *) preg, regex_cleanup, 
regex_cleanup);

    return preg;
}

/** Parse the name:
       VHOST/PATH

    If VHOST is empty, we map to the default host.

    The PATH will be further split in CONTEXT/LOCALPATH during init ( after
    we have all uris, including the context paths ).
*/
static int jk2_uriEnv_parseName( jk_env_t *env, jk_uriEnv_t *uriEnv,
                                 char *name)
{
    char *n;
    char *slash;
    
    if (*name == '!') {
        uriEnv->reverse = 1;
        ++name;
    }
    n = name;
    slash=strchr( name, '/' );
    
    /* fprintf( stderr, "XXX parseURI %s\n", name ); */
    
    if( slash==NULL ) {
        /* That's a virtual host definition ( no actual mapping, just global
         * settings like aliases, etc
         */
        uriEnv->match_type= MATCH_TYPE_HOST;
        if( name[0]=='\0' ) {
            uriEnv->virtual=NULL; /* "" for the default host */
        } else {
            uriEnv->virtual=name;
        }
        return JK_OK;
    }
    
    /* If it doesn't start with /, it must have a vhost */
    if( *name != '/' ) {
        /* char *portIdx=strchr( n, ':' ); */
        uriEnv->virtual=uriEnv->pool->calloc( env, uriEnv->pool, slash - name + 2 );
        strncpy( uriEnv->virtual, name, slash-name );
    }
    
    n=slash;
    
    uriEnv->uri=uriEnv->pool->pstrdup(env, uriEnv->pool, n);

    return JK_OK;
}

static void * JK_METHOD jk2_uriEnv_getAttribute(jk_env_t *env, jk_bean_t *bean,
                                     char *name )
{
    jk_uriEnv_t *uriEnv=(jk_uriEnv_t *)bean->object;
    
    if( strcmp( name, "host" )==0 ) {
        return  (uriEnv->virtual==NULL) ? "*" : uriEnv->virtual;
    } else if( strcmp( name, "uri" )==0 ) {
        return uriEnv->uri;
    } else if( strcmp( name, "group" )==0 ) {
        return uriEnv->workerName;
    }
    return NULL;
}

static int JK_METHOD jk2_uriEnv_setAttribute(jk_env_t *env,
                                  jk_bean_t *mbean,
                                  char *nameParam,
                                  void *valueP)
{
    jk_uriEnv_t *uriEnv=mbean->object;
    char *valueParam=valueP;
    
    char *name=uriEnv->pool->pstrdup(env,uriEnv->pool, nameParam);
    char *val=uriEnv->pool->pstrdup(env,uriEnv->pool, valueParam);

    uriEnv->properties->add( env ,uriEnv->properties,
                             name, val );

    if( strcmp("group", name) == 0 ) {
        uriEnv->workerName=val;
        return JK_OK;
    } else if( strcmp("context", name) == 0 ) {
        
        uriEnv->contextPath=val;
        uriEnv->ctxt_len=strlen( val );

        if( strcmp( val, uriEnv->uri ) == 0 ) {
            uriEnv->match_type= MATCH_TYPE_CONTEXT;
        }
        return JK_OK;
    } else if( strcmp("servlet", name) == 0 ) {
        uriEnv->servlet=val;
    } else if( strcmp("timing", name) == 0 ) {
        uriEnv->timing=atoi( val );
    } else if( strcmp("reverse", name) == 0 ) {
        uriEnv->reverse=atoi( val );
    } else if( strcmp("alias", name) == 0 ) {
        if( uriEnv->match_type == MATCH_TYPE_HOST ) {
            if( uriEnv->aliases==NULL ) {
                jk2_map_default_create( env, &uriEnv->aliases, mbean->pool );
            }
            uriEnv->aliases->put( env, uriEnv->aliases, val, uriEnv, NULL );
        }
        /* XXX: Add URI alias ? 
        */
    }
    
    /* OLD - DEPRECATED */
    if( strcmp("worker", name) == 0 ) {
        uriEnv->workerName=val;
    } else if( strcmp("path", name) == 0 ) {
        if( val==NULL )
            uriEnv->uri=NULL;
        else
            uriEnv->uri=uriEnv->pool->pstrdup(env, uriEnv->pool, val);
    }
    if( strcmp("uri", name) == 0 ) {
        jk2_uriEnv_parseName( env, uriEnv, val);
    }
    if( strcmp("name", name) == 0 ) {
        jk2_uriEnv_parseName( env, uriEnv, val);
    }
    if( strcmp("vhost", name) == 0 ) {
        if( val==NULL )
            uriEnv->virtual=NULL;
        else
            uriEnv->virtual=uriEnv->pool->pstrdup(env, uriEnv->pool, val);
    }
    return JK_OK;
}


static int jk2_uriEnv_init(jk_env_t *env, jk_uriEnv_t *uriEnv)
{
    char *uri, *wname;    
    uri=uriEnv->pool->pstrdup( env, uriEnv->pool, uriEnv->uri);

    /* Set the worker */
    wname=uriEnv->workerName;

    if( uriEnv->workerEnv->timing == JK_TRUE ) {
        uriEnv->timing=JK_TRUE;
    }
    if( uriEnv->workerName == NULL ) {
        /* The default worker */
        uriEnv->workerName=uriEnv->uriMap->workerEnv->defaultWorker->mbean->name;;
        uriEnv->worker=uriEnv->uriMap->workerEnv->defaultWorker;

        if( uriEnv->mbean->debug > 0 )
            env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                          "uriEnv.init() map %s %s\n",
                          uriEnv->uri, 
uriEnv->uriMap->workerEnv->defaultWorker->mbean->name);
    }

    /* No further init - will be called by uriMap.init() */

    if( uriEnv->workerName != NULL && uriEnv->worker==NULL ) {
        uriEnv->worker= env->getByName( env, wname );
        if( uriEnv->worker==NULL ) {
            uriEnv->worker= env->getByName2( env, "lb", wname );
            if( uriEnv->worker==NULL ) {
                env->l->jkLog(env, env->l, JK_LOG_ERROR,
                              "uriEnv.init() map to invalid worker %s %s\n",
                              uriEnv->uri, uriEnv->workerName);
                /* XXX that's allways a 'lb' worker, create it */
            }
        }
    } 
    
    if( uri==NULL ) 
        return JK_ERR;
    
    if ('/' != uri[0]) {
        /*
         * JFC: please check...
         * Not sure what to do, but I try to prevent problems.
         * I have fixed jk_mount_context() in apaches/mod_jk2.c so we should
         * not arrive here when using Apache.
         */
        env->l->jkLog(env, env->l, JK_LOG_ERROR,
                      "uriEnv.init() context must start with '/' in %s\n",
                      uri);
        return JK_ERR;
    }

    /* Something like:  JkMount /login/j_security_check ajp13 */
    uriEnv->uri_len  = strlen( uriEnv->uri );

    if( uriEnv->match_type != MATCH_TYPE_CONTEXT &&
        uriEnv->match_type != MATCH_TYPE_HOST ) {
        regex_t *r = (regex_t *)jk2_pregcomp(uriEnv->pool, uriEnv->uri, 
                                             REG_EXTENDED);
        if (!r) {
            env->l->jkLog(env, env->l, JK_LOG_ERROR,
                "uriEnv.init() Regular expression '%s' could not be compiled.\n",
                uriEnv->uri);
            return JK_ERR;
        }
        env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                "uriEnv.init() Compiled Regular expression '%s'.\n",
                uriEnv->uri);
        uriEnv->regexp      = r;
        uriEnv->match_type  = MATCH_TYPE_EXACT;
    }
    if( uriEnv->mbean->debug > 0 ) {
        if( uriEnv->match_type == MATCH_TYPE_CONTEXT ) {
            env->l->jkLog(env, env->l, JK_LOG_DEBUG,
               "uriEnv.init() context mapping %s=%s \n",
                uriEnv->contextPath, uriEnv->workerName);

        } else if( uriEnv->match_type == MATCH_TYPE_HOST ) {
            env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                "uriEnv.init() host mapping %s=%s \n",
                uriEnv->virtual, uriEnv->workerName);
        } else {
            env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                "uriEnv.init() exact mapping %s=%s \n",
                uriEnv->uri, uriEnv->workerName);
        }
    }
    
    if( uriEnv->mbean->debug > 0 )
        env->l->jkLog( env, env->l, JK_LOG_DEBUG,
                       "uriEnv.init()  %s  host=%s  uri=%s type=%d ctx=%s\n",
                       uriEnv->mbean->name, uriEnv->virtual, uriEnv->uri,
                       uriEnv->match_type, uriEnv->contextPath);
    
    return JK_OK;
}

static char *myAttInfo[]={ "host", "uri", "group", NULL };
    
int JK_METHOD jk2_uriEnv_factory(jk_env_t *env, jk_pool_t *pool,
                                 jk_bean_t *result,
                                 const char *type, const char *name)
{
    jk_pool_t *uriPool;
    jk_uriEnv_t *uriEnv;

    uriPool=(jk_pool_t *)pool->create( env, pool,
                                       HUGE_POOL_SIZE);

    uriEnv=(jk_uriEnv_t *)pool->calloc(env, uriPool,
                                       sizeof(jk_uriEnv_t));
    
    uriEnv->pool=uriPool;
    
    jk2_map_default_create( env, &uriEnv->properties, uriPool );

    uriEnv->init=jk2_uriEnv_init;

    result->setAttribute=jk2_uriEnv_setAttribute;
    result->getAttribute=jk2_uriEnv_getAttribute;
    uriEnv->mbean=result;
    result->object=uriEnv;
    result->getAttributeInfo=myAttInfo;

    uriEnv->name=result->localName;
    jk2_uriEnv_parseName(env, uriEnv, result->localName);

    uriEnv->workerEnv=env->getByName(env, "workerEnv" );
    uriEnv->workerEnv->uriMap->addUriEnv(env, uriEnv->workerEnv->uriMap,
                                         uriEnv);
    uriEnv->uriMap=uriEnv->workerEnv->uriMap;

    return JK_OK;
}


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to