You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by mt...@apache.org on 2003/05/05 08:37:21 UTC

cvs commit: jakarta-tomcat-connectors/jk/native2/server/aolserver jk_logger_ns.c jk_ns.h jk_service_ns.c jni_nslog.c jni_nstcl.c jni_nstcl.h nsjk2.c nsjk2.dsp

mturk       2003/05/04 23:37:21

  Added:       jk/native2/server/aolserver jk_logger_ns.c jk_ns.h
                        jk_service_ns.c jni_nslog.c jni_nstcl.c jni_nstcl.h
                        nsjk2.c nsjk2.dsp
  Log:
  Initial checkin.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat-connectors/jk/native2/server/aolserver/jk_logger_ns.c
  
  Index: jk_logger_ns.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 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 <ap...@apache.org>.                        *
   *                                                                           *
   * 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: Logger implementation using AOLserver's native logging.
   *
   * Author: Alexander Leykekh, aolserver@aol.net
   *
   * $Revision: 1.1 $
   *
   */ 
  
  #include "jk_ns.h"
  #include <stdio.h>
  
  static int JK_METHOD jk2_logger_ns_log(jk_env_t *env, jk_logger_t *l,                                 
  				       int level,
  				       const char *what)
  {
      return JK_OK;
  }
  
  
  static int JK_METHOD jk2_logger_ns_init(jk_env_t *env, jk_logger_t *_this)
  {
      return JK_OK;
  }
  
  static int JK_METHOD jk2_logger_ns_close(jk_env_t *env, jk_logger_t *_this)
  {
      return JK_OK;
  }
  
  static int JK_METHOD jk2_logger_ns_jkVLog(jk_env_t *env, jk_logger_t *l,
  					  const char *file,
  					  int line,
  					  int level,
  					  const char *fmt,
  					  va_list args)
  {
      apr_pool_t *aprPool;
      int rc;
      char *buf, *buf2, *buf3;
  
      if (env==NULL || env->tmpPool==NULL || l==NULL || fmt==NULL)
          return JK_ERR;
  
      aprPool=env->tmpPool->_private;
      if (aprPool == NULL)
          return JK_ERR;
  
      if( level < l->level )
          return JK_OK;
  
      buf=apr_pvsprintf( aprPool, fmt, args );
      if (buf == NULL)
          return JK_ERR;
      
      rc=strlen( buf );
      /* Remove trailing \n. */
      if( buf[rc-1] == '\n' )
          buf[rc-1]='\0';
  
      if (file != NULL) {
          buf2 = apr_psprintf (aprPool, "%s:%d:", file, line);
  	if (buf2 == NULL)
  	    return JK_ERR;
  
  	buf3 = apr_pstrcat (aprPool, buf2, buf, NULL);
  	if (buf3 == NULL)
  	    return JK_ERR;
  
      } else {
          buf3 = buf;
      }
      
      if( level == JK_LOG_DEBUG_LEVEL ) {
          Ns_Log (Debug, buf3);
      } else if( level == JK_LOG_INFO_LEVEL ) {
          Ns_Log (Notice, buf3);
      } else {
          Ns_Log (Error, buf3);
      }
  
      return JK_OK;
  }
  
  static int jk2_logger_ns_jkLog(jk_env_t *env, jk_logger_t *l,
                                 const char *file,
  			       int line,
  			       int level,
  			       const char *fmt, ...)
  {
      va_list args;
      int rc;
  
      if (env==NULL || l==NULL || fmt==NULL)
          return JK_ERR;    
  
      va_start(args, fmt);
      rc=jk2_logger_ns_jkVLog( env, l, file, line, level, fmt, args );
      va_end(args);
  
      return rc;
  }
  
  
  static int JK_METHOD
  jk2_logger_file_setProperty(jk_env_t *env, jk_bean_t *mbean, 
                              char *name,  void *valueP )
  {
      jk_logger_t *_this;
      char *value=valueP;
  
      if (env==NULL || mbean==NULL || name==NULL)
          return JK_ERR;
  
      _this=mbean->object;
      if (_this == NULL)
          return JK_ERR;
  
      if( strcmp( name, "level" )==0 ) {
          _this->level = jk2_logger_file_parseLogLevel(env, value);
          if( _this->level == JK_LOG_DEBUG_LEVEL ) {
              env->debug = 1;
              /*             _this->jkLog( env, _this, JK_LOG_ERROR, */
              /*                           "Level %s %d \n", value, _this->level ); */
          }
          return JK_OK;
      }
      return JK_ERR;
  }
  
  
  
  int JK_METHOD 
  jk2_logger_ns_factory(jk_env_t *env, jk_pool_t *pool, jk_bean_t *result,
  		      const char *type, const char *name)
  {
      jk_logger_t *l;
  
      if (env==NULL || pool==NULL || result==NULL)
          return JK_ERR;
  
      l = (jk_logger_t *)pool->calloc(env, pool, sizeof(jk_logger_t));
      if(l==NULL ) {
          return JK_ERR;
      }
      
      l->log = jk2_logger_ns_log;
      l->logger_private = NULL;
      l->init =jk2_logger_ns_init;
      l->jkLog = jk2_logger_ns_jkLog;
      l->jkVLog = jk2_logger_ns_jkVLog;
  
      l->level=JK_LOG_ERROR_LEVEL;
      
      result->object=(void *)l;
      l->mbean=result;
      result->setAttribute = jk2_logger_file_setProperty;
  
      return JK_OK;
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/server/aolserver/jk_ns.h
  
  Index: jk_ns.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 <ap...@apache.org>.                        *
   *                                                                           *
   * 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: AOLserver plugin for Jakarta/Tomcat                         
   * Author:      Alexander Leykekh, aolserver@aol.net 
   * Version:     $Revision: 1.1 $                                           
   */
  
  #ifndef JK_NS_H
  #define JK_NS_H
  
  #include "apu_compat.h"
  #include "apr_lib.h"
  #include "apr_date.h"
  #include "apr_strings.h"
  #include "apr_pools.h"
  #include "apr_tables.h"
  #include "apr_hash.h"
  
  #include "ns.h"
  
  #include "jk_global.h"
  #include "jk_map.h"
  #include "jk_pool.h"
  #include "jk_env.h"
  #include "jk_service.h"
  #include "jk_worker.h"
  #include "jk_workerEnv.h"
  #include "jk_uriMap.h"
  #include "jk_requtil.h"
  
  extern int Ns_ModuleVersion;
  
  int Ns_ModuleInit(char *server, char *module);
  
  int JK_METHOD jk2_service_ns_init(jk_env_t *env, jk_ws_service_t *s, char* serverNameOverride);
  
  int JK_METHOD jk2_logger_ns_factory(jk_env_t *env, jk_pool_t *pool,
                                           jk_bean_t *result, const char *type, const char *name);
  
  /* from ../../common/jk_pool_apr.c */
  int JK_METHOD jk2_pool_apr_factory(jk_env_t *env, jk_pool_t *pool,
                                     jk_bean_t *result, const char *type, const char *name);
  
  int JK_METHOD jk2_map_aprtable_factory(jk_env_t *env, jk_pool_t *pool,
                                         jk_bean_t *result,
                                         const char *type, const char *name);
  
  #endif /* JK_NS_H */
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/server/aolserver/jk_service_ns.c
  
  Index: jk_service_ns.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 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 <ap...@apache.org>.                        *
   *                                                                           *
   * 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/>.   *
   *                                                                           *
   * ========================================================================= */
  /**
   * Facility: AOLserver plugin for Jakarta/Tomcat                         
   * Description: Implementation of JK2 HTTP request phases
   * Author:      Alexander Leykekh, aolserver@aol.net 
   * Version:     $Revision: 1.1 $                                           
   */
  
  /*
   * Jakarta (jk_) include files
   */
  #include "jk_ns.h"
  
  #define NULL_FOR_EMPTY(x)   ((((x)!=NULL) && (strlen((x))!=0)) ? (x) : NULL ) 
  
  static int JK_METHOD jk2_service_ns_head(jk_env_t *env, jk_ws_service_t *s )
  {
      int h;
      int numheaders;
      Ns_Conn *conn;
      jk_map_t *headers;
      int debug=1;
      char *name, *val;
      time_t lastMod;
      
      if(env==NULL || env->l==NULL || env->l->jkLog==NULL)
         return JK_ERR;
  
      if(s==NULL ||  s->ws_private==NULL || s->headers_out==NULL || s->pool==NULL) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.head() NullPointerException\n");
          return JK_ERR;
      }
      
      if( s->uriEnv!=NULL && s->uriEnv->mbean!=NULL)
          debug=s->uriEnv->mbean->debug;
  
      conn = (Ns_Conn *)s->ws_private;
      if (conn == NULL) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.head() no current connection\n");
  	return JK_ERR;
      }
  
      if(s->msg==NULL) {
          s->msg = "";
      }
  
      headers=s->headers_out;
  
      numheaders = headers->size(env, headers);
  
      if( debug > 0 )
          env->l->jkLog(env, env->l, JK_LOG_DEBUG, 
                        "service.head() %d %d %#lx\n", s->status,
                        numheaders, s->uriEnv);
      
      for(h = 0 ; h < numheaders; h++) {
          name=headers->nameAt( env, headers, h );
          val=headers->valueAt( env, headers, h );
  
  	if (name==NULL || val==NULL) {
  	  env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.head() NullPointerException\n");
  	  return JK_ERR;
  	}
  
          name=s->pool->pstrdup( env, s->pool, name );
          val=s->pool->pstrdup( env, s->pool, val );
  
  	if (name==NULL || val==NULL) {
  	  env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.head() NullPointerException\n");
  	  return JK_ERR;
  	}
  
          if( debug > 0 ) 
              env->l->jkLog(env, env->l, JK_LOG_DEBUG, 
                            "service.head() %s: %s %d %d\n", name, val, h, headers->size( env, headers ));
  
          if(!strcasecmp(name, "Content-type")) {
  	    Ns_ConnSetTypeHeader (conn, Ns_StrToLower (val));
  
          } else if(!strcasecmp(name, "Last-Modified")) {
              /*
               * If the script gave us a Last-Modified header, we can't just
               * pass it on blindly because of restrictions on future values.
  	     *
               */
  	    lastMod = apr_date_parse_http (val);
  	    Ns_ConnSetLastModifiedHeader (conn, &lastMod);
  
          } else {                
  	    Ns_ConnSetHeaders (conn, name, val);
          }
      }
      
      if (Ns_ConnFlushHeaders (conn, s->status) != NS_OK) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.head() cannot flush headers\n");
  	return JK_ERR;
      }
  
      s->response_started = JK_TRUE;
      
      return JK_OK;
  }
  
  /*
   * Read a chunk of the request body into a buffer.  Attempt to read len
   * bytes into the buffer.  Write the number of bytes actually read into
   * actually_read.
   *
   * Think of this function as a method of the AOLserver-specific subclass of
   * the jk_ws_service class.  Think of the *s param as a "this" or "self"
   * pointer.
   */
  static int JK_METHOD jk2_service_ns_read(jk_env_t *env, jk_ws_service_t *s,
  					 void *b, unsigned len,
  					 unsigned *actually_read)
  {
      int rv;
  
      if(s==NULL || s->ws_private==NULL ||  b==NULL || actually_read==NULL || s->ws_private==NULL) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.read() NullPointerException\n");
          return JK_ERR;
      }
  
      s->read_body_started = JK_TRUE;
  
      if ((rv = Ns_ConnRead((Ns_Conn *)s->ws_private, b, len)) == NS_ERROR) {
          *actually_read = 0;
      } else {
          *actually_read = (unsigned) rv;
      }
  
      return JK_OK;
  }
  
  /*
   * Write a chunk of response data back to the browser.  If the headers
   * haven't yet been sent over, send over default header values (Status =
   * 200, basically).
   *
   * Write len bytes from buffer b.
   *
   * Think of this function as a method of the AOLserver-specific subclass of
   * the jk_ws_service class.  Think of the *s param as a "this" or "self"
   * pointer.
   */
  
  static int JK_METHOD jk2_service_ns_write(jk_env_t *env, jk_ws_service_t *s,
                                                 const void *b, unsigned len)
  {
      int r = 0;
      char *bb=(char *)b;
      Ns_Conn *conn;
      Ns_Set *outHeaders;
      int i;
      int headerCount;
      int debug=1;
      int rc;
  
      if (env->l->jkLog == NULL)
          return JK_ERR;
  
      if(s==NULL  || s->ws_private == NULL ||  b==NULL) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.write() NullPointerException\n");
          return JK_ERR;
      }
      if( s->uriEnv != NULL )
          debug=s->uriEnv->mbean->debug;
      
      if(len==0 ) {
          return JK_OK;
      }
  
      conn=(Ns_Conn *)s->ws_private;
      
      if(!s->response_started) {
          if( debug > 0 )
              env->l->jkLog(env, env->l, JK_LOG_DEBUG, 
                            "service.write() default head\n");
          rc=s->head(env, s);
          if( rc != JK_OK) {
              return rc;
          }
          
  	if (debug > 0) {
  	    outHeaders = Ns_ConnOutputHeaders (conn);
  	    headerCount = Ns_SetSize (outHeaders);
  
  	    if (outHeaders && headerCount) {
  	        for (i = 0 ; i < headerCount ; i++) {
  		    env->l->jkLog(env, env->l, JK_LOG_DEBUG, "OutHeaders %s: %s\n",
  				  Ns_SetKey (outHeaders, i), Ns_SetValue (outHeaders, i));
  		}
  	    }
  	}
      }
      
      while( len > 0 ) {
          r = Ns_ConnWrite (conn, bb, len);
  	
  	if (r == -1)
  	    return JK_ERR;
  
          len -= r;
          bb += r;
      } 
          
      return JK_OK;
  }
  
  /* ========================================================================= */
  /* Utility functions                                                         */
  /* ========================================================================= */
  
  static int JK_METHOD jk2_init_ws_service(jk_env_t *env, jk_ws_service_t *s,
                                           jk_worker_t *worker, void *serverObj)
  {
      jk_workerEnv_t *workerEnv;
      Ns_Conn *conn=serverObj;
      int need_content_length_header=JK_FALSE;
      char *query_str_begin, *query_str_end;
      Ns_DString dstr;
      int count, i;
      char *name, *val;
      Ns_Set *reqHdrs = Ns_ConnHeaders (conn);
      char* override = s->server_name; /* jk2_requtil_initRequest will null s->server_name */
  
      if (env == NULL)
          return JK_ERR;
  
      if (s==NULL || s->pool==NULL || worker==NULL || serverObj==NULL) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "init_ws_service() NullPointerException\n");
          return JK_ERR;
      }
  
      workerEnv = worker->workerEnv;
      /* Common initialization */
      jk2_requtil_initRequest(env, s);
  
      s->ws_private = conn;
      s->response_started = JK_FALSE;
      s->read_body_started = JK_FALSE;
      s->workerEnv=workerEnv;
  
      /* Unless s->realWorker is set, JNI channel will not detach thread from JVM at
         the end of request
      s->jvm_route = worker->route;
      s->realWorker = worker;
      */
  
      s->remote_user  = NULL_FOR_EMPTY(Ns_ConnAuthUser (conn));
      s->auth_type    = (s->remote_user==NULL? NULL : "Basic");
  
      s->protocol = Ns_ConnDriverName (conn);
  
      if (s->protocol==NULL || strcmp(s->protocol, "nssock")==0)
          s->protocol = "HTTP";
      else
          s->protocol = "HTTPS";
  
      s->remote_host  = s->remote_addr = NULL_FOR_EMPTY(Ns_ConnPeer (conn));
  
      /* get server name */
      if (override != NULL)
          s->server_name = override;
  
      else { 
          if (reqHdrs != NULL)
  	    s->server_name = Ns_SetIGet (reqHdrs, "Host");
  
  	if (s->server_name == NULL)
  	    s->server_name= Ns_ConnServer (conn);
      }
  
      /* get the real port (otherwise redirect failed) */
      s->server_port = Ns_ConnPort (conn);
  
      s->server_software = Ns_InfoServerVersion ();
  
      s->method         = conn->request->method;
      s->content_length = Ns_ConnContentLength (conn);
      s->is_chunked     = JK_FALSE;
      s->no_more_chunks = JK_FALSE;
      s->query_string   = conn->request->query;
  
      s->startTime = time (NULL);
      /*
       * The 2.2 servlet spec errata says the uri from
       * HttpServletRequest.getRequestURI() should remain encoded.
       * [http://java.sun.com/products/servlet/errata_042700.html]
       *
       * We use JkOptions to determine which method to be used
       *
       */
  
      switch (workerEnv->options & JK_OPT_FWDURIMASK) {
  
          case JK_OPT_FWDURICOMPATUNPARSED :
  	    /* Parse away method, query and protocol from request line, e.g.,
  	     * 
  	     * GET /x/y?q HTTP/1.1
  	     *
  	     */
  	    query_str_begin = strchr (conn->request->line, ' ');
  	    if (query_str_begin == NULL) {
  	        s->req_uri = NULL;
  		break;
  	    }
  
  	    query_str_end = strchr (++query_str_begin, '?'); /* exclude query */
  	    if (query_str_end == NULL) {
  	      query_str_end = strchr (query_str_begin, ' '); /* no query? find where URI ends */
  		
  		if (query_str_end == NULL)
  		    query_str_end = conn->request->line+strlen(conn->request->line);
  	    }
  
  	    s->req_uri = s->pool->alloc (env, s->pool, query_str_end-query_str_begin);
  	    if (s->req_uri == NULL)
  	        break;
  
              memcpy (s->req_uri, query_str_begin, query_str_end-query_str_begin+1); /* include 0 terminator */
  	    
  
          break;
  
          case JK_OPT_FWDURICOMPAT :
              s->req_uri = conn->request->url;
          break;
  
          case JK_OPT_FWDURIESCAPED :
  	    Ns_DStringInit (&dstr);
  	    query_str_begin = Ns_EncodeUrl (&dstr, conn->request->url);
  	    
  	    if (query_str_begin != NULL) {
  	        s->req_uri = s->pool->pstrdup (env, s->pool, query_str_begin+1); /* +1 because string starts with ? */
   	    } else {
  	        s->req_uri = NULL;
  	    }
  
  	    Ns_DStringFree (&dstr);
          break;
  
          default :
  	    return JK_ERR;
      }
  
      s->is_ssl       = JK_FALSE;
      s->ssl_cert     = NULL;
      s->ssl_cert_len = 0;
      s->ssl_cipher   = NULL;        /* required by Servlet 2.3 Api, 
                                     allready in original ajp13 */
      s->ssl_session  = NULL;
      s->ssl_key_size = -1;        /* required by Servlet 2.3 Api, added in jtc */
  
      if (workerEnv->ssl_enable || workerEnv->envvars_in_use) {
          if (workerEnv->ssl_enable) {
  	    if (s->protocol!=NULL && strcmp(s->protocol, workerEnv->https_indicator)==0)
  	        s->is_ssl = JK_TRUE;
  	    else 
  	        s->is_ssl = JK_FALSE;
  		
  	    if (s->is_ssl == JK_TRUE) {
  	        s->ssl_cert     = NULL; /* workerEnv->certs_indicator "SSL_CLIENT_CERT" */
  
  		if (s->ssl_cert) {
  		    s->ssl_cert_len = strlen(s->ssl_cert);
  		}
  
  		/* Servlet 2.3 API */
  		s->ssl_cipher   = NULL; /* workerEnv->cipher_indicator "HTTPS_CIPHER"/"SSL_CIPHER" */
  		s->ssl_session  = NULL; /* workerEnv->session_indicator "SSL_SESSION_ID" */
  
  		if (workerEnv->options & JK_OPT_FWDKEYSIZE) {
  		    /* Servlet 2.3 API */
  		    s->ssl_key_size = 0;
  		}
  	    }
  	}
  
  	jk2_map_default_create(env, &s->attributes, s->pool );
          
  	if (workerEnv->envvars_in_use && reqHdrs) {
  	    count = workerEnv->envvars->size( env, workerEnv->envvars );
  	
  	    for ( i=0; i< count ; i++ ) {
  	        name= workerEnv->envvars->nameAt( env, workerEnv->envvars, i );
  		val= Ns_SetIGet (reqHdrs, name);
  
  		if (val==NULL) {
  		    val=workerEnv->envvars->valueAt( env, workerEnv->envvars, i );
  		}
  
  		s->attributes->put( env, s->attributes, name, val, NULL );
  	    }
  	}
      }
  
      jk2_map_default_create(env, &s->headers_in, s->pool );
  
      if (reqHdrs && (count=Ns_SetSize (reqHdrs))) {
          for (i = 0 ; i < count ; i++) {
  	     s->headers_in->add( env, s->headers_in, Ns_SetKey (reqHdrs, i), Ns_SetValue (reqHdrs, i));
  	}
      }
  
      if(!s->is_chunked && s->content_length == 0) {
          /* if r->contentLength == 0 I assume there's no header
             or a header with '0'. In the second case, put will override it 
           */
          s->headers_in->put( env, s->headers_in, "content-length", "0", NULL );
      }
  
      jk2_map_default_create(env, &s->headers_out, s->pool );
  
      return JK_OK;
  }
  
  /*
   * If the servlet engine didn't consume all of the
   * request data, consume and discard all further
   * characters left to read from client
   *
   */
  static void JK_METHOD jk2_service_ns_afterRequest(jk_env_t *env, jk_ws_service_t *s )
  {
      Ns_Conn *conn;
      char buff[2048];
      int rd;
      struct jk_worker *w;
  
      if (env==NULL)
          return;
  
      if (s==NULL) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.afterRequest() NullPointerException\n");
          return;
      }
  
      if (s->content_read < s->content_length ||
          (s->is_chunked && ! s->no_more_chunks)) {
          
           conn = s->ws_private;
  
  	 while ((rd = Ns_ConnRead (conn, buff, sizeof(buff))) > 0) {
  	     s->content_read += rd;
  	 }
      }
  
      if (s->realWorker) {
          w = s->realWorker;
  
          if (w != NULL && w->channel != NULL && w->channel->afterRequest != NULL) {
              w->channel->afterRequest( env, w->channel, w, NULL, s );
          }
      }
  }
  
  
  
  int JK_METHOD jk2_service_ns_init(jk_env_t *env, jk_ws_service_t *s, char* serverNameOverride)
  {
      if(s==NULL ) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "service.init() NullPointerException\n");
          return JK_ERR;
      }
  
      s->head   = jk2_service_ns_head;
      s->read   = jk2_service_ns_read;
      s->write  = jk2_service_ns_write;
      s->init   = jk2_init_ws_service;
      s->afterRequest     = jk2_service_ns_afterRequest;
      s->server_name = serverNameOverride;
  
      return JK_OK;
  }
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/server/aolserver/jni_nslog.c
  
  Index: jni_nslog.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 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 <ap...@apache.org>.                        *
   *                                                                           *
   * 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/>.   *
   *                                                                           *
   * ========================================================================= */
  /*
   * Author Daniel Wickstrom, nsjava 1.0.5
   * Modified by Alexander Leykekh (aolserver@aol.net)
   *
   * Native implementation for Java logging to AOLserver log
   */
  
  #include <ns.h>
  #include "jni_nstcl.h"
  
  
  /*
   *----------------------------------------------------------------------
   * Class:     org.apache.nsjk2.NsLog
   * Method:    write
   * Signature: (BLjava/lang/String;)V
   *
   * JNI method for writing data into AOLserver log
   *
   * Results:
   *	Message is written to the log file using the module log format.
   *
   *----------------------------------------------------------------------
   */
  JNIEXPORT void JNICALL Java_org_apache_nsjk2_NsLog_write (JNIEnv *env, 
  							  jobject jvm, 
  							  jbyte severity, 
  							  jstring msg)
  {
      char* message = (char*)((*env)->GetStringUTFChars(env, msg, JNI_FALSE));
  
      if(message == NULL) {
        handleErr(env,"couldn't get input arg.");
        return;
      }
  
      Ns_Log(severity, message);
      (*env)->ReleaseStringUTFChars(env, msg, message);
  }
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/server/aolserver/jni_nstcl.c
  
  Index: jni_nstcl.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 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 <ap...@apache.org>.                        *
   *                                                                           *
   * 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/>.   *
   *                                                                           *
   * ========================================================================= */
  /*
   * Copyright (c) 2000 Daniel Wickstrom, nsjava 1.0.5
   * Modified by Alexander Leykekh (aolserver@aol.net)
   *
   * Native implementation of Java-to-Tcl calls
   */
  
  #define USE_TCL8X
  
  #include <ns.h>
  #include "jni_nstcl.h"
  
  /* Tcl variable to store ADP output */
  #define TCLVARNAME "org.apache.nsjk2.NsTcl.adpout"
  
  /* TLS slot to keep allocated Tcl interpreter for threads that have no active HTTP connection
     Gets initialized from nsjk2.c
  */
  Ns_Tls tclInterpData;
  
  
  /*
   *----------------------------------------------------------------------
   *
   * throwByName --
   *
   *      Throw a named java exception.  Null terminated varargs are passed as
   *      the exception message.
   *
   * Results:
   *      Exception is returned to java.
   *
   * Side effects:
   *      None.
   *
   *----------------------------------------------------------------------
   */
  
  static void throwByName(JNIEnv *env, const char *name, ...)
  {
      Ns_DString  dsPtr;
      jclass      cls;
      va_list     ap;
      char       *s;
  
      va_start(ap, name);
      Ns_DStringInit(&dsPtr);
      Ns_DStringVarAppend(&dsPtr, name, ": ", NULL);
  
      while ((s = va_arg(ap, char *)) != NULL) {
          Ns_DStringAppend(&dsPtr, s);
      }
      va_end(ap);
  
      cls = (*env)->FindClass(env, name);
      if (cls == NULL) {
          (*env)->ExceptionClear(env);
          cls = (*env)->FindClass(env, "java/lang/ClassNotFoundException");
      }
  
      if (cls != NULL) {
          (*env)->ThrowNew(env, cls, dsPtr.string);
          (*env)->DeleteLocalRef(env, cls);
      }
  
      Ns_DStringFree(&dsPtr);
  }
  
  
  /*
   *----------------------------------------------------------------------
   *
   * checkForException --
   *
   *      Check for an exception in java and clear it.  The exception message
   *      will appear in the aolserver log.
   *
   * Results:
   *      Returns true if exception occured.
   *
   * Side effects:
   *      Exception message will appear in the aolserver log file.
   *
   *----------------------------------------------------------------------
   */
  static int checkForException(JNIEnv *env) 
  {
    jobject exception = (*env)->ExceptionOccurred(env);
  
    if (exception != NULL) {
      (*env)->ExceptionDescribe(env);
      (*env)->ExceptionClear(env);
      (*env)->DeleteLocalRef(env, exception);
  
      return JNI_TRUE;
    }
  
    return JNI_FALSE;
  }
  
  
  /*
   *----------------------------------------------------------------------
   * Thread cleanup callback. Marks for deletion Tcl interpreter 
   * previously allocated for the thread that is exiting
   *
   * Parameters:
   *   arg - pointer registered for callback (a Tcl_Interp object)
   *
   *----------------------------------------------------------------------
   */
  void tclInterpDataDtor (void* arg) {
      Ns_TclDestroyInterp ((Tcl_Interp*) arg);
  }
  
  
  /*
   *----------------------------------------------------------------------
   *
   * GetTclInterp --
   *
   *	Get the connection interpreter if the connection is not null
   *      otherwise allocate a new interpreter. The new interpreter
   *      is not affiliated with any virtual servers since JVM is shared
   *      between all virtual servers. The example of non-server interpreter
   *      would be allocated is a new Java thread in a servlet, created to
   *      run independent of any connection and evaluating Tcl scripts.
   *
   * Results:
   *	Returns an interpreter.
   *
   * Side effects:
   *	A new interpreter is allocated if there is no connection.
   *
   *----------------------------------------------------------------------
   */
  static Tcl_Interp *GetTclInterp(Ns_Conn *conn)
  {
      Tcl_Interp* interp;  
  
      if (conn == NULL) {
          /* allocate/fetch and 0-filled chunk of memory */
          interp= (Tcl_Interp*) Ns_TlsGet (&tclInterpData);
  
          if (interp == NULL) {
              interp = Ns_TclAllocateInterp(NULL);
  	    Ns_TlsSet (&tclInterpData, interp);
  	}
  
  	return interp;
  
      } else
          return Ns_GetConnInterp(conn);
  }
  
  
  
  void handleErr(JNIEnv *env, char *msg) 
  {
      checkForException(env);
      throwByName(env, "java/lang/RuntimeException", msg, NULL);
      Ns_Log(Error, msg);
  }
  
  
  
  /*
   * Class:     org_apache_nsjk2_NsTcl
   * Method:    eval
   * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
   *
   *	JNI method for evaling tcl from within java.
   *
   * Parameters:
   *    cwd - current working directory for ADP context
   *    script - Tcl script to evaluate
   *
   * Results:
   *      ADP output, whose value depends upon existance of HTTP connection.
   *	connection exists: ADP output string is converted to java string and passed back to java.
   *      doesn't: NULL
   *
   * Side effects:
   *	affects the current tcl connection interpreter, stores Tcl result in a variable.
   *
   *----------------------------------------------------------------------
   */
  
  JNIEXPORT jstring JNICALL Java_org_apache_nsjk2_NsTcl_eval (JNIEnv* env, 
  							    jclass classNsTcl, 
  							    jstring cwd, 
  							    jstring script)
  {
      Tcl_Interp* interp;
      jstring     jstr=NULL;
      const char* cscript=NULL;
      const char* ccwd=NULL;
      int         result;
      Ns_Conn*    conn = Ns_GetConn();
      Ns_DString  tclcmd;
      const char* ctclcmd;
  
      if (script == NULL)
  	return NULL;
  
      /* Obtain Tcl interp for this thread */
      interp = GetTclInterp(conn);
      if (interp == NULL) {
  	handleErr (env, "Cannot get Tcl interpreter");
  	return NULL;
      }
      
      cscript = (*env)->GetStringUTFChars(env, script, JNI_FALSE);
      if(cscript == NULL) {
  	handleErr(env,"couldn't get script");
  	return NULL;
      }
  
      /* If conn==NULL, it means Tcl script is being evaluated in the interpreter
         which doesn't have ADP environment. This helps simplify Tcl command
      */
  
      if (conn!=NULL && cwd!=NULL) {
  	ccwd = (*env)->GetStringUTFChars (env, cwd, JNI_FALSE);
  	if (ccwd == NULL) {
  	    handleErr (env, "couldn't get cwd arg");
  	    (*env)->ReleaseStringUTFChars(env, script, cscript);
  	    return NULL;
  	}
      }
  	    
      /* Create ADP command string if connection exists */
      if (conn != NULL) {
  	Ns_DStringInit (&tclcmd);
  	Ns_DStringAppend (&tclcmd, "ns_adp_parse -savedresult " TCLVARNAME);
      
  	if (ccwd != NULL)
  	    Ns_DStringVarAppend (&tclcmd, " -cwd ", ccwd, NULL);
  
  	Ns_DStringVarAppend (&tclcmd, " -string {<% ", cscript, " %>}", NULL);
  
  	ctclcmd = Ns_DStringValue (&tclcmd);
  
      } else {
  	ctclcmd = cscript;
      }
      
      result = Tcl_Eval(interp, ctclcmd);
  
      /* cleanup */
      if (conn != NULL)
  	Ns_DStringFree (&tclcmd);
  
      if (cscript != NULL)
          (*env)->ReleaseStringUTFChars(env, script, cscript);
  
      if (ccwd != NULL)
          (*env)->ReleaseStringUTFChars(env, cwd, ccwd);
  
      if (result == TCL_ERROR) {
          handleErr (env, interp->result);
  	Tcl_ResetResult(interp);
  	return NULL;
      }
  
      /* If no current connection, defer return of result to flushResult method */
      if (conn!=NULL && interp->result!=NULL && interp->result[0]!='\0') {
          jstr = (*env)->NewStringUTF(env, interp->result);
  	if (jstr == NULL) {
  	    handleErr(env, "out of memory");
  	    return NULL;
  	}
      }
  
      return jstr;
  }
  
  
  /*
   * Class:     org_apache_nsjk2_NsTcl
   * Method:    flushResult
   * Signature: ()Ljava/lang/String;
   *
   * Returns:
   *    Result from Tcl command, which is
   *    if connection exists: value of special Tcl variable as Java string, unset the variable
   *    no connection: regular Tcl result
   *
   */
  JNIEXPORT jstring JNICALL Java_org_apache_nsjk2_NsTcl_flushResult (JNIEnv* env, 
  								   jclass classNsTcl)
  {
      jstring     jstr = NULL;
      Tcl_Interp* interp;
      const char* tclval;
      Ns_Conn*    conn = Ns_GetConn ();
  
      interp = GetTclInterp (conn);
      if (interp == NULL) {
  	handleErr (env, "Cannot get Tcl interpreter");
  	return NULL;
      }
  
      if (conn != NULL) {
  	tclval = Tcl_GetVar (interp, TCLVARNAME, 0);
  	/* don't care if variable doesn't exist - means no result returned */
  	if (tclval != NULL) {
  		
  	    if (tclval[0] != '\0') {
  		jstr = (*env)->NewStringUTF (env, tclval);
  		if (jstr == NULL)
  		    handleErr (env, "out of memory");
  	    }
  
  	    Tcl_UnsetVar (interp, TCLVARNAME, 0);
  	}
  
      } else if (interp->result!=NULL && interp->result[0]!='\0') {
          jstr = (*env)->NewStringUTF(env, interp->result);
  	if (jstr == NULL) {
  	    handleErr(env, "out of memory");
  	    return NULL;
  	}
      }
  
      return jstr;
  }
  
  
  /*
   * Class:     org_apache_nsjk2_NsTcl
   * Method:    listMerge
   * Signature: ([Ljava/lang/String;)Ljava/lang/String;
   *
   * JNI method for merging array of strings into properly formatted Tcl list
   *
   * Results: Tcl list in a string, null if null or empty array.
   */
  
  JNIEXPORT jstring JNICALL Java_org_apache_nsjk2_NsTcl_listMerge (JNIEnv* env, 
  								 jobject jvm, 
  								 jobjectArray strings) {
  
      jsize len = (strings==NULL? 0 : (*env)->GetArrayLength (env, strings));
      jstring jstrrefs[len];
      const char* cstrarray[len];
      jsize i;
      char* liststr;
      jstring res = NULL;
  
      if (len != 0) {
          // Convert Java array into C array
          for (i=0; i<len; i++) {
  	    jstrrefs[i] = (*env)->GetObjectArrayElement (env, strings, i);
  	    cstrarray[i] = (jstrrefs[i]==NULL? NULL : (*env)->GetStringUTFChars (env, jstrrefs[i], JNI_FALSE));
  	}
  
  	liststr = Tcl_Merge (len, cstrarray);
  
  	if (liststr != NULL)
  	    res = (*env)->NewStringUTF (env, liststr);
  
  	if (liststr==NULL || res==NULL)
  	    handleErr (env, "out of memory");
  
  	// Release references
  	if (liststr != NULL)
  	    Tcl_Free (liststr);
  
  	for (i=0; i<len; i++) {
  	    if (jstrrefs[i] != NULL) {
  	        (*env)->ReleaseStringUTFChars (env, jstrrefs[i], cstrarray[i]);
  		(*env)->DeleteLocalRef (env, jstrrefs[i]);
  	    }
  	}
      }
  
      return res;
  }
  
  
  
  /*
   * Class:     org_apache_nsjk2_NsTcl
   * Method:    listSplit
   * Signature: (Ljava/lang/String;)[Ljava/lang/String;
   *
   * JNI method for splitting Tcl list in a string into array of strings
   *
   * Results: array of strings, null if null or empty argument
   */
  JNIEXPORT jobjectArray JNICALL Java_org_apache_nsjk2_NsTcl_listSplit (JNIEnv* env, 
  								      jobject jvm, 
  								      jstring list) {
      const char* cstrlist = NULL;
      Tcl_Interp* interp;
      jclass clsString = NULL;
      int argc =0;
      const char** argv = NULL;
      jobjectArray jarray = NULL;
      jsize i;
      jstring jstr;
      int tclrc = TCL_ERROR;
  
      if (list==NULL || (*env)->GetStringUTFLength (env, list)==0)
          return NULL;
  
      clsString = (*env)->FindClass (env, "java/lang/String"); 
  
      if (clsString == NULL)
          handleErr (env, "Cannot find class java.lang.String");
  
      else {
          cstrlist = (*env)->GetStringUTFChars (env, list, JNI_FALSE);
  	interp = GetTclInterp(Ns_GetConn());
  	tclrc = Tcl_SplitList (interp, cstrlist, &argc, &argv);
  
  	if (tclrc == TCL_ERROR) {
  	    handleErr (env, interp->result);
  	    Tcl_ResetResult (interp);
  	}
      }
  
      if (tclrc == TCL_OK) {
  	jarray = (*env)->NewObjectArray (env, argc, clsString, NULL);
  
  	if (jarray == NULL)
  	    handleErr (env, "out of memory");
  
  	else {
  	    for (i=0; i<argc; i++) {
  		jstr = (*env)->NewStringUTF (env, argv[i]);
  		if (jstr == NULL) {
  		    handleErr (env, "out of memory");
  		    break;
  		}
  
  		(*env)->SetObjectArrayElement (env, jarray, i, jstr);
  	    }
  	}
  
      }
  	
      if (cstrlist != NULL)
          (*env)->ReleaseStringUTFChars (env, list, cstrlist);
  
      if (clsString != NULL)
          (*env)->DeleteLocalRef (env, clsString);
  
      if (argv != NULL)
          Tcl_Free ((char*) argv);
  
      return jarray;
  }
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/server/aolserver/jni_nstcl.h
  
  Index: jni_nstcl.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 <ap...@apache.org>.                        *
   *                                                                           *
   * 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/>.   *
   *                                                                           *
   * ========================================================================= */
  /*
   * Copyright (c) 2000 Daniel Wickstrom, nsjava 1.0.5
   * Modified by Alexander Leykekh (aolserver@aol.net)
   * 
   * Native implementation of Java-to-Tcl calls
   */
  
  #ifndef __JAVA_TCL_H__
  #define __JAVA_TCL_H__
  
  #include <jni.h>
  #include <nsthread.h>
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /*
   *----------------------------------------------------------------------
   *
   * Dump information about existing exception, then throw RuntimeException
   * object with given message
   *
   * Parameters:
   *    env - JNI environment
   *    msg - exception description
   *
   *----------------------------------------------------------------------
   */
  void handleErr(JNIEnv *env, char *msg);
  
  /* TLS key for storing non-server Tcl interpreter.
     Sole purpose is to be able to call a destructor and delete the
     interpreter when thread goes away
  */
  extern Ns_Tls tclInterpData;
  extern void tclInterpDataDtor (void*);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/server/aolserver/nsjk2.c
  
  Index: nsjk2.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 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 <ap...@apache.org>.                        *
   *                                                                           *
   * 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/>.   *
   *                                                                           *
   * ========================================================================= */
  /*
   * Module jk2: keeps all servlet/jakarta related ramblings together.
   *
   * Author: Alexander Leykekh (aolserver@aol.net)
   *
   */
  
  
  #include "ns.h"
  #include "jk_ns.h"
  #include "jni_nstcl.h"
  #include <jni.h>
  
  typedef struct {
      char* serverName;
      jk_uriEnv_t* uriEnv;
  } uriContext;
    
  
  #ifdef WIN32
  static char  file_name[_MAX_PATH];
  #endif
  
  
  int Ns_ModuleVersion = 1;
  
  /* Globals 
   *
   * There is one instance of JVM worker environment per process, regardless of 
   * virtual servers in AOLserver's nsd.tcl file or their counterparts in
   * Tomcat's server.xml. The only thing that AOLserver virtual servers do separately
   * is map URIs for Tomcat to process.
   *
   */
  static jk_workerEnv_t *workerEnv = NULL; /* JK2 environment */
  static JavaVM* jvmGlobal = NULL; /* JVM instance */
  static Ns_Thread initThread = 0; /* thread which initialized JVM */
  static Ns_Tls jkTls; /* TLS destructor detaches request thread from JVM */
  static unsigned jkInitCount =0; /* number of running virtual servers using this module */
  
  /* argument to pass into JK2 init. thread */
  struct init_thread_arg {
      /* Tomcat home */
      char* server_root;
  
      /* current working directory - temporary storage */
      char cwd_buf[PATH_MAX];
  
      /* synchronization for init phase */
      Ns_Mutex init_lock;
      Ns_Cond init_cond;
      int     init_flag;
      int     init_rc;
  
      /* synchronization for shutdown phase */
      Ns_Mutex shut_lock;
      Ns_Cond shut_cond;
      int     shut_flag;
  } initThreadArg;
  
  
  /** Basic initialization for jk2.
   */
  static int jk2_create_workerEnv(apr_pool_t *p, char* serverRoot) {
      jk_env_t *env;
      jk_logger_t *l;
      jk_pool_t *globalPool;
      jk_bean_t *jkb;
      
      if (jk2_pool_apr_create( NULL, &globalPool, NULL, p) != JK_OK) {
          Ns_Log (Error, "jk2_create_workerEnv: Cannot create apr pool");
  	return JK_ERR;
      }
  
      /** Create the global environment. This will register the default
          factories
      */
      env=jk2_env_getEnv( NULL, globalPool );
      if (env == NULL) {
          Ns_Log (Error, "jk2_create_workerEnv: Cannot get environment");
  	return JK_ERR;
      }
          
      /* Optional. Register more factories ( or replace existing ones ) */
      /* Init the environment. */
      
      /* Create the logger */
  #ifdef NO_NS_LOGGER
      jkb=env->createBean2( env, env->globalPool, "logger.file", "");
      if (jkb == NULL) {
          Ns_Log (Error, "jk2_create_workerEnv: Cannot create logger bean");
  	return JK_ERR;
      }
  
      env->alias( env, "logger.file:", "logger");
      env->alias( env, "logger.file:", "logger:");
      l = jkb->object;
  #else
      env->registerFactory( env, "logger.ns",  jk2_logger_ns_factory );
  
      jkb=env->createBean2( env, env->globalPool, "logger.ns", "");
      if (jkb == NULL) {
          Ns_Log (Error, "jk2_create_workerEnv: Cannot create logger bean (with factory)");
  	return JK_ERR;
      }
  
      env->alias( env, "logger.ns:", "logger");
      l = jkb->object;
  #endif
      
      env->l=l;
      
  #ifdef WIN32
      env->soName=env->globalPool->pstrdup(env, env->globalPool, file_name);
      
      if( env->soName == NULL ){
          env->l->jkLog(env, env->l, JK_LOG_ERROR, "Error creating env->soName\n");
          return JK_ERR;
      }
  #else 
      env->soName=NULL;
  #endif
      
      /* Create the workerEnv */
      jkb=env->createBean2( env, env->globalPool,"workerEnv", "");
      if (jkb == NULL) {
          Ns_Log (Error, "jk2_create_workerEnv: Cannot create worker environment bean");
  	return JK_ERR;
      }
  
      workerEnv= jkb->object;
  
      if( workerEnv==NULL ) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, "Error creating workerEnv\n");
          return JK_ERR;
      }
  
      env->alias( env, "workerEnv:" , "workerEnv");
  
      /* AOLserver is a single-process environment, but leaving childId as -1 breaks
         JNI initialization
      */
      workerEnv->childId=0;
      
      workerEnv->initData->add( env, workerEnv->initData, "serverRoot",
                                workerEnv->pool->pstrdup( env, workerEnv->pool, serverRoot));
  
      env->l->jkLog(env, env->l, JK_LOG_INFO, "Set JK2 serverRoot %s\n", serverRoot);
      
      return JK_OK;
  }
  
  
  /**
   * Shutdown callback for AOLserver
   */
  void jk2_shutdown_system (void* data)
  {
      void* thread_rc;
  
      if (--jkInitCount==0 && initThread!=0) {
  
          Ns_MutexLock (&initThreadArg.shut_lock);
  	initThreadArg.shut_flag=1;
  	Ns_CondSignal (&initThreadArg.shut_cond);
  	Ns_MutexUnlock (&initThreadArg.shut_lock);
  
  	Ns_ThreadJoin (&initThread, &thread_rc);
  	initThread = 0;
      }
  }    
  
  
  /**
   * JK2 module shutdown callback for APR (Apache Portable Runtime)
   */
  static apr_status_t jk2_shutdown(void *data)
  {
      jk_env_t *env;
      if (workerEnv) {
          env=workerEnv->globalEnv;
          /* bug in APR?? results in SEGV. Not important, the process is going away
  
  	workerEnv->close(env, workerEnv);
  	*/
  
  	if( workerEnv->vm != NULL  && ! workerEnv->vm->mbean->disabled )
  	    workerEnv->vm->destroy( env, workerEnv->vm );
  
          workerEnv = NULL;
      }
      return APR_SUCCESS;
  }
  
  
  /** Initialize jk, using workers2.properties. 
  */
  static int jk2_init(jk_env_t *env, apr_pool_t *pconf,
  		     jk_workerEnv_t *workerEnv)
  {
      if (workerEnv->init(env, workerEnv ) != JK_OK) {
          Ns_Log (Error, "jk2_init: Cannot initialize worker environment");
  	return JK_ERR;
      }
  
      workerEnv->server_name   = Ns_InfoServerVersion ();
      apr_pool_cleanup_register(pconf, NULL, jk2_shutdown, apr_pool_cleanup_null);
  
      return JK_OK;
  }
  
  
  
  /* ========================================================================= */
  /* The JK module handlers                                                    */
  /* ========================================================================= */
  
  /** Main service method, called to forward a request to tomcat
   */
  static int jk2_handler(void* context, Ns_Conn *conn)
  {   
      jk_logger_t      *l=NULL;
      int              rc;
      jk_worker_t *worker=NULL;
      jk_endpoint_t *end = NULL;
      jk_env_t *env;
      char* workerName;
      jk_ws_service_t *s=NULL;
      jk_pool_t *rPool=NULL;
      int rc1;
      jk_uriEnv_t *uriEnv;
      uriContext* uriCtx = (uriContext*)context;
  
  
      /* must make this call to assure TLS destructor runs when thread exists */
      Ns_TlsSet (&jkTls, jvmGlobal);
  
      uriEnv= uriCtx->uriEnv;
      /* there is a chance of dynamic reconfiguration, so instead of doing above statement, might map
         the URI to its context object on the fly, like this:
  
         uriEnv = workerEnv->uriMap->mapUri (workerEnv->globalEnv, workerEnv->uriMap, conn->request->host, conn->request->url);
      */
  
      /* Get an env instance */
      env = workerEnv->globalEnv->getEnv( workerEnv->globalEnv );
  
      worker = uriEnv->worker;
  
      if (worker == NULL) /* use global default */
          worker=workerEnv->defaultWorker;
  
      workerName = uriEnv->mbean->getAttribute (env, uriEnv->mbean, "group");
  
      if( worker==NULL && workerName!=NULL ) {
          worker=env->getByName( env, workerName);
          env->l->jkLog(env, env->l, JK_LOG_INFO, 
                        "nsjk2.handler() finding worker for %#lx %#lx %s\n",
                        worker, uriEnv, workerName);
          uriEnv->worker=worker;
      }
  
      if(worker==NULL || worker->mbean==NULL || worker->mbean->localName==NULL ) {
          env->l->jkLog(env, env->l, JK_LOG_ERROR, 
                        "nsjk2.handle() No worker for %s\n", conn->request->url); 
          workerEnv->globalEnv->releaseEnv( workerEnv->globalEnv, env );
          return NS_FILTER_RETURN;
      }
  
      if( uriEnv->mbean->debug > 0 )
          env->l->jkLog(env, env->l, JK_LOG_DEBUG, 
                        "nsjk2.handler() serving %s with %#lx %#lx %s\n",
                        uriEnv->mbean->localName, worker, worker->mbean, worker->mbean->localName );
  
      /* Get a pool for the request */
      rPool= worker->rPoolCache->get( env, worker->rPoolCache );
      if( rPool == NULL ) {
          rPool=worker->mbean->pool->create( env, worker->mbean->pool, HUGE_POOL_SIZE );
          if( uriEnv->mbean->debug > 0 )
              env->l->jkLog(env, env->l, JK_LOG_DEBUG,
                            "nsjk2.handler(): new rpool %#lx\n", rPool );
      }
      
      s=(jk_ws_service_t *)rPool->calloc( env, rPool, sizeof( jk_ws_service_t ));
      
      jk2_service_ns_init( env, s, uriCtx->serverName);
      
      s->pool = rPool;
      s->init( env, s, worker, conn );
      s->is_recoverable_error = JK_FALSE;
      s->uriEnv = uriEnv; 
      rc = worker->service(env, worker, s);    
      s->afterRequest(env, s);
      rPool->reset(env, rPool);
  
      rc1=worker->rPoolCache->put( env, worker->rPoolCache, rPool );
  
      if( rc1 == JK_OK ) {
          rPool=NULL;
      }
  
      if( rPool!=NULL ) {
          rPool->close(env, rPool);
      }
  
      if(rc==JK_OK) {
          workerEnv->globalEnv->releaseEnv( workerEnv->globalEnv, env );
          return NS_OK;
      }
  
      env->l->jkLog(env, env->l, JK_LOG_ERROR,
                    "nsjk2.handler() Error connecting to tomcat %d\n", rc);
      workerEnv->globalEnv->releaseEnv( workerEnv->globalEnv, env );
      Ns_ConnReturnInternalError (conn);
      return NS_FILTER_RETURN;
  }
  
  
  /*
   * TLS destructor. Sole purpose is to detach current thread from JVM before the thread exits
   */
  static void jkTlsDtor (void* arg) {
      void* env = NULL;
      jint err;
  
      /* check if attached 1st */
      if (jvmGlobal!=NULL && 
  	JNI_OK==((*jvmGlobal)->GetEnv(jvmGlobal, &env, JNI_VERSION_1_2 ))) 
          {
          (*jvmGlobal)->DetachCurrentThread (jvmGlobal);
  	}
  }
  
  
  /* APR, JNI and JK2 initialization. Call this from a thread separate from AOLserver main thread
   * because of the Java garbage collection using signals that AOLserver tends to override
   */
  static int InitJK2Module (char* server_root) {
      jk_env_t *env;
      apr_status_t aprrc;
      char errbuf[512];
      apr_pool_t *jk_globalPool = NULL;
          
      if ((aprrc=apr_initialize()) != APR_SUCCESS) {
          Ns_Log (Error, "InitJK2Module: Cannot initialize APR:%s", apr_strerror (aprrc, errbuf, sizeof(errbuf)));
  	return JK_ERR;
      }
  
      if ((aprrc=apr_pool_create(&jk_globalPool, NULL)) != APR_SUCCESS) {
          Ns_Log (Error, "InitJK2Module: Cannot create global APR pool:%s", apr_strerror (aprrc, errbuf, sizeof(errbuf)));
  	return JK_ERR;
      }
  
      if (workerEnv==NULL && jk2_create_workerEnv(jk_globalPool, server_root)==JK_ERR)
          return JK_ERR;
  
      env=workerEnv->globalEnv;
      env->setAprPool(env, jk_globalPool);
      
      if (jk2_init( env, jk_globalPool, workerEnv) != JK_OK) {
          Ns_Log (Error, "InitJK2Module: Cannot initialize module");
  	return JK_ERR;
      }
  
      workerEnv->was_initialized = JK_TRUE; 
      
      if ((aprrc=apr_pool_userdata_set( "INITOK", "InitJK2Module", NULL, jk_globalPool )) != APR_SUCCESS) {
          Ns_Log (Error, "InitJK2Module: Cannot set APR pool user data:%s", apr_strerror (aprrc, errbuf, sizeof(errbuf)));
  	return JK_ERR;
      }
  
      if (workerEnv->parentInit( env, workerEnv) != JK_OK) {
          Ns_Log (Error, "InitJK2Module: Cannot initialize global environment");
  	return JK_ERR;
      }
  
      /* Obtain TLS slot - it's destructor will detach threads from JVM */
      jvmGlobal = workerEnv->vm->jvm;
      Ns_TlsAlloc (&jkTls, jkTlsDtor);
  
      /* TLS slot for non-server Tcl interpreter */
      Ns_TlsAlloc (&tclInterpData, tclInterpDataDtor);
      
      return JK_OK;
  }
  
  /*
   * Must initialize JVM in a separate thread due to signal conflicts (failed to confirm existance, but strongly
   * recommended by nsjava code).
   * AOLserver main thread allegedly masks signals that JVM uses for garbage collection
   *
   */
  static void InitJK2ModuleThread (void* arg) {
     int rc;
  
     Ns_ThreadSetName ("nsjk2");
  
     rc =InitJK2Module (initThreadArg.server_root);
  
     /* prepare to report initialization results */
     Ns_MutexLock(&initThreadArg.init_lock);
     initThreadArg.init_rc = rc;
     initThreadArg.init_flag =1;
     Ns_CondSignal (&initThreadArg.init_cond);
     Ns_MutexUnlock(&initThreadArg.init_lock);
     
     if (rc==JK_OK) {
         /* wait for shutdown */
  
         Ns_MutexLock (&initThreadArg.shut_lock);
  
         while (!initThreadArg.shut_flag)
  	   Ns_CondWait (&initThreadArg.shut_cond, &initThreadArg.shut_lock);
      
         Ns_MutexUnlock (&initThreadArg.shut_lock);
  
         apr_pool_terminate ();
         apr_terminate ();
     }
       
     Ns_ThreadExit ((void*)rc);
  }
  
  
  /**
   * Initialize JK2 in a new thread
   */
  int CreateJK2InitThread (char* module)
  {
      int init_rc;
      char* modPath;
      char cwdBuf[PATH_MAX];
  
      modPath = Ns_ConfigGetPath (NULL, module, NULL);
      initThreadArg.server_root = (modPath? Ns_ConfigGetValue (modPath, "serverRoot") : NULL);
  
      if (initThreadArg.server_root == NULL)
         initThreadArg.server_root  = getenv ("TOMCAT_HOME");
  
      if (initThreadArg.server_root == NULL)
          initThreadArg.server_root = getcwd (initThreadArg.cwd_buf, sizeof(cwdBuf));
  
      initThreadArg.init_flag = 0;
      Ns_MutexInit (&initThreadArg.init_lock);
      Ns_CondInit (&initThreadArg.init_cond);
  
      initThreadArg.shut_flag = 0;
      Ns_MutexInit (&initThreadArg.shut_lock);
      Ns_CondInit (&initThreadArg.shut_cond);
  
      /* create thread with 2M of stack */
      Ns_ThreadCreate (InitJK2ModuleThread, &initThreadArg, 2*1024*1024, &initThread);
      if (initThread == 0) {
          Ns_Log (Error, "Ns_ModuleInit: Cannot create JK2 initialization thread");
  	return NS_ERROR;
      }
      
      /* wait till JVM is initialized */
      Ns_MutexLock (&initThreadArg.init_lock);
  
      while (initThreadArg.init_flag==0)
          Ns_CondWait (&initThreadArg.init_cond, &initThreadArg.init_lock);
  
      init_rc=initThreadArg.init_rc;
  
      Ns_MutexUnlock (&initThreadArg.init_lock);
  
      return init_rc;
  }
  
  
  /** Create context to pass to URI handler
   */
  uriContext* createURIContext (jk_uriEnv_t* uriEnv, char* serverName) {
      uriContext* ctx = Ns_Malloc (sizeof (uriContext));
  
      if (ctx) {
          ctx->serverName = serverName;
  	ctx->uriEnv = uriEnv;
      }
  
      return ctx;
  }
  
  
  /** Callback to get rid of URI context in registered procs
   */
  static void deleteURIContext (void* context) {
      Ns_Free (context);
  }
   
  /** Standard AOLserver callback.
   * Initialize jk2, unless already done in another server. Register URI mappping for Tomcat
   * If multiple virtual servers use this module, calls to Ns_ModuleInit will be made serially
   * in order of appearance of those servers in nsd.tcl
   */
  int Ns_ModuleInit(char *server, char *module)
  {
      int init_rc = JK_OK;
      jk_map_t* uriMap;
      int i, urimapsz;
      char *uriname, *vhost;
      jk_env_t *env;
      jk_uriEnv_t* uriEnv;
      uriContext* ctx;
      char* serverName=NULL;
      char* confPath;
  
      if (jkInitCount++ == 0)
          init_rc = CreateJK2InitThread (module);
  
      Ns_RegisterShutdown (jk2_shutdown_system, NULL);
  
      if (init_rc != JK_OK) {
          Ns_Log (Error, "Ns_ModuleInit: Cannot initialize JK2 module");
  	return NS_ERROR;
      }
  
      /* get Tomcat serverName override if specified */
      confPath = Ns_ConfigGetPath (server, module, NULL);
      if (confPath != NULL)
          serverName = Ns_ConfigGetValue (confPath, "serverName");
      
      /* create context with proper worker info for each URI registered in workers2.properties */
      uriMap = workerEnv->uriMap->maps;
      env=workerEnv->globalEnv;
  
      for (i=0, urimapsz=uriMap->size(env, uriMap); i<urimapsz; i++) {
          uriEnv = uriMap->valueAt(env, uriMap, i);
          uriname=uriEnv->mbean->getAttribute(env, uriEnv->mbean, "uri");
          vhost=uriEnv->mbean->getAttribute(env, uriEnv->mbean, "host");
  
  	if (uriname!=NULL && strcmp(uriname, "/") && /* i.e., not global root */ 
  	    (vhost==NULL || strcmp(vhost, "*")==0 || strcmp(vhost, server)==0)) /* match virtual server */ {
  
  	    ctx = createURIContext (uriEnv, serverName);
  	    Ns_RegisterRequest(server, "GET", uriname, jk2_handler, NULL, ctx, 0);
  	    Ns_RegisterRequest(server, "HEAD", uriname, jk2_handler, NULL, ctx, 0);
  	    Ns_RegisterRequest(server, "POST", uriname, jk2_handler, NULL, ctx, 0);
  	}
      }
  
      return NS_OK;
  }
  
  
  
  #ifdef WIN32
  
  BOOL WINAPI DllMain(HINSTANCE hInst,        // Instance Handle of the DLL
                      ULONG ulReason,         // Reason why NT called this DLL
                      LPVOID lpReserved)      // Reserved parameter for future use
  {
      GetModuleFileName( hInst, file_name, sizeof(file_name));
      return TRUE;
  }
  
  
  #endif
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/server/aolserver/nsjk2.dsp
  
  Index: nsjk2.dsp
  ===================================================================
  # Microsoft Developer Studio Project File - Name="nsjk2" - Package Owner=<4>
  # Microsoft Developer Studio Generated Build File, Format Version 6.00
  # ** DO NOT EDIT **
  
  # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
  
  CFG=nsjk2 - Win32 Debug
  !MESSAGE This is not a valid makefile. To build this project using NMAKE,
  !MESSAGE use the Export Makefile command and run
  !MESSAGE 
  !MESSAGE NMAKE /f "nsjk2.mak".
  !MESSAGE 
  !MESSAGE You can specify a configuration when running NMAKE
  !MESSAGE by defining the macro CFG on the command line. For example:
  !MESSAGE 
  !MESSAGE NMAKE /f "nsjk2.mak" CFG="nsjk2 - Win32 Debug"
  !MESSAGE 
  !MESSAGE Possible choices for configuration are:
  !MESSAGE 
  !MESSAGE "nsjk2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE "nsjk2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE 
  
  # Begin Project
  # PROP AllowPerConfigDependencies 0
  # PROP Scc_ProjName ""
  # PROP Scc_LocalPath ""
  CPP=cl.exe
  MTL=midl.exe
  RSC=rc.exe
  
  !IF  "$(CFG)" == "nsjk2 - Win32 Release"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 0
  # PROP BASE Output_Dir "Release"
  # PROP BASE Intermediate_Dir "Release"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 0
  # PROP Output_Dir "Release"
  # PROP Intermediate_Dir "Release"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSJK2_EXPORTS" /YX /FD /c
  # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /I "$(TCL_HOME)\include" /I "$(AOL_HOME)\include" /I "$(JAVA_HOME)\include" /I "$(APACHE2_HOME)\include" /D "NDEBUG" /D "NSJK2_EXPORTS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D FD_SETSIZE=128 /D TCL_THREADS=1 /D NO_CONST=1 /D "HAVE_JNI" /D "HAS_APR" /D "HAS_PCRE" /YX /FD /c
  # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x41a /d "NDEBUG"
  # ADD RSC /l 0x41a /d "NDEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
  # ADD LINK32 nsd.lib nsthread.lib libapr.lib libaprutil.lib wsock32.lib advapi32.lib pcre.lib pcreposix.lib /nologo /dll /machine:I386 /libpath:"$(TCL_HOME)\lib" /libpath:"$(AOL_HOME)\lib" /libpath:"$(APACHE2_HOME)\lib"
  
  !ELSEIF  "$(CFG)" == "nsjk2 - Win32 Debug"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 1
  # PROP BASE Output_Dir "Debug"
  # PROP BASE Intermediate_Dir "Debug"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 1
  # PROP Output_Dir "Debug"
  # PROP Intermediate_Dir "Debug"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSJK2_EXPORTS" /YX /FD /GZ /c
  # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "$(TCL_HOME)\include" /I "$(AOL_HOME)\include" /I "$(JAVA_HOME)\include" /I "$(APACHE2_HOME)\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D FD_SETSIZE=128 /D TCL_THREADS=1 /D NO_CONST=1 /D "HAVE_JNI" /D "HAS_APR" /D "HAS_PCRE" /YX /FD /GZ /c
  # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x41a /d "_DEBUG"
  # ADD RSC /l 0x41a /d "_DEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
  # ADD LINK32 nsd.lib nsthread.lib libapr.lib libaprutil.lib wsock32.lib advapi32.lib pcre.lib pcreposix.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"$(TCL_HOME)\lib" /libpath:"$(AOL_HOME)\lib" /libpath:"$(APACHE2_HOME)\lib"
  
  !ENDIF 
  
  # Begin Target
  
  # Name "nsjk2 - Win32 Release"
  # Name "nsjk2 - Win32 Debug"
  # Begin Group "Source Files"
  
  # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
  # Begin Source File
  
  SOURCE=.\jk_logger_ns.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\jk_service_ns.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\jni_nslog.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\jni_nstcl.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\nsjk2.c
  # End Source File
  # End Group
  # Begin Group "Header Files"
  
  # PROP Default_Filter "h;hpp;hxx;hm;inl"
  # Begin Source File
  
  SOURCE=..\..\include\jk_bean.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_channel.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_config.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_endpoint.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_env.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_global.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_handler.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_logger.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_md5.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_msg.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_mutex.h
  # End Source File
  # Begin Source File
  
  SOURCE=.\jk_ns.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_objCache.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_pool.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_requtil.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_service.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_shm.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_uriEnv.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_uriMap.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_vm.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\include\jk_workerEnv.h
  # End Source File
  # Begin Source File
  
  SOURCE=.\jni_nstcl.h
  # End Source File
  # End Group
  # Begin Group "Resource Files"
  
  # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
  # End Group
  # Begin Group "Common Files"
  
  # PROP Default_Filter ""
  # Begin Source File
  
  SOURCE=..\..\common\jk_channel.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_channel_apr_socket.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_channel_jni.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_channel_socket.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_channel_un.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_config.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_config_file.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_endpoint.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_env.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_handler_logon.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_handler_response.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_logger_file.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_logger_win32.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_md5.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_msg_ajp.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_mutex.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_mutex_proc.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_mutex_thread.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_objCache.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_pool.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_pool_apr.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_registry.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_requtil.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_shm.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_signal.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_uriEnv.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_uriMap.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_user.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_vm_default.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_worker_ajp13.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_worker_jni.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_worker_lb.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_worker_run.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_worker_status.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\..\common\jk_workerEnv.c
  # End Source File
  # End Group
  # End Target
  # End Project
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org